Task: Split every codegen template org into commented literate blocks
This page documents a task in the Codegen developer experience improvements story. It captures the goal, current status, acceptance, and any notes or results.
Goal
Make every codegen template genuinely literate: a reader should be able to open the template's org source and understand what each part of the generated artefact does and why, without reverse-engineering the mustache.
Today most template orgs under projects/ores.codegen/library/templates/ hold
their entire source in a single #+begin_src mustache :tangle <name>.mustache
block with little or no surrounding prose. org-babel-tangle concatenates all
same-target blocks in document order (proven: doc_archetype_org.org,
doc_facet_org.org, and ores.cpp.qt.controller_impl.org already do this),
so a template can be broken into several :tangle-to-the-same-file blocks
interleaved with explanatory prose — without changing the tangled output.
For each template org:
- Split the monolithic mustache block at natural seams (per generated
function / section / variability region) into multiple blocks that all
:tangleto the same.mustache. - Precede each block with detailed, human-level prose: what this section
generates, why it exists, the meaning of the variability switches it uses,
and any non-obvious contract with the runtime / base classes / DB triggers
(the
onRevertVersion"reset version to 0" section inores.cpp.qt.controller_impl.orgis the reference exemplar). - Keep the generated C++/SQL comment-free where the prose now carries the explanation — the code is instantiated per entity, so commentary belongs in the template, not multiplied across every generated file.
Reference exemplar: the ** Reverting to a historical version section added to
ores.cpp.qt.controller_impl.org in the country flag/revert work.
Status
| Field | Value |
|---|---|
| State | BLOCKED |
| Parent story | Codegen developer experience improvements |
| Now | Analysis and batch plan confirmed; pilot started on cpp_repository (entity_impl.org done, verified byte-identical), then paused. |
| Waiting on | Fix refdata entity model drift: update to latest format and regenerate — pre-existing drift found while verifying the pilot split's zero-diff guarantee; must be clean before any more splitting lands. |
| Next | Resume cpp_repository pilot (entity_header.org onward) once the drift task is DONE. |
| Last touched | 2026-07-29 |
Acceptance
- Every template org under
projects/ores.codegen/library/templates/whose body is a single mustache block is split into multiple same-target blocks with prose between them (templates that are already trivial/short may be left as one block with a clear leading paragraph — note which and why). - Each block is preceded by prose explaining what it generates and why, including the variability switches it consumes.
- Re-tangling (
compass build --direct tangle_codegen_templates) produces no diff in the.mustacheartefacts versus before the split (output is byte-identical; only the org sources gain structure + prose). template-driftCI stays green.- A full entity regen (e.g.
compass codegen entity generate country --address ores) shows no diff attributable to this task. - Generated artefacts gain no new inline comments (commentary lives in the org).
Plan
(Implementation strategy. Written when work starts; key decisions
are distilled into the parent story's * Decisions at close, but the
plan itself stays — it is the historical record of what we did.)
Analysis (2026-07-29)
Where this sits relative to sprint 20's literate-templates story
Convert codegen mustache templates to literate org-mode documents
(sprint 20, DONE) already built the hierarchy this task extends:
overview.org → group doc (ores.cpp.org, ores.sql.org, …) →
facet doc (ores.cpp.qt.org, …) → archetype doc — one org file
per output artefact, #+type: archetype, holding the
#+begin_src mustache :tangle <name>.mustache block(s) that actually
tangle to the .mustache codegen reads. That story deliberately
scoped out template content changes — it was a format migration, one
block per archetype, prose only at the top. This task goes one level
finer: split each archetype's single block into multiple
same-target blocks interleaved with prose, at the seam level
(per function / section / variability region) rather than per
artefact. The tangle tooling (tangle_codegen_templates CMake
target, ores-build-codegen-templates.el), the generated-file
header, and the template-drift CI drift check are already in place
and need no changes — this task only touches archetype-doc content.
Inventory
149 archetype docs under
projects/ores.codegen/library/templates/
(excluding the group/facet/overview docs, which hold no tangle
blocks), ~21k lines total, currently 147 single-block and 2 already
multi-block:
| Size (lines) | Count | Notes |
|---|---|---|
| < 50 (small) | 21 | Mostly boilerplate; acceptance already allows leaving these as one block with a leading paragraph. |
| 50–149 (medium) | 97 | The bulk. Some are one cohesive function (little to gain from splitting); others pack several independent seams (real candidates). |
| 150+ (large) | 31 | Where a reader most needs literate structure to navigate; includes the two current exemplars. |
The two existing multi-block docs are useful, but only partially:
ores.cpp.qt.controller_impl.org (828 lines) splits out two seams
(onRevertVersion, "remaining controller methods") out of what is
still an ~600-line first block — i.e. even the reference exemplar
this task's own Goal cites did not fully atomize per-function. That
sets a realistic bar: full per-function decomposition of all 149
archetypes (some 900–1600 lines) is a much larger effort than
"add prose to the existing single block," and blindly splitting every
seam in every archetype — including one-function medium files where a
split would just repeat the top-of-file prose — cuts against the
project's own no-premature-abstraction convention.
Coordination / blast-radius check (2026-07-29)
Checked every other worktree's branch (git diff origin/main...HEAD --
projects/ores.codegen/library/templates) and open PRs
(gh pr list --json files) for current touches to this directory:
- Only
clever_dijkstra(branchfeature/junction-qt-facet-codegen) and open PR #1737 touch anything here right now, both onlyores.cpp.qt.org(the facet doc, not an archetype impl file) — low overlap risk today. - However
cpp_qtis structurally the highest-churn family: badge work, calendar follow-ups, junction eventing, and parent-scoped lists have all landed edits tocpp_qtarchetypes in the last few sprints (confirmed: PR #1719 alone touchedcpp_qt_{controller,client_model,mdi_window}.{cpp,hpp}.mustache). A literate split touches the entire archetype body (reflowing content into new block boundaries), so any concurrent content PR against the same archetype is a near-guaranteed conflict, even though the tangled output doesn't change.cpp_qtshould be scheduled last, once other in-flight cpp_qt work has landed, not first despite having the richest exemplar already. - No other worktree currently touches
ores.sql.*,ores.cpp.repository.*,ores.cpp.domain.*, orores.cpp.nats-*— these are safe to start on immediately.
Proposed approach
- Scope interpretation (needs a decision, see questions below): apply full seam-splitting only to the 31 "large" archetypes, where the payoff (navigability of an 800–1600 line file) is real. For the 97 "medium" archetypes, split only where there's a genuine independent seam (a variability-gated block, an extension point, a distinct helper); leave single-function or boilerplate-heavy ones as one block with a clear leading paragraph, same as the 21 "small" ones — and say so explicitly per file, so the choice reads as a decision, not an oversight.
- Pilot (small, cross-family, before batching): one file each from
three different families not currently touched by anyone —
suggest
ores.cpp.repository.mapper_impl.org(478 lines,cpp_repository),ores.sql.schema.domain_entity_create.org(915 lines,sql_schema), and extending the existingores.cpp.qt.client_model_impl.orgexemplar further (already started, low new-conflict risk since it's already multi-block). Validates the split pattern across C++/SQL/Qt before committing to the full sweep, and gives reviewers a small, concrete diff to calibrate "how much prose is enough" against. - Batch by facet family, one PR per family: keeps each PR's diff
and review size manageable and keeps the window any one archetype
is "in flight" short, which matters given the coordination risk
above. Suggested order (safest/least-contended first):
cpp_repository→sql_schema/sql_service/sql_populate→cpp_domain/cpp_table→cpp_nats_*→cpp_service_app→cpp_component→doc_*→cpp_qtlast. - Per-file verification (every file, every batch): re-tangle
(
compass build --direct tangle_codegen_templates) must produce a byte-identical.mustache;template-driftCI stays green; one representative entity regen (e.g.compass codegen entity generate country --address ores) shows no diff. - Coordination protocol while other environments may be active: before starting a family's batch, re-run the blast-radius check above (diff every worktree branch + open PRs against that family's archetype files); post a note in the current sprint's Captures section naming the family about to be touched so other environments can avoid it mid-flight; keep each family's PR small enough to land same-day rather than sitting open across sessions.
Decisions (confirmed with user, 2026-07-29)
- Scope: all 149 archetypes get full seam-splitting, not just the 31 "large" ones — the literal reading of the acceptance criteria. Every archetype ends with prose preceding each same-target block; a template that is genuinely one cohesive seam still gets a clear leading paragraph (per the acceptance criteria's own allowance), but the decision to leave it as one block is made per file, not skipped by size bucket.
- cpp_qt timing: scheduled last, once other in-flight cpp_qt work (badge, calendar follow-ups, junction eventing, parent-scoped lists) has landed — highest churn family, highest conflict risk.
- Batching: one PR per facet family (~8-10 PRs total), not grouped — keeps each PR's diff small, review fast, and the window any one archetype is "in flight" short.
Batch plan (facet families, in order)
Counts are archetype docs (tangle-block-bearing files) per facet,
via filename prefix under ores.cpp.<facet>.*.org /
ores.sql.<facet>.*.org etc.:
| Order | Family | Archetypes | Notes |
|---|---|---|---|
| 1 | cpp_repository | 6 | No current cross-worktree touches; start here. |
| 2 | cpp_domain | 7 | Includes the base domain type layer other facets build on. |
| 3 | cpp_table (domain-adjacent) | (counted in domain/table split, confirm exact split when starting) | |
| 4 | sql_schema / sql_service / sql_populate | 19 (ores.sql.*) |
No current touches; group's own sub-families (schema/service/populate) may split into 2-3 PRs if any single one is large. |
| 5 | cpp_nats_* (eventing, event-cache, event-registrar, sub-registrar, handler) | 8 | Small facets; may combine into one PR given size. |
| 6 | cpp_service_app | 12 | Largest non-qt cpp facet. |
| 7 | cpp_component | 6 | |
| 8 | cpp_service | 2 | |
| 9 | cpp_presentation, cpp_protocol, cpp_generator, cpp_enum, cpp_field-group | 7 combined | Small facets, batch together. |
| 10 | doc_* | 22 | Lower priority — these document agile/knowledge artefacts, not runtime code; less variability-switch complexity to narrate. |
| 11 | cmake_* | 7 | Already fairly mechanical/uniform; low prose payoff. |
| 12 | cpp_qt | 9 | Last, once other in-flight cpp_qt work lands. Includes the two already-partially-split exemplars to finish. |
Re-check the coordination/blast-radius section immediately before starting each batch — the snapshot above is 2026-07-29 and will drift as other environments land work.
Next step
Pilot batch: cpp_repository (6 archetypes, no current conflicts,
moderate size — 190 to 1127 lines). Confirms the split pattern and
prose density on real files before committing to the full 12-batch
sweep.
Notes
The currency-pair pair_code work (Pair code doesn't recompute when base/quote currency changes)
added 6 new paste-block seams to ores.cpp.qt.detail_dialog_impl.org=/
=ores.cpp.qt.detail_dialog_header.org (extra includes, declarations,
connections, create-mode override, read-only override, extra methods)
and 1 to ores.cpp.qt.mdi_window_header.org (extra signal
declarations) — each currently documented only as a single
* Extension points prose summary near the top of the file, with a
one-line non-emitted \{\{! see * Extension points above \}\}
mustache comment at each marker (comment-free generated output, but
not yet split into the same-target-block-per-seam pattern this task
calls for). Good concrete starting point when this task is picked up:
retrofit those 7 seams as the first same-target-block splits, following
the \*\* Reverting to a historical version exemplar in
ores.cpp.qt.controller_impl.org.
PRs
| PR | Title |
|---|---|
| #1743 | [agile,codegen] Literate-split cpp_repository pilot (partial); block on refdata drift fix |
Review
| Comment summary | File | Decision | Notes |
|---|---|---|---|