Story: Codegen model safety guardrails
Table of Contents
This page documents a story in Sprint 21. It captures the goal, current status, acceptance criteria, and the tasks that compose it.
Goal
Before the C++ template audit (Refactor ores.codegen C++ generation) begins,
close the known silent failure modes in ores.codegen that would cause
the audit to produce misleading results:
- Missing
component_include/component_corefields cause generated files to land in a non-existentprojects/ores.<component>/directory. Git diff reports "clean" because the output is untracked — a false pass. - Running
--profile sqlon a_domain_entity.jsonmodel silently usessql_schema_domain_entity_create.mustache(the old template) rather than the new unified template, even when a_table.jsonexists for the same entity. - The
all-cppprofile excludes Qt,nats-eventing, and all non-temporal variants. Claiming "zero diff" after runningall-cppleaves Qt and non-temporal drift undetected. - Non-temporal entities run through the temporal
all-cppprofile silently produce C++ with audit columns (version,modified_by,recorded_at) that do not exist in the database table.
These guardrails convert silent wrong-path output and false "clean" signals into loud, actionable errors. They make the subsequent C++ audit trustworthy.
See Codegen architecture analysis and unified model roadmap for full context.
Status
| Field | Value |
|---|---|
| State | BACKLOG |
| Parent sprint | Sprint 21 |
| Now | Not yet started. |
| Waiting on | Nothing. Should start before C++ audit Task 1. |
| Next | Implement guard for missing component_include. |
| Last touched | 2026-05-30 |
Acceptance
generate.pyraises aValueErrorwhen a_domain_entity.jsonmodel is missingcomponent_includeorcomponent_core;codegen.pycatches it, logs a clean human-readable error message naming the missing field and the model file, and exits non-zero. No raw Python traceback is shown to the user.- Running
--profile sqlon a_domain_entity.jsonmodel that has a corresponding_table.jsonin the same directory raises an error or warning directing the user to use the_table.jsonmodel instead. - Running
--profile allon a_domain_entity.jsonmodel raises an error (extending the existing guard that already blockstableandschemamodels). - A comment or
--helpnote documents which facetsall-cppcovers and that Qt requires a separate--profile qtinvocation. - CI passes. No production C++ files are changed by this story.
Tasks
| Task | State | Start | End | Description |
|---|---|---|---|---|
| Task: Guard missing component_include/component_core in generator.py | BACKLOG | Raise an error at generation time when component_include or component_core is absent from a domain_entity model. | ||
| Task: Block dual-template SQL generation for domain_entity models | BACKLOG | Extend the –profile all guard and add a warning when –profile sql is run against a domain_entity with a co-located _table.json. | ||
| Task: Document all-cpp profile limitations | BACKLOG | Add –help annotation and CLI output note explaining Qt is excluded from all-cpp; add guard that warns when a model lacks is_temporal and a temporal profile is used. |
Decisions
- Errors not warnings for missing fields. The
component_includefallback silently writes to the wrong path; a warning is easily ignored. An error forces the model to be fixed before generation proceeds. - Warn, not error, for dual-template SQL. The
_domain_entity.jsonSQL output may legitimately be used for non-refdata components that have no_table.jsonyet. A warning with clear guidance is safer than a hard error until all components have migrated to_table.jsonmodels.
Out of scope
- Migrating any
_domain_entity.jsonmodels to add the missing fields — that is Task 3 of Refactor ores.codegen C++ generation. - Adding an
is_temporalfield to all 75 models — that belongs to Codegen unified model — Phase 3: unify temporal/non-temporal templates. - Any template or production file changes.