Skip to main content

QRG Generation Deep Dive

Overview

qrg-generation-workflow is a four-step Mastra workflow owned by packages/domain-k12/src/qrg-generation.workflow.ts. It turns compiled EOP annexes and exact General User Tag Categories into category-specific QRGs.

The current design replaced the former classify → group extraction → role mapping → generation chain. Annex classification is deterministic, and one profile-backed agent makes the recommendation and generation decision for each annex/category target.

Workflow Chain

StepResponsibilityDurable evidence
qrg_normalize_inputNormalize/generate request and session IDs, validate category selection, reject duplicate request IDs, and create the request/prompt audit records.qrg_requests, qrg_request_prompts
qrg_collect_k12_contextResolve the compiled snapshot, organization, selected categories, annex forms, and generation scope.request organization and qrg_generations metadata
qrg_process_annexesClean annex content, classify annex names, run the bounded target model pool, validate decisions, save recommended guides, and persist per-annex target evidence.qrg_generation_annexes, AI-call evidence, K12 save evidence
qrg_persist_resultsInsert generated item rows, calculate final status/warnings, complete generation metadata, and persist timing summaries.qrg_generated_items, final request/generation state, step timings

Input Resolution

The workflow accepts an emergencyOperationPlanId plus optional exact generalUserTagCategoryIds. It generates request/session IDs when absent and rejects more than 25 selected categories.

collectK12Data() resolves the compiled EOP context without loading role tags. collectGeneralUserTagCategoriesWithMetadata() then selects exact categories from master-copy, snapshot, configuration, and organization context. A request fails if it cannot resolve a compiled snapshot, any category, or any annex form.

The external form request can be narrowed with comma-separated K12_ANNEX_FORM_TYPE_IDS.

Target Construction

For each annex, the workflow:

  1. chooses name, then title, then Annex <id> as the display name;
  2. cleans all usable content from state.data;
  3. deterministically classifies the annex name as FUNCTIONAL, EMERGENCY, or OTHER;
  4. creates one target for each exact selected category.

An empty annex produces an audited skipped decision for every category without a model call. Non-empty targets enter the bounded model pool.

Agent Contract

getQrgCategoryGuideGenerationAgent() builds a fresh agent for the target with:

  • annexName;
  • deterministic annexClassification;
  • audienceCategoryName and category description;
  • generationScope (DISTRICT or FACILITY).

The profile ID is qrg-category-guide-generation; the runtime registry ID is qrg-category-guide-generation-agent.

The structured result contains:

{
"should_generate": true,
"recommendation_reason": "This category has distinct actions in the annex.",
"before_event": "- Review the approved procedure.",
"during_event": "- Follow the annex action sequence.",
"after_event": "- Report completion and exceptions."
}

during_event is mandatory when should_generate is true. The workflow converts markdown action lines to document-service-compatible HTML blocks.

QRG Shape And External Save

A generated QRG carries:

  • a deterministic annex/classification/category-derived name;
  • FUNCTIONAL or EMERGENCY type plus the applicable classification;
  • generalUserTagManagementType: "ASSIGN_SELECTED";
  • an empty generalUserTagIds list;
  • exactly one generalUserTagCategoryIds entry;
  • BEFORE, DURING, and AFTER content blocks.

The save behavior is controlled by QRG_SAVE_TO_K12, input dryRun, and the test-only organization validation override. District and facility generation scopes are both supported by current code. A K12 save failure increments saveFailedTargets and retains the generated guide and error evidence rather than discarding the entire request.

Concurrency

resolveQrgGenerationConcurrency() defaults to four concurrent target calls and clamps QRG_GENERATION_CONCURRENCY to one through six. The process-wide permit pool prevents concurrent requests from each independently saturating the model lane. Outcome assembly preserves the original annex/category order.

External K12 writes happen while results are assembled and remain sequential.

Status Semantics

The persisted request begins as accepted, moves to processing, and finishes as success or error. Public polling tools normalize the stored state for callers.

The final result contains qrgList, error, warning, optional errors, target statistics, and timing evidence. Important cases:

ConditionFinal behavior
Agent recommends no targetssuccess with a no-recommendation warning.
Some target/model calls failsuccess with warning and target errors if other targets generated or skipped.
Some K12 saves failsuccess with warning; generated content remains in internal evidence.
Every target failserror with the first error plus the full error list.

No fallback or placeholder QRG content is synthesized after a model failure.

Persistence Map

SQL surfaceCurrent role
K12SAFETY.qrg_requestsRequest type, state, organization, and workflow correlation.
K12SAFETY.qrg_generationsSnapshot, category-selection, mode, scope, and result summary.
K12SAFETY.qrg_generation_annexesPer-annex classification, cleaned/source evidence, category target decisions, generated count, and error.
K12SAFETY.qrg_generated_itemsOne row per generated category guide, content blocks, category IDs, and K12 save result.
K12SAFETY.qrg_ai_callsTarget model-call prompt/response, status, token, duration, and failure evidence.
K12SAFETY.qrg_execution_errorsClassified workflow and integration failures.
K12SAFETY.qrg_request_promptsRequest prompt/task audit evidence.

The SQL project under db/sqlproj/Mastra.Platform.K12SafetyDb/ is the schema authority; do not infer columns from historical examples.

Debugging Queries

SELECT
RequestId,
AnnexId,
AnnexName,
ClassifiedCategory,
CategoryTargetsJson,
GeneratedQrgCount,
ProcessingStatus,
ErrorMessage
FROM K12SAFETY.qrg_generation_annexes
WHERE RequestId = @RequestId;
SELECT
RequestId,
QrgName,
GeneralUserTagCategoryIdsJson,
GenerationScope,
K12SaveStatus,
K12SaveError
FROM K12SAFETY.qrg_generated_items
WHERE RequestId = @RequestId;

Code And Tests

ComponentPath
Workflowpackages/domain-k12/src/qrg-generation.workflow.ts
Kickoff and runnerpackages/domain-k12/src/qrg/qrg-generation-kickoff.ts, packages/domain-k12/src/qrg/qrg-generation-workflow-runner.ts
Agent and prompt contractpackages/domain-k12/src/agents/qrg-agents.ts, packages/domain-k12/src/qrg-prompts.ts
Context collectionpackages/domain-k12/src/k12-data-collector.ts
External clientpackages/domain-k12/src/clients/index.ts
Persistencepackages/domain-k12/src/qrg-dedicated-storage.ts
Tool schemas/statuspackages/domain-k12/src/qrg/qrg-schemas.ts, packages/domain-k12/src/qrg/qrg-status-tools.ts

Use the package lane plus the category-first local harness:

npm run test:k12
npm run typecheck:k12
npm run build:k12
npm run test:live:k12:qrg-category:local

The local harness blocks SQL/MOEOP hosts that are not clearly local, development, or testing targets. Real external writes require explicit opt-in flags; never enable them against production for a documentation check.