create-afe-project 0.0.0-stage → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/CHANGELOG.md +351 -0
  2. package/LICENSE +21 -0
  3. package/README.md +77 -2
  4. package/bin/create-afe-project.js +123 -0
  5. package/package.json +43 -4
  6. package/src/answers.js +147 -0
  7. package/src/config.js +152 -0
  8. package/src/project.js +217 -0
  9. package/src/render.js +51 -0
  10. package/template/.claude/harness.conf +47 -0
  11. package/template/.claude/hooks/post-edit-check.sh +38 -0
  12. package/template/.claude/hooks/protect-docs.sh +315 -0
  13. package/template/.claude/hooks/stop-check-decisions.sh +25 -0
  14. package/template/.claude/hooks/stop-check-docs.sh +29 -0
  15. package/template/.claude/hooks/stop-check-template.sh +23 -0
  16. package/template/.claude/hooks/stop-run-project-hooks.sh +27 -0
  17. package/template/.claude/path-classes +61 -0
  18. package/template/.claude/settings.project.json +5 -0
  19. package/template/.claude/settings.template.json +76 -0
  20. package/template/.claude/skills/afe-init/SKILL.md +104 -0
  21. package/template/.claude/skills/create-pr/SKILL.md.jinja +107 -0
  22. package/template/.claude/skills/update-template/SKILL.md +40 -0
  23. package/template/.claude/skills/{% if code_review %}review-code{% endif %}/SKILL.md.jinja +46 -0
  24. package/template/.claude/skills/{% if docs_review %}docs-review{% endif %}/SKILL.md +56 -0
  25. package/template/.claude/skills/{% if dual_review %}dual-review{% endif %}/SKILL.md +58 -0
  26. package/template/.github/workflows/decisions.yml.jinja +47 -0
  27. package/template/.github/workflows/docs.yml.jinja +40 -0
  28. package/template/.github/workflows/{% if code_review %}code-review.yml{% endif %}.jinja +51 -0
  29. package/template/.github/workflows/{% if docs_review %}docs-review.yml{% endif %}.jinja +49 -0
  30. package/template/.github/workflows/{% if fail_without_change %}fail-without-change.yml{% endif %}.jinja +40 -0
  31. package/template/.github/workflows/{% if secret_scan %}secret-scan.yml{% endif %}.jinja +47 -0
  32. package/template/.markdownlint-cli2.jsonc +27 -0
  33. package/template/.template/owned.txt.jinja +63 -0
  34. package/template/AGENTS.md.jinja +91 -0
  35. package/template/CLAUDE.md +3 -0
  36. package/template/README.md.jinja +41 -0
  37. package/template/_gitignore +14 -0
  38. package/template/docs/README.md.jinja +44 -0
  39. package/template/docs/contributing.md.jinja +206 -0
  40. package/template/docs/decisions/adr-template.md +38 -0
  41. package/template/docs/documentation-rules.md.jinja +200 -0
  42. package/template/docs/testing-rules.md +80 -0
  43. package/template/scripts/check-decisions.sh +382 -0
  44. package/template/scripts/check-docs.sh +20 -0
  45. package/template/scripts/check-links.mjs +142 -0
  46. package/template/scripts/check-project.sh +27 -0
  47. package/template/scripts/check-template.sh +88 -0
  48. package/template/scripts/check.sh +21 -0
  49. package/template/scripts/env.sh +29 -0
  50. package/template/scripts/gen-decisions-index.sh +57 -0
  51. package/template/scripts/gen-settings.sh +14 -0
  52. package/template/scripts/lib/classes.sh +89 -0
  53. package/template/scripts/lib/git-base.sh +23 -0
  54. package/template/scripts/lib/harness-conf.sh +48 -0
  55. package/template/scripts/lib/json.mjs +160 -0
  56. package/template/scripts/pr-metrics.sh +80 -0
  57. package/template/scripts/protect-branch.sh +53 -0
  58. package/template/scripts/{% if acceptance_check %}check-acceptance.sh{% endif %} +47 -0
  59. package/template/scripts/{% if fail_without_change %}fail-without-change.sh{% endif %} +88 -0
@@ -0,0 +1,200 @@
1
+ # Documentation rules
2
+
3
+ Reference for creating, changing, and retiring documentation. `AGENTS.md` holds the short rules
4
+ and takes precedence; this file comes from the template, so report a disagreement to the
5
+ template (section 8). It has at most 200 lines (checked): an addition pays with a removal.
6
+
7
+ ## 1. Principles
8
+
9
+ - Docs as code: documentation lives here, in Markdown, is reviewed like code, and is checked
10
+ automatically (section 7).
11
+ - Progressive disclosure: entry files (`AGENTS.md`, `docs/README.md`) stay short and link out.
12
+ - One owner per fact: `docs/README.md` maps kinds of facts to owner documents; others link, never
13
+ copy. Generated artefacts come from a script, are checked in CI, and are never hand-edited.
14
+ - Content before structure: a section exists only with real content; future ones are listed in
15
+ the map, not created as placeholders. Diátaxis is a lens for content type, not a folder tree.
16
+
17
+ ## 2. Document kinds and formats
18
+
19
+ | Kind | Location | Format |
20
+ | --- | --- | --- |
21
+ | Agent rules | `AGENTS.md` | at most 90 template lines plus a project block of at most 10 lines (checked); numbered sections; `CLAUDE.md` imports it with `@AGENTS.md` |
22
+ | Documentation map | `docs/README.md` | tables of existing and planned sections |
23
+ | Testing rules | `docs/testing-rules.md` | at most 80 lines (checked); numbered sections: what a test is for, how it proves behaviour, tests and the change, gates; the project's test levels, tools, and edge cases live in its own documents |
24
+ | Contribution rules | `docs/contributing.md` | at most 200 lines (checked); numbered sections: branches, commits, pull requests and when a change is done, template updates, review |
25
+ | Decision (ADR) | `docs/decisions/NNNN-title-with-dashes.md` | only for a decision that meets section 5; short MADR 4.0 from `adr-template.md`, about one page, details linked to their owner document; front matter `status`, `date`, `decision-makers`, `scope`, `summary`, optional `supersedes` |
26
+ | Decision index | `docs/decisions/README.md` | generated by `scripts/gen-decisions-index.sh` from the front matter of the records; never hand-edited |
27
+ | Plan | `docs/plans/<slug>.md` | front matter `status`, `owner`, `created`, `review-by`; sections Goal, Steps, Open questions |
28
+ | Requirement | `docs/requirements/` | one `REQ-NNN` per statement; RFC 2119 keywords; fields `status`, `source`, `verification`; its acceptance criteria `AC-NN` as Given, When, Then, with the check that establishes each |
29
+ | Invariants register | `docs/invariants.md` | one `INV-NN` per invariant that must hold everywhere (`testing-rules.md`, section 4); fields `statement`, `source` (the requirement or owner decision), `enforced-by` (the test or project check that fails when it breaks, or `none`, which is an open question) |
30
+ | Architecture | `docs/architecture/` | the system map: components, domain ownership, public interfaces and the dependency rules a project check enforces; explanation and reference; front matter `status`, `date`, `verified-against` (commit, or `none` while no code exists) |
31
+ | Contract | `contracts/` | machine-readable, for example OpenAPI or JSON Schema; the file is the contract; prose links to it |
32
+ | Operations | `docs/operations/` | how-to; every procedure names the command or file it relies on |
33
+ | Conventions and recipes | `docs/conventions/`, `docs/recipes/` | one area or task per file; a convention names the check that enforces it, or `none`; a recipe lists its steps and commands, and skills link to it |
34
+
35
+ This is the fixed set of document kinds the template defines; another project document, such as
36
+ a changelog, exists only when the owner approves it and the map lists it. Front matter is YAML
37
+ between `---` lines at the top of the file.
38
+
39
+ ## 3. Status vocabulary
40
+
41
+ | Document | Allowed `status` values and transitions | Transition set by |
42
+ | --- | --- | --- |
43
+ | ADR | `proposed` to `accepted` or `rejected`; `accepted` to `deprecated` or `superseded by ADR-NNNN` | owner; agents create `proposed` |
44
+ | Requirement | `draft` to `approved` to `implemented` or `retired` | owner; `implemented` needs a linked test |
45
+ | Plan | `active`, then the file is deleted when done or abandoned | the change that completes or abandons it |
46
+ | Architecture, operations | `draft` to `current`; `current` with a stale `verified-against` is suspect | the reviewer who verified it against code |
47
+ | Owner decision in an owner document | a statement carries its document's status until the owner decides it; then it ends with, or its section opens with, `Decided by the owner, YYYY-MM-DD.` | owner; an agent adds the marker only on the owner's explicit instruction and lists it in the pull request (`contributing.md`, section 3); the owner's merge confirms it |
48
+
49
+ Wording rules for behaviour:
50
+
51
+ - "X does Y" only for implemented behaviour, merged code with a test; link the test or module
52
+ when the claim matters. Requirements use RFC 2119 keywords and never claim to be implemented.
53
+ Proposals say "proposed", accepted decisions "accepted" or "decided", unknown things "not
54
+ decided" or "unknown", never guessed.
55
+ - A statement about a check (a lint rule, a test check, a hook, a workflow) names the forms it
56
+ catches and what is left to the review; an absolute claim about a check needs a test for each
57
+ form it covers.
58
+
59
+ ## 4. Currency
60
+
61
+ A document is current when its content agrees with its owner source (code, contract, decision).
62
+ `date` records the last content change. `verified-against: <commit>` records the last review
63
+ against code and is required for architecture and operations documents once code exists.
64
+ Touching a file or bumping a date is not verification.
65
+
66
+ ## 5. Lifecycle
67
+
68
+ - Create a document when its first real content exists. A new section or plan needs the owner's
69
+ approval, and the map moves the section from planned to existing in the same change. An agent
70
+ may create an ADR with `status: proposed`; the owner's acceptance is the approval.
71
+ - A new ADR only for a decision that is costly to reverse once code or data depend on it and had
72
+ a real alternative: language, runtime, or framework; storage and persistent data formats;
73
+ public protocols and contract formats; the security, isolation, or authentication model; an
74
+ external service or infrastructure. Copy `adr-template.md`, take the highest number plus one,
75
+ set `status: proposed`, record one decision in about one page, link the owner documents, and
76
+ regenerate the index: `scripts/gen-decisions-index.sh > docs/decisions/README.md`.
77
+ - Other owner decisions are edits of the owner document with the marker of section 3; a decision
78
+ about a template-owned file goes to the template. Process rules live in the rule documents and
79
+ their checks; implementation choices stay in the pull request and the commit messages.
80
+ - A plan only for work that spans sessions or needs owner follow-up; the change that completes or
81
+ abandons it deletes the file. A plan past `review-by` is updated or deleted in the next change
82
+ to `docs/`, and agents flag it.
83
+ - Update the owner document in the same change that makes it wrong; refactoring that leaves
84
+ behaviour, contracts, and operations unchanged needs none. Update links and the map.
85
+ - An ADR on `main` changes only its `status` line along section 3. A `proposed` ADR that needs
86
+ other wording is `rejected` and replaced; an ADR is never deleted or renamed. `superseded by
87
+ ADR-NNNN` names an ADR the same change adds, which lists the records it replaces in
88
+ `supersedes`. Requirements are retired with a reason and a link to their replacement.
89
+ - There is no archive directory: a retired document stays with its retired status. Temporary
90
+ material (research notes, logs, transcripts, agent reports) never enters `docs/`; a person
91
+ extracts durable facts into the owner document.
92
+
93
+ ## 6. Alignment of documentation, contracts, and code
94
+
95
+ These rules apply once code exists; they are fixed now so the first code follows them.
96
+
97
+ - Contracts are machine-readable files in `contracts/`. The file is the source of truth for the
98
+ interface. The implementation conforms to it, and prose documentation links to it. Contract
99
+ linting and breaking-change detection are added to CI with the first contract, as decided in
100
+ an ADR together with the contract format.
101
+ - Implemented behaviour is proven by tests that follow `docs/testing-rules.md`. Documentation
102
+ that describes behaviour links to the test or module. A described behaviour without a test is
103
+ `proposed`, not `implemented`.
104
+ - CI runs the documentation checks, the contract checks, and the tests on every pull request.
105
+ - Architecture documents carry `verified-against`; a review against code updates it.
106
+ - With the first code: the project adds its code checks to `scripts/checks.d/` (section 9), and
107
+ `docs/README.md` moves "implemented behaviour" to existing.
108
+
109
+ ## 7. Automated checks and semantic review
110
+
111
+ | Concern | Automated (`scripts/check.sh`, CI) | Semantic review, per change |
112
+ | --- | --- | --- |
113
+ | Markdown syntax and structure | markdownlint-cli2 | none |
114
+ | Broken internal links and anchors | `scripts/check-links.mjs`, offline, with anchors | none |
115
+ | Secrets in a change | {% if secret_scan %}gitleaks in the `secret-scan` workflow; {% endif %}the protect hook asks when an edit contains a known token format | none |
116
+ | External links | not checked automatically | author verifies when adding; spot check on review |
117
+ | Status correctness | none | status matches the evidence (section 3) |
118
+ | Invented facts | none | every new fact has a source or is marked unknown |
119
+ | Duplication | none | new content links instead of copying |
120
+ | Currency | none | `verified-against` and the map are updated |
121
+ | Documentation updated together with code | {% if docs_review %}`docs-review` workflow on pull requests, one pass, a sensor{% else %}none{% endif %} | reviewer confirms the owner document changed |
122
+ | ADRs on `main` change only their status line (section 5); new ADRs carry `scope` and `summary`; the decision index matches the records | `scripts/check-decisions.sh`: Stop hook and `decisions` workflow | none |
123
+ | A new ADR meets the criteria of section 5 | none | {% if docs_review %}`docs-review` reports it; {% endif %}the owner decides |
124
+ | Template-owned files unchanged; one project block in `AGENTS.md`; the line budgets of the rule documents; `.claude/settings.json` generated, and every hook command it names exists (sections 2 and 9) | `scripts/check-template.sh`: Stop hook and `docs` workflow | none |
125
+ | Each invariant names its check (section 2) | none | the review checks `docs/invariants.md` against the checks it names |
126
+ | Project checks (section 9) | `scripts/check-project.sh` runs `scripts/checks.d/*.sh`: `scripts/check.sh` and `docs` workflow; a Stop hook only if the project adds one | as the project defines |
127
+ | Code and tests meet the review rubric and the testing rules (`contributing.md`, section 6; `testing-rules.md`) | the project's test checks in `scripts/checks.d/`{% if fail_without_change %}; `scripts/fail-without-change.sh`{% endif %}{% if code_review %}; `code-review` workflow, a sensor{% endif %} | reviewer applies the rubric, by the class of the paths |
128
+ | Merge readiness (`contributing.md`, section 3) | `scripts/check-decisions.sh --ready`, in the forms that section names{% if acceptance_check %}, with `scripts/check-acceptance.sh`{% endif %}; `decisions` workflow; signals, does not block | whether the tests prove their identifiers; no `blocker` open; the owner's merge confirms the listed markers |
129
+ | Measurement of the sensors (`contributing.md`, section 3) | `scripts/pr-metrics.sh` aggregates the Metrics of merged pull requests | the owner removes a rule or check that never fires |
130
+ | Finishing with failing checks | Stop hook in Claude Code | none |
131
+ | Class approval and irreversible actions (section 8) | protect hook: owner prompt in Claude Code, denied headless; deny rules of `.claude/settings.json` | explicit, separate, owner-approved |
132
+
133
+ Semantic review checklist for any documentation change:
134
+
135
+ 1. Each new statement has a status, and the status matches the evidence; a statement about a
136
+ check names the forms it catches and what is left to the review, and an absolute claim about
137
+ a check has a test for each form it covers (section 3).
138
+ 2. No requirement, default, or decision was invented; gaps are listed as open questions.
139
+ 3. No content duplicates another document; links point to the owner.
140
+ 4. The map (`docs/README.md`) and all links are updated; `scripts/check.sh` passes.
141
+ 5. ADRs that exist on `main` (apart from their status line), template-owned files, the
142
+ documentation map, and the structure are unchanged unless the change is explicitly about them.
143
+ 6. A new ADR meets the criteria of section 5 and links details instead of listing them; every
144
+ new `Decided by the owner` marker is listed in the pull request with the owner's instruction,
145
+ quoted with its date (`contributing.md`, section 3).
146
+
147
+ ## 8. Path classes, access, and changing these rules
148
+
149
+ Governance follows risk and reversibility: every path a change touches takes the highest class
150
+ that applies, from the template's built-in rules and the project's `.claude/path-classes`
151
+ (section 9); `scripts/check-decisions.sh --classes` prints them and the review they need.
152
+
153
+ | Class | Paths (defaults; the project adds its own) | Before the edit | Review before the pull request (`contributing.md`, section 6) |
154
+ | --- | --- | --- | --- |
155
+ | low | Markdown outside the rules, the decision index, a template update | nothing | none |
156
+ | normal | code, tests, scripts: every path no other class takes | nothing | one reviewer |
157
+ | gate | workflows, project checks and Stop hooks, `.claude/harness.conf`, dependency manifests and lock files, linter, test, coverage, and mutation configuration | nothing; listed under "Gate files", reviewed by the owner after the merge | one reviewer |
158
+ | high | security, secrets, access and authentication, data migrations, money and billing, public contracts (`contracts/`) | nothing | {% if dual_review %}Santa loop{% else %}one reviewer; the Santa loop comes with the review module{% endif %} |
159
+ | approval | `AGENTS.md`, the template-owned files, the generated manifest, answers file, and `.claude/settings.json`, the map, `.claude/path-classes`, `.claude/settings.project.json`, `.mcp.json`, credentials, ADRs on `main` or not `proposed` | the protect hook asks the owner; a headless run is denied | by the class of the content |
160
+
161
+ The protect hook (`.claude/hooks/protect-docs.sh`) asks on an Edit, Write, or MultiEdit call and
162
+ on a shell command of a form its comments name (a redirect, `cp`, `mv`, `tee`, `rm`, `sed -i`,
163
+ and the like), and on the irreversible commands it names: `git push` that forces, deletes,
164
+ mirrors, prunes, or pushes tags (a release); `gh pr merge`; `gh release create` and `delete`;
165
+ `gh repo delete`. A side effect of a tool, a path or command named only inside a script or
166
+ behind a variable, an alias, or a directory a script changes is not caught and is left to the
167
+ review of the diff.
168
+
169
+ Access control comes before prompts: an agent gets no credentials or tools for irreversible or
170
+ production actions outside its task. `.claude/settings.json` denies force pushes and deletions
171
+ of remote branches in the forms its rules spell out, and reading `.env`, `.env.*`, `*.pem`, and
172
+ `*.key`; in `.claude/settings.project.json` the project adds deny rules, for example for the
173
+ destructive tools of an MCP server (`mcp__<server>__<tool>`), and takes a template entry out
174
+ with `"remove"`. For scripted, owner-driven changes the owner starts Claude Code
175
+ with `DOCS_GUARD=off`, which also lifts the Stop hooks for decisions and template integrity.
176
+ Other agents are bound by `AGENTS.md` and the review only.
177
+
178
+ Template-owned files (section 9), including this file and `AGENTS.md` outside its project block,
179
+ change only in the template and arrive through an update (`contributing.md`, section 5). A
180
+ change to the map or the structure is a dedicated change approved by the owner.
181
+
182
+ ## 9. Ownership of files
183
+
184
+ Every file belongs to exactly one class:
185
+
186
+ | Class | Files | Changed by |
187
+ | --- | --- | --- |
188
+ | Template-owned | the files listed with their hashes in `.template/owned.sha256` (rules, ADR template, checks, hooks, skills, workflows, linter configuration), and `AGENTS.md` outside its project block | a release of the template, applied with `npx create-afe-project@latest update` (`contributing.md`, section 5); never edited in this repository |
189
+ | Seeded | `README.md`, `CLAUDE.md`, `.gitignore`, `docs/README.md`, `.claude/path-classes`, `.claude/harness.conf`, `.claude/settings.project.json`, and the project block of `AGENTS.md`: created once by the template | the project |
190
+ | Generated | `docs/decisions/README.md`, `.template/owned.sha256`, `.afe-answers.json`, `.claude/settings.json` (by `scripts/gen-settings.sh` from `.claude/settings.template.json` and `.claude/settings.project.json`) | their generator only |
191
+ | Project | everything else, including the documentation sections of section 2 and the extension points below | the project |
192
+
193
+ The project extends the template only at its extension points: checks in `scripts/checks.d/*.sh`,
194
+ run in name order by `scripts/check.sh` and the `docs` workflow, which provision any tool they
195
+ need beyond Git, bash, and Node.js; Stop hooks in `.claude/hooks/project/stop/*.sh`, which
196
+ receive the Stop hook input and block the agent by exiting with 2; its own workflows in
197
+ `.github/workflows/`; its path classes in `.claude/path-classes`; its harness settings in
198
+ `.claude/harness.conf` (the Ralph cap, the identifier pattern, test globs, test commands); and
199
+ its Claude Code settings in `.claude/settings.project.json`. Checks and Stop hooks keep their
200
+ executable bit. Personal settings go into `.claude/settings.local.json`, never committed.
@@ -0,0 +1,80 @@
1
+ # Testing rules
2
+
3
+ Rules that every test in this repository follows, whatever its language or tools. `AGENTS.md`
4
+ holds the short rules and takes precedence if the two ever disagree. This file comes from the
5
+ project template: report such a disagreement to the template instead of editing it. The project
6
+ adds the levels of its verification ladder (static checks, unit, integration, user journeys),
7
+ tools, commands, thresholds, and the edge cases of its domain in documents the map names, and
8
+ its test checks in `scripts/checks.d/` (`documentation-rules.md`, section 9).
9
+
10
+ ## 1. What a test is for
11
+
12
+ - A test protects a behaviour that a requirement, an acceptance criterion, a contract, or a fixed
13
+ defect names. It carries that identifier (`REQ-NNN`, `AC-NN`) in its name or a tag when one
14
+ applies, so that an `implemented` status and the "Acceptance and test plan" of a pull request can
15
+ point at it (`documentation-rules.md`, section 3; `contributing.md`, section 3). The project's
16
+ checks in `scripts/checks.d/` map each identifier to the tests that carry it.
17
+ - Test count and coverage are not goals. Coverage shows which lines ran, not what a test checked:
18
+ it is a floor the project sets, never evidence of quality. Where the project runs mutation
19
+ testing, the mutation score is the measure.
20
+ - What the type checker, schema validation, or the contract check already proves (a shape, a
21
+ required field, a closed set of values) gets no test of its own.
22
+ - One behaviour has one test, or one parametrised test over its table of inputs. A test that
23
+ catches nothing the other tests miss is removed, and removing it is a valid change.
24
+
25
+ ## 2. How a test proves behaviour
26
+
27
+ - A test asserts an observable outcome: the returned value or result, the resulting state, or the
28
+ emitted events, records, and output. An assertion that a mock was called, that a value is
29
+ defined or truthy, or that nothing threw is not enough on its own.
30
+ - Fakes stand in for the boundaries of the unit under test (external services, storage, the
31
+ clock, randomness), never for code inside it.
32
+ - Expected values are literals or fixtures. A test never computes its expectation with the logic
33
+ it tests, and a snapshot is never the only assertion of a rule.
34
+ - Failure paths are tested as deliberately as success: every distinct outcome or error a unit can
35
+ return has a test that produces it, and every invalid example of a contract is rejected where
36
+ the input is validated.
37
+ - The edge cases that apply are covered: boundaries, empty and missing values, unknown against
38
+ zero, duplicates and retries, concurrent use, time zones and period boundaries, and the largest
39
+ input the requirement allows. The project lists the edge cases of its domain.
40
+ - Tests are deterministic: no sleeps, no real clock, no real network or external service, and no
41
+ dependence on the order in which tests run.
42
+
43
+ ## 3. Tests and the change they cover
44
+
45
+ - Tests come first: they are written before the implementation and run once to see them fail for
46
+ the expected reason. A test that passes before the implementation exists tests nothing.
47
+ - The acceptance tests of a requirement's criteria are written or reviewed by someone other than
48
+ the author of the implementation, before it exists; the author changes them only with the
49
+ owner's agreement.
50
+ - The agent derives the test plan from the identifiers the change serves: their cases, failure
51
+ paths, and edge cases (section 2). It is a report under "Acceptance and test plan"
52
+ (`contributing.md`, section 3), never approved per pull request and not maintained afterwards.
53
+ Each new or changed test fails on the base and passes with the change.
54
+ - A defect is fixed only after a regression test that reproduces it fails.
55
+ - A refactoring keeps the tests as they are. A change of behaviour first changes the requirement
56
+ or the acceptance criterion, then the test that carries the same identifier; the pull request
57
+ names both.
58
+
59
+ ## 4. Gates
60
+
61
+ - No test is skipped, focused, or deleted, no assertion is weakened, no code is excluded from
62
+ coverage, and no threshold is lowered to make a check pass. Such a need is an open question for
63
+ the owner.
64
+ - The quality measures the project records (coverage, mutation score) never fall below those of
65
+ the base branch.
66
+ - The configuration of the test runner, coverage, mutation testing, and linters is class gate in
67
+ `.claude/path-classes` (`documentation-rules.md`, section 8): it changes without a prompt, the
68
+ pull request lists it under "Gate files", which the readiness check enforces, and the owner
69
+ reviews it after the merge.
70
+ - An invariant that must hold everywhere (for example, a secret never appears in output) is an
71
+ executable check, a test or a project check, and the register `docs/invariants.md` names it
72
+ with that check (`documentation-rules.md`, section 2); its invariants are criteria of the
73
+ review of class high (`contributing.md`, section 6).
74
+ - Threat model of development gates: a gate (a lint rule, a test check, a coverage or mutation
75
+ setting, an agent hook) catches honest mistakes and shortcuts; it is not a security boundary.
76
+ It decides which bypass is a `blocker` (`contributing.md`, section 6): a diff that itself
77
+ loosens or evades a gate (a test skipped, an assertion weakened, a threshold lowered, a test
78
+ behind an aliased import), and any bypass of a product invariant (security, secrets, policy
79
+ enforcement, limits), whatever it takes. A gap that only deliberate evasion exploits, such as
80
+ a computed property or tampering with a gate's own state, is a `suggestion`.