Context
A new feature starts as a blank folder that each author fills differently. An agent that adds a module needs a machine-readable statement of what the module contributes, and a catalogue written by hand would become a second source of truth beside the code. The owner settled on 2026-10-21 that the code is the truth, the catalogue is generated from it, and a plan is data that is consumed once.Decision
- Code is the truth; the catalogue is generated. The committed
app-manifest.json(0158) holds what each module contributes.stackra cataloguerenders the catalogue from that manifest, as YAML for machines and Markdown for review, plus a small hand-written overlay. The overlay holds what code cannot hold:summary,home.reason,sourcecitations and openquestions. Each service has one catalogue, and each package has one with the same shape. - Plans live in spec folders. A module that does not exist yet is planned in
.agents/specs/<sta-n>/module-plan.yaml, with the same schema as the catalogue.pnpm new moduleconsumes the plan once to emit stubs. It does not keep the plan as a second copy. - The generator.
pnpm new module <svc> <feature>reads the module’s plan, when one exists, and emits:- the module file, its README,
definePermissions,defineEvents, settings andcontracts; @Modelstubs with TODO fields;@Actionand@Querystubs with akey@1, Zod placeholders, a permission and a risk level;- an
@Resourcestub; - an action body that throws
not_implemented; - a module boot test.
- the module file, its README,
- Contract docblocks. Every emitted file opens with a contract block (0007) taken from the plan, so a file says what it is for before anyone edits it.
- Idempotent. A re-run adds the files that are missing and never overwrites a file that exists. A re-run that finds nothing missing changes nothing.
- No empty folders. A kind folder is created with its first file (0126 decision 3).
- Drift is a to-do list.
stackra catalogue --diffshows the plan against the code. A difference is a task for the author. The generator never rewrites code to match a plan, and the plan never overrides the code. - Pilot catalogues move to plans. A hand-written catalogue file is split into one plan file per module as each module is built. The published catalogue is always the generated one.
Consequences
- A module starts in a shape that passes the validator, and each stub fails loudly until it is implemented.
- The catalogue cannot drift from the code, because it is rendered from the manifest. A plan that has not been built shows up as a diff.
- Authors who change a module’s contributions change the code and the manifest follows; there is no second catalogue to keep in step.
- Plans need a schema, which
pnpm validatechecks.
Enforcement
planned —tools/scripts/__tests__/scaffold.test.mjs renders a module twice and asserts that the second run creates no file and changes none,
and that every emitted file opens with a contract block. Planned: pnpm validate checks each module-plan.yaml against its schema, and
stackra catalogue --diff runs in CI as a report, not a gate.