Capability 002: Modules¶
Status: Accepted
Context¶
A developer selects per artifact what repo update generates, in coarse modules rather than file
by file (mission statement; target picture,
sections Modules and Commands). This capability defines the standard modules, their defaults and
dependencies, which files a module owns, how repo update writes them, and repo check. It
builds on the configuration of capability 001.
References¶
Details¶
Standard modules:
| Module | Generates | Default |
|---|---|---|
scaffold |
Source and test tree, build files, Makefile, Devbox, lint configuration, README.md, LICENSE, .gitignore |
on |
ci |
CI pipeline, cliff.toml, CHANGELOG.md |
on |
specs |
specs/ tree, mkdocs.yml, make docs |
on |
domain-model |
specs/functional_design/domain_model.md |
on for service, off otherwise |
bdd |
BDD harness, test/bdd/, make bdd-test |
on, except for electronics |
manual-test |
test/manual/ with the manual test template |
on for firmware-stm32 and electronics, off otherwise |
ai |
CLAUDE.md, .claude/, .mcp.json, Copilot files, each for the assistants in assistants |
on |
guidelines |
Every applicable guideline in guidelines/ at the repository root, listed in the docs site |
off |
Dependencies:
| Module | Needs |
|---|---|
ci |
scaffold |
bdd |
scaffold |
domain-model |
specs |
Ownership of a file:
| Owner | Written by repo update |
Examples |
|---|---|---|
| Generator | On every run | .claude/rules/, CI pipeline, Makefile, mkdocs.yml, guidelines |
| Developer | Once, when the configuration first generates it | README.md, source code, specs/, Makefile.local, Compose files |
The docs site takes in guidelines/ while it is built, so no copy below specs/ is committed.
In a mono-repository, the artifacts' guidelines go to guidelines/ at the repository root as well.
meta records the modules generated per artifact:
Functional Requirements¶
- Without
modules, an artifact gets the default modules of its type. Withmodules, it gets exactly the listed ones. - A module that is not on, by default or by selection, generates no file, no
Makefiletarget, and no CI job. repo updatewrites the generator-owned files of every selected module.repo updatewrites a developer-owned file only if it does not exist and the configuration recorded inmeta.artifactswould not generate it: on the first run, for a new artifact, for a module added later, and for a repository-level file that a new artifact needs, such as the Compose files with the first service. It never overwrites an existing developer-owned file.- After a successful run,
meta.artifactslists, per artifact, the modules generated. repo updatedeletes no file. For a module or artifact recorded inmeta.artifactsbut no longer configured, it prints each existing file the module or artifact would generate, one path per line on standard output, and removes the record frommeta.artifacts.repo checkvalidates.repo.yamllikerepo update, then prints, one path per line, every file thatrepo updatewould create or change,.repo.yamlincluded, and exits non-zero if there is one. It writes nothing.- A repository-level file of a mono-repository exists as soon as one artifact selects the module
that needs it: the root pipeline with
ci, the combined docs site withspecs, the rootCLAUDE.mdand.claude/withai,guidelines/withguidelines. - Validation (capability 001, Functional Requirement 7) additionally reports:
- an unknown module
- a selected module whose dependency is not selected, naming the missing module
- A generated file refers to no file that only a module not selected generates. Guidelines and the rules taken from them are exempt.
- For an existing repository-level developer-owned file whose generated content differs between
the recorded and the current configuration,
repo updateprintsreview:and its path on standard output.
Non-Functional Requirements¶
repo checkandrepo updateproduce the same list of paths for the same repository state.
Technical Requirements¶
None.
Error Handling¶
repo updaterefuses a Git working tree with changes other than to.repo.yaml, names the changed files, and writes nothing.repo updateandrepo checkoutside a Git working tree fail with a message and write nothing.
Out of Scope¶
- The content a module generates, beyond the files named above
- Interface modules, such as
can - Removing files the generator no longer generates
Acceptance Criteria¶
- Go service without
modules:specs/functional_design/domain_model.md,test/bdd/, and notest/manual/, noguidelines/. - KiCad electronics without
modules:test/manual/, notest/bdd/, nomake bdd-test. - Go tool with
modules: [scaffold, specs]: no CI pipeline, noCLAUDE.md, notest/bdd/, nomake bdd-test. modules: [ci]: reported as "ci needs scaffold";modules: [scaffld]: reported as unknown.- Generated repository,
README.mdchanged and committed,.claude/rules/core.mdchanged and committed,repo update:README.mdkeeps the change,.claude/rules/core.mdis regenerated. - Generated repository with
modules: [scaffold, specs],bddadded,repo update:test/bdd/is generated;README.md, changed and committed before, keeps the change. - Generated repository, sample source file deleted and committed,
repo update: the file stays deleted. - Generated repository with
bdd,bddremoved,repo update: every file belowtest/bdd/is printed and still exists;meta.artifactsno longer listsbdd. - Mono-repository, artifact removed from
artifacts,repo update: the files of its directory are printed and still exist. - Generated, committed repository,
repo check: prints nothing, exits 0. - Same repository,
.claude/rules/core.mdchanged and committed:repo checkprints.claude/rules/core.md, exits non-zero, and the file keeps the change. - Same repository,
bddadded to.repo.yaml:repo checkprints the files oftest/bdd/and.repo.yaml, exits non-zero. .repo.yamlchanged and not committed,repo update: runs.README.mdchanged and not committed: refused, namingREADME.md.- Mono-repository with two artifacts, only one with
ai: rootCLAUDE.mdexists. - Every profile with both assistants, each module left out in turn together with the modules that need it: no generated Markdown file other than a guideline or a rule taken from one names in backticks a path that the profile generates with all modules but this repository lacks.
- Generated repository,
README.mdchanged and a sample source file deleted,meta.artifactsremoved, all committed,repo update:README.mdkeeps the change; the sample source file is generated again. - Mono-repository with a Go tool only, generated and committed, a Go service added,
repo update:docker-compose.ymlanddocker-compose.e2e.ymlexist. - Same repository, committed, a second Go service added,
repo update: both Compose files are unchanged, andreview: docker-compose.ymlandreview: docker-compose.e2e.ymlare printed. - Mono-repository with a Go service, generated,
docker-compose.ymldeleted, all committed, a Go tool added,repo update:docker-compose.ymlstays deleted. - Every profile except
electronics, withoutmodules:test/bdd/features/holds a feature file, and theMakefilehas the targetbdd-test.
Decisions¶
meta.artifactsrecords the generated modules instead ofrepo updatewriting missing developer-owned files. A developer deletes sample files on purpose; regenerating them on the next run would be wrong. Consequence:metagrows with the artifacts, and a developer-owned file deleted by mistake is restored only by removing its module frommetaor by Git.- Generator-owned files are overwritten without asking; the clean working tree is the safety net.
A change to such a file shows up in
git diffafterrepo update. Consequence: a developer who wants to keep a change to a generator-owned file deselects the module that owns it. .repo.yamlis exempt from the clean working tree. Editing it and runningrepo updateis the normal workflow; requiring a commit in between would be tedious.- The generator never deletes.
Deleting is the developer's decision, and
git rmmakes it reviewable.repo updatelists the candidates. - A module never pulls in its dependency on its own. An implicit addition would surprise the developer as much as a missing file; the violation names what to add.
- Guidelines live in
guidelines/at the repository root, not belowspecs/. They apply to the repository but do not specify it. Consequence: the docs site configuration takes them in by its own means, agen-filesscript in a single repository and an includedguidelines/mkdocs.ymlin a mono-repository. - Guidelines and the rules taken from them name files regardless of the selected modules. A guideline reads the same for every profile (capability 005); it states conventions, such as where feature files go, that hold before the files exist. Consequence: a rule may name a directory that a repository without the module lacks.
repo updatenever overwrites an existing developer-owned file. A repository that existed before its firstrepo update, or one whosemetawas lost, keeps the developer's content; only missing files are added. Consequence: a developer-owned file that a newer generator version writes differently keeps its old content.- A developer-owned file is new when the configuration recorded in
meta.artifactswould not generate it. Recording modules alone cannot tell whether a repository-level file, such as a Compose file, depends on the set of artifacts; at the root, every module counts as recorded after the first run. Consequence:repo updaterenders the recorded configuration as well.