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
| Step | Responsibility | Durable evidence |
|---|---|---|
qrg_normalize_input | Normalize/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_context | Resolve the compiled snapshot, organization, selected categories, annex forms, and generation scope. | request organization and qrg_generations metadata |
qrg_process_annexes | Clean 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_results | Insert 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:
- chooses
name, thentitle, thenAnnex <id>as the display name; - cleans all usable content from
state.data; - deterministically classifies the annex name as FUNCTIONAL, EMERGENCY, or OTHER;
- 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; audienceCategoryNameand category description;generationScope(DISTRICTorFACILITY).
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;
FUNCTIONALorEMERGENCYtype plus the applicable classification;generalUserTagManagementType: "ASSIGN_SELECTED";- an empty
generalUserTagIdslist; - exactly one
generalUserTagCategoryIdsentry; - 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:
| Condition | Final behavior |
|---|---|
| Agent recommends no targets | success with a no-recommendation warning. |
| Some target/model calls fail | success with warning and target errors if other targets generated or skipped. |
| Some K12 saves fail | success with warning; generated content remains in internal evidence. |
| Every target fails | error with the first error plus the full error list. |
No fallback or placeholder QRG content is synthesized after a model failure.
Persistence Map
| SQL surface | Current role |
|---|---|
K12SAFETY.qrg_requests | Request type, state, organization, and workflow correlation. |
K12SAFETY.qrg_generations | Snapshot, category-selection, mode, scope, and result summary. |
K12SAFETY.qrg_generation_annexes | Per-annex classification, cleaned/source evidence, category target decisions, generated count, and error. |
K12SAFETY.qrg_generated_items | One row per generated category guide, content blocks, category IDs, and K12 save result. |
K12SAFETY.qrg_ai_calls | Target model-call prompt/response, status, token, duration, and failure evidence. |
K12SAFETY.qrg_execution_errors | Classified workflow and integration failures. |
K12SAFETY.qrg_request_prompts | Request 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
| Component | Path |
|---|---|
| Workflow | packages/domain-k12/src/qrg-generation.workflow.ts |
| Kickoff and runner | packages/domain-k12/src/qrg/qrg-generation-kickoff.ts, packages/domain-k12/src/qrg/qrg-generation-workflow-runner.ts |
| Agent and prompt contract | packages/domain-k12/src/agents/qrg-agents.ts, packages/domain-k12/src/qrg-prompts.ts |
| Context collection | packages/domain-k12/src/k12-data-collector.ts |
| External client | packages/domain-k12/src/clients/index.ts |
| Persistence | packages/domain-k12/src/qrg-dedicated-storage.ts |
| Tool schemas/status | packages/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.