Task: Mark generated recipes, and give them a gate
Table of Contents
This page documents a task in the Harden the gates the component clean standard rests on story. It captures the goal, current status, acceptance, and any notes or results.
1. Goal
Give generated org output the codegen marker every other generated kind already carries, and give the generated recipes the gate they have never had.
The recipe templates do carry a marker, but as a Mustache comment, and Mustache
comments produce no output. So no generated recipe reached the tree with one:
247 files sit at the generated recipe path shape and 172 carry the :tangle
block a generated recipe exports, against 6,478 tracked C++ files that name their
template. Nothing could tell a generated recipe from a hand-written one, and
nothing checked either, because the sweep rendered per technical space and the
recipe facets need a facet from another space.
2. Status
| Field | Value |
|---|---|
| State | DONE |
| Parent story | Harden the gates the component clean standard rests on |
| Now | Nothing. |
| Waiting on | Nothing. |
| Next | Nothing. |
| Last touched | 2026-09-27 |
3. Acceptance
- Every generated org document carries a marker naming its template, emitted at the render seam rather than by each template.
- The marker does not disturb the document's frontmatter, its blurb, or the doc index that reads them.
- The sweep renders the whole
oresaddress, so the recipe facets fire and the generated recipes are covered. - The rollout changes nothing but the marker: no generated recipe is rewritten beyond adding one line, and the check proves it.
- A test fails if the org marker stops being emitted.
4. Plan
Where the marker goes, and why there. Org has no licence block to append a
marker to, so the marker is a #+generated: keyword inserted after the leading
:PROPERTIES: drawer. Placement is not cosmetic. The doc index reads the drawer
from the first line and folds whatever precedes it into the document's blurb –
the prose compass show prints – so a marker above the drawer gives the blurb
the drawer's own text. And the blurb skips #+ lines and blank lines and stops
at anything else, so a # comment in the same position becomes the blurb too.
Both were measured against doc_index.extract_blurb before the change: the
#+generated: keyword after the drawer preserves the blurb and the id, and a
marker above the drawer corrupts the blurb.
The coverage half. _render_components expands ores into the technical
spaces, and passing ores to it does not render the whole address. A facet
whose #+requires_facet: names a facet in another space therefore never fires,
which is how the recipe facets were missed: for ores.trading the per-space path
gives 1,867 files and no recipe, while rendering each model at the whole address
gives 2,003 files and 22 recipes. The sweep now asks for the whole address; the
per-component modes keep the expansion they have always had.
The rollout, and its safety rule. Applying a marker to files that already exist is a rewrite, and 58 of the renderable recipes disagree with their models by more than a marker. So the rollout wrote a recipe only where the marker was the sole difference, and left the rest alone. That is the rule the check enforces, and it is what keeps a hand edit from being overwritten by a marker pass.
5. Notes
Measured at the rebased head.
- The whole-address render produces 185 recipe files. 111 took the marker with nothing else changed, 60 differ by more than the marker and were left alone, and 14 the render produces are absent from the tree entirely.
- The rollout is exactly additive: 113 files changed, 113 lines added, 0 removed,
and every added line is a
#+generated:line, over the 113 the marker pass wrote. Two of those were reverted when the rebase moved them into the stale set, so the branch carries 111 andgit grep -l "^#+generated:" -- '*.org'finds 111 tracked org files carrying it. - The canonical doc index loads all 281 org files under
doc/recipes/shell/anddoc/recipes/http/, every one with a non-empty blurb, and none with the marker in its blurb. - 6,478 tracked
.cppand.hppfiles carry the C++ marker, measured withgit grep -l "AUTO-GENERATED FILE - DO NOT EDIT MANUALLY" -- '*.cpp' '*.hpp'. That is the figure the comparison is against, and it is smaller than the number of files on disk because generated trees outside version control do not count. - The sweep renders the whole address now and reports 857 files drifting across the catalogue in CI, against 645 before it reached the recipes; the same run reports 858 locally, so the figure moves by one with the clang-format version the machine has. It takes about a minute and stays green: none of that drift is this branch's.
- Proved end to end: appending a line to
doc/recipes/shell/trade_types/trade_type.orgmakes the sweep exit 1 and name that file, where before the change it could not see a recipe at all. - Codegen suite 906 passed;
compass lintclean;validate_docs.sh40 of 40.
What the rollout exposed, none of it fixed here.
- 60 recipes are stale against their template. Fifty-eight differ only inside
their
#+begin_src ores-shell :tangle ...blocks, and only by__none__becoming-in the placeholder positions, with no prose changed, so they are stale rather than hand-edited. Which of the two the shell accepts is the shell owner's call, and the staleness is filed as a capture. - Two more the rebase exposed, and the reason the branch carries 111 rather
than 113.
doc/recipes/shell/lei_entities/lei_entity.organddoc/recipes/shell/lei_relationships/lei_relationship.orgare staging shims, and main's staging-only change means the generator now renders them with no command sections at all: 77 lines where the tree holds 224. Regenerating them would delete 147 lines of generated recipe content, and whether a staging shim should keep a recipe at all is thedqowner's call, not a marker pass's. The marker was reverted on those two so this change stays purely additive, and the finding is filed with the staleness. - 76 files sit at the generated recipe path shape that no render produces. The shape holds 247; the render accounts for 171 of them once the 14 it produces but the tree lacks are set aside, leaving 76 with no model behind them, which is what a retired or renamed template leaves. Nothing deletes them, and nothing should: a clean-up that removed files no render produces would delete whatever a hand-written nested recipe looks like.
6. Test Scenarios
Manual QA scenarios (scaffolded via compass add test_scenario)
that verify this task. Link
new ones here as they're created; the scenario doc itself links back
via its "Verifies task" field.
| Scenario | State | Notes |
|---|---|---|
7. PRs
| PR | Title |
|---|---|
| #2271 | [codegen] Mark generated org output and give the recipes a gate |
8. Review
Independent verification of PR #2271 at head d2a71283c9, patch-id
dda645468331431c700c7ec56a55c6eac7679e95, verdict FAIL confined to the record's
numbers. Every substantive claim passed: the rollout is purely additive (113
insertions, 0 deletions, every added line a marker), the placement is sound
against the canonical parser with both counterfactuals measured, coverage reaches
recipes end to end, and the tests constrain in both directions.
| # | Comment summary | File | Decision | Notes |
|---|---|---|---|---|
| 1 | "the sweep reports 969 files drifting" sits under a heading that says measured at this head, and measures 856. 856 + 113 = 969, so it was taken before the rollout and never re-measured. | task doc | Fixed | The sweep reports 857 in CI and 858 locally at the rebased head, and both are named. |
| 2 | "7,854 C++ files" carrying the marker does not reproduce: 6,494 tracked .cpp=/.hpp= on the verifier's count, 6,478 by git grep -l over the index here. |
task doc, story | Fixed | The claim now names its command and the figure that command returns, 6,478. |
| 3 | The arithmetic is inconsistent: 247 = 185 + 62, yet 14 of the 185 are absent from the tree, which leaves 76 files with no model behind them, not 62. | task doc | Fixed | Corrected to 76: the shape holds 247, the render accounts for 171 of them, and 76 have no model behind them. |
| 4 | The 185/58/14 split was not re-measured for want of budget. | task doc | Fixed | Re-measured, and it moved: 111 marked, 60 stale, 14 absent. |
| 5 | The CI sweep job fails on lei_entity.org and lei_relationship.org. Rendering after a rebase produces 77 lines where the tree holds 224, so main's staging-only change left both recipes stale, and this branch had touched them with the marker. |
doc/recipes/shell/lei_*/ |
Reverted, recorded | The marker was reverted on those two so the change stays purely additive. Regenerating would delete 147 lines of generated content, and whether a staging shim keeps a recipe at all is the dq owner's call, so it is filed rather than guessed at. |
9. Result
Generated org output now carries the codegen marker every other generated kind
already carried. The recipe templates had one, but as a Mustache comment, and
Mustache comments emit nothing, so no generated recipe ever reached the tree
with one: 247 files sit at the generated recipe path shape and 172 carry the
tangle block a generated recipe exports, against 6,478 tracked C++ files that
name their template.
The marker is emitted at the render seam as a #+generated: keyword placed
immediately after the frontmatter drawer. The placement is measured rather than
chosen for looks: the doc index reads the drawer from the first line and folds
whatever precedes it into the blurb that compass show prints, and the blurb
skips #+ lines and blank lines and stops at anything else, so a marker above
the drawer corrupts the blurb in either spelling. All 281 org files under the two
recipe directories load with a non-empty blurb and none with the marker in it.
The rollout rewrote existing files, so it wrote a recipe only where the marker
was the sole difference: 111 files changed, 111 lines added, 0 removed, every
added line a marker, and nothing but the marker in any of them. Two further
recipes the marker pass had touched were reverted when the rebase showed main's
staging-only change now renders them with no command sections, because deleting
147 lines of generated content is the dq owner's call and not a marker pass's.
The sweep renders the whole ores address now, so the recipe facets fire and the
generated recipes have a gate for the first time. It reports 857 files drifting
elsewhere in the catalogue where it reported 645 before, and stays green because
none of that drift is a branch's. Proven end to end: appending a line to a
generated recipe makes the sweep exit 1 and name it, where before the change it
could not see a recipe at all.
Three findings are filed rather than fixed: 58 recipes are stale by __none__
becoming a hyphen, the two staging-shim recipes above, and 76 files at the
generated path shape with no model behind them. Codegen suite 906 passed,
compass lint clean, validate_docs.sh 40 of 40, and all eleven CI checks pass
including the new sweep job.