forgecraft-mcp 1.2.0 → 1.3.2
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.
- package/README.md +525 -525
- package/dist/cli/help.js +44 -44
- package/dist/registry/renderer-skeletons.js +92 -92
- package/dist/shared/gs-score-logger.js +6 -6
- package/dist/tools/add-module.js +123 -123
- package/dist/tools/advice-registry.js +18 -18
- package/dist/tools/check-cascade-report.js +64 -64
- package/dist/tools/configure-mcp.d.ts +3 -0
- package/dist/tools/configure-mcp.d.ts.map +1 -1
- package/dist/tools/configure-mcp.js +10 -0
- package/dist/tools/configure-mcp.js.map +1 -1
- package/dist/tools/forgecraft-dispatch.d.ts.map +1 -1
- package/dist/tools/forgecraft-dispatch.js +3 -0
- package/dist/tools/forgecraft-dispatch.js.map +1 -1
- package/dist/tools/forgecraft-schema-params.d.ts +9 -0
- package/dist/tools/forgecraft-schema-params.d.ts.map +1 -1
- package/dist/tools/forgecraft-schema-params.js +21 -0
- package/dist/tools/forgecraft-schema-params.js.map +1 -1
- package/dist/tools/forgecraft-schema.d.ts +9 -0
- package/dist/tools/forgecraft-schema.d.ts.map +1 -1
- package/dist/tools/refresh-output.js +14 -14
- package/dist/tools/scaffold-spec-stubs.js +115 -115
- package/dist/tools/scaffold-templates.js +62 -62
- package/dist/tools/setup-artifact-writers.d.ts +30 -0
- package/dist/tools/setup-artifact-writers.d.ts.map +1 -1
- package/dist/tools/setup-artifact-writers.js +120 -8
- package/dist/tools/setup-artifact-writers.js.map +1 -1
- package/dist/tools/setup-phase1.d.ts +3 -0
- package/dist/tools/setup-phase1.d.ts.map +1 -1
- package/dist/tools/setup-phase1.js +79 -35
- package/dist/tools/setup-phase1.js.map +1 -1
- package/dist/tools/setup-phase2.d.ts +2 -0
- package/dist/tools/setup-phase2.d.ts.map +1 -1
- package/dist/tools/setup-phase2.js +10 -1
- package/dist/tools/setup-phase2.js.map +1 -1
- package/dist/tools/setup-project.d.ts +18 -0
- package/dist/tools/setup-project.d.ts.map +1 -1
- package/dist/tools/setup-project.js +77 -1
- package/dist/tools/setup-project.js.map +1 -1
- package/dist/tools/spec-parser-tags.d.ts +9 -0
- package/dist/tools/spec-parser-tags.d.ts.map +1 -1
- package/dist/tools/spec-parser-tags.js +92 -0
- package/dist/tools/spec-parser-tags.js.map +1 -1
- package/package.json +89 -86
- package/templates/analytics/instructions.yaml +37 -37
- package/templates/analytics/mcp-servers.yaml +11 -11
- package/templates/analytics/structure.yaml +25 -25
- package/templates/api/instructions.yaml +231 -231
- package/templates/api/mcp-servers.yaml +22 -13
- package/templates/api/nfr.yaml +23 -23
- package/templates/api/review.yaml +103 -103
- package/templates/api/structure.yaml +34 -34
- package/templates/api/verification.yaml +132 -132
- package/templates/cli/instructions.yaml +31 -31
- package/templates/cli/mcp-servers.yaml +11 -11
- package/templates/cli/review.yaml +53 -53
- package/templates/cli/structure.yaml +16 -16
- package/templates/data-lineage/instructions.yaml +28 -28
- package/templates/data-lineage/mcp-servers.yaml +22 -22
- package/templates/data-pipeline/instructions.yaml +84 -84
- package/templates/data-pipeline/mcp-servers.yaml +13 -13
- package/templates/data-pipeline/nfr.yaml +39 -39
- package/templates/data-pipeline/structure.yaml +23 -23
- package/templates/fintech/hooks.yaml +55 -55
- package/templates/fintech/instructions.yaml +112 -112
- package/templates/fintech/mcp-servers.yaml +13 -13
- package/templates/fintech/nfr.yaml +46 -46
- package/templates/fintech/playbook.yaml +210 -210
- package/templates/fintech/verification.yaml +239 -239
- package/templates/game/instructions.yaml +289 -289
- package/templates/game/mcp-servers.yaml +38 -38
- package/templates/game/nfr.yaml +64 -64
- package/templates/game/playbook.yaml +214 -214
- package/templates/game/review.yaml +97 -97
- package/templates/game/structure.yaml +67 -67
- package/templates/game/verification.yaml +174 -174
- package/templates/healthcare/instructions.yaml +42 -42
- package/templates/healthcare/mcp-servers.yaml +13 -13
- package/templates/healthcare/nfr.yaml +47 -47
- package/templates/hipaa/instructions.yaml +41 -41
- package/templates/hipaa/mcp-servers.yaml +13 -13
- package/templates/infra/instructions.yaml +104 -104
- package/templates/infra/mcp-servers.yaml +20 -20
- package/templates/infra/nfr.yaml +46 -46
- package/templates/infra/review.yaml +65 -65
- package/templates/infra/structure.yaml +25 -25
- package/templates/library/instructions.yaml +36 -36
- package/templates/library/mcp-servers.yaml +20 -20
- package/templates/library/review.yaml +56 -56
- package/templates/library/structure.yaml +19 -19
- package/templates/medallion-architecture/instructions.yaml +41 -41
- package/templates/medallion-architecture/mcp-servers.yaml +22 -22
- package/templates/ml/instructions.yaml +85 -85
- package/templates/ml/mcp-servers.yaml +11 -11
- package/templates/ml/nfr.yaml +39 -39
- package/templates/ml/structure.yaml +25 -25
- package/templates/ml/verification.yaml +156 -156
- package/templates/mobile/instructions.yaml +44 -44
- package/templates/mobile/mcp-servers.yaml +11 -11
- package/templates/mobile/nfr.yaml +49 -49
- package/templates/mobile/structure.yaml +27 -27
- package/templates/mobile/verification.yaml +121 -121
- package/templates/observability-xray/instructions.yaml +40 -40
- package/templates/observability-xray/mcp-servers.yaml +15 -15
- package/templates/realtime/instructions.yaml +42 -42
- package/templates/realtime/mcp-servers.yaml +13 -13
- package/templates/soc2/instructions.yaml +41 -41
- package/templates/soc2/mcp-servers.yaml +24 -24
- package/templates/social/instructions.yaml +43 -43
- package/templates/social/mcp-servers.yaml +24 -24
- package/templates/state-machine/instructions.yaml +42 -42
- package/templates/state-machine/mcp-servers.yaml +11 -11
- package/templates/tools-registry.yaml +164 -164
- package/templates/universal/hooks.yaml +531 -531
- package/templates/universal/instructions.yaml +1692 -1692
- package/templates/universal/mcp-servers.yaml +50 -50
- package/templates/universal/nfr.yaml +197 -197
- package/templates/universal/reference.yaml +326 -326
- package/templates/universal/review.yaml +204 -204
- package/templates/universal/skills.yaml +262 -262
- package/templates/universal/structure.yaml +67 -67
- package/templates/universal/verification.yaml +416 -416
- package/templates/web-react/hooks.yaml +44 -44
- package/templates/web-react/instructions.yaml +207 -207
- package/templates/web-react/mcp-servers.yaml +20 -20
- package/templates/web-react/nfr.yaml +27 -27
- package/templates/web-react/review.yaml +94 -94
- package/templates/web-react/structure.yaml +46 -46
- package/templates/web-react/verification.yaml +126 -126
- package/templates/web-static/instructions.yaml +115 -115
- package/templates/web-static/mcp-servers.yaml +20 -20
- package/templates/web3/instructions.yaml +44 -44
- package/templates/web3/mcp-servers.yaml +11 -11
- package/templates/web3/verification.yaml +159 -159
- package/templates/zero-trust/instructions.yaml +41 -41
- package/templates/zero-trust/mcp-servers.yaml +15 -15
|
@@ -1,1692 +1,1692 @@
|
|
|
1
|
-
tag: UNIVERSAL
|
|
2
|
-
section: instructions
|
|
3
|
-
blocks:
|
|
4
|
-
- id: project-identity
|
|
5
|
-
tier: core
|
|
6
|
-
title: "Project Identity"
|
|
7
|
-
content: |
|
|
8
|
-
## Project Identity
|
|
9
|
-
- **Repo**: {{repo_url}}
|
|
10
|
-
- **Primary Language**: {{language}}
|
|
11
|
-
- **Framework**: {{framework}}
|
|
12
|
-
- **Domain**: {{domain}}
|
|
13
|
-
- **Sensitive Data**: {{sensitive_data}}
|
|
14
|
-
- **Project Tags**: {{tags}}
|
|
15
|
-
- **Release Phase**: {{release_phase | default: development}}
|
|
16
|
-
|
|
17
|
-
- id: code-standards
|
|
18
|
-
tier: core
|
|
19
|
-
title: "Code Standards"
|
|
20
|
-
content: |
|
|
21
|
-
## Code Standards
|
|
22
|
-
- Maximum function/method length: {{max_function_length | default: 50}} lines. If a function reads like it does two things, decompose it.
|
|
23
|
-
- Split a file when you find yourself using "and" to describe what it does — not when it hits a line count.
|
|
24
|
-
- Maximum function parameters: {{max_function_params | default: 5}}. If more, use a parameter object.
|
|
25
|
-
- No circular imports — module dependency graph must be acyclic (hook-enforced).
|
|
26
|
-
{{#if language_is_typescript}}- `tsconfig.json` must include `"strict": true` AND `"noUncheckedIndexedAccess": true`.
|
|
27
|
-
`strict: true` alone does not narrow `process.env.*` from `string | undefined` — the second flag is required
|
|
28
|
-
to catch unguarded environment variable access at compile time.{{/if}}
|
|
29
|
-
- Every public function/method must have {{#if language_is_typescript}}a JSDoc comment{{/if}}{{#if language_is_python}}a docstring (Google or NumPy style){{/if}} with typed params and returns.
|
|
30
|
-
- Delete orphaned code. Do not comment it out. Git has history.
|
|
31
|
-
- Before creating a new utility, search the entire codebase for existing ones.
|
|
32
|
-
- Reuse existing patterns — check shared modules before writing new.
|
|
33
|
-
- No abbreviations in names except universally understood ones (id, url, http, db, api).
|
|
34
|
-
- All names must be intention-revealing. If you need a comment to explain what a variable
|
|
35
|
-
holds, the name is wrong.
|
|
36
|
-
|
|
37
|
-
- id: dev-environment-hygiene
|
|
38
|
-
tier: core
|
|
39
|
-
title: "Dev Environment Hygiene"
|
|
40
|
-
content: |
|
|
41
|
-
## Dev Environment Hygiene
|
|
42
|
-
|
|
43
|
-
AI-assisted development can silently fill disk space. These rules are non-negotiable.
|
|
44
|
-
A full disk kills every running tool simultaneously — VS Code, Docker, the terminal, the DB.
|
|
45
|
-
|
|
46
|
-
### VS Code Extensions
|
|
47
|
-
- Before installing any extension: `code --list-extensions | grep -i <name>`.
|
|
48
|
-
- Only install if no version in the required major range is already present.
|
|
49
|
-
- Never run `code --install-extension` unconditionally in scripts or setup steps.
|
|
50
|
-
- Installing the same extension twice on the same day = a bug in your script.
|
|
51
|
-
|
|
52
|
-
### Docker Containers & Volumes
|
|
53
|
-
- Check before creating: `docker ps -a --filter name=<service>` — if it exists, start it, don't create it.
|
|
54
|
-
- Prefer `docker compose up` (reuse) over bare `docker run` (always creates new).
|
|
55
|
-
- One Compose file per project. Split files for the same project = tech debt.
|
|
56
|
-
- Log pruning: run `docker system prune -f` periodically. Never let container logs exceed 500 MB total.
|
|
57
|
-
- Time-series or synthetic data volumes: before writing >100 MB, ask whether raw retention,
|
|
58
|
-
statistical condensation, or deletion after the run is preferred.
|
|
59
|
-
- Synthetic datasets older than 7 days with no code reference: ask to delete.
|
|
60
|
-
|
|
61
|
-
### Python Virtual Environments
|
|
62
|
-
- One `.venv` per project root, one per standalone package subdirectory — never more.
|
|
63
|
-
- Before creating: check if `.venv/` exists and `python --version` matches the required major.minor.
|
|
64
|
-
Recreate only on major version mismatch or explicit user request.
|
|
65
|
-
- Never create a venv in a subdirectory unless that directory is a standalone installable package.
|
|
66
|
-
- Sanitize dependencies: if `pip list --not-required` reveals packages not in requirements, flag them.
|
|
67
|
-
|
|
68
|
-
### General Install Hygiene
|
|
69
|
-
- Before any install/download: check version already installed. Skip if within the required range.
|
|
70
|
-
- If project directory disk usage outside of `node_modules/`, `.venv/`, `dist/`, `.next/`
|
|
71
|
-
exceeds 2 GB: surface a warning and ask before continuing any file-generating operation.
|
|
72
|
-
- Never silently grow the workspace. When uncertain about retention, ask.
|
|
73
|
-
|
|
74
|
-
- id: dependency-registry
|
|
75
|
-
tier: core
|
|
76
|
-
title: "Dependency Registry"
|
|
77
|
-
content: |
|
|
78
|
-
## Dependency Registry — AI-Maintained Security Contract
|
|
79
|
-
|
|
80
|
-
The project's approved dependency set is a **living GS artifact maintained by the AI
|
|
81
|
-
assistant**. It is not a template rule — template authors cannot predict which library
|
|
82
|
-
will gain a CVE next quarter. The AI can run an audit at the moment a dependency is
|
|
83
|
-
about to be added. This block prescribes that it must.
|
|
84
|
-
|
|
85
|
-
### The registry artifact
|
|
86
|
-
|
|
87
|
-
File: **`docs/approved-packages.md`** — emit in P1 alongside schema, tsconfig, package.json.
|
|
88
|
-
Update it every time a dependency is added or upgraded. If it exists only in prose or a
|
|
89
|
-
README reference, it does not exist.
|
|
90
|
-
|
|
91
|
-
```markdown
|
|
92
|
-
# Approved Packages
|
|
93
|
-
|
|
94
|
-
| Package | Version range | Purpose | Alternatives rejected | Rationale | Audit status |
|
|
95
|
-
|---|---|---|---|---|---|
|
|
96
|
-
| example-pkg | ^2.4 | HTTP client | axios (larger bundle), node-fetch (no TS types) | Wide adoption, zero known CVEs | 0 HIGH/CRITICAL |
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
The AI populates every row. The registry is the authoritative record of WHY each
|
|
100
|
-
dependency was chosen and that it was clean at the time of addition.
|
|
101
|
-
|
|
102
|
-
### Process rules — stack-agnostic
|
|
103
|
-
|
|
104
|
-
1. **Before adding any package**: run the project's audit command (see table below)
|
|
105
|
-
with `--dry-run` or equivalent to check the candidate for known CVEs.
|
|
106
|
-
- If HIGH or CRITICAL found: choose an alternative and document the rejection.
|
|
107
|
-
- If no CVE-free alternative exists: document the accepted risk and create an ADR
|
|
108
|
-
naming the approver. Zero-tolerance is the default; exceptions require a record.
|
|
109
|
-
2. **After adding a package**: add a row to `docs/approved-packages.md` with audit status.
|
|
110
|
-
3. **Commit gate**: the pre-commit hook runs the audit command. HIGH or CRITICAL blocks
|
|
111
|
-
the commit. If audit is not in the pre-commit hook, the gate does not exist.
|
|
112
|
-
4. **Version pins**: approved version ranges are locked in the lockfile (package-lock.json,
|
|
113
|
-
uv.lock, Cargo.lock). The lockfile is committed. Ranges without a lockfile are not pins.
|
|
114
|
-
|
|
115
|
-
### Audit commands by ecosystem
|
|
116
|
-
|
|
117
|
-
| Ecosystem | Audit command | Threshold |
|
|
118
|
-
|---|---|---|
|
|
119
|
-
| npm / Node.js | `npm audit --audit-level=high` | HIGH or CRITICAL |
|
|
120
|
-
| pnpm | `pnpm audit --audit-level=high` | HIGH or CRITICAL |
|
|
121
|
-
| yarn | `yarn npm audit --severity high` | HIGH or CRITICAL |
|
|
122
|
-
| Python / pip | `pip-audit --fail-on-severity high` | HIGH or CRITICAL |
|
|
123
|
-
| Python / uv | `uv audit` | HIGH or CRITICAL |
|
|
124
|
-
| Rust | `cargo audit` | HIGH or CRITICAL |
|
|
125
|
-
| Go | `govulncheck ./...` | Any directly imported |
|
|
126
|
-
| Java / Maven | `mvn dependency-check:check -DfailBuildOnCVSS=7` | CVSS ≥ 7 |
|
|
127
|
-
| Ruby | `bundle audit` | HIGH or CRITICAL |
|
|
128
|
-
|
|
129
|
-
The correct command for **this project's ecosystem** must appear in the pre-commit hook
|
|
130
|
-
emitted in P1. Discovering CVEs at code review is too late.
|
|
131
|
-
|
|
132
|
-
- id: language-stack-constraints
|
|
133
|
-
tier: core
|
|
134
|
-
title: "Language Stack Constraints"
|
|
135
|
-
content: |
|
|
136
|
-
## Language Stack Constraints — Seed Defaults
|
|
137
|
-
|
|
138
|
-
These are **starting defaults for {{language}} projects** — use them to populate the
|
|
139
|
-
initial rows of `docs/approved-packages.md` in P1. They are not a permanent approved
|
|
140
|
-
list: the AI maintains the registry from here forward, keeps versions current, and
|
|
141
|
-
replaces any entry that develops a known CVE. The Dependency Registry block above
|
|
142
|
-
governs the process.
|
|
143
|
-
|
|
144
|
-
Before adding any dependency not listed here, apply the audit-before-add process.
|
|
145
|
-
|
|
146
|
-
{{#if language_is_typescript}}
|
|
147
|
-
### TypeScript / Node.js — Approved Toolchain
|
|
148
|
-
|
|
149
|
-
**Runtime & compiler**
|
|
150
|
-
- Node.js: `^20 LTS` minimum. NOT `^16` or `^18` (EOL or near-EOL).
|
|
151
|
-
- TypeScript: `^5.4` minimum. `tsconfig.json` must include `"strict": true` AND
|
|
152
|
-
`"noUncheckedIndexedAccess": true`. The second flag is required to narrow
|
|
153
|
-
`process.env.*` from `string | undefined` at compile time.
|
|
154
|
-
|
|
155
|
-
**Linting**
|
|
156
|
-
- `eslint@^9` + `@typescript-eslint/eslint-plugin@^8` + `@typescript-eslint/parser@^8`
|
|
157
|
-
- NOT `@typescript-eslint@^5` or `^6` — old `minimatch` transitive dep has known CVEs.
|
|
158
|
-
- NOT `tslint` — deprecated.
|
|
159
|
-
|
|
160
|
-
**Test runner**
|
|
161
|
-
- `vitest@^2` (preferred — native ESM, fast, Jest-compatible API) or `jest@^29`.
|
|
162
|
-
- NOT `mocha` + `chai` for new projects (weaker TypeScript support).
|
|
163
|
-
- NOT `jasmine` (no active maintenance for Node.js use).
|
|
164
|
-
|
|
165
|
-
**Formatting**
|
|
166
|
-
- `prettier@^3` — configured via `.prettierrc`, integrated with ESLint via
|
|
167
|
-
`eslint-config-prettier`. NOT separate manual formatting.
|
|
168
|
-
{{/if}}
|
|
169
|
-
|
|
170
|
-
{{#if language_is_python}}
|
|
171
|
-
### Python — Approved Toolchain
|
|
172
|
-
|
|
173
|
-
**Runtime**
|
|
174
|
-
- Python `^3.11` minimum. NOT `3.8` or `3.9` for new projects — `3.11+` brings
|
|
175
|
-
`tomllib` builtin, `ExceptionGroup`, and significant performance improvements.
|
|
176
|
-
|
|
177
|
-
**Linting / formatting**
|
|
178
|
-
- `ruff@^0.4` — replaces `flake8` + `isort` + `black` with a single 10–100× faster tool.
|
|
179
|
-
- NOT separate `flake8` + `isort` + `black` for new projects.
|
|
180
|
-
|
|
181
|
-
**Type checking**
|
|
182
|
-
- `pyright@^1.1` (strict mode) — same engine as Pylance, best TypedDict support.
|
|
183
|
-
- `mypy@^1.9` is acceptable. Strict mode required in both cases.
|
|
184
|
-
- NOT unchecked Python — all public functions must be typed.
|
|
185
|
-
|
|
186
|
-
**Test runner**
|
|
187
|
-
- `pytest@^8` — NOT `unittest` for new projects.
|
|
188
|
-
- Async tests: `pytest-asyncio@^0.23`.
|
|
189
|
-
|
|
190
|
-
**Dependency management**
|
|
191
|
-
- `uv@^0.1` (recommended — fastest resolver) or `poetry@^1.7`.
|
|
192
|
-
- ALL dependencies pinned in lockfile (`uv.lock` or `poetry.lock`). Lockfile committed.
|
|
193
|
-
- `pip-tools` acceptable for library projects.
|
|
194
|
-
{{/if}}
|
|
195
|
-
|
|
196
|
-
- id: production-code-standards
|
|
197
|
-
tier: core
|
|
198
|
-
title: "Production Code Standards"
|
|
199
|
-
content: |
|
|
200
|
-
## Production Code Standards — NON-NEGOTIABLE
|
|
201
|
-
|
|
202
|
-
These apply to ALL code including prototypes. "It's just a prototype" is never a valid
|
|
203
|
-
exception. Prototypes become production code within days at CC development speed.
|
|
204
|
-
|
|
205
|
-
### SOLID Principles
|
|
206
|
-
- **Single Responsibility**: One module = one reason to change. Use "and" to describe it? Split it.
|
|
207
|
-
- **Open/Closed**: Extend via interfaces and composition. Never modify working code for new behavior.
|
|
208
|
-
- **Liskov Substitution**: Any interface implementation must be fully swappable. No isinstance checks.
|
|
209
|
-
- **Interface Segregation**: Small focused interfaces. No god-interfaces.
|
|
210
|
-
- **Dependency Inversion**: Depend on abstractions. Concrete classes are injected, never instantiated
|
|
211
|
-
inside business logic. **In practice**: define `IUserRepository`, `IOrderRepository`,
|
|
212
|
-
`IEmailSender` etc. as interfaces in the domain/service layer first. Services depend on
|
|
213
|
-
the interface. The Prisma/SQL/HTTP concrete implementation lives in the adapter layer and
|
|
214
|
-
is injected at the composition root. Emit these interfaces in P1 alongside the schema —
|
|
215
|
-
a service that imports a concrete class cannot be unit-tested, cannot be swapped, and
|
|
216
|
-
is not Composable.
|
|
217
|
-
|
|
218
|
-
### Zero Hardcoded Values
|
|
219
|
-
- ALL configuration through environment variables or config files. No exceptions.
|
|
220
|
-
- ALL external URLs, ports, credentials, thresholds, feature flags must be configurable.
|
|
221
|
-
- ALL magic numbers must be named constants with documentation.
|
|
222
|
-
- Config is validated at startup — fail fast if required values are missing.
|
|
223
|
-
|
|
224
|
-
### Zero Mocks in Application Code
|
|
225
|
-
- No mock objects, fake data, or stub responses in source code. Ever.
|
|
226
|
-
- Mocks belong ONLY in test files.
|
|
227
|
-
- For local dev: create proper interface implementations selected via config.
|
|
228
|
-
- No `if DEBUG: return fake_data` patterns. Use dependency injection to swap implementations.
|
|
229
|
-
- No TODO/FIXME stubs returning hardcoded values. Use NotImplementedError with a description.
|
|
230
|
-
|
|
231
|
-
### Interfaces First
|
|
232
|
-
Before writing any implementation:
|
|
233
|
-
1. Define the interface/protocol/abstract class
|
|
234
|
-
2. Define the data contracts (input/output DTOs)
|
|
235
|
-
3. Write the consuming code against the interface
|
|
236
|
-
4. Write tests against the interface
|
|
237
|
-
5. THEN implement the concrete class
|
|
238
|
-
|
|
239
|
-
### Dependency Injection
|
|
240
|
-
- Every service receives dependencies through its constructor.
|
|
241
|
-
- A composition root (main.py / app.ts / container) wires everything.
|
|
242
|
-
- No service locator pattern. No global singletons. No module-level instances.
|
|
243
|
-
|
|
244
|
-
### Error Handling
|
|
245
|
-
- Custom exception hierarchy per module. No bare Exception raises.
|
|
246
|
-
- Errors carry context: IDs, timestamps, operation names.
|
|
247
|
-
- Fail fast, fail loud. No silent swallowing of exceptions.
|
|
248
|
-
- Domain code never returns HTTP status codes — that's the API layer's job.
|
|
249
|
-
|
|
250
|
-
### Modular from Day One
|
|
251
|
-
- Feature-based modules over layer-based. Each feature owns its models, service, repository, routes.
|
|
252
|
-
- Module dependency graph must be acyclic.
|
|
253
|
-
- Every module has a clear public API via {{#if language_is_typescript}}index.ts{{/if}}{{#if language_is_python}}__init__.py{{/if}} exports.
|
|
254
|
-
|
|
255
|
-
- id: layered-architecture
|
|
256
|
-
tier: recommended
|
|
257
|
-
title: "Layered Architecture"
|
|
258
|
-
content: |
|
|
259
|
-
## Layered Architecture (Ports & Adapters / Hexagonal)
|
|
260
|
-
|
|
261
|
-
```
|
|
262
|
-
┌─────────────────────────────┐
|
|
263
|
-
│ API / CLI / Event Handlers │ ← Thin. Validation + delegation only. No logic.
|
|
264
|
-
├─────────────────────────────┤ These are DRIVING ADAPTERS (primary).
|
|
265
|
-
│ Services (Business Logic) │ ← Orchestration. Depends on PORT INTERFACES only.
|
|
266
|
-
├─────────────────────────────┤
|
|
267
|
-
│ Domain Models │ ← Pure data + behavior. No I/O. No framework imports.
|
|
268
|
-
│ (Entities, Value Objects) │ The inner hexagon. Zero external dependencies.
|
|
269
|
-
├─────────────────────────────┤
|
|
270
|
-
│ Port Interfaces │ ← Abstract contracts (Repository, Gateway, Notifier).
|
|
271
|
-
│ │ Defined by the domain, implemented by adapters.
|
|
272
|
-
├─────────────────────────────┤
|
|
273
|
-
│ Repositories / Adapters │ ← DRIVEN ADAPTERS (secondary). All external I/O
|
|
274
|
-
│ │ (DB, APIs, files, queues, email, caches).
|
|
275
|
-
├─────────────────────────────┤
|
|
276
|
-
│ Infrastructure / Config │ ← DI container, env config, connection factories
|
|
277
|
-
└─────────────────────────────┘
|
|
278
|
-
```
|
|
279
|
-
|
|
280
|
-
### Ports (Interfaces owned by the domain)
|
|
281
|
-
- **Repository ports**: `UserRepository`, `OrderRepository` — data persistence contracts.
|
|
282
|
-
- **Gateway ports**: `PaymentGateway`, `EmailSender` — external service contracts.
|
|
283
|
-
- Ports are defined in the domain/service layer, never in the adapter layer.
|
|
284
|
-
- Port interfaces specify WHAT, never HOW.
|
|
285
|
-
|
|
286
|
-
### Adapters (Implementations of ports)
|
|
287
|
-
- **Driving adapters** (primary): HTTP controllers, CLI handlers, message consumers
|
|
288
|
-
— they CALL the application through port interfaces.
|
|
289
|
-
- **Driven adapters** (secondary): PostgresUserRepository, StripePaymentGateway,
|
|
290
|
-
SESEmailSender — they ARE CALLED BY the application through port interfaces.
|
|
291
|
-
- Adapters are interchangeable. Swap `PostgresUserRepository` for `InMemoryUserRepository`
|
|
292
|
-
in tests without changing a single line of business logic.
|
|
293
|
-
|
|
294
|
-
### Data Transfer Objects (DTOs)
|
|
295
|
-
- Use DTOs at layer boundaries — never pass domain entities to/from the API layer.
|
|
296
|
-
- **Request DTOs**: validated at the API boundary ({{#if language_is_typescript}}Zod schema{{/if}}{{#if language_is_python}}Pydantic model{{/if}} → typed object).
|
|
297
|
-
- **Response DTOs**: shaped for the consumer, not mirroring the domain model.
|
|
298
|
-
- **Domain ↔ Persistence mapping**: repositories map between domain entities and DB rows/documents.
|
|
299
|
-
- DTOs are plain data objects — no methods, no behavior, no framework decorators.
|
|
300
|
-
|
|
301
|
-
### Layer Rules
|
|
302
|
-
- Never skip layers. API handlers do not call repositories directly.
|
|
303
|
-
- Dependencies point INWARD only. Inner layers never import from outer layers.
|
|
304
|
-
- Domain models have ZERO external dependencies.
|
|
305
|
-
- The domain layer does not know HTTP, SQL, or any framework exists.
|
|
306
|
-
|
|
307
|
-
- id: clean-code-principles
|
|
308
|
-
tier: recommended
|
|
309
|
-
title: "Clean Code Principles"
|
|
310
|
-
content: |
|
|
311
|
-
## Clean Code Principles
|
|
312
|
-
|
|
313
|
-
### Command-Query Separation (CQS)
|
|
314
|
-
- **Commands** change state but return nothing (void).
|
|
315
|
-
- **Queries** return data but change nothing (no side effects).
|
|
316
|
-
- A function should do one or the other, never both.
|
|
317
|
-
- Exception: stack.pop() style operations where separation is impractical — document why.
|
|
318
|
-
|
|
319
|
-
### Guard Clauses & Early Return
|
|
320
|
-
- Eliminate deep nesting. Handle invalid cases first, return early.
|
|
321
|
-
- The happy path runs at the shallowest indentation level.
|
|
322
|
-
- Before:
|
|
323
|
-
```
|
|
324
|
-
if (user) {
|
|
325
|
-
if (user.isActive) {
|
|
326
|
-
if (user.hasPermission) {
|
|
327
|
-
// actual logic buried 3 levels deep
|
|
328
|
-
```
|
|
329
|
-
- After:
|
|
330
|
-
```
|
|
331
|
-
if (!user) throw new NotFoundError(...);
|
|
332
|
-
if (!user.isActive) throw new InactiveError(...);
|
|
333
|
-
if (!user.hasPermission) throw new ForbiddenError(...);
|
|
334
|
-
// actual logic at top level
|
|
335
|
-
```
|
|
336
|
-
|
|
337
|
-
### Composition over Inheritance
|
|
338
|
-
- Prefer composing objects via interfaces and delegation over class inheritance.
|
|
339
|
-
- Inheritance creates tight coupling and fragile hierarchies.
|
|
340
|
-
- Use inheritance ONLY for genuine "is-a" relationships (rare).
|
|
341
|
-
- When in doubt, compose: inject a collaborator, don't extend a base class.
|
|
342
|
-
|
|
343
|
-
### Law of Demeter (Principle of Least Knowledge)
|
|
344
|
-
- A method should only call methods on: its own object, its parameters, objects it creates,
|
|
345
|
-
its direct dependencies.
|
|
346
|
-
- Do NOT chain through objects: `order.getCustomer().getAddress().getCity()` — BAD.
|
|
347
|
-
- Instead: `order.getShippingCity()` or pass the needed data directly.
|
|
348
|
-
|
|
349
|
-
### Immutability by Default
|
|
350
|
-
{{#if language_is_typescript}}- Use `const` over `let`. Use `readonly` on properties and parameters.
|
|
351
|
-
- Prefer `ReadonlyArray<T>`, `Readonly<T>`, `ReadonlyMap`, `ReadonlySet`.{{/if}}{{#if language_is_python}}- Use `Final` for constants. Use `frozen=True` on dataclasses.
|
|
352
|
-
- Prefer `tuple` over `list` for immutable sequences. Use `MappingProxyType` for immutable dicts.{{/if}}
|
|
353
|
-
- When you need to "modify" data, create a new copy with the change.
|
|
354
|
-
- Mutable state is the #1 source of bugs. Restrict it to the smallest possible scope.
|
|
355
|
-
|
|
356
|
-
### Pure Functions
|
|
357
|
-
- A pure function: same inputs → same outputs, no side effects.
|
|
358
|
-
- Domain logic, validation, transformation, and calculation should be pure.
|
|
359
|
-
- Side effects (I/O, logging, database) are pushed to the edges (adapters).
|
|
360
|
-
- Pure functions are trivially testable — no mocks needed.
|
|
361
|
-
|
|
362
|
-
### Factory Pattern
|
|
363
|
-
- Use factories to encapsulate complex object construction.
|
|
364
|
-
- Factory methods on the class itself for simple cases: `User.create(dto)`.
|
|
365
|
-
- Factory classes/functions when construction involves dependencies or conditional logic.
|
|
366
|
-
- Factories are the natural companion to dependency injection — the DI container
|
|
367
|
-
IS the top-level factory.
|
|
368
|
-
|
|
369
|
-
> **Design reference patterns** (DDD, CQRS, GoF) available on demand via `get_design_reference` tool.
|
|
370
|
-
|
|
371
|
-
- id: twelve-factor-ops
|
|
372
|
-
tier: optional
|
|
373
|
-
title: "12-Factor & Operational Readiness"
|
|
374
|
-
content: |
|
|
375
|
-
## 12-Factor App & Operational Readiness
|
|
376
|
-
|
|
377
|
-
### Configuration
|
|
378
|
-
- ALL config comes from environment variables or external config services. Zero config in code.
|
|
379
|
-
- Config is validated at startup — fail fast with a clear error if required values are missing.
|
|
380
|
-
- `.env.example` committed with every variable documented. `.env` is gitignored.
|
|
381
|
-
|
|
382
|
-
### Stateless Processes
|
|
383
|
-
- Application processes are stateless. Session data lives in external stores (Redis, DB).
|
|
384
|
-
- Any process can be killed and restarted without data loss.
|
|
385
|
-
- File uploads go to object storage (S3, GCS), not local disk.
|
|
386
|
-
|
|
387
|
-
### Port Binding
|
|
388
|
-
- The application is self-contained and exports services via port binding.
|
|
389
|
-
- No runtime injection of a web server — the app embeds its own (Express, Uvicorn, etc.).
|
|
390
|
-
|
|
391
|
-
### Disposability
|
|
392
|
-
- Processes start fast (< 5 seconds) and shut down gracefully.
|
|
393
|
-
- SIGTERM triggers: stop accepting new work → finish in-flight requests → close connections → exit.
|
|
394
|
-
- Workers use robust job queues so interrupted work is retried, not lost.
|
|
395
|
-
|
|
396
|
-
### Dev/Prod Parity
|
|
397
|
-
- Minimize gaps between development and production environments.
|
|
398
|
-
- Use the same backing services in dev as prod (same DB engine, same cache).
|
|
399
|
-
- Docker / containers recommended for environment parity.
|
|
400
|
-
|
|
401
|
-
### Logs as Event Streams
|
|
402
|
-
- The app writes logs to stdout/stderr — never to local files.
|
|
403
|
-
- Log aggregation is an ops concern (ELK, Datadog, CloudWatch), not an application concern.
|
|
404
|
-
- Structured JSON logs with correlation IDs for tracing across services.
|
|
405
|
-
|
|
406
|
-
### Build, Release, Run
|
|
407
|
-
- Strict separation: build (compile + assets), release (build + config), run (execute).
|
|
408
|
-
- Every release is immutable and tagged. Rollback = deploy a previous release.
|
|
409
|
-
- CI/CD pipeline automates: lint → test → build → deploy with gates at each stage.
|
|
410
|
-
|
|
411
|
-
- id: cicd-deployment
|
|
412
|
-
tier: recommended
|
|
413
|
-
title: "CI/CD & Deployment"
|
|
414
|
-
content: |
|
|
415
|
-
## CI/CD & Deployment
|
|
416
|
-
|
|
417
|
-
### Pipeline
|
|
418
|
-
- Every push triggers: lint → type-check → unit tests → build → integration tests.
|
|
419
|
-
- Merges to main additionally run: security scan → deploy to staging → smoke tests → promote.
|
|
420
|
-
- Pipeline must complete in under 10 minutes. Parallelize test suites, cache dependencies.
|
|
421
|
-
- Failed pipelines block merge. No exceptions.
|
|
422
|
-
|
|
423
|
-
### Environments
|
|
424
|
-
- Minimum three environments: **development** (local), **staging** (mirrors prod), **production**.
|
|
425
|
-
- Environment config is injected — same artifact runs everywhere with different env vars.
|
|
426
|
-
- Staging is a faithful replica of production (same provider, same DB engine, same services).
|
|
427
|
-
|
|
428
|
-
### Deployment Strategy
|
|
429
|
-
- Default: **rolling deployment** with health checks (zero downtime).
|
|
430
|
-
- For critical services: **blue-green** or **canary** with automated rollback on error rate spike.
|
|
431
|
-
- Every deploy is tagged with git SHA. Rollback = redeploy a previous SHA.
|
|
432
|
-
- Deployment must be one command or one button. No multi-step manual runbooks.
|
|
433
|
-
|
|
434
|
-
### Preview Environments
|
|
435
|
-
- Pull requests get ephemeral preview deployments where feasible (Vercel, Netlify, Railway).
|
|
436
|
-
- Preview URLs in PR comments for stakeholder review before merge.
|
|
437
|
-
|
|
438
|
-
- id: testing-pyramid
|
|
439
|
-
tier: core
|
|
440
|
-
title: "Testing Pyramid"
|
|
441
|
-
content: |
|
|
442
|
-
## Testing Pyramid
|
|
443
|
-
|
|
444
|
-
```
|
|
445
|
-
/ E2E \ ← 5-10% of tests. Core journeys only.
|
|
446
|
-
/ Integration \ ← 20-30%. Real dependencies at boundaries.
|
|
447
|
-
/ Unit Tests \ ← 60-75%. Fast, isolated, every public function.
|
|
448
|
-
```
|
|
449
|
-
|
|
450
|
-
### Coverage Targets
|
|
451
|
-
- Overall minimum: {{coverage_minimum | default: 80}}% line coverage (blocks commit)
|
|
452
|
-
- New/changed code: {{coverage_new_code_min | default: 90}}% minimum (measured on diff)
|
|
453
|
-
- Critical paths: 95%+ (data pipelines, auth, PHI handling, financial calculations)
|
|
454
|
-
- Mutation score (MSI) — overall: ≥ 65% (blocks PR merge)
|
|
455
|
-
- Mutation score (MSI) — new/changed code: ≥ 70% (measured on diff)
|
|
456
|
-
- Note: Line coverage and mutation score are both required. 80% line coverage can coexist
|
|
457
|
-
with 58% MSI when tests execute code without asserting its behavior (confirmed in Shattered
|
|
458
|
-
Stars). Run stryker-mutator immediately after writing each test batch, not only pre-release.
|
|
459
|
-
Tooling: stryker-mutator (JS/TS), mutmut (Python), Pitest (Java).
|
|
460
|
-
|
|
461
|
-
### Test Rules
|
|
462
|
-
- Every test name is a specification: `test_rejects_duplicate_member_ids` not `test_validation`
|
|
463
|
-
- No empty catch blocks. No `assert True`. No tests that can't fail.
|
|
464
|
-
- Test files colocated: `[module].test.[ext]` or in `tests/` mirroring src structure.
|
|
465
|
-
- Flaky tests are bugs — fix or quarantine, never ignore.
|
|
466
|
-
- After writing tests for any module, run Stryker on that module before moving on.
|
|
467
|
-
Surviving mutants = missing assertions. Fix before proceeding.
|
|
468
|
-
|
|
469
|
-
### Test Doubles Taxonomy
|
|
470
|
-
Use the correct double for the job:
|
|
471
|
-
- **Stub**: Returns canned data. No assertions on calls. Use when you need to control input.
|
|
472
|
-
- **Spy**: Records calls. Assert after the fact. Use to verify side effects.
|
|
473
|
-
- **Fake**: Working implementation with shortcuts (in-memory DB). Use for integration-speed tests.
|
|
474
|
-
- **Mock**: Pre-programmed expectations. Assert call patterns. Use sparingly — they couple to implementation.
|
|
475
|
-
Prefer stubs and fakes over mocks. Tests that mock everything test nothing.
|
|
476
|
-
|
|
477
|
-
### Test Data Builders
|
|
478
|
-
- Use Builder or Factory pattern for test data: `UserBuilder.anAdmin().withName('Alice').build()`.
|
|
479
|
-
- One builder per domain entity. Builders provide sensible defaults so tests only specify what matters.
|
|
480
|
-
- No raw object literals scattered across tests. Centralize in `tests/fixtures/` or `tests/builders/`.
|
|
481
|
-
|
|
482
|
-
### Property-Based Testing
|
|
483
|
-
- For pure functions with wide input ranges, add property tests (fast-check, Hypothesis, QuickCheck).
|
|
484
|
-
- Define invariants, not examples: "sorting is idempotent", "encode then decode = identity".
|
|
485
|
-
- Property tests complement, not replace, example-based tests.
|
|
486
|
-
|
|
487
|
-
- id: tdd-methodology
|
|
488
|
-
tier: core
|
|
489
|
-
title: "Test-Driven Development"
|
|
490
|
-
content: |
|
|
491
|
-
## Test-Driven Development (TDD)
|
|
492
|
-
|
|
493
|
-
### Red-Green-Refactor — The Only Cycle
|
|
494
|
-
1. **RED**: Write a failing test that describes the desired behavior. Run it. It MUST fail.
|
|
495
|
-
If it passes, the test is wrong — it's not testing what you think.
|
|
496
|
-
2. **GREEN**: Write the minimum code to make the test pass. No more.
|
|
497
|
-
3. **REFACTOR**: Clean up while all tests stay green. No new behavior in this step.
|
|
498
|
-
Repeat. Every feature, every function, every bug fix follows this cycle.
|
|
499
|
-
|
|
500
|
-
### Tests Are Specifications, Not Confirmations
|
|
501
|
-
- Write tests against **expected behavior**, never against current implementation.
|
|
502
|
-
- A test that passes on broken code is worse than no test — it provides false confidence.
|
|
503
|
-
- Never weaken an assertion to match what the code currently does. If the code disagrees
|
|
504
|
-
with the spec, the code is wrong.
|
|
505
|
-
- Never write a test suite after the fact that just "locks in" existing behavior without
|
|
506
|
-
verifying it's correct.
|
|
507
|
-
|
|
508
|
-
### Bug Fix Protocol
|
|
509
|
-
- **Every bug fix starts with a failing test** that reproduces the bug.
|
|
510
|
-
- The test must fail before the fix and pass after. No exceptions.
|
|
511
|
-
- If you can't write a reproducing test, you don't understand the bug well enough to fix it.
|
|
512
|
-
|
|
513
|
-
### One Behavior Per Test
|
|
514
|
-
- Each test verifies exactly one behavior or rule.
|
|
515
|
-
- A test with multiple unrelated assertions is testing multiple things — split it.
|
|
516
|
-
- Test name = the specification: `rejects_expired_tokens`, not `test_auth`.
|
|
517
|
-
|
|
518
|
-
- id: tdd-enforcement
|
|
519
|
-
tier: core
|
|
520
|
-
title: "TDD Enforcement — Forbidden Patterns and Gate Protocol"
|
|
521
|
-
content: |
|
|
522
|
-
## TDD Enforcement — Forbidden Patterns and Gate Protocol
|
|
523
|
-
|
|
524
|
-
Instructions describe a process. Gates enforce it. This block defines what is
|
|
525
|
-
structurally prohibited, what output is required at each gate, and how the
|
|
526
|
-
commit sequence makes the TDD cycle auditable.
|
|
527
|
-
|
|
528
|
-
### Forbidden Patterns (non-negotiable)
|
|
529
|
-
The following are architecture violations, not style preferences:
|
|
530
|
-
- **NEVER write an implementation file before running and showing a failing test.**
|
|
531
|
-
Stating that "the test would fail" is not equivalent to running it. Run it.
|
|
532
|
-
- **NEVER write tests after implementation** except for bug fix reproduction tests on
|
|
533
|
-
pre-existing code not yet covered. Even then: write the test, show it fails, fix,
|
|
534
|
-
show it passes.
|
|
535
|
-
- **NEVER weaken an assertion** to make a test pass. If the assertion disagrees with
|
|
536
|
-
the output, the implementation is wrong.
|
|
537
|
-
- **NEVER skip the refactor phase** because "the code is clean enough." The refactor
|
|
538
|
-
phase exists to enforce separation of concerns under green. Skipping it is a
|
|
539
|
-
commitment not to separate concerns in that increment.
|
|
540
|
-
- **NEVER commit a `feat:` or `fix:` with no corresponding `test:` commit** preceding
|
|
541
|
-
it in the same branch. The test commit is the audit trail that the red phase occurred.
|
|
542
|
-
|
|
543
|
-
### The Session Gate Protocol
|
|
544
|
-
TDD across a multi-step session requires explicit checkpoints the AI reports and the
|
|
545
|
-
human can verify. At each gate, the AI must output the actual test runner output,
|
|
546
|
-
not a summary of what it expects.
|
|
547
|
-
|
|
548
|
-
```
|
|
549
|
-
┌─────────────────────────────────────────────────────┐
|
|
550
|
-
│ PHASE 1: RED │
|
|
551
|
-
│ Action: Write test for the specified behavior │
|
|
552
|
-
│ Gate: Run test — paste full failure output │
|
|
553
|
-
│ Block: Cannot proceed until failure is shown │
|
|
554
|
-
│ Commit: test(scope): [RED] describe behavior │
|
|
555
|
-
└───────────────────┬─────────────────────────────────┘
|
|
556
|
-
│ failure confirmed
|
|
557
|
-
┌───────────────────▼─────────────────────────────────┐
|
|
558
|
-
│ PHASE 2: GREEN │
|
|
559
|
-
│ Action: Write minimum implementation │
|
|
560
|
-
│ Gate: Run test — paste full passing output │
|
|
561
|
-
│ Block: Cannot proceed until passing is shown │
|
|
562
|
-
│ Commit: feat(scope): implement to satisfy test │
|
|
563
|
-
└───────────────────┬─────────────────────────────────┘
|
|
564
|
-
│ green confirmed
|
|
565
|
-
┌───────────────────▼─────────────────────────────────┐
|
|
566
|
-
│ PHASE 3: REFACTOR │
|
|
567
|
-
│ Action: Improve structure, not behavior │
|
|
568
|
-
│ Gate: Run full suite — paste summary output │
|
|
569
|
-
│ Block: Cannot commit if any test regresses │
|
|
570
|
-
│ Commit: refactor(scope): clean without behavior │
|
|
571
|
-
└─────────────────────────────────────────────────────┘
|
|
572
|
-
```
|
|
573
|
-
|
|
574
|
-
### Commit Sequence as Audit Trail
|
|
575
|
-
The git log for any feature must be readable as:
|
|
576
|
-
```
|
|
577
|
-
test(cart): [RED] add test for removing last item empties cart
|
|
578
|
-
feat(cart): remove last item empties cart
|
|
579
|
-
refactor(cart): extract empty-check to CartState predicate
|
|
580
|
-
```
|
|
581
|
-
This sequence is auditable. An AI that wrote the `feat:` commit without the preceding
|
|
582
|
-
`test:` commit either skipped the red phase entirely or conflated it with implementation.
|
|
583
|
-
The commit hook `pre-commit-tdd-check.sh` detects the second pattern before it lands.
|
|
584
|
-
|
|
585
|
-
### Why Instructions Alone Are Not Sufficient
|
|
586
|
-
A language model generating in a single context window experiences no time delay between
|
|
587
|
-
writing a test and writing an implementation that passes it. The RED phase is structurally
|
|
588
|
-
collapsed. The gates above exist precisely to make the phases non-simultaneous:
|
|
589
|
-
- The test commit must happen before the implementation can be written.
|
|
590
|
-
- The failure output must be produced (by running the code) before the game state is known.
|
|
591
|
-
- The model cannot "know" the failure output without actually running the test,
|
|
592
|
-
because the failure messages are not in the training distribution for this specific code.
|
|
593
|
-
These gates transform TDD from a discipline into a constraint.
|
|
594
|
-
|
|
595
|
-
- id: adversarial-testing
|
|
596
|
-
tier: core
|
|
597
|
-
title: "Adversarial Testing Posture"
|
|
598
|
-
content: |
|
|
599
|
-
## Adversarial Testing Posture
|
|
600
|
-
|
|
601
|
-
Tests are not documentation of what the code does. Tests are adversarial assertions
|
|
602
|
-
that the code does the right thing even when given inputs designed to break it.
|
|
603
|
-
|
|
604
|
-
### The adversarial posture
|
|
605
|
-
- Design every test as if the implementation is wrong until proven otherwise.
|
|
606
|
-
- Write tests that FAIL on incorrect code — not tests that pass on any reasonable implementation.
|
|
607
|
-
- If a test is hard to make fail, the specification is underspecified, not the test.
|
|
608
|
-
|
|
609
|
-
### Name tests as behaviors, not paths
|
|
610
|
-
- `rejects_expired_tokens` not `test_validate_token`
|
|
611
|
-
- `throws_on_missing_required_field` not `test_error_handling`
|
|
612
|
-
- `returns_empty_list_not_null_when_no_results` not `test_query`
|
|
613
|
-
|
|
614
|
-
### Cover the adversarial surface
|
|
615
|
-
For every public function or API endpoint, write tests for:
|
|
616
|
-
1. **Valid boundary values**: minimum, maximum, exact-zero, single-element
|
|
617
|
-
2. **Invalid boundary values**: below-minimum, above-maximum, empty, null/undefined
|
|
618
|
-
3. **Constraint violations**: values that look valid but break invariants (negative balance, future birth date)
|
|
619
|
-
4. **Ordering and concurrency**: does order matter? what if called twice?
|
|
620
|
-
5. **Authorization boundaries**: can a user access another user's resource?
|
|
621
|
-
|
|
622
|
-
A test suite that only exercises the happy path is documentation, not specification.
|
|
623
|
-
Every mutation that survives is a missing adversarial test.
|
|
624
|
-
|
|
625
|
-
- id: property-based-testing
|
|
626
|
-
tier: recommended
|
|
627
|
-
title: "Property-Based Testing"
|
|
628
|
-
content: |
|
|
629
|
-
## Property-Based Testing
|
|
630
|
-
|
|
631
|
-
Example-based tests verify that `f(x) = y` for specific known pairs.
|
|
632
|
-
Property-based tests verify that invariants hold for ALL inputs the generator can produce.
|
|
633
|
-
Both are required. Neither replaces the other.
|
|
634
|
-
|
|
635
|
-
### When to add property tests
|
|
636
|
-
- Pure functions with wide input domains (serialization, parsing, math, sorting)
|
|
637
|
-
- Functions where "same inputs → same outputs" must hold across edge cases
|
|
638
|
-
- Any encoder/decoder pair: `decode(encode(x)) === x` must hold for all x
|
|
639
|
-
- Any sort or ranking: `sort(sort(xs))` must equal `sort(xs)` (idempotence)
|
|
640
|
-
- Any financial calculation: results must be within bounds for all valid inputs
|
|
641
|
-
|
|
642
|
-
### Ecosystem tools (language-agnostic principle)
|
|
643
|
-
Use whatever property testing library matches the project's language:
|
|
644
|
-
- TypeScript / JavaScript: `fast-check`
|
|
645
|
-
- Python: `hypothesis`
|
|
646
|
-
- Java / Kotlin: `jqwik` or `kotest`
|
|
647
|
-
- Go: `gopter` or `rapid`
|
|
648
|
-
- Rust: `proptest`
|
|
649
|
-
- Scala: `scalacheck`
|
|
650
|
-
|
|
651
|
-
### Template invariant structure
|
|
652
|
-
```
|
|
653
|
-
property("encode-decode round trip", () => {
|
|
654
|
-
forAll(arbitrary_valid_input(), (input) => {
|
|
655
|
-
expect(decode(encode(input))).toEqual(input);
|
|
656
|
-
});
|
|
657
|
-
});
|
|
658
|
-
```
|
|
659
|
-
|
|
660
|
-
If a property test fails with an unexpected input, add that input as a regression example test.
|
|
661
|
-
Property failures are bugs, not edge cases to suppress.
|
|
662
|
-
|
|
663
|
-
- id: spec-meta-query
|
|
664
|
-
tier: recommended
|
|
665
|
-
title: "Specification Completeness Meta-Query"
|
|
666
|
-
content: |
|
|
667
|
-
## Specification Completeness Meta-Query
|
|
668
|
-
|
|
669
|
-
Before writing implementation code, ask the model:
|
|
670
|
-
|
|
671
|
-
> "What dimensions of correctness does this specification not yet address?"
|
|
672
|
-
|
|
673
|
-
This activates domain depth and returns the surface that is missing. A complete answer
|
|
674
|
-
identifies gaps before they become bugs — not after.
|
|
675
|
-
|
|
676
|
-
### Six dimensions to probe systematically
|
|
677
|
-
|
|
678
|
-
1. **Concurrency behavior** — What happens when two users modify the same resource simultaneously?
|
|
679
|
-
Are there race conditions? What is the consistency model (eventual, strong, linearizable)?
|
|
680
|
-
|
|
681
|
-
2. **Partial failure handling** — What state is the system in if the operation fails halfway?
|
|
682
|
-
Is the operation idempotent? Is retry safe? Is rollback possible? Who cleans up?
|
|
683
|
-
|
|
684
|
-
3. **Authorization edge cases** — What happens with an expired token? A revoked role?
|
|
685
|
-
Can a user with partial permissions complete a multi-step operation?
|
|
686
|
-
What does "no access" mean vs "resource does not exist"?
|
|
687
|
-
|
|
688
|
-
4. **Observable side effects** — Does this operation send emails, fire webhooks, publish events,
|
|
689
|
-
write audit logs? Are those effects specified? Are they retryable? Can they duplicate?
|
|
690
|
-
|
|
691
|
-
5. **Performance constraints** — Is there an SLA? A timeout? A maximum payload size?
|
|
692
|
-
What is the expected order of magnitude of inputs? What degrades gracefully?
|
|
693
|
-
|
|
694
|
-
6. **Backwards compatibility** — If this changes an existing interface, what breaks?
|
|
695
|
-
Is there a migration path? Who depends on the current behavior?
|
|
696
|
-
|
|
697
|
-
Each unanswered dimension is a test to write before implementation begins.
|
|
698
|
-
If the specification has no answer, the answer must be decided now — not discovered during an incident.
|
|
699
|
-
|
|
700
|
-
- id: data-guardrails
|
|
701
|
-
tier: core
|
|
702
|
-
title: "Data Guardrails"
|
|
703
|
-
content: |
|
|
704
|
-
## Data Guardrails ⚠️
|
|
705
|
-
- NEVER sample, truncate, or subset data unless explicitly instructed.
|
|
706
|
-
- NEVER make simplifying assumptions about distributions, scales, or schemas.
|
|
707
|
-
- State exact row counts, column sets, and filters for every data operation.
|
|
708
|
-
- If data is too large for in-memory, say so — don't silently downsample.
|
|
709
|
-
|
|
710
|
-
- id: commit-protocol
|
|
711
|
-
tier: core
|
|
712
|
-
title: "Commit Protocol"
|
|
713
|
-
content: |
|
|
714
|
-
## Commit Protocol
|
|
715
|
-
|
|
716
|
-
A commit is a **verified state** of the system — not a save point, not a checkpoint.
|
|
717
|
-
A valid commit requires all three: test suite passes, delta is bounded and coherent,
|
|
718
|
-
no new anti-patterns introduced.
|
|
719
|
-
|
|
720
|
-
- Conventional commits: `feat|fix|refactor|docs|test|chore(scope): description`
|
|
721
|
-
- Commits must pass: compilation, lint, tests, coverage gate, mutation score gate (Stryker on changed modules), anti-pattern scan.
|
|
722
|
-
- Keep commits atomic — one logical change per commit.
|
|
723
|
-
- Commit BEFORE any risky refactor. Tag stable states.
|
|
724
|
-
- Update Status.md at the end of every session.
|
|
725
|
-
|
|
726
|
-
### Commit Hooks — Emit, Don't Reference
|
|
727
|
-
Commit hooks, commit-message linting, and the CI pipeline must be **emitted as fenced
|
|
728
|
-
code blocks** in the first session response — not merely referenced in prose or README
|
|
729
|
-
text. A hook that exists only as "you should add a pre-commit hook" in documentation
|
|
730
|
-
provides zero enforcement. If the file is not written to disk, the gate does not exist.
|
|
731
|
-
|
|
732
|
-
The following files must be emitted for any new project:
|
|
733
|
-
|
|
734
|
-
**`package.json`** — add to `scripts` and `devDependencies`:
|
|
735
|
-
```json
|
|
736
|
-
"scripts": { "prepare": "husky install" },
|
|
737
|
-
"devDependencies": {
|
|
738
|
-
"husky": "^9.0.0",
|
|
739
|
-
"@commitlint/cli": "^19.0.0",
|
|
740
|
-
"@commitlint/config-conventional": "^19.0.0"
|
|
741
|
-
}
|
|
742
|
-
```
|
|
743
|
-
|
|
744
|
-
**`.husky/pre-commit`**:
|
|
745
|
-
```bash
|
|
746
|
-
#!/usr/bin/env sh
|
|
747
|
-
. "$(dirname -- "$0")/_/husky.sh"
|
|
748
|
-
npx tsc --noEmit && npm run lint && npm test -- --passWithNoTests
|
|
749
|
-
```
|
|
750
|
-
|
|
751
|
-
**`.husky/commit-msg`**:
|
|
752
|
-
```bash
|
|
753
|
-
#!/usr/bin/env sh
|
|
754
|
-
. "$(dirname -- "$0")/_/husky.sh"
|
|
755
|
-
npx commitlint --edit "$1"
|
|
756
|
-
```
|
|
757
|
-
|
|
758
|
-
**`commitlint.config.js`**:
|
|
759
|
-
```js
|
|
760
|
-
module.exports = { extends: ['@commitlint/config-conventional'] };
|
|
761
|
-
```
|
|
762
|
-
|
|
763
|
-
### Linter Config — Emit in P0, Don't Reference
|
|
764
|
-
Linter configuration is infrastructure, not application code. It must be committed to the
|
|
765
|
-
repo root in the **first response** (P0) alongside hooks and CI config — not added post-hoc.
|
|
766
|
-
A linter mentioned only in documentation does not enforce anything.
|
|
767
|
-
|
|
768
|
-
**TypeScript / JavaScript** — emit `.eslintrc.json` (or `eslint.config.js` for flat config):
|
|
769
|
-
```json
|
|
770
|
-
{
|
|
771
|
-
"parser": "@typescript-eslint/parser",
|
|
772
|
-
"plugins": ["@typescript-eslint"],
|
|
773
|
-
"rules": {
|
|
774
|
-
"no-unused-vars": "off",
|
|
775
|
-
"@typescript-eslint/no-unused-vars": "error",
|
|
776
|
-
"@typescript-eslint/no-explicit-any": "error"
|
|
777
|
-
}
|
|
778
|
-
}
|
|
779
|
-
```
|
|
780
|
-
|
|
781
|
-
**Python** — emit `ruff.toml` (or `[tool.ruff]` section in `pyproject.toml`):
|
|
782
|
-
```toml
|
|
783
|
-
[tool.ruff]
|
|
784
|
-
select = ["E", "F", "I"]
|
|
785
|
-
ignore = []
|
|
786
|
-
line-length = 100
|
|
787
|
-
```
|
|
788
|
-
|
|
789
|
-
**Go** — emit `.golangci.yaml`:
|
|
790
|
-
```yaml
|
|
791
|
-
linters:
|
|
792
|
-
enable:
|
|
793
|
-
- unused
|
|
794
|
-
- govet
|
|
795
|
-
- errcheck
|
|
796
|
-
```
|
|
797
|
-
|
|
798
|
-
The correct linter config for **this project's language** must be committed to the repo root
|
|
799
|
-
in the same response that emits hooks and CI. Discovering lint errors at code review is too late.
|
|
800
|
-
|
|
801
|
-
### CI Pipeline — Emit, Don't Reference
|
|
802
|
-
`.github/workflows/ci.yml` must be emitted as a fenced code block in the first response.
|
|
803
|
-
A CI configuration described only in documentation does not enforce anything.
|
|
804
|
-
Adapt service blocks, branch names, and language-specific commands to the project stack.
|
|
805
|
-
The mutation gate step (`npx stryker run` for JS/TS, `mutmut run` for Python, `pitest` for
|
|
806
|
-
Java) is non-negotiable — it is the only gate that verifies test quality, not just
|
|
807
|
-
test execution. Line coverage at 80% can coexist with 58% mutation score; the mutation
|
|
808
|
-
gate catches the difference.
|
|
809
|
-
|
|
810
|
-
Minimum CI for a Node.js/TypeScript project:
|
|
811
|
-
```yaml
|
|
812
|
-
name: CI
|
|
813
|
-
on:
|
|
814
|
-
push:
|
|
815
|
-
branches: [main, develop]
|
|
816
|
-
pull_request:
|
|
817
|
-
branches: [main, develop]
|
|
818
|
-
jobs:
|
|
819
|
-
ci:
|
|
820
|
-
runs-on: ubuntu-latest
|
|
821
|
-
steps:
|
|
822
|
-
- uses: actions/checkout@v4
|
|
823
|
-
- uses: actions/setup-node@v4
|
|
824
|
-
with:
|
|
825
|
-
node-version: '20'
|
|
826
|
-
cache: 'npm'
|
|
827
|
-
- run: npm ci
|
|
828
|
-
- run: npx tsc --noEmit
|
|
829
|
-
- run: npm run lint
|
|
830
|
-
- run: npm test -- --coverage --passWithNoTests
|
|
831
|
-
- name: Mutation gate
|
|
832
|
-
run: npx stryker run
|
|
833
|
-
```
|
|
834
|
-
|
|
835
|
-
### Commit Message Precision
|
|
836
|
-
The commit message is the sentence describing this state in the project's typed corpus.
|
|
837
|
-
- ❌ `fix bug` — not a sentence; not queryable; useless as episodic memory.
|
|
838
|
-
- ✅ `fix(auth): reject expired tokens at middleware boundary before service layer invocation`
|
|
839
|
-
The AI uses commit history as context in future sessions. Typed, scoped conventional
|
|
840
|
-
messages are a queryable episodic record. `wip` and `changes` are not.
|
|
841
|
-
|
|
842
|
-
### What Constitutes One Logical Change
|
|
843
|
-
- A new feature and its tests: one commit.
|
|
844
|
-
- A refactor of an existing module that does not change behavior: one commit.
|
|
845
|
-
- A spec update (constitution change + the code change it governs): one commit.
|
|
846
|
-
- A bug fix with the reproducing test included: one commit.
|
|
847
|
-
Never combine a behavior change with a refactor in the same commit.
|
|
848
|
-
|
|
849
|
-
- id: clarification-protocol
|
|
850
|
-
tier: core
|
|
851
|
-
title: "Clarification Protocol"
|
|
852
|
-
content: |
|
|
853
|
-
## Clarification Protocol
|
|
854
|
-
Before writing code for any new feature or significant change:
|
|
855
|
-
- If the request implies architectural trade-offs that are not explicit, **ask one targeted
|
|
856
|
-
question** before proceeding. Do not silently choose an architecture.
|
|
857
|
-
- If the domain model is ambiguous (cardinality, ownership, event ordering, shared state),
|
|
858
|
-
state your assumption and ask for confirmation before implementing.
|
|
859
|
-
- If the request has two or more meaningfully different interpretations, present the options
|
|
860
|
-
briefly and ask — do not guess and hide the choice.
|
|
861
|
-
- Do NOT ask about mechanical details (naming conventions, file placement, test structure) —
|
|
862
|
-
apply the conventions already in this document without asking.
|
|
863
|
-
- Maximum one clarification round. If told "use your judgment," proceed with the most
|
|
864
|
-
conservative interpretation and record the assumption in a code comment or new ADR.
|
|
865
|
-
|
|
866
|
-
- id: feature-completion-protocol
|
|
867
|
-
tier: recommended
|
|
868
|
-
title: "Feature Completion Protocol"
|
|
869
|
-
content: |
|
|
870
|
-
## Feature Completion Protocol
|
|
871
|
-
After implementing any feature (new or changed):
|
|
872
|
-
|
|
873
|
-
### 1. Verify (local, pre-commit)
|
|
874
|
-
Run: `npx forgecraft-mcp verify .`
|
|
875
|
-
(Or `npm test` + manual HTTP check if forgecraft is not installed.)
|
|
876
|
-
A feature is not done until verify passes. Do not proceed to docs if it fails.
|
|
877
|
-
|
|
878
|
-
### 2. Commit (code only)
|
|
879
|
-
Commit after `verify` passes. This triggers CI and the staging deploy pipeline.
|
|
880
|
-
`feat(scope): <description>` — describes the feature, not the docs update.
|
|
881
|
-
|
|
882
|
-
### 3. Deploy to Staging + Smoke Gate
|
|
883
|
-
After the CI pipeline deploys to staging, run the smoke suite:
|
|
884
|
-
```
|
|
885
|
-
npx playwright test --config playwright.smoke.config.ts --grep @smoke
|
|
886
|
-
```
|
|
887
|
-
If smoke fails: **revert the deploy**. Do not proceed to production and do not cascade docs
|
|
888
|
-
for a feature that is broken in the deployed environment.
|
|
889
|
-
|
|
890
|
-
### 4. Doc Sync Cascade
|
|
891
|
-
Update the following in order — skip any that do not exist in this project:
|
|
892
|
-
1. **spec.md** — update the relevant feature section (APIs, behavior, contract changes)
|
|
893
|
-
2. **docs/adrs/** — add an ADR if a new architectural decision was made
|
|
894
|
-
3. **docs/diagrams/c4-*.md** — update `c4-context.md` or `c4-container.md` if a new
|
|
895
|
-
module, container, or external dependency was added. Diagrams must be written to disk
|
|
896
|
-
as fenced Mermaid blocks — updating prose that references a diagram is not an update.
|
|
897
|
-
4. **docs/diagrams/sequence-*.md / state-*.md / flow-*.md** — update or create the
|
|
898
|
-
relevant diagram file for the changed surface. Sequence diagrams must name real
|
|
899
|
-
participants; state diagrams must name real states and transitions; flow diagrams must
|
|
900
|
-
have entry/exit nodes and decision diamonds. A file containing only `<!-- UNFILLED -->`
|
|
901
|
-
markers is a specification gap, not a completed diagram.
|
|
902
|
-
5. **docs/TechSpec.md** — update module list, API reference, or technology choice sections
|
|
903
|
-
6. **docs/use-cases.md** — update or add use cases if new actor interactions were introduced
|
|
904
|
-
7. **Status.md** — always update: what changed, current state, next steps
|
|
905
|
-
|
|
906
|
-
- id: mcp-tooling
|
|
907
|
-
tier: recommended
|
|
908
|
-
title: "MCP-Powered Tooling"
|
|
909
|
-
content: |
|
|
910
|
-
## MCP-Powered Tooling
|
|
911
|
-
### CodeSeeker — Graph-Powered Code Intelligence
|
|
912
|
-
CodeSeeker builds a knowledge graph of the codebase with hybrid search
|
|
913
|
-
(vector + text + path, fused with RRF). Use it for:
|
|
914
|
-
- **Semantic search**: "find code that handles errors like this" — not just grep.
|
|
915
|
-
- **Graph traversal**: imports, calls, extends — follow dependency chains.
|
|
916
|
-
- **Coding standards**: auto-detected validation, error handling, and state patterns.
|
|
917
|
-
- **Contextual reads**: `get_file_context` returns a file with its related code.
|
|
918
|
-
Indexing is automatic on first search (~30s–5min depending on codebase size).
|
|
919
|
-
Most valuable on mid-to-large projects (10K+ files) with established patterns.
|
|
920
|
-
Install: `npx codeseeker install --vscode` or see https://github.com/jghiringhelli/codeseeker
|
|
921
|
-
|
|
922
|
-
- id: engineering-preferences
|
|
923
|
-
tier: recommended
|
|
924
|
-
title: "Engineering Preferences"
|
|
925
|
-
content: |
|
|
926
|
-
## Engineering Preferences
|
|
927
|
-
These calibrate the AI assistant's judgment on subjective trade-offs.
|
|
928
|
-
- **DRY is important** — flag repetition aggressively.
|
|
929
|
-
- **Well-tested code is non-negotiable**; I'd rather have too many tests than too few.
|
|
930
|
-
- **"Engineered enough"** — not under-engineered (fragile, hacky) and not over-engineered
|
|
931
|
-
(premature abstraction, unnecessary complexity).
|
|
932
|
-
- **Handle more edge cases**, not fewer; thoughtfulness > speed.
|
|
933
|
-
- **Bias toward explicit over clever** — readability wins over brevity.
|
|
934
|
-
- When in doubt, ask rather than assume.
|
|
935
|
-
|
|
936
|
-
- id: agent-mechanics
|
|
937
|
-
tier: core
|
|
938
|
-
title: "Agent Mechanical Constraints"
|
|
939
|
-
content: |
|
|
940
|
-
## Agent Mechanical Constraints — Non-Negotiable Overrides
|
|
941
|
-
|
|
942
|
-
These rules exist because the model has hard constraints that silently produce wrong
|
|
943
|
-
results without them. Each override targets a specific failure mode observed in practice.
|
|
944
|
-
|
|
945
|
-
### 1. Step 0 — Dead Code First
|
|
946
|
-
Before ANY structural refactor on a file > 300 LOC:
|
|
947
|
-
1. Delete all dead props, unused exports, unused imports, and debug logs.
|
|
948
|
-
2. Commit that cleanup separately under `chore(scope): strip dead code`.
|
|
949
|
-
3. Only then begin the real work.
|
|
950
|
-
Dead code accelerates context compaction. Every orphaned import is budget spent on
|
|
951
|
-
tokens that contribute nothing to the task.
|
|
952
|
-
|
|
953
|
-
### 2. Phase Limit — 5 Files Maximum
|
|
954
|
-
Never attempt multi-file refactors in a single response. Break work into explicit phases.
|
|
955
|
-
Each phase must touch **no more than 5 files**. Complete Phase N, verify it compiles and
|
|
956
|
-
all tests pass, then wait for explicit approval before Phase N+1.
|
|
957
|
-
Why: context compaction fires around 167K tokens and discards all intermediate reasoning,
|
|
958
|
-
file reads, and decision chains. Keeping phases small prevents mid-task compaction.
|
|
959
|
-
|
|
960
|
-
### 3. Senior Dev Override
|
|
961
|
-
The model's default system-level directives instruct it to "try the simplest approach
|
|
962
|
-
first" and "avoid refactoring beyond what was asked." These are active constraints that
|
|
963
|
-
fight your intent on architectural tasks.
|
|
964
|
-
**Override them explicitly** when quality requires it:
|
|
965
|
-
> "What would a senior, experienced, perfectionist dev reject in code review? Fix all of it."
|
|
966
|
-
This reframes what "done" means. System-level brevity mandates yield to an explicit
|
|
967
|
-
quality bar stated in the prompt.
|
|
968
|
-
|
|
969
|
-
### 4. Sub-Agent Parallelism for Large Tasks
|
|
970
|
-
For tasks spanning > 5 independent files, **launch parallel sub-agents** (5–8 files per
|
|
971
|
-
agent). Each agent gets its own isolated context window and compaction cycle.
|
|
972
|
-
Sequential processing of large tasks guarantees context decay by the later files.
|
|
973
|
-
Batching into parallel agents multiplies the effective working memory proportionally.
|
|
974
|
-
|
|
975
|
-
### 5. File Read Budget — 2,000-Line Cap
|
|
976
|
-
Each file read is hard-capped at 2,000 lines. Everything past that is silently truncated.
|
|
977
|
-
The model does not know what it didn't see — it will hallucinate the rest.
|
|
978
|
-
**For any file over 500 LOC**: read in sequential chunks using `offset` and `limit`
|
|
979
|
-
parameters. Never assume a single read captured the full file.
|
|
980
|
-
|
|
981
|
-
### 6. Tool Result Truncation
|
|
982
|
-
Tool results exceeding ~50,000 characters are truncated to a 2,000-byte preview.
|
|
983
|
-
The model works from the preview and does not know results were cut.
|
|
984
|
-
If any search returns suspiciously few results: re-run it with narrower scope
|
|
985
|
-
(single directory, stricter glob). State explicitly when truncation may have occurred.
|
|
986
|
-
|
|
987
|
-
### 7. Grep Is Not an AST
|
|
988
|
-
`grep` is raw text pattern matching. It cannot distinguish a function call from a
|
|
989
|
-
comment, a type reference from a string literal, or an import from one module vs another.
|
|
990
|
-
On any rename or signature change, search **separately** for:
|
|
991
|
-
- Direct calls and references
|
|
992
|
-
- Type-level references (interfaces, generics, `typeof`)
|
|
993
|
-
- String literals containing the name
|
|
994
|
-
- Dynamic imports and `require()` calls
|
|
995
|
-
- Re-exports and barrel file entries (`index.ts`, `__init__.py`)
|
|
996
|
-
- Test files and mocks
|
|
997
|
-
Never assume a single grep caught everything. Verify or expect regressions.
|
|
998
|
-
|
|
999
|
-
- id: code-generation-verification
|
|
1000
|
-
tier: core
|
|
1001
|
-
title: "Code Generation — Self-Verify Loop"
|
|
1002
|
-
content: |
|
|
1003
|
-
## Code Generation — Verify Before Returning
|
|
1004
|
-
|
|
1005
|
-
When emitting implementation code across one or more files, the response is not complete
|
|
1006
|
-
until the following are true. Show the evidence in your response — do not claim without running.
|
|
1007
|
-
|
|
1008
|
-
### Verification steps (in order)
|
|
1009
|
-
1. **Compile check**: Run `tsc --noEmit` (TypeScript), `mypy` (Python), or equivalent.
|
|
1010
|
-
Zero errors required. Do not return with type errors outstanding.
|
|
1011
|
-
2. **Test suite**: Run the full test suite (`jest --runInBand`, `pytest`, etc.).
|
|
1012
|
-
Zero failures required. Fix every failure before returning.
|
|
1013
|
-
3. **Interface consistency**: When fixing a compile error in file A, check ALL callers of
|
|
1014
|
-
the changed interface. Fixing one side without seeing the other causes oscillation:
|
|
1015
|
-
the model fixes `service.ts` (3-param signature) but `routes.ts` still calls it with
|
|
1016
|
-
an object — same error reappears inverted next pass.
|
|
1017
|
-
4. **§8 DRY Check**: Run duplication detector on `src/`. Duplicated lines must be < 5%
|
|
1018
|
-
(min-tokens 50). Use the tool appropriate for your stack (see project-gates.yaml:
|
|
1019
|
-
`no-code-duplication`). If above threshold, extract duplicated logic to a shared utility
|
|
1020
|
-
before closing.
|
|
1021
|
-
5. **§9 Interface Completeness**: Every method declared in each interface must be implemented
|
|
1022
|
-
by its concrete class. Run static type checking (0 errors required). Use the tool
|
|
1023
|
-
appropriate for your stack (see project-gates.yaml: `interface-contract-completeness`).
|
|
1024
|
-
If errors exist, implement missing methods before closing.
|
|
1025
|
-
|
|
1026
|
-
### Required evidence in the final response
|
|
1027
|
-
```
|
|
1028
|
-
tsc --noEmit: 0 errors
|
|
1029
|
-
Jest: 109 passed, 0 failed, 11 suites
|
|
1030
|
-
```
|
|
1031
|
-
|
|
1032
|
-
### Common test setup pitfalls (TypeScript / Prisma)
|
|
1033
|
-
- **`prisma db push`, not `prisma migrate deploy`** in test environments.
|
|
1034
|
-
`migrate deploy` silently no-ops when no `prisma/migrations/` folder exists,
|
|
1035
|
-
leaving all tables absent. `db push --accept-data-loss` syncs `schema.prisma` directly.
|
|
1036
|
-
- **`deleteMany` in FK order, not `DROP SCHEMA`**.
|
|
1037
|
-
`$executeRawUnsafe('DROP SCHEMA public CASCADE; CREATE SCHEMA public;')` throws
|
|
1038
|
-
error 42601 — pg rejects multi-statement queries in prepared statements.
|
|
1039
|
-
Use ordered `deleteMany()` calls in `beforeEach` instead.
|
|
1040
|
-
- **JWT_SECRET minimum length**: HS256 requires ≥ 32 characters.
|
|
1041
|
-
Test secrets like `"test-secret"` (11 chars) cause startup errors.
|
|
1042
|
-
Use `"test-secret-that-is-at-least-32-chars"` in test env.
|
|
1043
|
-
|
|
1044
|
-
- id: known-pitfalls
|
|
1045
|
-
tier: core
|
|
1046
|
-
title: "Known Pitfalls"
|
|
1047
|
-
content: |
|
|
1048
|
-
## Known Pitfalls
|
|
1049
|
-
Recurring type errors and runtime traps specific to this project's stack.
|
|
1050
|
-
Resolve exactly as documented — no `any` casts, ignore directives, or unlisted workarounds.
|
|
1051
|
-
### [Add project-specific pitfalls here]
|
|
1052
|
-
<!-- Entry format:
|
|
1053
|
-
### Library — trap description
|
|
1054
|
-
What goes wrong and why, then:
|
|
1055
|
-
```
|
|
1056
|
-
// ❌ wrong
|
|
1057
|
-
```
|
|
1058
|
-
```
|
|
1059
|
-
// ✅ correct
|
|
1060
|
-
```
|
|
1061
|
-
-->
|
|
1062
|
-
|
|
1063
|
-
- id: corrections-log
|
|
1064
|
-
tier: core
|
|
1065
|
-
title: "Corrections Log"
|
|
1066
|
-
content: |
|
|
1067
|
-
## Corrections Log
|
|
1068
|
-
When I correct your output, record the correction pattern here so you don't repeat it.
|
|
1069
|
-
### Learned Corrections
|
|
1070
|
-
- [AI assistant appends corrections here with date and description]
|
|
1071
|
-
|
|
1072
|
-
- id: techniques-registry
|
|
1073
|
-
tier: core
|
|
1074
|
-
title: "Techniques"
|
|
1075
|
-
content: |
|
|
1076
|
-
## Techniques
|
|
1077
|
-
Named techniques, algorithms, and domain frameworks active in this project.
|
|
1078
|
-
Each name activates the AI's full training on that technique — no explanation needed.
|
|
1079
|
-
A technique named here is available at the full depth of the model's training on it.
|
|
1080
|
-
### Active Techniques
|
|
1081
|
-
<!-- Add project-specific techniques below.
|
|
1082
|
-
Examples: RAPTOR indexing · BM25+vector hybrid with RRF fusion ·
|
|
1083
|
-
PCA geometric validation · deontic modal logic · CQRS · Saga pattern -->
|
|
1084
|
-
- [Add named techniques here]
|
|
1085
|
-
|
|
1086
|
-
- id: test-taxonomy
|
|
1087
|
-
tier: recommended
|
|
1088
|
-
title: "Test Taxonomy"
|
|
1089
|
-
content: |
|
|
1090
|
-
## Testing Architecture
|
|
1091
|
-
|
|
1092
|
-
### Test Types by Scope and Purpose
|
|
1093
|
-
Listed from fastest/most-isolated to slowest/most-integrated:
|
|
1094
|
-
|
|
1095
|
-
| Type | Description | Tooling |
|
|
1096
|
-
|---|---|---|
|
|
1097
|
-
| **Unit — Solitary** | Single unit; mock all collaborators. | Jest, Vitest, pytest |
|
|
1098
|
-
| **Unit — Sociable** | Single unit; allow fast non-I/O collaborators (no mocking real logic). | Jest, Vitest, pytest |
|
|
1099
|
-
| **Integration — Narrow (DB)** | Exercise one layer against a real local DB; no external services. | Testcontainers, SQLite, in-process Postgres |
|
|
1100
|
-
| **Integration — Service** | Service + stubs for external deps via WireMock or equivalent. | WireMock, Wiremock-rs, msw |
|
|
1101
|
-
| **Contract / Consumer-Driven (CDC)** | Consumer writes pact file; provider verifies. Prevents API breakage without full E2E infra. | Pact, Spring Cloud Contract |
|
|
1102
|
-
| **API / Subcutaneous** | HTTP or WebSocket layer below the UI; tests the full request-response cycle without browser. | Supertest, Playwright APIRequestContext, httpx |
|
|
1103
|
-
| **Acceptance / BDD** | Given-When-Then; orthogonal to pyramid — level is a performance choice, not semantic. | Cucumber, behave, should-style assertions |
|
|
1104
|
-
| **E2E** | Full user flows in a real browser. Keep minimal — expensive and brittle. Reserve for highest-value journeys. | Playwright, Cypress |
|
|
1105
|
-
| **Visual Regression** | Pixel-diff baseline + LLM visual analysis for judgment-requiring defects. | Percy, Chromatic, Playwright snapshots |
|
|
1106
|
-
| **Smoke** | Deployed environment only. Strictly happy-path. Binary pass/fail deploy gate. | Playwright, custom health check suite |
|
|
1107
|
-
| **Regression** | Discipline: full suite green before merge. Not a test type — a required gate. | All layers |
|
|
1108
|
-
| **Security — SAST** | Static analysis at commit: code pattern scanning and dep vulnerability scanning. | Semgrep, SonarQube, ESLint security plugins, npm audit, Snyk |
|
|
1109
|
-
| **Security — DAST** | Dynamic analysis at staging: automated attack surface probing. | OWASP ZAP, Burp Suite |
|
|
1110
|
-
| **Security — Penetration** | Adversarial session at release candidate gate; OWASP Top 10 coverage. | Manual + OWASP ZAP, Burp Suite |
|
|
1111
|
-
| **Mutation** | Tests the tests: injects code mutations and verifies the suite catches them. Tracked at PR; required above threshold at RC. | Stryker (JS), PIT (Java), mutmut (Python) |
|
|
1112
|
-
| **Property-Based / Fuzz** | Auto-generates input space against stated invariants. Fuzzing is the adversarial variant. | fast-check (JS), Hypothesis (Python) |
|
|
1113
|
-
| **Accessibility / a11y** | WCAG 2.1 AA. Automated at PR; full manual audit at RC. | axe-core, Playwright @axe-core, Lighthouse |
|
|
1114
|
-
| **Performance: Load / Stress / Soak** | At staging. Required before production on systems with SLAs. | k6, Locust, Gatling |
|
|
1115
|
-
| **Chaos / Resilience** | Random fault injection against deployed environment; named resilience contracts. | Toxiproxy, ChaosMesh, custom fault injection |
|
|
1116
|
-
| **Exploratory** | Manual, session-based, scheduled. Charter-driven. Findings become regression tests. | Manual + session notes |
|
|
1117
|
-
|
|
1118
|
-
### Variant Coverage Dimensions
|
|
1119
|
-
For each test scope, the following input/condition variants are required:
|
|
1120
|
-
|
|
1121
|
-
- **Happy path** — nominal, valid inputs. Necessary but never sufficient.
|
|
1122
|
-
- **Sad / Negative path** — correct rejection of invalid input or sequences.
|
|
1123
|
-
- **Edge case / BVA** — boundary values: max, min, empty, null, type coercions.
|
|
1124
|
-
- **Corner case** — intersection of two or more simultaneous edge conditions. Requires explicit enumeration.
|
|
1125
|
-
- **State transition** — valid and invalid state machine transitions. Requires a state diagram as prerequisite.
|
|
1126
|
-
- **Equivalence partitioning** — one representative from each equivalence class. Reduces test count without reducing coverage.
|
|
1127
|
-
- **Error path** — infrastructure/dependency failure: timeout, 500, DB refused, queue full — conditions the user did not cause.
|
|
1128
|
-
- **Security / Adversarial input** — SQL injection, XSS, path traversal, oversized payloads, malformed tokens. Required at every layer touching user-supplied data.
|
|
1129
|
-
- **Random / Monkey** — unstructured random input. Subsumed by property-based layer.
|
|
1130
|
-
|
|
1131
|
-
**Variant coverage matrix** (✓ = required, ~ = structural constraint, — = not applicable):
|
|
1132
|
-
|
|
1133
|
-
| Variant | Unit | Integration | Contract | API | E2E | Smoke | Chaos |
|
|
1134
|
-
|---|---|---|---|---|---|---|---|
|
|
1135
|
-
| Happy path | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | — |
|
|
1136
|
-
| Sad / Negative | ✓ | ✓ | ✓ | ✓ | ~ | ~ happy-path only | — |
|
|
1137
|
-
| Edge / BVA | ✓ | ✓ | — | ✓ | — | — | — |
|
|
1138
|
-
| Corner case | ✓ | — | — | ✓ | — | — | — |
|
|
1139
|
-
| State transition | ✓ | ✓ | — | ✓ | ✓ | — | — |
|
|
1140
|
-
| Equivalence partition | ✓ | — | — | ✓ | — | — | — |
|
|
1141
|
-
| Error path | ✓ | ✓ | — | ✓ | — | — | ✓ |
|
|
1142
|
-
| Security / Adversarial | — | — | — | ✓ | — | — | ~ always adversarial |
|
|
1143
|
-
| Random / Monkey | via property-based | — | — | — | — | — | ✓ |
|
|
1144
|
-
|
|
1145
|
-
### Test Pipeline Mapping
|
|
1146
|
-
Each trigger gate accumulates the prior gates. A gate may not be skipped.
|
|
1147
|
-
|
|
1148
|
-
| Trigger | Gate Contents | Target Duration |
|
|
1149
|
-
|---|---|---|
|
|
1150
|
-
| **File save** | Unit only | ~seconds |
|
|
1151
|
-
| **git commit / push** | Unit + integration + SAST + dependency scan + lint + regression gate | ~2–5 min |
|
|
1152
|
-
| **Pull request** | All prior + contract + API/subcutaneous + E2E (core flows) + acceptance + visual regression + a11y (automated) + property-based | ~10–20 min |
|
|
1153
|
-
| **Deploy to staging** | Smoke → DAST → performance baseline → chaos/resilience | ~45–60 min |
|
|
1154
|
-
| **Release candidate** | All layers blocking + penetration test + full a11y audit + mutation score gate + compatibility matrix | Per schedule |
|
|
1155
|
-
| **Production deploy** | Canary deploy + synthetic monitoring + A/B if applicable | Continuous |
|
|
1156
|
-
|
|
1157
|
-
> Mutation score gate: minimum 70% at PR, 80% at RC on changed code. Stryker/mutmut reports block promotion below threshold.
|
|
1158
|
-
|
|
1159
|
-
- id: release-phase-gate
|
|
1160
|
-
tier: core
|
|
1161
|
-
title: "Active Release Phase Gate"
|
|
1162
|
-
content: |
|
|
1163
|
-
## Active Release Phase: {{release_phase | default: development}}
|
|
1164
|
-
|
|
1165
|
-
Your current phase determines which test gates are **required now**, not advisory.
|
|
1166
|
-
The full taxonomy and trigger mapping are in the Testing section above.
|
|
1167
|
-
Read your phase row below and apply every requirement listed.
|
|
1168
|
-
|
|
1169
|
-
| Phase | Required now — blocking | Not required yet |
|
|
1170
|
-
|---|---|---|
|
|
1171
|
-
| **development** | Unit + integration + lint + tsc --noEmit + npm audit (no HIGH/CRITICAL) | DAST, load/stress, penetration, mutation score gate |
|
|
1172
|
-
| **pre-release / staging** | All development requirements + smoke → DAST (OWASP ZAP / Burp Suite) + load test at 2× peak (k6 / Locust) + chaos/resilience (Toxiproxy) + mutation score ≥ 80% on changed code | Manual penetration test, full a11y audit |
|
|
1173
|
-
| **release-candidate** | All staging requirements + manual penetration test (OWASP Top 10, JWT vectors, BOLA/IDOR) + full a11y audit (if UI) + compatibility matrix + mutation score ≥ 80% overall + zero unresolved HIGH/CRITICAL CVEs | Production canary |
|
|
1174
|
-
| **production** | Canary deploy + automatic rollback on error rate spike + synthetic health probes + incident runbook verified | — |
|
|
1175
|
-
|
|
1176
|
-
**Current active phase: `{{release_phase | default: development}}`**
|
|
1177
|
-
|
|
1178
|
-
> If the phase is `pre-release` or `release-candidate`:
|
|
1179
|
-
> Hardening tests (load, DAST, penetration) are REQUIRED in this session, not deferred.
|
|
1180
|
-
> Do not proceed to merge without completing the required gate for your phase.
|
|
1181
|
-
> The Testing section above maps each gate to its tooling and target duration.
|
|
1182
|
-
|
|
1183
|
-
- id: gs-test-techniques
|
|
1184
|
-
tier: recommended
|
|
1185
|
-
title: "Generative Specification — Testing Techniques"
|
|
1186
|
-
content: |
|
|
1187
|
-
## Generative Specification: Testing Techniques
|
|
1188
|
-
|
|
1189
|
-
These five techniques are specific to GS practice and extend the standard taxonomy above.
|
|
1190
|
-
|
|
1191
|
-
### Adversarial Test Posture
|
|
1192
|
-
The test is a hunter, not a witness.
|
|
1193
|
-
- Tests are written to FAIL on incorrect code — to find the input or condition that exposes
|
|
1194
|
-
a violation, not to confirm the current behavior.
|
|
1195
|
-
- Tests must be written against interfaces, not implementations.
|
|
1196
|
-
A test coupled to internal state fails on correct refactors and passes on behavioral violations
|
|
1197
|
-
that happen to preserve internal structure. That is the worst outcome.
|
|
1198
|
-
|
|
1199
|
-
### Expose-Store-to-Window (Interactive / Game / Real-Time UIs)
|
|
1200
|
-
For applications with a shared state store (Redux, Zustand, Pinia, state machine), expose the
|
|
1201
|
-
store to `window` in the test environment:
|
|
1202
|
-
```typescript
|
|
1203
|
-
if (process.env.NODE_ENV === 'test') {
|
|
1204
|
-
(window as any).__store = store;
|
|
1205
|
-
}
|
|
1206
|
-
```
|
|
1207
|
-
Playwright tests can then assert both what the screen renders AND what the application believes
|
|
1208
|
-
is true — the store's internal state — without coupling assertions to DOM structure. This catches
|
|
1209
|
-
the failure class that renders correctly but corrupts internal state (score displays right, stored wrong;
|
|
1210
|
-
entity in undefined state not yet manifested as a visual defect).
|
|
1211
|
-
|
|
1212
|
-
### Vertical Chain Test
|
|
1213
|
-
A single UI action triggers Playwright, which then:
|
|
1214
|
-
1. Queries the service layer response
|
|
1215
|
-
2. Queries the database state and any affected indexes
|
|
1216
|
-
3. Verifies correct propagation through every boundary the action crosses
|
|
1217
|
-
4. Returns to the UI to confirm the visible outcome matches the stored state
|
|
1218
|
-
|
|
1219
|
-
Not a unit test, not a visual check, not a flow test: a chain verification. One trigger, inspected
|
|
1220
|
-
at every boundary it crosses. Specify which critical flows receive this treatment in the test
|
|
1221
|
-
architecture document. A defect anywhere in the chain (service logic, persistence, index consistency,
|
|
1222
|
-
UI rendering) is surfaced in a single pass.
|
|
1223
|
-
|
|
1224
|
-
### Mutation Testing as Adversarial Audit
|
|
1225
|
-
An AI-generated test suite carries a structural risk: tests written by a system that knows the
|
|
1226
|
-
correct implementation may pass it rather than catch violations of it.
|
|
1227
|
-
- Run Stryker (JS/TS) or mutmut (Python) against every AI-generated suite before accepting it.
|
|
1228
|
-
- A test that passes a mutant is not testing the contract — it is confirming the absence of one
|
|
1229
|
-
specific mutation, no more.
|
|
1230
|
-
- Coverage measures what was executed. Mutation score measures what was caught. The second is
|
|
1231
|
-
the meaningful metric.
|
|
1232
|
-
- Gates: 70% mutation score at PR, 80% at release candidate on changed code.
|
|
1233
|
-
|
|
1234
|
-
### Multimodal Quality Gates (Generative Assets)
|
|
1235
|
-
When content is AI-generated (images, audio, video), the acceptance criteria must be executable.
|
|
1236
|
-
Manual review at scale is not a pipeline.
|
|
1237
|
-
|
|
1238
|
-
**Visual assets (sprite sheets, generated imagery):**
|
|
1239
|
-
```python
|
|
1240
|
-
# PCA-based orientation check
|
|
1241
|
-
from sklearn.decomposition import PCA
|
|
1242
|
-
pca = PCA(n_components=2).fit(ship_pixel_coordinates)
|
|
1243
|
-
angle = np.degrees(np.arctan2(*pca.components_[0][::-1]))
|
|
1244
|
-
assert abs(angle) <= 15, f"Sprite orientation {angle:.1f}° exceeds 15° tolerance"
|
|
1245
|
-
|
|
1246
|
-
# Symmetry check (horizontal flip similarity)
|
|
1247
|
-
similarity = ssim(img_half_left, np.fliplr(img_half_right))
|
|
1248
|
-
assert similarity >= 0.85, f"Symmetry {similarity:.2f} below 0.85 threshold"
|
|
1249
|
-
```
|
|
1250
|
-
|
|
1251
|
-
**Audio assets:**
|
|
1252
|
-
- Loudness normalization: assert target LUFS within ±1 dB of spec (pyloudnorm).
|
|
1253
|
-
- Frequency profile: no asset competes in the 2–4 kHz presence range during dialogue.
|
|
1254
|
-
- Silence detection: reject assets with generation artifacts (> X ms silence in unexpected positions).
|
|
1255
|
-
|
|
1256
|
-
**MCP-mediated inspection (judgment-requiring defects):**
|
|
1257
|
-
An instrumented game/app state exposed through an MCP server lets a language model
|
|
1258
|
-
evaluate whether a running scene satisfies its acceptance criteria without pre-scripting
|
|
1259
|
-
every assertion. Feed the model the scene spec + MCP access; it reports violations.
|
|
1260
|
-
This addresses defects that are easy to name but hard to encode as assertions.
|
|
1261
|
-
|
|
1262
|
-
- id: artifact-grammar
|
|
1263
|
-
tier: core
|
|
1264
|
-
title: "Artifact Grammar"
|
|
1265
|
-
content: |
|
|
1266
|
-
## Artifact Grammar — The Generative Specification
|
|
1267
|
-
|
|
1268
|
-
A system achieves generative specification when any AI coding assistant, given access to
|
|
1269
|
-
its artifacts alone, can: correctly identify what should and should not change for any
|
|
1270
|
-
requirement; produce output conforming to architectural, quality, and behavioral contracts;
|
|
1271
|
-
and detect when any existing artifact violates those contracts.
|
|
1272
|
-
|
|
1273
|
-
Each artifact type below is a production rule in the system's grammar. Absent artifacts
|
|
1274
|
-
are specification gaps. A gap is not a documentation debt — it is an architecturally
|
|
1275
|
-
incomplete grammar.
|
|
1276
|
-
|
|
1277
|
-
| Artifact | Function in the System | Required |
|
|
1278
|
-
|---|---|---|
|
|
1279
|
-
| **Architectural constitution** (`CLAUDE.md` / `AGENTS.md` / `.cursor/rules/` / `.github/copilot-instructions.md`) | Defines what is and is not a valid sentence in this system. Governs every AI interaction. Agent-agnostic concept; filename is agent-specific. | Core |
|
|
1280
|
-
| **Architecture Decision Records (ADRs)** | Documents why the grammar evolved. Prevents the AI from "correcting" intentional decisions that appear suboptimal without context. | Core |
|
|
1281
|
-
| **C4 diagrams / structural diagrams** (PlantUML, Mermaid) | The parsed structural representation: system context, container topology, component composition. Static structure at a glance for any agent entering the codebase. **Emit as files in P1** — `docs/diagrams/c4-context.md` and `docs/diagrams/c4-container.md`. A diagram referenced in prose but not written to disk provides zero structural constraint. | Recommended |
|
|
1282
|
-
| **Sequence diagrams** | Fix the inter-component protocol: which call, in which order, with which contracts. A sequence diagram specifying that auth precedes data fetch is an unambiguous ordering constraint. The AI has two valid sentences: the one matching the diagram, and deviations from it. **Emit as `docs/diagrams/sequence-[feature].md` in P1** with real `participant` declarations and message arrows — not an empty file. | Recommended |
|
|
1283
|
-
| **State machine diagrams** | Enumerate every valid state and every valid transition. Directly generate state transition test cases and user-facing modal behavior documentation. **Emit as `docs/diagrams/state-[entity].md` in P1** with real `stateDiagram-v2` states and transitions — these become the source of truth for state transition tests. | When system has states |
|
|
1284
|
-
| **User flow diagrams** | Define the expected journey from entry to outcome. Simultaneously the script for every E2E test in that flow and the user journey narrative for the manual. **Emit as `docs/diagrams/flow-[usecase].md` in P1** with real `flowchart` Start/End nodes and decision diamonds. | Recommended |
|
|
1285
|
-
| **Use cases** | Single, precise descriptions of an interaction. One use case seeds three artifacts: implementation contract, acceptance test, user documentation. See `use-case-triple-derivation`. | Recommended |
|
|
1286
|
-
| **Schema definitions** (DB, API, events) | The vocabulary of the system with constraints formally stated. Types, relations, validation rules, value ranges. | Core |
|
|
1287
|
-
| **Living documentation** (derived) | OpenAPI from decorators/schemas; TypeDoc/JSDoc auto-published; Storybook from component specs; README sections from centralized specs. Documentation maintained separately from code drifts — documentation derived from the same artifacts cannot be wrong in a way the code is right. | Recommended |
|
|
1288
|
-
| **Naming conventions** (explicit in constitution) | Semantic signal at every token. `calculateMonthlyCostPerMember` carries domain, operation, unit, scope. `processData` carries nothing. Names are grammar; the AI propagates every name it reads. | Core |
|
|
1289
|
-
| **Package and module hierarchy** | Communicates responsibility and ownership through structure. The location of a file is a claim about what it is. | Core |
|
|
1290
|
-
| **Conventional atomic commits** | Typed corpus: `feat(billing): add prorated invoice calculation` has a part of speech, scope, and semantic payload. The git log is a readable history of how the grammar evolved and why. | Core |
|
|
1291
|
-
| **Test suite (adversarial)** | Each test is a specification assertion AND adversarial challenge. The suite is a continuously-running audit and standing challenge to the implementation. Written against interfaces, not implementations. | Core |
|
|
1292
|
-
| **Commit hooks and quality gates** | Malformed input is structurally rejected before entering the system. Certain classes of mistake are architecturally unreachable. | Core |
|
|
1293
|
-
| **Status.md** | Session bridge: current implementation state, what was completed, where the session stopped, what was tried. The Auditable property requires both that the record exists and that the next session begins by reading it. | Core |
|
|
1294
|
-
| **MCP tools and environment tooling** | The tools available to the agent define what operations are possible. Bounded tool access is bounded agency. Specification governs not just code but the system that can act. | Optional |
|
|
1295
|
-
|
|
1296
|
-
> **Emit, Don't Reference.** Every diagram type above that is marked "Recommended" or
|
|
1297
|
-
> higher must be written as a file on disk with real, parseable content. A spec that
|
|
1298
|
-
> says "a sequence diagram should be created later" is not a grammar production rule — it
|
|
1299
|
-
> is a forward reference. Forward references do not constrain the AI. Only emitted files
|
|
1300
|
-
> do. If a diagram file exists but still contains `<!-- UNFILLED -->`, it is a known gap.
|
|
1301
|
-
> Known gaps must be on the cascade backlog; they are not acceptable as a final state.
|
|
1302
|
-
|
|
1303
|
-
### The Six Properties (self-test)
|
|
1304
|
-
A generative specification satisfies all six. Use as an inspection checklist:
|
|
1305
|
-
- **Self-describing**: Does the system explain its own architecture, decisions, and conventions from its own artifacts?
|
|
1306
|
-
- **Bounded**: Does every unit have explicit scope and seams? Is the context window to modify any unit predictably bounded?
|
|
1307
|
-
- **Verifiable**: Can the correctness of any output be checked without human judgment? Is verification automatic, fast, and blocking?
|
|
1308
|
-
- **Defended**: Are destructive operations structurally prevented (hooks, gates) rather than merely discouraged?
|
|
1309
|
-
- **Auditable**: Is the current state and full history recoverable from artifacts alone? Would the AI treat an intentional decision as a defect to correct?
|
|
1310
|
-
- **Composable**: Can units be combined without unexpected coupling? Can the AI work on any unit in isolation because isolation is structural?
|
|
1311
|
-
|
|
1312
|
-
> **GS Protocol on demand:** call `get_reference(resource: guidance)` for the full
|
|
1313
|
-
> session-loop procedure, context-loading strategy, incremental cascade, bound roadmap
|
|
1314
|
-
> format, and diagnostic checklist. These procedures are NOT inlined here to preserve
|
|
1315
|
-
> the token budget of this instruction file.
|
|
1316
|
-
|
|
1317
|
-
- id: naming-as-grammar
|
|
1318
|
-
tier: core
|
|
1319
|
-
title: "Names Are Production Rules"
|
|
1320
|
-
content: |
|
|
1321
|
-
## Names Are Production Rules
|
|
1322
|
-
|
|
1323
|
-
In a context-sensitive system, naming is not style. It is grammar.
|
|
1324
|
-
|
|
1325
|
-
A function named `getUser` in a domain model that talks to a database is an architecture
|
|
1326
|
-
violation the compiler will not catch, the linter may not catch, and a human reviewer
|
|
1327
|
-
will tolerate — but the AI will propagate. The name signals layer; the AI reads the signal.
|
|
1328
|
-
|
|
1329
|
-
### Layer-Scoped Naming Vocabulary
|
|
1330
|
-
Enforce consistent naming by layer. Deviations are architecture violations.
|
|
1331
|
-
|
|
1332
|
-
| Layer | Allowed verbs / patterns | Examples |
|
|
1333
|
-
|---|---|---|
|
|
1334
|
-
| **Repository** | `find`, `save`, `delete`, `exists`, `count` | `findUserByEmail`, `saveOrder`, `deleteById` |
|
|
1335
|
-
| **Service** | `get`, `create`, `update`, `process`, `calculate`, `validate` | `getUserProfile`, `createInvoice`, `calculateMonthlyCost` |
|
|
1336
|
-
| **Controller / Handler** | `handle`, `on` + event name | `handleCreateUser`, `onPaymentReceived` |
|
|
1337
|
-
| **Domain model** | noun + computed property / behavior | `Invoice.totalWithTax`, `User.isExpired` |
|
|
1338
|
-
| **Event** | past tense, domain noun | `UserRegistered`, `OrderShipped`, `PaymentFailed` |
|
|
1339
|
-
| **DTO** | noun + `Request` / `Response` or `Dto` | `CreateUserRequest`, `UserProfileResponse` |
|
|
1340
|
-
| **Interface / Port** | capability noun | `UserRepository`, `EmailSender`, `PaymentGateway` |
|
|
1341
|
-
|
|
1342
|
-
### Naming as Technique Transport
|
|
1343
|
-
What a practitioner names in a specification, the AI knows how to apply.
|
|
1344
|
-
Every technique in the model's training corpus becomes available to any system whose
|
|
1345
|
-
specification names it. A specification that says "analyze legal arguments" receives
|
|
1346
|
-
legal analysis. A specification that names prosody, argumentation theory, fallacy
|
|
1347
|
-
classification, and deontic modal logic receives a specialist instrument calibrated
|
|
1348
|
-
to the domain. The naming cost is one word. The activation cost of the AI's knowledge
|
|
1349
|
-
of the field is zero once the name appears.
|
|
1350
|
-
|
|
1351
|
-
Name patterns, techniques, and domain frameworks explicitly in the architectural
|
|
1352
|
-
constitution. The specification is a technique registry whose scope is the full depth
|
|
1353
|
-
of the model's training, activated at the cost of knowing the correct words to write.
|
|
1354
|
-
|
|
1355
|
-
- id: adr-protocol
|
|
1356
|
-
tier: core
|
|
1357
|
-
title: "ADR Protocol"
|
|
1358
|
-
content: |
|
|
1359
|
-
## ADR Protocol — Persistent Memory
|
|
1360
|
-
|
|
1361
|
-
Every non-obvious architectural decision produces an ADR before implementation begins.
|
|
1362
|
-
An unrecorded architectural decision is a gap in the grammar.
|
|
1363
|
-
|
|
1364
|
-
Without an ADR, the AI will "improve" intentional decisions that appear suboptimal
|
|
1365
|
-
without context — turning deliberate architectural tradeoffs into silently-introduced drift.
|
|
1366
|
-
|
|
1367
|
-
### Format (minimal)
|
|
1368
|
-
```markdown
|
|
1369
|
-
# ADR-NNNN: [Decision Title]
|
|
1370
|
-
|
|
1371
|
-
**Date**: YYYY-MM-DD
|
|
1372
|
-
**Status**: Proposed | Accepted | Deprecated | Superseded by ADR-NNNN
|
|
1373
|
-
|
|
1374
|
-
## Context
|
|
1375
|
-
What is the situation that requires a decision? What forces are in tension?
|
|
1376
|
-
|
|
1377
|
-
## Decision
|
|
1378
|
-
What was decided? State it plainly.
|
|
1379
|
-
|
|
1380
|
-
## Alternatives Considered
|
|
1381
|
-
What other options were evaluated and why were they not chosen?
|
|
1382
|
-
|
|
1383
|
-
## Consequences
|
|
1384
|
-
What becomes easier or harder as a result of this decision?
|
|
1385
|
-
What will the AI need to know to work within this constraint?
|
|
1386
|
-
```
|
|
1387
|
-
|
|
1388
|
-
### When to Write an ADR
|
|
1389
|
-
- Any architectural choice that is not obvious from the code structure
|
|
1390
|
-
- Any decision that involves a tradeoff (performance vs. simplicity, security vs. UX)
|
|
1391
|
-
- Any decision that was reached after considering alternatives
|
|
1392
|
-
- Any decision that future engineers (or AI sessions) might be tempted to "fix"
|
|
1393
|
-
- Any change to the architectural constitution itself
|
|
1394
|
-
|
|
1395
|
-
### ADR Directory
|
|
1396
|
-
- Path: `docs/adrs/` (zero-padded, kebab-case: `ADR-0001-short-title.md`)
|
|
1397
|
-
- ADRs are immutable once Accepted. To change a decision: write a new ADR that supersedes the old one.
|
|
1398
|
-
- The old ADR is updated only to add `Superseded by ADR-NNNN` to its status.
|
|
1399
|
-
|
|
1400
|
-
### ADR Stubs — Emit in P1
|
|
1401
|
-
When starting a new project, emit ADR stub files as **fenced code blocks** in the first
|
|
1402
|
-
response alongside `prisma/schema.prisma`, `tsconfig.json`, and `package.json`.
|
|
1403
|
-
ADRs referenced only in a README but not written as files are not present in the project.
|
|
1404
|
-
The model cannot reference a file that does not exist. Emit the file.
|
|
1405
|
-
|
|
1406
|
-
**Minimum ADRs to emit in P1** (adapt titles to the actual stack chosen):
|
|
1407
|
-
- `docs/adrs/ADR-0001-stack.md` — language, runtime, framework, ORM selection and rationale
|
|
1408
|
-
- `docs/adrs/ADR-0002-authentication.md` — auth strategy (JWT/session), hashing algorithm and why
|
|
1409
|
-
- `docs/adrs/ADR-0003-architecture.md` — layered/hexagonal architecture decision and boundary rules
|
|
1410
|
-
|
|
1411
|
-
Each ADR stub must contain real content in `Status`, `Context`, `Decision`, and `Consequences`
|
|
1412
|
-
fields — not placeholder text. A stub that says "TBD" is not an ADR.
|
|
1413
|
-
|
|
1414
|
-
**ADR reference check:** If your README mentions `docs/adrs/ADR-0001-stack.md`, that file
|
|
1415
|
-
must appear as a fenced code block in the same response. A reference to a non-emitted file
|
|
1416
|
-
is an Auditable violation — it creates the appearance of traceability without the substance.
|
|
1417
|
-
|
|
1418
|
-
Also emit **`CHANGELOG.md`** in P1 with initial content documenting the P1 decisions:
|
|
1419
|
-
```markdown
|
|
1420
|
-
# Changelog
|
|
1421
|
-
All notable changes to this project will be documented here.
|
|
1422
|
-
Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
|
|
1423
|
-
|
|
1424
|
-
## [Unreleased]
|
|
1425
|
-
### Added
|
|
1426
|
-
- Initial project scaffold: layered architecture, Prisma schema, repository interfaces
|
|
1427
|
-
- Authentication: JWT + Argon2 (see ADR-0002)
|
|
1428
|
-
- Dependency registry: docs/approved-packages.md with audit baseline
|
|
1429
|
-
- CI pipeline: lint, type-check, test, npm audit, mutation gate
|
|
1430
|
-
- Pre-commit hooks: tsc, lint, audit, test gates
|
|
1431
|
-
```
|
|
1432
|
-
A CHANGELOG that exists only as "we will add one" is not Auditable. Write the file.
|
|
1433
|
-
Document the P1 decisions immediately — the first entry is not a release entry, it is the
|
|
1434
|
-
architectural record of what was built in this session.
|
|
1435
|
-
|
|
1436
|
-
### Session Protocol
|
|
1437
|
-
Every session begins by reading the open ADRs. The status of each ADR is the authoritative
|
|
1438
|
-
record of what is intentional. A session that modifies an ADR-governed boundary without
|
|
1439
|
-
first reading the ADR has produced drift, regardless of whether the code compiles.
|
|
1440
|
-
|
|
1441
|
-
- id: use-case-triple-derivation
|
|
1442
|
-
tier: recommended
|
|
1443
|
-
title: "Use Case Triple Derivation"
|
|
1444
|
-
content: |
|
|
1445
|
-
## Use Cases — Triple Derivation
|
|
1446
|
-
|
|
1447
|
-
A use case is not a requirements artifact produced before implementation and superseded by it.
|
|
1448
|
-
In a generative specification it is a multi-purpose production rule: a single, precise
|
|
1449
|
-
description of an interaction from which three artifacts derive independently and without
|
|
1450
|
-
redundancy.
|
|
1451
|
-
|
|
1452
|
-
### The Three Derivations
|
|
1453
|
-
1. **Implementation contract** — The use case names the actor, precondition, trigger, and
|
|
1454
|
-
postcondition with enough precision to be unambiguous. This is the specification the
|
|
1455
|
-
service layer is written against. When the AI reads a well-formed use case before
|
|
1456
|
-
generating the corresponding service method, it has what a human architect would
|
|
1457
|
-
communicate in a design review.
|
|
1458
|
-
|
|
1459
|
-
2. **Acceptance test** — The use case and the test scenario are the same artifact expressed
|
|
1460
|
-
in different dialects. A Playwright E2E test for a checkout flow is the checkout use case
|
|
1461
|
-
transcribed into executable form. A Cucumber scenario in Given-When-Then is the use case
|
|
1462
|
-
in declarative test notation. When the use case is precise, the test writes itself.
|
|
1463
|
-
**When the test is hard to write, the use case is underspecified.** The test difficulty
|
|
1464
|
-
is the diagnostic for underspecification.
|
|
1465
|
-
|
|
1466
|
-
3. **User documentation** — A use case narrated to a non-technical reader (actor, goal,
|
|
1467
|
-
precondition, sequence, expected outcome, error cases) is a user manual section.
|
|
1468
|
-
The content is identical. The framing is different. A specification with complete use
|
|
1469
|
-
cases does not need a separate documentation writing pass — it needs a rendering pass.
|
|
1470
|
-
|
|
1471
|
-
### Use Case Format (minimal)
|
|
1472
|
-
```markdown
|
|
1473
|
-
## UC-NNN: [Action] [Domain Object]
|
|
1474
|
-
|
|
1475
|
-
**Actor**: [who initiates]
|
|
1476
|
-
**Precondition**: [what must be true before]
|
|
1477
|
-
**Trigger**: [what event or action starts the flow]
|
|
1478
|
-
**Main Flow**:
|
|
1479
|
-
1. [Step one]
|
|
1480
|
-
2. [Step two]
|
|
1481
|
-
**Postcondition**: [what is true after success]
|
|
1482
|
-
**Error Cases**:
|
|
1483
|
-
- [Condition]: [System response]
|
|
1484
|
-
**Acceptance Criteria** (machine-checkable):
|
|
1485
|
-
- [ ] [Criterion 1]
|
|
1486
|
-
- [ ] [Criterion 2]
|
|
1487
|
-
```
|
|
1488
|
-
|
|
1489
|
-
### The Diagnostic Rule
|
|
1490
|
-
Before writing any service method, write the use case first. If you cannot state the
|
|
1491
|
-
precondition and postcondition precisely, you do not yet understand the behavior well enough
|
|
1492
|
-
to implement it correctly. The implementation will be wrong. The use case forces the
|
|
1493
|
-
understanding the implementation requires.
|
|
1494
|
-
|
|
1495
|
-
- id: living-documentation
|
|
1496
|
-
tier: recommended
|
|
1497
|
-
title: "Living Documentation"
|
|
1498
|
-
content: |
|
|
1499
|
-
## Living Documentation — Derived, Not Maintained
|
|
1500
|
-
|
|
1501
|
-
Documentation maintained separately from the code it describes is structurally certain
|
|
1502
|
-
to drift. An API reference written by hand becomes wrong the moment the signature changes.
|
|
1503
|
-
A system overview written at architecture time becomes misleading the moment the first
|
|
1504
|
-
refactor lands.
|
|
1505
|
-
|
|
1506
|
-
The failure is structural, not motivational. The documentation and the code share no source
|
|
1507
|
-
of truth. Drift is the natural consequence, not a failure of discipline.
|
|
1508
|
-
|
|
1509
|
-
### The Generative Specification Resolution
|
|
1510
|
-
Documentation is a derivation from the same artifacts the AI reads — which means it cannot
|
|
1511
|
-
be wrong in a way the code is right, because they share a source.
|
|
1512
|
-
|
|
1513
|
-
| Documentation type | Derivation source | Tooling |
|
|
1514
|
-
|---|---|---|
|
|
1515
|
-
| **API reference** | TypeScript type annotations + Zod schemas → OpenAPI/Swagger | `swagger-jsdoc`, `zod-to-openapi`, `ts-rest` |
|
|
1516
|
-
| **Function/class docs** | Inline JSDoc / docstrings, auto-published | TypeDoc, pdoc, mkdocs |
|
|
1517
|
-
| **Component catalog** | Component spec files | Storybook |
|
|
1518
|
-
| **README sections** | Centralized spec files, not narrative paragraphs | Custom scripts, code-gen templates |
|
|
1519
|
-
| **Database schema docs** | Prisma schema / migration files | `prisma-docs-generator` |
|
|
1520
|
-
| **Event catalog** | Event type definitions | AsyncAPI |
|
|
1521
|
-
| **Architecture diagrams** | Code structure → diagram | Structurizr, Mermaid auto-gen |
|
|
1522
|
-
|
|
1523
|
-
### Rules
|
|
1524
|
-
- Never write documentation that paraphrases code. If the doc says what the code says,
|
|
1525
|
-
one of them is redundant — and the code wins on recency.
|
|
1526
|
-
- Inline documentation (JSDoc/docstrings) belongs at the declaration, not in a separate file.
|
|
1527
|
-
- A README section that duplicates a type definition is a liability. Point to the type.
|
|
1528
|
-
- Documentation is a derivation step in the CI pipeline, not a separate task.
|
|
1529
|
-
|
|
1530
|
-
### Polyglot Systems
|
|
1531
|
-
The argument is sharpest when the system spans multiple languages, runtimes, or paradigms.
|
|
1532
|
-
Without a specification that holds naming contracts and behavioral contracts at the layer
|
|
1533
|
-
where they cross language lines, the system fragments. Cross-language interface contracts
|
|
1534
|
-
must be stated explicitly in language-neutral terms — the architectural constitution that
|
|
1535
|
-
both runtimes read.
|
|
1536
|
-
|
|
1537
|
-
- id: agentic-self-refinement
|
|
1538
|
-
tier: recommended
|
|
1539
|
-
title: "Agentic Self-Refinement"
|
|
1540
|
-
content: |
|
|
1541
|
-
## Agentic Self-Refinement
|
|
1542
|
-
|
|
1543
|
-
Wherever desired output can be specified and actual output can be observed, the agent
|
|
1544
|
-
can close a feedback loop on its own execution without human intervention between cycles.
|
|
1545
|
-
The structure is identical regardless of domain: desired state → generate → evaluate
|
|
1546
|
-
against spec-defined acceptance criteria → adjust parameters or session context → regenerate.
|
|
1547
|
-
|
|
1548
|
-
### The Loop Structure
|
|
1549
|
-
```
|
|
1550
|
-
SPECIFY → GENERATE → EVALUATE (against acceptance criteria)
|
|
1551
|
-
↑ |
|
|
1552
|
-
└──── ADJUST ────────┘
|
|
1553
|
-
(if criteria not met)
|
|
1554
|
-
```
|
|
1555
|
-
|
|
1556
|
-
The loop terminates when acceptance criteria are satisfied or retry budget is exhausted.
|
|
1557
|
-
The retry budget is itself a constraint in the specification.
|
|
1558
|
-
|
|
1559
|
-
### Applications by Domain
|
|
1560
|
-
| Domain | Generate | Evaluate | Adjust |
|
|
1561
|
-
|---|---|---|---|
|
|
1562
|
-
| **Code** | Service method | Tests pass / coverage / mutation score | Refactor implementation |
|
|
1563
|
-
| **Visual assets** | Sprite/image | Symmetry, orientation, background checks | Regenerate with refined prompt |
|
|
1564
|
-
| **Audio assets** | Sound / music | LUFS, frequency profile, artifact detection | Regenerate with adjusted parameters |
|
|
1565
|
-
| **Infrastructure** | Cloud resources | Health checks, policy compliance | Reconfigure and redeploy |
|
|
1566
|
-
| **Hyperparameter optimization** | Model training run | Win rate, drawdown, Sharpe threshold | Adjust classifier weights, retry |
|
|
1567
|
-
| **Session continuity** | Prior session output | Specification conformance on resume | Adjust strategy before proceeding |
|
|
1568
|
-
|
|
1569
|
-
### Session Continuity Pattern (Status.md)
|
|
1570
|
-
The Status.md file is the simplest form of agentic self-evaluation. A subsequent session
|
|
1571
|
-
begins not from a blank context but from a specification-informed account of what the
|
|
1572
|
-
prior session achieved, where it stopped, and what it tried. The agent evaluates its
|
|
1573
|
-
own prior output against the specification before beginning new work.
|
|
1574
|
-
- End of every session: update Status.md with completed work, current state, open questions.
|
|
1575
|
-
- Start of every session: read Status.md and open ADRs before any implementation.
|
|
1576
|
-
- The Auditable property requires both: that the record exists, and that the next session
|
|
1577
|
-
begins by reading it.
|
|
1578
|
-
|
|
1579
|
-
### Wrong History Pattern (Anti-Pattern)
|
|
1580
|
-
An audit trail that exists but is not read as state is equivalent to an absent audit trail.
|
|
1581
|
-
If the resume logic calculates from scratch rather than reading persisted state, the prior
|
|
1582
|
-
session's work is invisible — despite full persistence. The artifact was not absent; it was
|
|
1583
|
-
not consulted. Both conditions are violations of the Auditable property.
|
|
1584
|
-
|
|
1585
|
-
- id: wrong-specification-risk
|
|
1586
|
-
tier: recommended
|
|
1587
|
-
title: "Wrong Specification Risk"
|
|
1588
|
-
content: |
|
|
1589
|
-
## Wrong Specification Risk
|
|
1590
|
-
|
|
1591
|
-
The most important risk of generative specification is not an underspecified system — it
|
|
1592
|
-
is a *wrongly* specified one. A faithful AI executing a flawed architectural constitution
|
|
1593
|
-
will produce flawed code at scale, with high confidence and no complaint. The specification
|
|
1594
|
-
being a well-formed grammar does not guarantee it is the *right* grammar.
|
|
1595
|
-
|
|
1596
|
-
### Mitigation 1: Specification Verification Before Code
|
|
1597
|
-
The specification should face the same verification discipline as the implementation.
|
|
1598
|
-
Before any code is written:
|
|
1599
|
-
- Write concrete behavioral outcomes and make them checkable (acceptance criteria, ADRs
|
|
1600
|
-
with stated consequences).
|
|
1601
|
-
- If the stated rationale for a decision does not survive being written down (the "would
|
|
1602
|
-
I defend this in a code review?" test), the decision is not sound.
|
|
1603
|
-
- If the use case cannot be stated with a clear precondition and postcondition, the
|
|
1604
|
-
requirement is not understood well enough to specify correctly.
|
|
1605
|
-
|
|
1606
|
-
### Mitigation 2: Living Specification
|
|
1607
|
-
The architectural constitution is a living document, revised through the same atomic
|
|
1608
|
-
commit discipline as the code it governs.
|
|
1609
|
-
- An architectural constitution written at project inception and never revisited is a
|
|
1610
|
-
static grammar for a living system.
|
|
1611
|
-
- The ADR record documents when and why the grammar must change — making changes
|
|
1612
|
-
visible, intentional, and recoverable.
|
|
1613
|
-
- A specification change follows the same protocol as a code change: one ADR, one
|
|
1614
|
-
commit, one clear reason.
|
|
1615
|
-
|
|
1616
|
-
### Diagnostic Signs of a Wrong Specification
|
|
1617
|
-
- The AI produces code that compiles, passes tests, and violates architectural intent.
|
|
1618
|
-
(Tests are not testing architecture; the architectural constitution is not specific enough.)
|
|
1619
|
-
- The same class of mistake recurs across sessions.
|
|
1620
|
-
(The correction belongs in the architectural constitution, not the session prompt.)
|
|
1621
|
-
- The AI "improves" a known intentional decision.
|
|
1622
|
-
(The ADR is missing or was not included in the session context.)
|
|
1623
|
-
- Two modules with different responsibilities share a boundary that is not explicitly stated.
|
|
1624
|
-
(The Bounded property is violated; the constitution needs explicit module boundaries.)
|
|
1625
|
-
|
|
1626
|
-
- id: gs-five-memory-types
|
|
1627
|
-
tier: core
|
|
1628
|
-
title: "GS — Five Memory Types"
|
|
1629
|
-
content: |
|
|
1630
|
-
## Generative Specification: The Five Memory Types
|
|
1631
|
-
|
|
1632
|
-
An AI assistant has no persistent memory across sessions. The methodology distributes
|
|
1633
|
-
memory across five artifact classes, each serving a distinct cognitive function. Every
|
|
1634
|
-
artifact in a well-formed specification belongs to exactly one type. When an artifact
|
|
1635
|
-
is ambiguous about which type it serves, it is trying to do too much and will do none well.
|
|
1636
|
-
|
|
1637
|
-
| Memory Type | Cognitive Function | Primary Artifacts |
|
|
1638
|
-
|---|---|---|
|
|
1639
|
-
| **Semantic** | What the system *is* — identity, contracts, constraints | `CLAUDE.md`, tech spec, domain models, glossary |
|
|
1640
|
-
| **Procedural** | *How* things are done — execution rules, pipelines, bound prompts | `DEVELOPMENT_PROMPTS.md`, roadmap, CI/CD spec, commit hooks |
|
|
1641
|
-
| **Episodic** | What *happened* — decisions, sessions completed, history | ADRs, `Status.md`, session summaries, git commit log |
|
|
1642
|
-
| **Relationship** | *How things connect* — topology, flows, protocols | C4 diagrams, sequence diagrams, state machines, use cases |
|
|
1643
|
-
| **Working** | What is *active now* — current task, loaded context, scope | Session prompt, loaded artifacts, clarification state |
|
|
1644
|
-
|
|
1645
|
-
### Missing Types = Compounding Failure
|
|
1646
|
-
- **Semantic absent** → no grammar; output is locally correct and globally incoherent.
|
|
1647
|
-
- **Procedural absent** → each session starts from scratch; nothing is reproducible.
|
|
1648
|
-
- **Episodic absent** → decisions are repeated or overwritten; intentional choices become drift.
|
|
1649
|
-
- **Relationship absent** → inter-component contracts are implicit; integration points drift.
|
|
1650
|
-
- **Working absent (not loaded)** → the current session inherits no context; practitioner re-narrates everything.
|
|
1651
|
-
|
|
1652
|
-
A project missing all five types is using interactive prompting with no structural discipline.
|
|
1653
|
-
Use the five types as a diagnostic before beginning any session on an inherited project.
|
|
1654
|
-
|
|
1655
|
-
- id: gs-status-format
|
|
1656
|
-
tier: core
|
|
1657
|
-
title: "GS — Status.md Format"
|
|
1658
|
-
content: |
|
|
1659
|
-
## Status.md — Required Format
|
|
1660
|
-
|
|
1661
|
-
Status.md is the episodic artifact closest to working memory. Updated at the close of
|
|
1662
|
-
every session, without exception. The "Next" section is the handoff: specific enough
|
|
1663
|
-
that an agent could begin from it alone, without any narration.
|
|
1664
|
-
|
|
1665
|
-
```markdown
|
|
1666
|
-
# [Project Name] — Status
|
|
1667
|
-
|
|
1668
|
-
**Last updated:** YYYY-MM-DD
|
|
1669
|
-
**Current version / branch:**
|
|
1670
|
-
|
|
1671
|
-
## Completed (this session)
|
|
1672
|
-
- [What was done, with commit hashes where relevant]
|
|
1673
|
-
|
|
1674
|
-
## In Progress
|
|
1675
|
-
- [Partial state — what the immediate next step is]
|
|
1676
|
-
|
|
1677
|
-
## Next
|
|
1678
|
-
- [The immediate next action — specific enough to begin from this line alone]
|
|
1679
|
-
- Example: "Implement `updateConnectionStatus` in `src/connections/service.ts`,
|
|
1680
|
-
write tests for the three state transition paths, verify against `/connections/:id/status`"
|
|
1681
|
-
|
|
1682
|
-
## Decisions made (this session)
|
|
1683
|
-
- [Any choice not yet in an ADR — these are ADR candidates]
|
|
1684
|
-
|
|
1685
|
-
## Blockers / Dependencies
|
|
1686
|
-
- [What is waiting on an external input or a parallel workstream]
|
|
1687
|
-
```
|
|
1688
|
-
|
|
1689
|
-
A vague "Next" entry ("continue working on the feature") forces the next session to
|
|
1690
|
-
reconstruct intent. A specific "Next" entry enables a cold start from the artifact alone.
|
|
1691
|
-
The "Next" section is the primary quality measure of Status.md.
|
|
1692
|
-
|
|
1
|
+
tag: UNIVERSAL
|
|
2
|
+
section: instructions
|
|
3
|
+
blocks:
|
|
4
|
+
- id: project-identity
|
|
5
|
+
tier: core
|
|
6
|
+
title: "Project Identity"
|
|
7
|
+
content: |
|
|
8
|
+
## Project Identity
|
|
9
|
+
- **Repo**: {{repo_url}}
|
|
10
|
+
- **Primary Language**: {{language}}
|
|
11
|
+
- **Framework**: {{framework}}
|
|
12
|
+
- **Domain**: {{domain}}
|
|
13
|
+
- **Sensitive Data**: {{sensitive_data}}
|
|
14
|
+
- **Project Tags**: {{tags}}
|
|
15
|
+
- **Release Phase**: {{release_phase | default: development}}
|
|
16
|
+
|
|
17
|
+
- id: code-standards
|
|
18
|
+
tier: core
|
|
19
|
+
title: "Code Standards"
|
|
20
|
+
content: |
|
|
21
|
+
## Code Standards
|
|
22
|
+
- Maximum function/method length: {{max_function_length | default: 50}} lines. If a function reads like it does two things, decompose it.
|
|
23
|
+
- Split a file when you find yourself using "and" to describe what it does — not when it hits a line count.
|
|
24
|
+
- Maximum function parameters: {{max_function_params | default: 5}}. If more, use a parameter object.
|
|
25
|
+
- No circular imports — module dependency graph must be acyclic (hook-enforced).
|
|
26
|
+
{{#if language_is_typescript}}- `tsconfig.json` must include `"strict": true` AND `"noUncheckedIndexedAccess": true`.
|
|
27
|
+
`strict: true` alone does not narrow `process.env.*` from `string | undefined` — the second flag is required
|
|
28
|
+
to catch unguarded environment variable access at compile time.{{/if}}
|
|
29
|
+
- Every public function/method must have {{#if language_is_typescript}}a JSDoc comment{{/if}}{{#if language_is_python}}a docstring (Google or NumPy style){{/if}} with typed params and returns.
|
|
30
|
+
- Delete orphaned code. Do not comment it out. Git has history.
|
|
31
|
+
- Before creating a new utility, search the entire codebase for existing ones.
|
|
32
|
+
- Reuse existing patterns — check shared modules before writing new.
|
|
33
|
+
- No abbreviations in names except universally understood ones (id, url, http, db, api).
|
|
34
|
+
- All names must be intention-revealing. If you need a comment to explain what a variable
|
|
35
|
+
holds, the name is wrong.
|
|
36
|
+
|
|
37
|
+
- id: dev-environment-hygiene
|
|
38
|
+
tier: core
|
|
39
|
+
title: "Dev Environment Hygiene"
|
|
40
|
+
content: |
|
|
41
|
+
## Dev Environment Hygiene
|
|
42
|
+
|
|
43
|
+
AI-assisted development can silently fill disk space. These rules are non-negotiable.
|
|
44
|
+
A full disk kills every running tool simultaneously — VS Code, Docker, the terminal, the DB.
|
|
45
|
+
|
|
46
|
+
### VS Code Extensions
|
|
47
|
+
- Before installing any extension: `code --list-extensions | grep -i <name>`.
|
|
48
|
+
- Only install if no version in the required major range is already present.
|
|
49
|
+
- Never run `code --install-extension` unconditionally in scripts or setup steps.
|
|
50
|
+
- Installing the same extension twice on the same day = a bug in your script.
|
|
51
|
+
|
|
52
|
+
### Docker Containers & Volumes
|
|
53
|
+
- Check before creating: `docker ps -a --filter name=<service>` — if it exists, start it, don't create it.
|
|
54
|
+
- Prefer `docker compose up` (reuse) over bare `docker run` (always creates new).
|
|
55
|
+
- One Compose file per project. Split files for the same project = tech debt.
|
|
56
|
+
- Log pruning: run `docker system prune -f` periodically. Never let container logs exceed 500 MB total.
|
|
57
|
+
- Time-series or synthetic data volumes: before writing >100 MB, ask whether raw retention,
|
|
58
|
+
statistical condensation, or deletion after the run is preferred.
|
|
59
|
+
- Synthetic datasets older than 7 days with no code reference: ask to delete.
|
|
60
|
+
|
|
61
|
+
### Python Virtual Environments
|
|
62
|
+
- One `.venv` per project root, one per standalone package subdirectory — never more.
|
|
63
|
+
- Before creating: check if `.venv/` exists and `python --version` matches the required major.minor.
|
|
64
|
+
Recreate only on major version mismatch or explicit user request.
|
|
65
|
+
- Never create a venv in a subdirectory unless that directory is a standalone installable package.
|
|
66
|
+
- Sanitize dependencies: if `pip list --not-required` reveals packages not in requirements, flag them.
|
|
67
|
+
|
|
68
|
+
### General Install Hygiene
|
|
69
|
+
- Before any install/download: check version already installed. Skip if within the required range.
|
|
70
|
+
- If project directory disk usage outside of `node_modules/`, `.venv/`, `dist/`, `.next/`
|
|
71
|
+
exceeds 2 GB: surface a warning and ask before continuing any file-generating operation.
|
|
72
|
+
- Never silently grow the workspace. When uncertain about retention, ask.
|
|
73
|
+
|
|
74
|
+
- id: dependency-registry
|
|
75
|
+
tier: core
|
|
76
|
+
title: "Dependency Registry"
|
|
77
|
+
content: |
|
|
78
|
+
## Dependency Registry — AI-Maintained Security Contract
|
|
79
|
+
|
|
80
|
+
The project's approved dependency set is a **living GS artifact maintained by the AI
|
|
81
|
+
assistant**. It is not a template rule — template authors cannot predict which library
|
|
82
|
+
will gain a CVE next quarter. The AI can run an audit at the moment a dependency is
|
|
83
|
+
about to be added. This block prescribes that it must.
|
|
84
|
+
|
|
85
|
+
### The registry artifact
|
|
86
|
+
|
|
87
|
+
File: **`docs/approved-packages.md`** — emit in P1 alongside schema, tsconfig, package.json.
|
|
88
|
+
Update it every time a dependency is added or upgraded. If it exists only in prose or a
|
|
89
|
+
README reference, it does not exist.
|
|
90
|
+
|
|
91
|
+
```markdown
|
|
92
|
+
# Approved Packages
|
|
93
|
+
|
|
94
|
+
| Package | Version range | Purpose | Alternatives rejected | Rationale | Audit status |
|
|
95
|
+
|---|---|---|---|---|---|
|
|
96
|
+
| example-pkg | ^2.4 | HTTP client | axios (larger bundle), node-fetch (no TS types) | Wide adoption, zero known CVEs | 0 HIGH/CRITICAL |
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
The AI populates every row. The registry is the authoritative record of WHY each
|
|
100
|
+
dependency was chosen and that it was clean at the time of addition.
|
|
101
|
+
|
|
102
|
+
### Process rules — stack-agnostic
|
|
103
|
+
|
|
104
|
+
1. **Before adding any package**: run the project's audit command (see table below)
|
|
105
|
+
with `--dry-run` or equivalent to check the candidate for known CVEs.
|
|
106
|
+
- If HIGH or CRITICAL found: choose an alternative and document the rejection.
|
|
107
|
+
- If no CVE-free alternative exists: document the accepted risk and create an ADR
|
|
108
|
+
naming the approver. Zero-tolerance is the default; exceptions require a record.
|
|
109
|
+
2. **After adding a package**: add a row to `docs/approved-packages.md` with audit status.
|
|
110
|
+
3. **Commit gate**: the pre-commit hook runs the audit command. HIGH or CRITICAL blocks
|
|
111
|
+
the commit. If audit is not in the pre-commit hook, the gate does not exist.
|
|
112
|
+
4. **Version pins**: approved version ranges are locked in the lockfile (package-lock.json,
|
|
113
|
+
uv.lock, Cargo.lock). The lockfile is committed. Ranges without a lockfile are not pins.
|
|
114
|
+
|
|
115
|
+
### Audit commands by ecosystem
|
|
116
|
+
|
|
117
|
+
| Ecosystem | Audit command | Threshold |
|
|
118
|
+
|---|---|---|
|
|
119
|
+
| npm / Node.js | `npm audit --audit-level=high` | HIGH or CRITICAL |
|
|
120
|
+
| pnpm | `pnpm audit --audit-level=high` | HIGH or CRITICAL |
|
|
121
|
+
| yarn | `yarn npm audit --severity high` | HIGH or CRITICAL |
|
|
122
|
+
| Python / pip | `pip-audit --fail-on-severity high` | HIGH or CRITICAL |
|
|
123
|
+
| Python / uv | `uv audit` | HIGH or CRITICAL |
|
|
124
|
+
| Rust | `cargo audit` | HIGH or CRITICAL |
|
|
125
|
+
| Go | `govulncheck ./...` | Any directly imported |
|
|
126
|
+
| Java / Maven | `mvn dependency-check:check -DfailBuildOnCVSS=7` | CVSS ≥ 7 |
|
|
127
|
+
| Ruby | `bundle audit` | HIGH or CRITICAL |
|
|
128
|
+
|
|
129
|
+
The correct command for **this project's ecosystem** must appear in the pre-commit hook
|
|
130
|
+
emitted in P1. Discovering CVEs at code review is too late.
|
|
131
|
+
|
|
132
|
+
- id: language-stack-constraints
|
|
133
|
+
tier: core
|
|
134
|
+
title: "Language Stack Constraints"
|
|
135
|
+
content: |
|
|
136
|
+
## Language Stack Constraints — Seed Defaults
|
|
137
|
+
|
|
138
|
+
These are **starting defaults for {{language}} projects** — use them to populate the
|
|
139
|
+
initial rows of `docs/approved-packages.md` in P1. They are not a permanent approved
|
|
140
|
+
list: the AI maintains the registry from here forward, keeps versions current, and
|
|
141
|
+
replaces any entry that develops a known CVE. The Dependency Registry block above
|
|
142
|
+
governs the process.
|
|
143
|
+
|
|
144
|
+
Before adding any dependency not listed here, apply the audit-before-add process.
|
|
145
|
+
|
|
146
|
+
{{#if language_is_typescript}}
|
|
147
|
+
### TypeScript / Node.js — Approved Toolchain
|
|
148
|
+
|
|
149
|
+
**Runtime & compiler**
|
|
150
|
+
- Node.js: `^20 LTS` minimum. NOT `^16` or `^18` (EOL or near-EOL).
|
|
151
|
+
- TypeScript: `^5.4` minimum. `tsconfig.json` must include `"strict": true` AND
|
|
152
|
+
`"noUncheckedIndexedAccess": true`. The second flag is required to narrow
|
|
153
|
+
`process.env.*` from `string | undefined` at compile time.
|
|
154
|
+
|
|
155
|
+
**Linting**
|
|
156
|
+
- `eslint@^9` + `@typescript-eslint/eslint-plugin@^8` + `@typescript-eslint/parser@^8`
|
|
157
|
+
- NOT `@typescript-eslint@^5` or `^6` — old `minimatch` transitive dep has known CVEs.
|
|
158
|
+
- NOT `tslint` — deprecated.
|
|
159
|
+
|
|
160
|
+
**Test runner**
|
|
161
|
+
- `vitest@^2` (preferred — native ESM, fast, Jest-compatible API) or `jest@^29`.
|
|
162
|
+
- NOT `mocha` + `chai` for new projects (weaker TypeScript support).
|
|
163
|
+
- NOT `jasmine` (no active maintenance for Node.js use).
|
|
164
|
+
|
|
165
|
+
**Formatting**
|
|
166
|
+
- `prettier@^3` — configured via `.prettierrc`, integrated with ESLint via
|
|
167
|
+
`eslint-config-prettier`. NOT separate manual formatting.
|
|
168
|
+
{{/if}}
|
|
169
|
+
|
|
170
|
+
{{#if language_is_python}}
|
|
171
|
+
### Python — Approved Toolchain
|
|
172
|
+
|
|
173
|
+
**Runtime**
|
|
174
|
+
- Python `^3.11` minimum. NOT `3.8` or `3.9` for new projects — `3.11+` brings
|
|
175
|
+
`tomllib` builtin, `ExceptionGroup`, and significant performance improvements.
|
|
176
|
+
|
|
177
|
+
**Linting / formatting**
|
|
178
|
+
- `ruff@^0.4` — replaces `flake8` + `isort` + `black` with a single 10–100× faster tool.
|
|
179
|
+
- NOT separate `flake8` + `isort` + `black` for new projects.
|
|
180
|
+
|
|
181
|
+
**Type checking**
|
|
182
|
+
- `pyright@^1.1` (strict mode) — same engine as Pylance, best TypedDict support.
|
|
183
|
+
- `mypy@^1.9` is acceptable. Strict mode required in both cases.
|
|
184
|
+
- NOT unchecked Python — all public functions must be typed.
|
|
185
|
+
|
|
186
|
+
**Test runner**
|
|
187
|
+
- `pytest@^8` — NOT `unittest` for new projects.
|
|
188
|
+
- Async tests: `pytest-asyncio@^0.23`.
|
|
189
|
+
|
|
190
|
+
**Dependency management**
|
|
191
|
+
- `uv@^0.1` (recommended — fastest resolver) or `poetry@^1.7`.
|
|
192
|
+
- ALL dependencies pinned in lockfile (`uv.lock` or `poetry.lock`). Lockfile committed.
|
|
193
|
+
- `pip-tools` acceptable for library projects.
|
|
194
|
+
{{/if}}
|
|
195
|
+
|
|
196
|
+
- id: production-code-standards
|
|
197
|
+
tier: core
|
|
198
|
+
title: "Production Code Standards"
|
|
199
|
+
content: |
|
|
200
|
+
## Production Code Standards — NON-NEGOTIABLE
|
|
201
|
+
|
|
202
|
+
These apply to ALL code including prototypes. "It's just a prototype" is never a valid
|
|
203
|
+
exception. Prototypes become production code within days at CC development speed.
|
|
204
|
+
|
|
205
|
+
### SOLID Principles
|
|
206
|
+
- **Single Responsibility**: One module = one reason to change. Use "and" to describe it? Split it.
|
|
207
|
+
- **Open/Closed**: Extend via interfaces and composition. Never modify working code for new behavior.
|
|
208
|
+
- **Liskov Substitution**: Any interface implementation must be fully swappable. No isinstance checks.
|
|
209
|
+
- **Interface Segregation**: Small focused interfaces. No god-interfaces.
|
|
210
|
+
- **Dependency Inversion**: Depend on abstractions. Concrete classes are injected, never instantiated
|
|
211
|
+
inside business logic. **In practice**: define `IUserRepository`, `IOrderRepository`,
|
|
212
|
+
`IEmailSender` etc. as interfaces in the domain/service layer first. Services depend on
|
|
213
|
+
the interface. The Prisma/SQL/HTTP concrete implementation lives in the adapter layer and
|
|
214
|
+
is injected at the composition root. Emit these interfaces in P1 alongside the schema —
|
|
215
|
+
a service that imports a concrete class cannot be unit-tested, cannot be swapped, and
|
|
216
|
+
is not Composable.
|
|
217
|
+
|
|
218
|
+
### Zero Hardcoded Values
|
|
219
|
+
- ALL configuration through environment variables or config files. No exceptions.
|
|
220
|
+
- ALL external URLs, ports, credentials, thresholds, feature flags must be configurable.
|
|
221
|
+
- ALL magic numbers must be named constants with documentation.
|
|
222
|
+
- Config is validated at startup — fail fast if required values are missing.
|
|
223
|
+
|
|
224
|
+
### Zero Mocks in Application Code
|
|
225
|
+
- No mock objects, fake data, or stub responses in source code. Ever.
|
|
226
|
+
- Mocks belong ONLY in test files.
|
|
227
|
+
- For local dev: create proper interface implementations selected via config.
|
|
228
|
+
- No `if DEBUG: return fake_data` patterns. Use dependency injection to swap implementations.
|
|
229
|
+
- No TODO/FIXME stubs returning hardcoded values. Use NotImplementedError with a description.
|
|
230
|
+
|
|
231
|
+
### Interfaces First
|
|
232
|
+
Before writing any implementation:
|
|
233
|
+
1. Define the interface/protocol/abstract class
|
|
234
|
+
2. Define the data contracts (input/output DTOs)
|
|
235
|
+
3. Write the consuming code against the interface
|
|
236
|
+
4. Write tests against the interface
|
|
237
|
+
5. THEN implement the concrete class
|
|
238
|
+
|
|
239
|
+
### Dependency Injection
|
|
240
|
+
- Every service receives dependencies through its constructor.
|
|
241
|
+
- A composition root (main.py / app.ts / container) wires everything.
|
|
242
|
+
- No service locator pattern. No global singletons. No module-level instances.
|
|
243
|
+
|
|
244
|
+
### Error Handling
|
|
245
|
+
- Custom exception hierarchy per module. No bare Exception raises.
|
|
246
|
+
- Errors carry context: IDs, timestamps, operation names.
|
|
247
|
+
- Fail fast, fail loud. No silent swallowing of exceptions.
|
|
248
|
+
- Domain code never returns HTTP status codes — that's the API layer's job.
|
|
249
|
+
|
|
250
|
+
### Modular from Day One
|
|
251
|
+
- Feature-based modules over layer-based. Each feature owns its models, service, repository, routes.
|
|
252
|
+
- Module dependency graph must be acyclic.
|
|
253
|
+
- Every module has a clear public API via {{#if language_is_typescript}}index.ts{{/if}}{{#if language_is_python}}__init__.py{{/if}} exports.
|
|
254
|
+
|
|
255
|
+
- id: layered-architecture
|
|
256
|
+
tier: recommended
|
|
257
|
+
title: "Layered Architecture"
|
|
258
|
+
content: |
|
|
259
|
+
## Layered Architecture (Ports & Adapters / Hexagonal)
|
|
260
|
+
|
|
261
|
+
```
|
|
262
|
+
┌─────────────────────────────┐
|
|
263
|
+
│ API / CLI / Event Handlers │ ← Thin. Validation + delegation only. No logic.
|
|
264
|
+
├─────────────────────────────┤ These are DRIVING ADAPTERS (primary).
|
|
265
|
+
│ Services (Business Logic) │ ← Orchestration. Depends on PORT INTERFACES only.
|
|
266
|
+
├─────────────────────────────┤
|
|
267
|
+
│ Domain Models │ ← Pure data + behavior. No I/O. No framework imports.
|
|
268
|
+
│ (Entities, Value Objects) │ The inner hexagon. Zero external dependencies.
|
|
269
|
+
├─────────────────────────────┤
|
|
270
|
+
│ Port Interfaces │ ← Abstract contracts (Repository, Gateway, Notifier).
|
|
271
|
+
│ │ Defined by the domain, implemented by adapters.
|
|
272
|
+
├─────────────────────────────┤
|
|
273
|
+
│ Repositories / Adapters │ ← DRIVEN ADAPTERS (secondary). All external I/O
|
|
274
|
+
│ │ (DB, APIs, files, queues, email, caches).
|
|
275
|
+
├─────────────────────────────┤
|
|
276
|
+
│ Infrastructure / Config │ ← DI container, env config, connection factories
|
|
277
|
+
└─────────────────────────────┘
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Ports (Interfaces owned by the domain)
|
|
281
|
+
- **Repository ports**: `UserRepository`, `OrderRepository` — data persistence contracts.
|
|
282
|
+
- **Gateway ports**: `PaymentGateway`, `EmailSender` — external service contracts.
|
|
283
|
+
- Ports are defined in the domain/service layer, never in the adapter layer.
|
|
284
|
+
- Port interfaces specify WHAT, never HOW.
|
|
285
|
+
|
|
286
|
+
### Adapters (Implementations of ports)
|
|
287
|
+
- **Driving adapters** (primary): HTTP controllers, CLI handlers, message consumers
|
|
288
|
+
— they CALL the application through port interfaces.
|
|
289
|
+
- **Driven adapters** (secondary): PostgresUserRepository, StripePaymentGateway,
|
|
290
|
+
SESEmailSender — they ARE CALLED BY the application through port interfaces.
|
|
291
|
+
- Adapters are interchangeable. Swap `PostgresUserRepository` for `InMemoryUserRepository`
|
|
292
|
+
in tests without changing a single line of business logic.
|
|
293
|
+
|
|
294
|
+
### Data Transfer Objects (DTOs)
|
|
295
|
+
- Use DTOs at layer boundaries — never pass domain entities to/from the API layer.
|
|
296
|
+
- **Request DTOs**: validated at the API boundary ({{#if language_is_typescript}}Zod schema{{/if}}{{#if language_is_python}}Pydantic model{{/if}} → typed object).
|
|
297
|
+
- **Response DTOs**: shaped for the consumer, not mirroring the domain model.
|
|
298
|
+
- **Domain ↔ Persistence mapping**: repositories map between domain entities and DB rows/documents.
|
|
299
|
+
- DTOs are plain data objects — no methods, no behavior, no framework decorators.
|
|
300
|
+
|
|
301
|
+
### Layer Rules
|
|
302
|
+
- Never skip layers. API handlers do not call repositories directly.
|
|
303
|
+
- Dependencies point INWARD only. Inner layers never import from outer layers.
|
|
304
|
+
- Domain models have ZERO external dependencies.
|
|
305
|
+
- The domain layer does not know HTTP, SQL, or any framework exists.
|
|
306
|
+
|
|
307
|
+
- id: clean-code-principles
|
|
308
|
+
tier: recommended
|
|
309
|
+
title: "Clean Code Principles"
|
|
310
|
+
content: |
|
|
311
|
+
## Clean Code Principles
|
|
312
|
+
|
|
313
|
+
### Command-Query Separation (CQS)
|
|
314
|
+
- **Commands** change state but return nothing (void).
|
|
315
|
+
- **Queries** return data but change nothing (no side effects).
|
|
316
|
+
- A function should do one or the other, never both.
|
|
317
|
+
- Exception: stack.pop() style operations where separation is impractical — document why.
|
|
318
|
+
|
|
319
|
+
### Guard Clauses & Early Return
|
|
320
|
+
- Eliminate deep nesting. Handle invalid cases first, return early.
|
|
321
|
+
- The happy path runs at the shallowest indentation level.
|
|
322
|
+
- Before:
|
|
323
|
+
```
|
|
324
|
+
if (user) {
|
|
325
|
+
if (user.isActive) {
|
|
326
|
+
if (user.hasPermission) {
|
|
327
|
+
// actual logic buried 3 levels deep
|
|
328
|
+
```
|
|
329
|
+
- After:
|
|
330
|
+
```
|
|
331
|
+
if (!user) throw new NotFoundError(...);
|
|
332
|
+
if (!user.isActive) throw new InactiveError(...);
|
|
333
|
+
if (!user.hasPermission) throw new ForbiddenError(...);
|
|
334
|
+
// actual logic at top level
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
### Composition over Inheritance
|
|
338
|
+
- Prefer composing objects via interfaces and delegation over class inheritance.
|
|
339
|
+
- Inheritance creates tight coupling and fragile hierarchies.
|
|
340
|
+
- Use inheritance ONLY for genuine "is-a" relationships (rare).
|
|
341
|
+
- When in doubt, compose: inject a collaborator, don't extend a base class.
|
|
342
|
+
|
|
343
|
+
### Law of Demeter (Principle of Least Knowledge)
|
|
344
|
+
- A method should only call methods on: its own object, its parameters, objects it creates,
|
|
345
|
+
its direct dependencies.
|
|
346
|
+
- Do NOT chain through objects: `order.getCustomer().getAddress().getCity()` — BAD.
|
|
347
|
+
- Instead: `order.getShippingCity()` or pass the needed data directly.
|
|
348
|
+
|
|
349
|
+
### Immutability by Default
|
|
350
|
+
{{#if language_is_typescript}}- Use `const` over `let`. Use `readonly` on properties and parameters.
|
|
351
|
+
- Prefer `ReadonlyArray<T>`, `Readonly<T>`, `ReadonlyMap`, `ReadonlySet`.{{/if}}{{#if language_is_python}}- Use `Final` for constants. Use `frozen=True` on dataclasses.
|
|
352
|
+
- Prefer `tuple` over `list` for immutable sequences. Use `MappingProxyType` for immutable dicts.{{/if}}
|
|
353
|
+
- When you need to "modify" data, create a new copy with the change.
|
|
354
|
+
- Mutable state is the #1 source of bugs. Restrict it to the smallest possible scope.
|
|
355
|
+
|
|
356
|
+
### Pure Functions
|
|
357
|
+
- A pure function: same inputs → same outputs, no side effects.
|
|
358
|
+
- Domain logic, validation, transformation, and calculation should be pure.
|
|
359
|
+
- Side effects (I/O, logging, database) are pushed to the edges (adapters).
|
|
360
|
+
- Pure functions are trivially testable — no mocks needed.
|
|
361
|
+
|
|
362
|
+
### Factory Pattern
|
|
363
|
+
- Use factories to encapsulate complex object construction.
|
|
364
|
+
- Factory methods on the class itself for simple cases: `User.create(dto)`.
|
|
365
|
+
- Factory classes/functions when construction involves dependencies or conditional logic.
|
|
366
|
+
- Factories are the natural companion to dependency injection — the DI container
|
|
367
|
+
IS the top-level factory.
|
|
368
|
+
|
|
369
|
+
> **Design reference patterns** (DDD, CQRS, GoF) available on demand via `get_design_reference` tool.
|
|
370
|
+
|
|
371
|
+
- id: twelve-factor-ops
|
|
372
|
+
tier: optional
|
|
373
|
+
title: "12-Factor & Operational Readiness"
|
|
374
|
+
content: |
|
|
375
|
+
## 12-Factor App & Operational Readiness
|
|
376
|
+
|
|
377
|
+
### Configuration
|
|
378
|
+
- ALL config comes from environment variables or external config services. Zero config in code.
|
|
379
|
+
- Config is validated at startup — fail fast with a clear error if required values are missing.
|
|
380
|
+
- `.env.example` committed with every variable documented. `.env` is gitignored.
|
|
381
|
+
|
|
382
|
+
### Stateless Processes
|
|
383
|
+
- Application processes are stateless. Session data lives in external stores (Redis, DB).
|
|
384
|
+
- Any process can be killed and restarted without data loss.
|
|
385
|
+
- File uploads go to object storage (S3, GCS), not local disk.
|
|
386
|
+
|
|
387
|
+
### Port Binding
|
|
388
|
+
- The application is self-contained and exports services via port binding.
|
|
389
|
+
- No runtime injection of a web server — the app embeds its own (Express, Uvicorn, etc.).
|
|
390
|
+
|
|
391
|
+
### Disposability
|
|
392
|
+
- Processes start fast (< 5 seconds) and shut down gracefully.
|
|
393
|
+
- SIGTERM triggers: stop accepting new work → finish in-flight requests → close connections → exit.
|
|
394
|
+
- Workers use robust job queues so interrupted work is retried, not lost.
|
|
395
|
+
|
|
396
|
+
### Dev/Prod Parity
|
|
397
|
+
- Minimize gaps between development and production environments.
|
|
398
|
+
- Use the same backing services in dev as prod (same DB engine, same cache).
|
|
399
|
+
- Docker / containers recommended for environment parity.
|
|
400
|
+
|
|
401
|
+
### Logs as Event Streams
|
|
402
|
+
- The app writes logs to stdout/stderr — never to local files.
|
|
403
|
+
- Log aggregation is an ops concern (ELK, Datadog, CloudWatch), not an application concern.
|
|
404
|
+
- Structured JSON logs with correlation IDs for tracing across services.
|
|
405
|
+
|
|
406
|
+
### Build, Release, Run
|
|
407
|
+
- Strict separation: build (compile + assets), release (build + config), run (execute).
|
|
408
|
+
- Every release is immutable and tagged. Rollback = deploy a previous release.
|
|
409
|
+
- CI/CD pipeline automates: lint → test → build → deploy with gates at each stage.
|
|
410
|
+
|
|
411
|
+
- id: cicd-deployment
|
|
412
|
+
tier: recommended
|
|
413
|
+
title: "CI/CD & Deployment"
|
|
414
|
+
content: |
|
|
415
|
+
## CI/CD & Deployment
|
|
416
|
+
|
|
417
|
+
### Pipeline
|
|
418
|
+
- Every push triggers: lint → type-check → unit tests → build → integration tests.
|
|
419
|
+
- Merges to main additionally run: security scan → deploy to staging → smoke tests → promote.
|
|
420
|
+
- Pipeline must complete in under 10 minutes. Parallelize test suites, cache dependencies.
|
|
421
|
+
- Failed pipelines block merge. No exceptions.
|
|
422
|
+
|
|
423
|
+
### Environments
|
|
424
|
+
- Minimum three environments: **development** (local), **staging** (mirrors prod), **production**.
|
|
425
|
+
- Environment config is injected — same artifact runs everywhere with different env vars.
|
|
426
|
+
- Staging is a faithful replica of production (same provider, same DB engine, same services).
|
|
427
|
+
|
|
428
|
+
### Deployment Strategy
|
|
429
|
+
- Default: **rolling deployment** with health checks (zero downtime).
|
|
430
|
+
- For critical services: **blue-green** or **canary** with automated rollback on error rate spike.
|
|
431
|
+
- Every deploy is tagged with git SHA. Rollback = redeploy a previous SHA.
|
|
432
|
+
- Deployment must be one command or one button. No multi-step manual runbooks.
|
|
433
|
+
|
|
434
|
+
### Preview Environments
|
|
435
|
+
- Pull requests get ephemeral preview deployments where feasible (Vercel, Netlify, Railway).
|
|
436
|
+
- Preview URLs in PR comments for stakeholder review before merge.
|
|
437
|
+
|
|
438
|
+
- id: testing-pyramid
|
|
439
|
+
tier: core
|
|
440
|
+
title: "Testing Pyramid"
|
|
441
|
+
content: |
|
|
442
|
+
## Testing Pyramid
|
|
443
|
+
|
|
444
|
+
```
|
|
445
|
+
/ E2E \ ← 5-10% of tests. Core journeys only.
|
|
446
|
+
/ Integration \ ← 20-30%. Real dependencies at boundaries.
|
|
447
|
+
/ Unit Tests \ ← 60-75%. Fast, isolated, every public function.
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
### Coverage Targets
|
|
451
|
+
- Overall minimum: {{coverage_minimum | default: 80}}% line coverage (blocks commit)
|
|
452
|
+
- New/changed code: {{coverage_new_code_min | default: 90}}% minimum (measured on diff)
|
|
453
|
+
- Critical paths: 95%+ (data pipelines, auth, PHI handling, financial calculations)
|
|
454
|
+
- Mutation score (MSI) — overall: ≥ 65% (blocks PR merge)
|
|
455
|
+
- Mutation score (MSI) — new/changed code: ≥ 70% (measured on diff)
|
|
456
|
+
- Note: Line coverage and mutation score are both required. 80% line coverage can coexist
|
|
457
|
+
with 58% MSI when tests execute code without asserting its behavior (confirmed in Shattered
|
|
458
|
+
Stars). Run stryker-mutator immediately after writing each test batch, not only pre-release.
|
|
459
|
+
Tooling: stryker-mutator (JS/TS), mutmut (Python), Pitest (Java).
|
|
460
|
+
|
|
461
|
+
### Test Rules
|
|
462
|
+
- Every test name is a specification: `test_rejects_duplicate_member_ids` not `test_validation`
|
|
463
|
+
- No empty catch blocks. No `assert True`. No tests that can't fail.
|
|
464
|
+
- Test files colocated: `[module].test.[ext]` or in `tests/` mirroring src structure.
|
|
465
|
+
- Flaky tests are bugs — fix or quarantine, never ignore.
|
|
466
|
+
- After writing tests for any module, run Stryker on that module before moving on.
|
|
467
|
+
Surviving mutants = missing assertions. Fix before proceeding.
|
|
468
|
+
|
|
469
|
+
### Test Doubles Taxonomy
|
|
470
|
+
Use the correct double for the job:
|
|
471
|
+
- **Stub**: Returns canned data. No assertions on calls. Use when you need to control input.
|
|
472
|
+
- **Spy**: Records calls. Assert after the fact. Use to verify side effects.
|
|
473
|
+
- **Fake**: Working implementation with shortcuts (in-memory DB). Use for integration-speed tests.
|
|
474
|
+
- **Mock**: Pre-programmed expectations. Assert call patterns. Use sparingly — they couple to implementation.
|
|
475
|
+
Prefer stubs and fakes over mocks. Tests that mock everything test nothing.
|
|
476
|
+
|
|
477
|
+
### Test Data Builders
|
|
478
|
+
- Use Builder or Factory pattern for test data: `UserBuilder.anAdmin().withName('Alice').build()`.
|
|
479
|
+
- One builder per domain entity. Builders provide sensible defaults so tests only specify what matters.
|
|
480
|
+
- No raw object literals scattered across tests. Centralize in `tests/fixtures/` or `tests/builders/`.
|
|
481
|
+
|
|
482
|
+
### Property-Based Testing
|
|
483
|
+
- For pure functions with wide input ranges, add property tests (fast-check, Hypothesis, QuickCheck).
|
|
484
|
+
- Define invariants, not examples: "sorting is idempotent", "encode then decode = identity".
|
|
485
|
+
- Property tests complement, not replace, example-based tests.
|
|
486
|
+
|
|
487
|
+
- id: tdd-methodology
|
|
488
|
+
tier: core
|
|
489
|
+
title: "Test-Driven Development"
|
|
490
|
+
content: |
|
|
491
|
+
## Test-Driven Development (TDD)
|
|
492
|
+
|
|
493
|
+
### Red-Green-Refactor — The Only Cycle
|
|
494
|
+
1. **RED**: Write a failing test that describes the desired behavior. Run it. It MUST fail.
|
|
495
|
+
If it passes, the test is wrong — it's not testing what you think.
|
|
496
|
+
2. **GREEN**: Write the minimum code to make the test pass. No more.
|
|
497
|
+
3. **REFACTOR**: Clean up while all tests stay green. No new behavior in this step.
|
|
498
|
+
Repeat. Every feature, every function, every bug fix follows this cycle.
|
|
499
|
+
|
|
500
|
+
### Tests Are Specifications, Not Confirmations
|
|
501
|
+
- Write tests against **expected behavior**, never against current implementation.
|
|
502
|
+
- A test that passes on broken code is worse than no test — it provides false confidence.
|
|
503
|
+
- Never weaken an assertion to match what the code currently does. If the code disagrees
|
|
504
|
+
with the spec, the code is wrong.
|
|
505
|
+
- Never write a test suite after the fact that just "locks in" existing behavior without
|
|
506
|
+
verifying it's correct.
|
|
507
|
+
|
|
508
|
+
### Bug Fix Protocol
|
|
509
|
+
- **Every bug fix starts with a failing test** that reproduces the bug.
|
|
510
|
+
- The test must fail before the fix and pass after. No exceptions.
|
|
511
|
+
- If you can't write a reproducing test, you don't understand the bug well enough to fix it.
|
|
512
|
+
|
|
513
|
+
### One Behavior Per Test
|
|
514
|
+
- Each test verifies exactly one behavior or rule.
|
|
515
|
+
- A test with multiple unrelated assertions is testing multiple things — split it.
|
|
516
|
+
- Test name = the specification: `rejects_expired_tokens`, not `test_auth`.
|
|
517
|
+
|
|
518
|
+
- id: tdd-enforcement
|
|
519
|
+
tier: core
|
|
520
|
+
title: "TDD Enforcement — Forbidden Patterns and Gate Protocol"
|
|
521
|
+
content: |
|
|
522
|
+
## TDD Enforcement — Forbidden Patterns and Gate Protocol
|
|
523
|
+
|
|
524
|
+
Instructions describe a process. Gates enforce it. This block defines what is
|
|
525
|
+
structurally prohibited, what output is required at each gate, and how the
|
|
526
|
+
commit sequence makes the TDD cycle auditable.
|
|
527
|
+
|
|
528
|
+
### Forbidden Patterns (non-negotiable)
|
|
529
|
+
The following are architecture violations, not style preferences:
|
|
530
|
+
- **NEVER write an implementation file before running and showing a failing test.**
|
|
531
|
+
Stating that "the test would fail" is not equivalent to running it. Run it.
|
|
532
|
+
- **NEVER write tests after implementation** except for bug fix reproduction tests on
|
|
533
|
+
pre-existing code not yet covered. Even then: write the test, show it fails, fix,
|
|
534
|
+
show it passes.
|
|
535
|
+
- **NEVER weaken an assertion** to make a test pass. If the assertion disagrees with
|
|
536
|
+
the output, the implementation is wrong.
|
|
537
|
+
- **NEVER skip the refactor phase** because "the code is clean enough." The refactor
|
|
538
|
+
phase exists to enforce separation of concerns under green. Skipping it is a
|
|
539
|
+
commitment not to separate concerns in that increment.
|
|
540
|
+
- **NEVER commit a `feat:` or `fix:` with no corresponding `test:` commit** preceding
|
|
541
|
+
it in the same branch. The test commit is the audit trail that the red phase occurred.
|
|
542
|
+
|
|
543
|
+
### The Session Gate Protocol
|
|
544
|
+
TDD across a multi-step session requires explicit checkpoints the AI reports and the
|
|
545
|
+
human can verify. At each gate, the AI must output the actual test runner output,
|
|
546
|
+
not a summary of what it expects.
|
|
547
|
+
|
|
548
|
+
```
|
|
549
|
+
┌─────────────────────────────────────────────────────┐
|
|
550
|
+
│ PHASE 1: RED │
|
|
551
|
+
│ Action: Write test for the specified behavior │
|
|
552
|
+
│ Gate: Run test — paste full failure output │
|
|
553
|
+
│ Block: Cannot proceed until failure is shown │
|
|
554
|
+
│ Commit: test(scope): [RED] describe behavior │
|
|
555
|
+
└───────────────────┬─────────────────────────────────┘
|
|
556
|
+
│ failure confirmed
|
|
557
|
+
┌───────────────────▼─────────────────────────────────┐
|
|
558
|
+
│ PHASE 2: GREEN │
|
|
559
|
+
│ Action: Write minimum implementation │
|
|
560
|
+
│ Gate: Run test — paste full passing output │
|
|
561
|
+
│ Block: Cannot proceed until passing is shown │
|
|
562
|
+
│ Commit: feat(scope): implement to satisfy test │
|
|
563
|
+
└───────────────────┬─────────────────────────────────┘
|
|
564
|
+
│ green confirmed
|
|
565
|
+
┌───────────────────▼─────────────────────────────────┐
|
|
566
|
+
│ PHASE 3: REFACTOR │
|
|
567
|
+
│ Action: Improve structure, not behavior │
|
|
568
|
+
│ Gate: Run full suite — paste summary output │
|
|
569
|
+
│ Block: Cannot commit if any test regresses │
|
|
570
|
+
│ Commit: refactor(scope): clean without behavior │
|
|
571
|
+
└─────────────────────────────────────────────────────┘
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
### Commit Sequence as Audit Trail
|
|
575
|
+
The git log for any feature must be readable as:
|
|
576
|
+
```
|
|
577
|
+
test(cart): [RED] add test for removing last item empties cart
|
|
578
|
+
feat(cart): remove last item empties cart
|
|
579
|
+
refactor(cart): extract empty-check to CartState predicate
|
|
580
|
+
```
|
|
581
|
+
This sequence is auditable. An AI that wrote the `feat:` commit without the preceding
|
|
582
|
+
`test:` commit either skipped the red phase entirely or conflated it with implementation.
|
|
583
|
+
The commit hook `pre-commit-tdd-check.sh` detects the second pattern before it lands.
|
|
584
|
+
|
|
585
|
+
### Why Instructions Alone Are Not Sufficient
|
|
586
|
+
A language model generating in a single context window experiences no time delay between
|
|
587
|
+
writing a test and writing an implementation that passes it. The RED phase is structurally
|
|
588
|
+
collapsed. The gates above exist precisely to make the phases non-simultaneous:
|
|
589
|
+
- The test commit must happen before the implementation can be written.
|
|
590
|
+
- The failure output must be produced (by running the code) before the game state is known.
|
|
591
|
+
- The model cannot "know" the failure output without actually running the test,
|
|
592
|
+
because the failure messages are not in the training distribution for this specific code.
|
|
593
|
+
These gates transform TDD from a discipline into a constraint.
|
|
594
|
+
|
|
595
|
+
- id: adversarial-testing
|
|
596
|
+
tier: core
|
|
597
|
+
title: "Adversarial Testing Posture"
|
|
598
|
+
content: |
|
|
599
|
+
## Adversarial Testing Posture
|
|
600
|
+
|
|
601
|
+
Tests are not documentation of what the code does. Tests are adversarial assertions
|
|
602
|
+
that the code does the right thing even when given inputs designed to break it.
|
|
603
|
+
|
|
604
|
+
### The adversarial posture
|
|
605
|
+
- Design every test as if the implementation is wrong until proven otherwise.
|
|
606
|
+
- Write tests that FAIL on incorrect code — not tests that pass on any reasonable implementation.
|
|
607
|
+
- If a test is hard to make fail, the specification is underspecified, not the test.
|
|
608
|
+
|
|
609
|
+
### Name tests as behaviors, not paths
|
|
610
|
+
- `rejects_expired_tokens` not `test_validate_token`
|
|
611
|
+
- `throws_on_missing_required_field` not `test_error_handling`
|
|
612
|
+
- `returns_empty_list_not_null_when_no_results` not `test_query`
|
|
613
|
+
|
|
614
|
+
### Cover the adversarial surface
|
|
615
|
+
For every public function or API endpoint, write tests for:
|
|
616
|
+
1. **Valid boundary values**: minimum, maximum, exact-zero, single-element
|
|
617
|
+
2. **Invalid boundary values**: below-minimum, above-maximum, empty, null/undefined
|
|
618
|
+
3. **Constraint violations**: values that look valid but break invariants (negative balance, future birth date)
|
|
619
|
+
4. **Ordering and concurrency**: does order matter? what if called twice?
|
|
620
|
+
5. **Authorization boundaries**: can a user access another user's resource?
|
|
621
|
+
|
|
622
|
+
A test suite that only exercises the happy path is documentation, not specification.
|
|
623
|
+
Every mutation that survives is a missing adversarial test.
|
|
624
|
+
|
|
625
|
+
- id: property-based-testing
|
|
626
|
+
tier: recommended
|
|
627
|
+
title: "Property-Based Testing"
|
|
628
|
+
content: |
|
|
629
|
+
## Property-Based Testing
|
|
630
|
+
|
|
631
|
+
Example-based tests verify that `f(x) = y` for specific known pairs.
|
|
632
|
+
Property-based tests verify that invariants hold for ALL inputs the generator can produce.
|
|
633
|
+
Both are required. Neither replaces the other.
|
|
634
|
+
|
|
635
|
+
### When to add property tests
|
|
636
|
+
- Pure functions with wide input domains (serialization, parsing, math, sorting)
|
|
637
|
+
- Functions where "same inputs → same outputs" must hold across edge cases
|
|
638
|
+
- Any encoder/decoder pair: `decode(encode(x)) === x` must hold for all x
|
|
639
|
+
- Any sort or ranking: `sort(sort(xs))` must equal `sort(xs)` (idempotence)
|
|
640
|
+
- Any financial calculation: results must be within bounds for all valid inputs
|
|
641
|
+
|
|
642
|
+
### Ecosystem tools (language-agnostic principle)
|
|
643
|
+
Use whatever property testing library matches the project's language:
|
|
644
|
+
- TypeScript / JavaScript: `fast-check`
|
|
645
|
+
- Python: `hypothesis`
|
|
646
|
+
- Java / Kotlin: `jqwik` or `kotest`
|
|
647
|
+
- Go: `gopter` or `rapid`
|
|
648
|
+
- Rust: `proptest`
|
|
649
|
+
- Scala: `scalacheck`
|
|
650
|
+
|
|
651
|
+
### Template invariant structure
|
|
652
|
+
```
|
|
653
|
+
property("encode-decode round trip", () => {
|
|
654
|
+
forAll(arbitrary_valid_input(), (input) => {
|
|
655
|
+
expect(decode(encode(input))).toEqual(input);
|
|
656
|
+
});
|
|
657
|
+
});
|
|
658
|
+
```
|
|
659
|
+
|
|
660
|
+
If a property test fails with an unexpected input, add that input as a regression example test.
|
|
661
|
+
Property failures are bugs, not edge cases to suppress.
|
|
662
|
+
|
|
663
|
+
- id: spec-meta-query
|
|
664
|
+
tier: recommended
|
|
665
|
+
title: "Specification Completeness Meta-Query"
|
|
666
|
+
content: |
|
|
667
|
+
## Specification Completeness Meta-Query
|
|
668
|
+
|
|
669
|
+
Before writing implementation code, ask the model:
|
|
670
|
+
|
|
671
|
+
> "What dimensions of correctness does this specification not yet address?"
|
|
672
|
+
|
|
673
|
+
This activates domain depth and returns the surface that is missing. A complete answer
|
|
674
|
+
identifies gaps before they become bugs — not after.
|
|
675
|
+
|
|
676
|
+
### Six dimensions to probe systematically
|
|
677
|
+
|
|
678
|
+
1. **Concurrency behavior** — What happens when two users modify the same resource simultaneously?
|
|
679
|
+
Are there race conditions? What is the consistency model (eventual, strong, linearizable)?
|
|
680
|
+
|
|
681
|
+
2. **Partial failure handling** — What state is the system in if the operation fails halfway?
|
|
682
|
+
Is the operation idempotent? Is retry safe? Is rollback possible? Who cleans up?
|
|
683
|
+
|
|
684
|
+
3. **Authorization edge cases** — What happens with an expired token? A revoked role?
|
|
685
|
+
Can a user with partial permissions complete a multi-step operation?
|
|
686
|
+
What does "no access" mean vs "resource does not exist"?
|
|
687
|
+
|
|
688
|
+
4. **Observable side effects** — Does this operation send emails, fire webhooks, publish events,
|
|
689
|
+
write audit logs? Are those effects specified? Are they retryable? Can they duplicate?
|
|
690
|
+
|
|
691
|
+
5. **Performance constraints** — Is there an SLA? A timeout? A maximum payload size?
|
|
692
|
+
What is the expected order of magnitude of inputs? What degrades gracefully?
|
|
693
|
+
|
|
694
|
+
6. **Backwards compatibility** — If this changes an existing interface, what breaks?
|
|
695
|
+
Is there a migration path? Who depends on the current behavior?
|
|
696
|
+
|
|
697
|
+
Each unanswered dimension is a test to write before implementation begins.
|
|
698
|
+
If the specification has no answer, the answer must be decided now — not discovered during an incident.
|
|
699
|
+
|
|
700
|
+
- id: data-guardrails
|
|
701
|
+
tier: core
|
|
702
|
+
title: "Data Guardrails"
|
|
703
|
+
content: |
|
|
704
|
+
## Data Guardrails ⚠️
|
|
705
|
+
- NEVER sample, truncate, or subset data unless explicitly instructed.
|
|
706
|
+
- NEVER make simplifying assumptions about distributions, scales, or schemas.
|
|
707
|
+
- State exact row counts, column sets, and filters for every data operation.
|
|
708
|
+
- If data is too large for in-memory, say so — don't silently downsample.
|
|
709
|
+
|
|
710
|
+
- id: commit-protocol
|
|
711
|
+
tier: core
|
|
712
|
+
title: "Commit Protocol"
|
|
713
|
+
content: |
|
|
714
|
+
## Commit Protocol
|
|
715
|
+
|
|
716
|
+
A commit is a **verified state** of the system — not a save point, not a checkpoint.
|
|
717
|
+
A valid commit requires all three: test suite passes, delta is bounded and coherent,
|
|
718
|
+
no new anti-patterns introduced.
|
|
719
|
+
|
|
720
|
+
- Conventional commits: `feat|fix|refactor|docs|test|chore(scope): description`
|
|
721
|
+
- Commits must pass: compilation, lint, tests, coverage gate, mutation score gate (Stryker on changed modules), anti-pattern scan.
|
|
722
|
+
- Keep commits atomic — one logical change per commit.
|
|
723
|
+
- Commit BEFORE any risky refactor. Tag stable states.
|
|
724
|
+
- Update Status.md at the end of every session.
|
|
725
|
+
|
|
726
|
+
### Commit Hooks — Emit, Don't Reference
|
|
727
|
+
Commit hooks, commit-message linting, and the CI pipeline must be **emitted as fenced
|
|
728
|
+
code blocks** in the first session response — not merely referenced in prose or README
|
|
729
|
+
text. A hook that exists only as "you should add a pre-commit hook" in documentation
|
|
730
|
+
provides zero enforcement. If the file is not written to disk, the gate does not exist.
|
|
731
|
+
|
|
732
|
+
The following files must be emitted for any new project:
|
|
733
|
+
|
|
734
|
+
**`package.json`** — add to `scripts` and `devDependencies`:
|
|
735
|
+
```json
|
|
736
|
+
"scripts": { "prepare": "husky install" },
|
|
737
|
+
"devDependencies": {
|
|
738
|
+
"husky": "^9.0.0",
|
|
739
|
+
"@commitlint/cli": "^19.0.0",
|
|
740
|
+
"@commitlint/config-conventional": "^19.0.0"
|
|
741
|
+
}
|
|
742
|
+
```
|
|
743
|
+
|
|
744
|
+
**`.husky/pre-commit`**:
|
|
745
|
+
```bash
|
|
746
|
+
#!/usr/bin/env sh
|
|
747
|
+
. "$(dirname -- "$0")/_/husky.sh"
|
|
748
|
+
npx tsc --noEmit && npm run lint && npm test -- --passWithNoTests
|
|
749
|
+
```
|
|
750
|
+
|
|
751
|
+
**`.husky/commit-msg`**:
|
|
752
|
+
```bash
|
|
753
|
+
#!/usr/bin/env sh
|
|
754
|
+
. "$(dirname -- "$0")/_/husky.sh"
|
|
755
|
+
npx commitlint --edit "$1"
|
|
756
|
+
```
|
|
757
|
+
|
|
758
|
+
**`commitlint.config.js`**:
|
|
759
|
+
```js
|
|
760
|
+
module.exports = { extends: ['@commitlint/config-conventional'] };
|
|
761
|
+
```
|
|
762
|
+
|
|
763
|
+
### Linter Config — Emit in P0, Don't Reference
|
|
764
|
+
Linter configuration is infrastructure, not application code. It must be committed to the
|
|
765
|
+
repo root in the **first response** (P0) alongside hooks and CI config — not added post-hoc.
|
|
766
|
+
A linter mentioned only in documentation does not enforce anything.
|
|
767
|
+
|
|
768
|
+
**TypeScript / JavaScript** — emit `.eslintrc.json` (or `eslint.config.js` for flat config):
|
|
769
|
+
```json
|
|
770
|
+
{
|
|
771
|
+
"parser": "@typescript-eslint/parser",
|
|
772
|
+
"plugins": ["@typescript-eslint"],
|
|
773
|
+
"rules": {
|
|
774
|
+
"no-unused-vars": "off",
|
|
775
|
+
"@typescript-eslint/no-unused-vars": "error",
|
|
776
|
+
"@typescript-eslint/no-explicit-any": "error"
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
```
|
|
780
|
+
|
|
781
|
+
**Python** — emit `ruff.toml` (or `[tool.ruff]` section in `pyproject.toml`):
|
|
782
|
+
```toml
|
|
783
|
+
[tool.ruff]
|
|
784
|
+
select = ["E", "F", "I"]
|
|
785
|
+
ignore = []
|
|
786
|
+
line-length = 100
|
|
787
|
+
```
|
|
788
|
+
|
|
789
|
+
**Go** — emit `.golangci.yaml`:
|
|
790
|
+
```yaml
|
|
791
|
+
linters:
|
|
792
|
+
enable:
|
|
793
|
+
- unused
|
|
794
|
+
- govet
|
|
795
|
+
- errcheck
|
|
796
|
+
```
|
|
797
|
+
|
|
798
|
+
The correct linter config for **this project's language** must be committed to the repo root
|
|
799
|
+
in the same response that emits hooks and CI. Discovering lint errors at code review is too late.
|
|
800
|
+
|
|
801
|
+
### CI Pipeline — Emit, Don't Reference
|
|
802
|
+
`.github/workflows/ci.yml` must be emitted as a fenced code block in the first response.
|
|
803
|
+
A CI configuration described only in documentation does not enforce anything.
|
|
804
|
+
Adapt service blocks, branch names, and language-specific commands to the project stack.
|
|
805
|
+
The mutation gate step (`npx stryker run` for JS/TS, `mutmut run` for Python, `pitest` for
|
|
806
|
+
Java) is non-negotiable — it is the only gate that verifies test quality, not just
|
|
807
|
+
test execution. Line coverage at 80% can coexist with 58% mutation score; the mutation
|
|
808
|
+
gate catches the difference.
|
|
809
|
+
|
|
810
|
+
Minimum CI for a Node.js/TypeScript project:
|
|
811
|
+
```yaml
|
|
812
|
+
name: CI
|
|
813
|
+
on:
|
|
814
|
+
push:
|
|
815
|
+
branches: [main, develop]
|
|
816
|
+
pull_request:
|
|
817
|
+
branches: [main, develop]
|
|
818
|
+
jobs:
|
|
819
|
+
ci:
|
|
820
|
+
runs-on: ubuntu-latest
|
|
821
|
+
steps:
|
|
822
|
+
- uses: actions/checkout@v4
|
|
823
|
+
- uses: actions/setup-node@v4
|
|
824
|
+
with:
|
|
825
|
+
node-version: '20'
|
|
826
|
+
cache: 'npm'
|
|
827
|
+
- run: npm ci
|
|
828
|
+
- run: npx tsc --noEmit
|
|
829
|
+
- run: npm run lint
|
|
830
|
+
- run: npm test -- --coverage --passWithNoTests
|
|
831
|
+
- name: Mutation gate
|
|
832
|
+
run: npx stryker run
|
|
833
|
+
```
|
|
834
|
+
|
|
835
|
+
### Commit Message Precision
|
|
836
|
+
The commit message is the sentence describing this state in the project's typed corpus.
|
|
837
|
+
- ❌ `fix bug` — not a sentence; not queryable; useless as episodic memory.
|
|
838
|
+
- ✅ `fix(auth): reject expired tokens at middleware boundary before service layer invocation`
|
|
839
|
+
The AI uses commit history as context in future sessions. Typed, scoped conventional
|
|
840
|
+
messages are a queryable episodic record. `wip` and `changes` are not.
|
|
841
|
+
|
|
842
|
+
### What Constitutes One Logical Change
|
|
843
|
+
- A new feature and its tests: one commit.
|
|
844
|
+
- A refactor of an existing module that does not change behavior: one commit.
|
|
845
|
+
- A spec update (constitution change + the code change it governs): one commit.
|
|
846
|
+
- A bug fix with the reproducing test included: one commit.
|
|
847
|
+
Never combine a behavior change with a refactor in the same commit.
|
|
848
|
+
|
|
849
|
+
- id: clarification-protocol
|
|
850
|
+
tier: core
|
|
851
|
+
title: "Clarification Protocol"
|
|
852
|
+
content: |
|
|
853
|
+
## Clarification Protocol
|
|
854
|
+
Before writing code for any new feature or significant change:
|
|
855
|
+
- If the request implies architectural trade-offs that are not explicit, **ask one targeted
|
|
856
|
+
question** before proceeding. Do not silently choose an architecture.
|
|
857
|
+
- If the domain model is ambiguous (cardinality, ownership, event ordering, shared state),
|
|
858
|
+
state your assumption and ask for confirmation before implementing.
|
|
859
|
+
- If the request has two or more meaningfully different interpretations, present the options
|
|
860
|
+
briefly and ask — do not guess and hide the choice.
|
|
861
|
+
- Do NOT ask about mechanical details (naming conventions, file placement, test structure) —
|
|
862
|
+
apply the conventions already in this document without asking.
|
|
863
|
+
- Maximum one clarification round. If told "use your judgment," proceed with the most
|
|
864
|
+
conservative interpretation and record the assumption in a code comment or new ADR.
|
|
865
|
+
|
|
866
|
+
- id: feature-completion-protocol
|
|
867
|
+
tier: recommended
|
|
868
|
+
title: "Feature Completion Protocol"
|
|
869
|
+
content: |
|
|
870
|
+
## Feature Completion Protocol
|
|
871
|
+
After implementing any feature (new or changed):
|
|
872
|
+
|
|
873
|
+
### 1. Verify (local, pre-commit)
|
|
874
|
+
Run: `npx forgecraft-mcp verify .`
|
|
875
|
+
(Or `npm test` + manual HTTP check if forgecraft is not installed.)
|
|
876
|
+
A feature is not done until verify passes. Do not proceed to docs if it fails.
|
|
877
|
+
|
|
878
|
+
### 2. Commit (code only)
|
|
879
|
+
Commit after `verify` passes. This triggers CI and the staging deploy pipeline.
|
|
880
|
+
`feat(scope): <description>` — describes the feature, not the docs update.
|
|
881
|
+
|
|
882
|
+
### 3. Deploy to Staging + Smoke Gate
|
|
883
|
+
After the CI pipeline deploys to staging, run the smoke suite:
|
|
884
|
+
```
|
|
885
|
+
npx playwright test --config playwright.smoke.config.ts --grep @smoke
|
|
886
|
+
```
|
|
887
|
+
If smoke fails: **revert the deploy**. Do not proceed to production and do not cascade docs
|
|
888
|
+
for a feature that is broken in the deployed environment.
|
|
889
|
+
|
|
890
|
+
### 4. Doc Sync Cascade
|
|
891
|
+
Update the following in order — skip any that do not exist in this project:
|
|
892
|
+
1. **spec.md** — update the relevant feature section (APIs, behavior, contract changes)
|
|
893
|
+
2. **docs/adrs/** — add an ADR if a new architectural decision was made
|
|
894
|
+
3. **docs/diagrams/c4-*.md** — update `c4-context.md` or `c4-container.md` if a new
|
|
895
|
+
module, container, or external dependency was added. Diagrams must be written to disk
|
|
896
|
+
as fenced Mermaid blocks — updating prose that references a diagram is not an update.
|
|
897
|
+
4. **docs/diagrams/sequence-*.md / state-*.md / flow-*.md** — update or create the
|
|
898
|
+
relevant diagram file for the changed surface. Sequence diagrams must name real
|
|
899
|
+
participants; state diagrams must name real states and transitions; flow diagrams must
|
|
900
|
+
have entry/exit nodes and decision diamonds. A file containing only `<!-- UNFILLED -->`
|
|
901
|
+
markers is a specification gap, not a completed diagram.
|
|
902
|
+
5. **docs/TechSpec.md** — update module list, API reference, or technology choice sections
|
|
903
|
+
6. **docs/use-cases.md** — update or add use cases if new actor interactions were introduced
|
|
904
|
+
7. **Status.md** — always update: what changed, current state, next steps
|
|
905
|
+
|
|
906
|
+
- id: mcp-tooling
|
|
907
|
+
tier: recommended
|
|
908
|
+
title: "MCP-Powered Tooling"
|
|
909
|
+
content: |
|
|
910
|
+
## MCP-Powered Tooling
|
|
911
|
+
### CodeSeeker — Graph-Powered Code Intelligence
|
|
912
|
+
CodeSeeker builds a knowledge graph of the codebase with hybrid search
|
|
913
|
+
(vector + text + path, fused with RRF). Use it for:
|
|
914
|
+
- **Semantic search**: "find code that handles errors like this" — not just grep.
|
|
915
|
+
- **Graph traversal**: imports, calls, extends — follow dependency chains.
|
|
916
|
+
- **Coding standards**: auto-detected validation, error handling, and state patterns.
|
|
917
|
+
- **Contextual reads**: `get_file_context` returns a file with its related code.
|
|
918
|
+
Indexing is automatic on first search (~30s–5min depending on codebase size).
|
|
919
|
+
Most valuable on mid-to-large projects (10K+ files) with established patterns.
|
|
920
|
+
Install: `npx codeseeker install --vscode` or see https://github.com/jghiringhelli/codeseeker
|
|
921
|
+
|
|
922
|
+
- id: engineering-preferences
|
|
923
|
+
tier: recommended
|
|
924
|
+
title: "Engineering Preferences"
|
|
925
|
+
content: |
|
|
926
|
+
## Engineering Preferences
|
|
927
|
+
These calibrate the AI assistant's judgment on subjective trade-offs.
|
|
928
|
+
- **DRY is important** — flag repetition aggressively.
|
|
929
|
+
- **Well-tested code is non-negotiable**; I'd rather have too many tests than too few.
|
|
930
|
+
- **"Engineered enough"** — not under-engineered (fragile, hacky) and not over-engineered
|
|
931
|
+
(premature abstraction, unnecessary complexity).
|
|
932
|
+
- **Handle more edge cases**, not fewer; thoughtfulness > speed.
|
|
933
|
+
- **Bias toward explicit over clever** — readability wins over brevity.
|
|
934
|
+
- When in doubt, ask rather than assume.
|
|
935
|
+
|
|
936
|
+
- id: agent-mechanics
|
|
937
|
+
tier: core
|
|
938
|
+
title: "Agent Mechanical Constraints"
|
|
939
|
+
content: |
|
|
940
|
+
## Agent Mechanical Constraints — Non-Negotiable Overrides
|
|
941
|
+
|
|
942
|
+
These rules exist because the model has hard constraints that silently produce wrong
|
|
943
|
+
results without them. Each override targets a specific failure mode observed in practice.
|
|
944
|
+
|
|
945
|
+
### 1. Step 0 — Dead Code First
|
|
946
|
+
Before ANY structural refactor on a file > 300 LOC:
|
|
947
|
+
1. Delete all dead props, unused exports, unused imports, and debug logs.
|
|
948
|
+
2. Commit that cleanup separately under `chore(scope): strip dead code`.
|
|
949
|
+
3. Only then begin the real work.
|
|
950
|
+
Dead code accelerates context compaction. Every orphaned import is budget spent on
|
|
951
|
+
tokens that contribute nothing to the task.
|
|
952
|
+
|
|
953
|
+
### 2. Phase Limit — 5 Files Maximum
|
|
954
|
+
Never attempt multi-file refactors in a single response. Break work into explicit phases.
|
|
955
|
+
Each phase must touch **no more than 5 files**. Complete Phase N, verify it compiles and
|
|
956
|
+
all tests pass, then wait for explicit approval before Phase N+1.
|
|
957
|
+
Why: context compaction fires around 167K tokens and discards all intermediate reasoning,
|
|
958
|
+
file reads, and decision chains. Keeping phases small prevents mid-task compaction.
|
|
959
|
+
|
|
960
|
+
### 3. Senior Dev Override
|
|
961
|
+
The model's default system-level directives instruct it to "try the simplest approach
|
|
962
|
+
first" and "avoid refactoring beyond what was asked." These are active constraints that
|
|
963
|
+
fight your intent on architectural tasks.
|
|
964
|
+
**Override them explicitly** when quality requires it:
|
|
965
|
+
> "What would a senior, experienced, perfectionist dev reject in code review? Fix all of it."
|
|
966
|
+
This reframes what "done" means. System-level brevity mandates yield to an explicit
|
|
967
|
+
quality bar stated in the prompt.
|
|
968
|
+
|
|
969
|
+
### 4. Sub-Agent Parallelism for Large Tasks
|
|
970
|
+
For tasks spanning > 5 independent files, **launch parallel sub-agents** (5–8 files per
|
|
971
|
+
agent). Each agent gets its own isolated context window and compaction cycle.
|
|
972
|
+
Sequential processing of large tasks guarantees context decay by the later files.
|
|
973
|
+
Batching into parallel agents multiplies the effective working memory proportionally.
|
|
974
|
+
|
|
975
|
+
### 5. File Read Budget — 2,000-Line Cap
|
|
976
|
+
Each file read is hard-capped at 2,000 lines. Everything past that is silently truncated.
|
|
977
|
+
The model does not know what it didn't see — it will hallucinate the rest.
|
|
978
|
+
**For any file over 500 LOC**: read in sequential chunks using `offset` and `limit`
|
|
979
|
+
parameters. Never assume a single read captured the full file.
|
|
980
|
+
|
|
981
|
+
### 6. Tool Result Truncation
|
|
982
|
+
Tool results exceeding ~50,000 characters are truncated to a 2,000-byte preview.
|
|
983
|
+
The model works from the preview and does not know results were cut.
|
|
984
|
+
If any search returns suspiciously few results: re-run it with narrower scope
|
|
985
|
+
(single directory, stricter glob). State explicitly when truncation may have occurred.
|
|
986
|
+
|
|
987
|
+
### 7. Grep Is Not an AST
|
|
988
|
+
`grep` is raw text pattern matching. It cannot distinguish a function call from a
|
|
989
|
+
comment, a type reference from a string literal, or an import from one module vs another.
|
|
990
|
+
On any rename or signature change, search **separately** for:
|
|
991
|
+
- Direct calls and references
|
|
992
|
+
- Type-level references (interfaces, generics, `typeof`)
|
|
993
|
+
- String literals containing the name
|
|
994
|
+
- Dynamic imports and `require()` calls
|
|
995
|
+
- Re-exports and barrel file entries (`index.ts`, `__init__.py`)
|
|
996
|
+
- Test files and mocks
|
|
997
|
+
Never assume a single grep caught everything. Verify or expect regressions.
|
|
998
|
+
|
|
999
|
+
- id: code-generation-verification
|
|
1000
|
+
tier: core
|
|
1001
|
+
title: "Code Generation — Self-Verify Loop"
|
|
1002
|
+
content: |
|
|
1003
|
+
## Code Generation — Verify Before Returning
|
|
1004
|
+
|
|
1005
|
+
When emitting implementation code across one or more files, the response is not complete
|
|
1006
|
+
until the following are true. Show the evidence in your response — do not claim without running.
|
|
1007
|
+
|
|
1008
|
+
### Verification steps (in order)
|
|
1009
|
+
1. **Compile check**: Run `tsc --noEmit` (TypeScript), `mypy` (Python), or equivalent.
|
|
1010
|
+
Zero errors required. Do not return with type errors outstanding.
|
|
1011
|
+
2. **Test suite**: Run the full test suite (`jest --runInBand`, `pytest`, etc.).
|
|
1012
|
+
Zero failures required. Fix every failure before returning.
|
|
1013
|
+
3. **Interface consistency**: When fixing a compile error in file A, check ALL callers of
|
|
1014
|
+
the changed interface. Fixing one side without seeing the other causes oscillation:
|
|
1015
|
+
the model fixes `service.ts` (3-param signature) but `routes.ts` still calls it with
|
|
1016
|
+
an object — same error reappears inverted next pass.
|
|
1017
|
+
4. **§8 DRY Check**: Run duplication detector on `src/`. Duplicated lines must be < 5%
|
|
1018
|
+
(min-tokens 50). Use the tool appropriate for your stack (see project-gates.yaml:
|
|
1019
|
+
`no-code-duplication`). If above threshold, extract duplicated logic to a shared utility
|
|
1020
|
+
before closing.
|
|
1021
|
+
5. **§9 Interface Completeness**: Every method declared in each interface must be implemented
|
|
1022
|
+
by its concrete class. Run static type checking (0 errors required). Use the tool
|
|
1023
|
+
appropriate for your stack (see project-gates.yaml: `interface-contract-completeness`).
|
|
1024
|
+
If errors exist, implement missing methods before closing.
|
|
1025
|
+
|
|
1026
|
+
### Required evidence in the final response
|
|
1027
|
+
```
|
|
1028
|
+
tsc --noEmit: 0 errors
|
|
1029
|
+
Jest: 109 passed, 0 failed, 11 suites
|
|
1030
|
+
```
|
|
1031
|
+
|
|
1032
|
+
### Common test setup pitfalls (TypeScript / Prisma)
|
|
1033
|
+
- **`prisma db push`, not `prisma migrate deploy`** in test environments.
|
|
1034
|
+
`migrate deploy` silently no-ops when no `prisma/migrations/` folder exists,
|
|
1035
|
+
leaving all tables absent. `db push --accept-data-loss` syncs `schema.prisma` directly.
|
|
1036
|
+
- **`deleteMany` in FK order, not `DROP SCHEMA`**.
|
|
1037
|
+
`$executeRawUnsafe('DROP SCHEMA public CASCADE; CREATE SCHEMA public;')` throws
|
|
1038
|
+
error 42601 — pg rejects multi-statement queries in prepared statements.
|
|
1039
|
+
Use ordered `deleteMany()` calls in `beforeEach` instead.
|
|
1040
|
+
- **JWT_SECRET minimum length**: HS256 requires ≥ 32 characters.
|
|
1041
|
+
Test secrets like `"test-secret"` (11 chars) cause startup errors.
|
|
1042
|
+
Use `"test-secret-that-is-at-least-32-chars"` in test env.
|
|
1043
|
+
|
|
1044
|
+
- id: known-pitfalls
|
|
1045
|
+
tier: core
|
|
1046
|
+
title: "Known Pitfalls"
|
|
1047
|
+
content: |
|
|
1048
|
+
## Known Pitfalls
|
|
1049
|
+
Recurring type errors and runtime traps specific to this project's stack.
|
|
1050
|
+
Resolve exactly as documented — no `any` casts, ignore directives, or unlisted workarounds.
|
|
1051
|
+
### [Add project-specific pitfalls here]
|
|
1052
|
+
<!-- Entry format:
|
|
1053
|
+
### Library — trap description
|
|
1054
|
+
What goes wrong and why, then:
|
|
1055
|
+
```
|
|
1056
|
+
// ❌ wrong
|
|
1057
|
+
```
|
|
1058
|
+
```
|
|
1059
|
+
// ✅ correct
|
|
1060
|
+
```
|
|
1061
|
+
-->
|
|
1062
|
+
|
|
1063
|
+
- id: corrections-log
|
|
1064
|
+
tier: core
|
|
1065
|
+
title: "Corrections Log"
|
|
1066
|
+
content: |
|
|
1067
|
+
## Corrections Log
|
|
1068
|
+
When I correct your output, record the correction pattern here so you don't repeat it.
|
|
1069
|
+
### Learned Corrections
|
|
1070
|
+
- [AI assistant appends corrections here with date and description]
|
|
1071
|
+
|
|
1072
|
+
- id: techniques-registry
|
|
1073
|
+
tier: core
|
|
1074
|
+
title: "Techniques"
|
|
1075
|
+
content: |
|
|
1076
|
+
## Techniques
|
|
1077
|
+
Named techniques, algorithms, and domain frameworks active in this project.
|
|
1078
|
+
Each name activates the AI's full training on that technique — no explanation needed.
|
|
1079
|
+
A technique named here is available at the full depth of the model's training on it.
|
|
1080
|
+
### Active Techniques
|
|
1081
|
+
<!-- Add project-specific techniques below.
|
|
1082
|
+
Examples: RAPTOR indexing · BM25+vector hybrid with RRF fusion ·
|
|
1083
|
+
PCA geometric validation · deontic modal logic · CQRS · Saga pattern -->
|
|
1084
|
+
- [Add named techniques here]
|
|
1085
|
+
|
|
1086
|
+
- id: test-taxonomy
|
|
1087
|
+
tier: recommended
|
|
1088
|
+
title: "Test Taxonomy"
|
|
1089
|
+
content: |
|
|
1090
|
+
## Testing Architecture
|
|
1091
|
+
|
|
1092
|
+
### Test Types by Scope and Purpose
|
|
1093
|
+
Listed from fastest/most-isolated to slowest/most-integrated:
|
|
1094
|
+
|
|
1095
|
+
| Type | Description | Tooling |
|
|
1096
|
+
|---|---|---|
|
|
1097
|
+
| **Unit — Solitary** | Single unit; mock all collaborators. | Jest, Vitest, pytest |
|
|
1098
|
+
| **Unit — Sociable** | Single unit; allow fast non-I/O collaborators (no mocking real logic). | Jest, Vitest, pytest |
|
|
1099
|
+
| **Integration — Narrow (DB)** | Exercise one layer against a real local DB; no external services. | Testcontainers, SQLite, in-process Postgres |
|
|
1100
|
+
| **Integration — Service** | Service + stubs for external deps via WireMock or equivalent. | WireMock, Wiremock-rs, msw |
|
|
1101
|
+
| **Contract / Consumer-Driven (CDC)** | Consumer writes pact file; provider verifies. Prevents API breakage without full E2E infra. | Pact, Spring Cloud Contract |
|
|
1102
|
+
| **API / Subcutaneous** | HTTP or WebSocket layer below the UI; tests the full request-response cycle without browser. | Supertest, Playwright APIRequestContext, httpx |
|
|
1103
|
+
| **Acceptance / BDD** | Given-When-Then; orthogonal to pyramid — level is a performance choice, not semantic. | Cucumber, behave, should-style assertions |
|
|
1104
|
+
| **E2E** | Full user flows in a real browser. Keep minimal — expensive and brittle. Reserve for highest-value journeys. | Playwright, Cypress |
|
|
1105
|
+
| **Visual Regression** | Pixel-diff baseline + LLM visual analysis for judgment-requiring defects. | Percy, Chromatic, Playwright snapshots |
|
|
1106
|
+
| **Smoke** | Deployed environment only. Strictly happy-path. Binary pass/fail deploy gate. | Playwright, custom health check suite |
|
|
1107
|
+
| **Regression** | Discipline: full suite green before merge. Not a test type — a required gate. | All layers |
|
|
1108
|
+
| **Security — SAST** | Static analysis at commit: code pattern scanning and dep vulnerability scanning. | Semgrep, SonarQube, ESLint security plugins, npm audit, Snyk |
|
|
1109
|
+
| **Security — DAST** | Dynamic analysis at staging: automated attack surface probing. | OWASP ZAP, Burp Suite |
|
|
1110
|
+
| **Security — Penetration** | Adversarial session at release candidate gate; OWASP Top 10 coverage. | Manual + OWASP ZAP, Burp Suite |
|
|
1111
|
+
| **Mutation** | Tests the tests: injects code mutations and verifies the suite catches them. Tracked at PR; required above threshold at RC. | Stryker (JS), PIT (Java), mutmut (Python) |
|
|
1112
|
+
| **Property-Based / Fuzz** | Auto-generates input space against stated invariants. Fuzzing is the adversarial variant. | fast-check (JS), Hypothesis (Python) |
|
|
1113
|
+
| **Accessibility / a11y** | WCAG 2.1 AA. Automated at PR; full manual audit at RC. | axe-core, Playwright @axe-core, Lighthouse |
|
|
1114
|
+
| **Performance: Load / Stress / Soak** | At staging. Required before production on systems with SLAs. | k6, Locust, Gatling |
|
|
1115
|
+
| **Chaos / Resilience** | Random fault injection against deployed environment; named resilience contracts. | Toxiproxy, ChaosMesh, custom fault injection |
|
|
1116
|
+
| **Exploratory** | Manual, session-based, scheduled. Charter-driven. Findings become regression tests. | Manual + session notes |
|
|
1117
|
+
|
|
1118
|
+
### Variant Coverage Dimensions
|
|
1119
|
+
For each test scope, the following input/condition variants are required:
|
|
1120
|
+
|
|
1121
|
+
- **Happy path** — nominal, valid inputs. Necessary but never sufficient.
|
|
1122
|
+
- **Sad / Negative path** — correct rejection of invalid input or sequences.
|
|
1123
|
+
- **Edge case / BVA** — boundary values: max, min, empty, null, type coercions.
|
|
1124
|
+
- **Corner case** — intersection of two or more simultaneous edge conditions. Requires explicit enumeration.
|
|
1125
|
+
- **State transition** — valid and invalid state machine transitions. Requires a state diagram as prerequisite.
|
|
1126
|
+
- **Equivalence partitioning** — one representative from each equivalence class. Reduces test count without reducing coverage.
|
|
1127
|
+
- **Error path** — infrastructure/dependency failure: timeout, 500, DB refused, queue full — conditions the user did not cause.
|
|
1128
|
+
- **Security / Adversarial input** — SQL injection, XSS, path traversal, oversized payloads, malformed tokens. Required at every layer touching user-supplied data.
|
|
1129
|
+
- **Random / Monkey** — unstructured random input. Subsumed by property-based layer.
|
|
1130
|
+
|
|
1131
|
+
**Variant coverage matrix** (✓ = required, ~ = structural constraint, — = not applicable):
|
|
1132
|
+
|
|
1133
|
+
| Variant | Unit | Integration | Contract | API | E2E | Smoke | Chaos |
|
|
1134
|
+
|---|---|---|---|---|---|---|---|
|
|
1135
|
+
| Happy path | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | — |
|
|
1136
|
+
| Sad / Negative | ✓ | ✓ | ✓ | ✓ | ~ | ~ happy-path only | — |
|
|
1137
|
+
| Edge / BVA | ✓ | ✓ | — | ✓ | — | — | — |
|
|
1138
|
+
| Corner case | ✓ | — | — | ✓ | — | — | — |
|
|
1139
|
+
| State transition | ✓ | ✓ | — | ✓ | ✓ | — | — |
|
|
1140
|
+
| Equivalence partition | ✓ | — | — | ✓ | — | — | — |
|
|
1141
|
+
| Error path | ✓ | ✓ | — | ✓ | — | — | ✓ |
|
|
1142
|
+
| Security / Adversarial | — | — | — | ✓ | — | — | ~ always adversarial |
|
|
1143
|
+
| Random / Monkey | via property-based | — | — | — | — | — | ✓ |
|
|
1144
|
+
|
|
1145
|
+
### Test Pipeline Mapping
|
|
1146
|
+
Each trigger gate accumulates the prior gates. A gate may not be skipped.
|
|
1147
|
+
|
|
1148
|
+
| Trigger | Gate Contents | Target Duration |
|
|
1149
|
+
|---|---|---|
|
|
1150
|
+
| **File save** | Unit only | ~seconds |
|
|
1151
|
+
| **git commit / push** | Unit + integration + SAST + dependency scan + lint + regression gate | ~2–5 min |
|
|
1152
|
+
| **Pull request** | All prior + contract + API/subcutaneous + E2E (core flows) + acceptance + visual regression + a11y (automated) + property-based | ~10–20 min |
|
|
1153
|
+
| **Deploy to staging** | Smoke → DAST → performance baseline → chaos/resilience | ~45–60 min |
|
|
1154
|
+
| **Release candidate** | All layers blocking + penetration test + full a11y audit + mutation score gate + compatibility matrix | Per schedule |
|
|
1155
|
+
| **Production deploy** | Canary deploy + synthetic monitoring + A/B if applicable | Continuous |
|
|
1156
|
+
|
|
1157
|
+
> Mutation score gate: minimum 70% at PR, 80% at RC on changed code. Stryker/mutmut reports block promotion below threshold.
|
|
1158
|
+
|
|
1159
|
+
- id: release-phase-gate
|
|
1160
|
+
tier: core
|
|
1161
|
+
title: "Active Release Phase Gate"
|
|
1162
|
+
content: |
|
|
1163
|
+
## Active Release Phase: {{release_phase | default: development}}
|
|
1164
|
+
|
|
1165
|
+
Your current phase determines which test gates are **required now**, not advisory.
|
|
1166
|
+
The full taxonomy and trigger mapping are in the Testing section above.
|
|
1167
|
+
Read your phase row below and apply every requirement listed.
|
|
1168
|
+
|
|
1169
|
+
| Phase | Required now — blocking | Not required yet |
|
|
1170
|
+
|---|---|---|
|
|
1171
|
+
| **development** | Unit + integration + lint + tsc --noEmit + npm audit (no HIGH/CRITICAL) | DAST, load/stress, penetration, mutation score gate |
|
|
1172
|
+
| **pre-release / staging** | All development requirements + smoke → DAST (OWASP ZAP / Burp Suite) + load test at 2× peak (k6 / Locust) + chaos/resilience (Toxiproxy) + mutation score ≥ 80% on changed code | Manual penetration test, full a11y audit |
|
|
1173
|
+
| **release-candidate** | All staging requirements + manual penetration test (OWASP Top 10, JWT vectors, BOLA/IDOR) + full a11y audit (if UI) + compatibility matrix + mutation score ≥ 80% overall + zero unresolved HIGH/CRITICAL CVEs | Production canary |
|
|
1174
|
+
| **production** | Canary deploy + automatic rollback on error rate spike + synthetic health probes + incident runbook verified | — |
|
|
1175
|
+
|
|
1176
|
+
**Current active phase: `{{release_phase | default: development}}`**
|
|
1177
|
+
|
|
1178
|
+
> If the phase is `pre-release` or `release-candidate`:
|
|
1179
|
+
> Hardening tests (load, DAST, penetration) are REQUIRED in this session, not deferred.
|
|
1180
|
+
> Do not proceed to merge without completing the required gate for your phase.
|
|
1181
|
+
> The Testing section above maps each gate to its tooling and target duration.
|
|
1182
|
+
|
|
1183
|
+
- id: gs-test-techniques
|
|
1184
|
+
tier: recommended
|
|
1185
|
+
title: "Generative Specification — Testing Techniques"
|
|
1186
|
+
content: |
|
|
1187
|
+
## Generative Specification: Testing Techniques
|
|
1188
|
+
|
|
1189
|
+
These five techniques are specific to GS practice and extend the standard taxonomy above.
|
|
1190
|
+
|
|
1191
|
+
### Adversarial Test Posture
|
|
1192
|
+
The test is a hunter, not a witness.
|
|
1193
|
+
- Tests are written to FAIL on incorrect code — to find the input or condition that exposes
|
|
1194
|
+
a violation, not to confirm the current behavior.
|
|
1195
|
+
- Tests must be written against interfaces, not implementations.
|
|
1196
|
+
A test coupled to internal state fails on correct refactors and passes on behavioral violations
|
|
1197
|
+
that happen to preserve internal structure. That is the worst outcome.
|
|
1198
|
+
|
|
1199
|
+
### Expose-Store-to-Window (Interactive / Game / Real-Time UIs)
|
|
1200
|
+
For applications with a shared state store (Redux, Zustand, Pinia, state machine), expose the
|
|
1201
|
+
store to `window` in the test environment:
|
|
1202
|
+
```typescript
|
|
1203
|
+
if (process.env.NODE_ENV === 'test') {
|
|
1204
|
+
(window as any).__store = store;
|
|
1205
|
+
}
|
|
1206
|
+
```
|
|
1207
|
+
Playwright tests can then assert both what the screen renders AND what the application believes
|
|
1208
|
+
is true — the store's internal state — without coupling assertions to DOM structure. This catches
|
|
1209
|
+
the failure class that renders correctly but corrupts internal state (score displays right, stored wrong;
|
|
1210
|
+
entity in undefined state not yet manifested as a visual defect).
|
|
1211
|
+
|
|
1212
|
+
### Vertical Chain Test
|
|
1213
|
+
A single UI action triggers Playwright, which then:
|
|
1214
|
+
1. Queries the service layer response
|
|
1215
|
+
2. Queries the database state and any affected indexes
|
|
1216
|
+
3. Verifies correct propagation through every boundary the action crosses
|
|
1217
|
+
4. Returns to the UI to confirm the visible outcome matches the stored state
|
|
1218
|
+
|
|
1219
|
+
Not a unit test, not a visual check, not a flow test: a chain verification. One trigger, inspected
|
|
1220
|
+
at every boundary it crosses. Specify which critical flows receive this treatment in the test
|
|
1221
|
+
architecture document. A defect anywhere in the chain (service logic, persistence, index consistency,
|
|
1222
|
+
UI rendering) is surfaced in a single pass.
|
|
1223
|
+
|
|
1224
|
+
### Mutation Testing as Adversarial Audit
|
|
1225
|
+
An AI-generated test suite carries a structural risk: tests written by a system that knows the
|
|
1226
|
+
correct implementation may pass it rather than catch violations of it.
|
|
1227
|
+
- Run Stryker (JS/TS) or mutmut (Python) against every AI-generated suite before accepting it.
|
|
1228
|
+
- A test that passes a mutant is not testing the contract — it is confirming the absence of one
|
|
1229
|
+
specific mutation, no more.
|
|
1230
|
+
- Coverage measures what was executed. Mutation score measures what was caught. The second is
|
|
1231
|
+
the meaningful metric.
|
|
1232
|
+
- Gates: 70% mutation score at PR, 80% at release candidate on changed code.
|
|
1233
|
+
|
|
1234
|
+
### Multimodal Quality Gates (Generative Assets)
|
|
1235
|
+
When content is AI-generated (images, audio, video), the acceptance criteria must be executable.
|
|
1236
|
+
Manual review at scale is not a pipeline.
|
|
1237
|
+
|
|
1238
|
+
**Visual assets (sprite sheets, generated imagery):**
|
|
1239
|
+
```python
|
|
1240
|
+
# PCA-based orientation check
|
|
1241
|
+
from sklearn.decomposition import PCA
|
|
1242
|
+
pca = PCA(n_components=2).fit(ship_pixel_coordinates)
|
|
1243
|
+
angle = np.degrees(np.arctan2(*pca.components_[0][::-1]))
|
|
1244
|
+
assert abs(angle) <= 15, f"Sprite orientation {angle:.1f}° exceeds 15° tolerance"
|
|
1245
|
+
|
|
1246
|
+
# Symmetry check (horizontal flip similarity)
|
|
1247
|
+
similarity = ssim(img_half_left, np.fliplr(img_half_right))
|
|
1248
|
+
assert similarity >= 0.85, f"Symmetry {similarity:.2f} below 0.85 threshold"
|
|
1249
|
+
```
|
|
1250
|
+
|
|
1251
|
+
**Audio assets:**
|
|
1252
|
+
- Loudness normalization: assert target LUFS within ±1 dB of spec (pyloudnorm).
|
|
1253
|
+
- Frequency profile: no asset competes in the 2–4 kHz presence range during dialogue.
|
|
1254
|
+
- Silence detection: reject assets with generation artifacts (> X ms silence in unexpected positions).
|
|
1255
|
+
|
|
1256
|
+
**MCP-mediated inspection (judgment-requiring defects):**
|
|
1257
|
+
An instrumented game/app state exposed through an MCP server lets a language model
|
|
1258
|
+
evaluate whether a running scene satisfies its acceptance criteria without pre-scripting
|
|
1259
|
+
every assertion. Feed the model the scene spec + MCP access; it reports violations.
|
|
1260
|
+
This addresses defects that are easy to name but hard to encode as assertions.
|
|
1261
|
+
|
|
1262
|
+
- id: artifact-grammar
|
|
1263
|
+
tier: core
|
|
1264
|
+
title: "Artifact Grammar"
|
|
1265
|
+
content: |
|
|
1266
|
+
## Artifact Grammar — The Generative Specification
|
|
1267
|
+
|
|
1268
|
+
A system achieves generative specification when any AI coding assistant, given access to
|
|
1269
|
+
its artifacts alone, can: correctly identify what should and should not change for any
|
|
1270
|
+
requirement; produce output conforming to architectural, quality, and behavioral contracts;
|
|
1271
|
+
and detect when any existing artifact violates those contracts.
|
|
1272
|
+
|
|
1273
|
+
Each artifact type below is a production rule in the system's grammar. Absent artifacts
|
|
1274
|
+
are specification gaps. A gap is not a documentation debt — it is an architecturally
|
|
1275
|
+
incomplete grammar.
|
|
1276
|
+
|
|
1277
|
+
| Artifact | Function in the System | Required |
|
|
1278
|
+
|---|---|---|
|
|
1279
|
+
| **Architectural constitution** (`CLAUDE.md` / `AGENTS.md` / `.cursor/rules/` / `.github/copilot-instructions.md`) | Defines what is and is not a valid sentence in this system. Governs every AI interaction. Agent-agnostic concept; filename is agent-specific. | Core |
|
|
1280
|
+
| **Architecture Decision Records (ADRs)** | Documents why the grammar evolved. Prevents the AI from "correcting" intentional decisions that appear suboptimal without context. | Core |
|
|
1281
|
+
| **C4 diagrams / structural diagrams** (PlantUML, Mermaid) | The parsed structural representation: system context, container topology, component composition. Static structure at a glance for any agent entering the codebase. **Emit as files in P1** — `docs/diagrams/c4-context.md` and `docs/diagrams/c4-container.md`. A diagram referenced in prose but not written to disk provides zero structural constraint. | Recommended |
|
|
1282
|
+
| **Sequence diagrams** | Fix the inter-component protocol: which call, in which order, with which contracts. A sequence diagram specifying that auth precedes data fetch is an unambiguous ordering constraint. The AI has two valid sentences: the one matching the diagram, and deviations from it. **Emit as `docs/diagrams/sequence-[feature].md` in P1** with real `participant` declarations and message arrows — not an empty file. | Recommended |
|
|
1283
|
+
| **State machine diagrams** | Enumerate every valid state and every valid transition. Directly generate state transition test cases and user-facing modal behavior documentation. **Emit as `docs/diagrams/state-[entity].md` in P1** with real `stateDiagram-v2` states and transitions — these become the source of truth for state transition tests. | When system has states |
|
|
1284
|
+
| **User flow diagrams** | Define the expected journey from entry to outcome. Simultaneously the script for every E2E test in that flow and the user journey narrative for the manual. **Emit as `docs/diagrams/flow-[usecase].md` in P1** with real `flowchart` Start/End nodes and decision diamonds. | Recommended |
|
|
1285
|
+
| **Use cases** | Single, precise descriptions of an interaction. One use case seeds three artifacts: implementation contract, acceptance test, user documentation. See `use-case-triple-derivation`. | Recommended |
|
|
1286
|
+
| **Schema definitions** (DB, API, events) | The vocabulary of the system with constraints formally stated. Types, relations, validation rules, value ranges. | Core |
|
|
1287
|
+
| **Living documentation** (derived) | OpenAPI from decorators/schemas; TypeDoc/JSDoc auto-published; Storybook from component specs; README sections from centralized specs. Documentation maintained separately from code drifts — documentation derived from the same artifacts cannot be wrong in a way the code is right. | Recommended |
|
|
1288
|
+
| **Naming conventions** (explicit in constitution) | Semantic signal at every token. `calculateMonthlyCostPerMember` carries domain, operation, unit, scope. `processData` carries nothing. Names are grammar; the AI propagates every name it reads. | Core |
|
|
1289
|
+
| **Package and module hierarchy** | Communicates responsibility and ownership through structure. The location of a file is a claim about what it is. | Core |
|
|
1290
|
+
| **Conventional atomic commits** | Typed corpus: `feat(billing): add prorated invoice calculation` has a part of speech, scope, and semantic payload. The git log is a readable history of how the grammar evolved and why. | Core |
|
|
1291
|
+
| **Test suite (adversarial)** | Each test is a specification assertion AND adversarial challenge. The suite is a continuously-running audit and standing challenge to the implementation. Written against interfaces, not implementations. | Core |
|
|
1292
|
+
| **Commit hooks and quality gates** | Malformed input is structurally rejected before entering the system. Certain classes of mistake are architecturally unreachable. | Core |
|
|
1293
|
+
| **Status.md** | Session bridge: current implementation state, what was completed, where the session stopped, what was tried. The Auditable property requires both that the record exists and that the next session begins by reading it. | Core |
|
|
1294
|
+
| **MCP tools and environment tooling** | The tools available to the agent define what operations are possible. Bounded tool access is bounded agency. Specification governs not just code but the system that can act. | Optional |
|
|
1295
|
+
|
|
1296
|
+
> **Emit, Don't Reference.** Every diagram type above that is marked "Recommended" or
|
|
1297
|
+
> higher must be written as a file on disk with real, parseable content. A spec that
|
|
1298
|
+
> says "a sequence diagram should be created later" is not a grammar production rule — it
|
|
1299
|
+
> is a forward reference. Forward references do not constrain the AI. Only emitted files
|
|
1300
|
+
> do. If a diagram file exists but still contains `<!-- UNFILLED -->`, it is a known gap.
|
|
1301
|
+
> Known gaps must be on the cascade backlog; they are not acceptable as a final state.
|
|
1302
|
+
|
|
1303
|
+
### The Six Properties (self-test)
|
|
1304
|
+
A generative specification satisfies all six. Use as an inspection checklist:
|
|
1305
|
+
- **Self-describing**: Does the system explain its own architecture, decisions, and conventions from its own artifacts?
|
|
1306
|
+
- **Bounded**: Does every unit have explicit scope and seams? Is the context window to modify any unit predictably bounded?
|
|
1307
|
+
- **Verifiable**: Can the correctness of any output be checked without human judgment? Is verification automatic, fast, and blocking?
|
|
1308
|
+
- **Defended**: Are destructive operations structurally prevented (hooks, gates) rather than merely discouraged?
|
|
1309
|
+
- **Auditable**: Is the current state and full history recoverable from artifacts alone? Would the AI treat an intentional decision as a defect to correct?
|
|
1310
|
+
- **Composable**: Can units be combined without unexpected coupling? Can the AI work on any unit in isolation because isolation is structural?
|
|
1311
|
+
|
|
1312
|
+
> **GS Protocol on demand:** call `get_reference(resource: guidance)` for the full
|
|
1313
|
+
> session-loop procedure, context-loading strategy, incremental cascade, bound roadmap
|
|
1314
|
+
> format, and diagnostic checklist. These procedures are NOT inlined here to preserve
|
|
1315
|
+
> the token budget of this instruction file.
|
|
1316
|
+
|
|
1317
|
+
- id: naming-as-grammar
|
|
1318
|
+
tier: core
|
|
1319
|
+
title: "Names Are Production Rules"
|
|
1320
|
+
content: |
|
|
1321
|
+
## Names Are Production Rules
|
|
1322
|
+
|
|
1323
|
+
In a context-sensitive system, naming is not style. It is grammar.
|
|
1324
|
+
|
|
1325
|
+
A function named `getUser` in a domain model that talks to a database is an architecture
|
|
1326
|
+
violation the compiler will not catch, the linter may not catch, and a human reviewer
|
|
1327
|
+
will tolerate — but the AI will propagate. The name signals layer; the AI reads the signal.
|
|
1328
|
+
|
|
1329
|
+
### Layer-Scoped Naming Vocabulary
|
|
1330
|
+
Enforce consistent naming by layer. Deviations are architecture violations.
|
|
1331
|
+
|
|
1332
|
+
| Layer | Allowed verbs / patterns | Examples |
|
|
1333
|
+
|---|---|---|
|
|
1334
|
+
| **Repository** | `find`, `save`, `delete`, `exists`, `count` | `findUserByEmail`, `saveOrder`, `deleteById` |
|
|
1335
|
+
| **Service** | `get`, `create`, `update`, `process`, `calculate`, `validate` | `getUserProfile`, `createInvoice`, `calculateMonthlyCost` |
|
|
1336
|
+
| **Controller / Handler** | `handle`, `on` + event name | `handleCreateUser`, `onPaymentReceived` |
|
|
1337
|
+
| **Domain model** | noun + computed property / behavior | `Invoice.totalWithTax`, `User.isExpired` |
|
|
1338
|
+
| **Event** | past tense, domain noun | `UserRegistered`, `OrderShipped`, `PaymentFailed` |
|
|
1339
|
+
| **DTO** | noun + `Request` / `Response` or `Dto` | `CreateUserRequest`, `UserProfileResponse` |
|
|
1340
|
+
| **Interface / Port** | capability noun | `UserRepository`, `EmailSender`, `PaymentGateway` |
|
|
1341
|
+
|
|
1342
|
+
### Naming as Technique Transport
|
|
1343
|
+
What a practitioner names in a specification, the AI knows how to apply.
|
|
1344
|
+
Every technique in the model's training corpus becomes available to any system whose
|
|
1345
|
+
specification names it. A specification that says "analyze legal arguments" receives
|
|
1346
|
+
legal analysis. A specification that names prosody, argumentation theory, fallacy
|
|
1347
|
+
classification, and deontic modal logic receives a specialist instrument calibrated
|
|
1348
|
+
to the domain. The naming cost is one word. The activation cost of the AI's knowledge
|
|
1349
|
+
of the field is zero once the name appears.
|
|
1350
|
+
|
|
1351
|
+
Name patterns, techniques, and domain frameworks explicitly in the architectural
|
|
1352
|
+
constitution. The specification is a technique registry whose scope is the full depth
|
|
1353
|
+
of the model's training, activated at the cost of knowing the correct words to write.
|
|
1354
|
+
|
|
1355
|
+
- id: adr-protocol
|
|
1356
|
+
tier: core
|
|
1357
|
+
title: "ADR Protocol"
|
|
1358
|
+
content: |
|
|
1359
|
+
## ADR Protocol — Persistent Memory
|
|
1360
|
+
|
|
1361
|
+
Every non-obvious architectural decision produces an ADR before implementation begins.
|
|
1362
|
+
An unrecorded architectural decision is a gap in the grammar.
|
|
1363
|
+
|
|
1364
|
+
Without an ADR, the AI will "improve" intentional decisions that appear suboptimal
|
|
1365
|
+
without context — turning deliberate architectural tradeoffs into silently-introduced drift.
|
|
1366
|
+
|
|
1367
|
+
### Format (minimal)
|
|
1368
|
+
```markdown
|
|
1369
|
+
# ADR-NNNN: [Decision Title]
|
|
1370
|
+
|
|
1371
|
+
**Date**: YYYY-MM-DD
|
|
1372
|
+
**Status**: Proposed | Accepted | Deprecated | Superseded by ADR-NNNN
|
|
1373
|
+
|
|
1374
|
+
## Context
|
|
1375
|
+
What is the situation that requires a decision? What forces are in tension?
|
|
1376
|
+
|
|
1377
|
+
## Decision
|
|
1378
|
+
What was decided? State it plainly.
|
|
1379
|
+
|
|
1380
|
+
## Alternatives Considered
|
|
1381
|
+
What other options were evaluated and why were they not chosen?
|
|
1382
|
+
|
|
1383
|
+
## Consequences
|
|
1384
|
+
What becomes easier or harder as a result of this decision?
|
|
1385
|
+
What will the AI need to know to work within this constraint?
|
|
1386
|
+
```
|
|
1387
|
+
|
|
1388
|
+
### When to Write an ADR
|
|
1389
|
+
- Any architectural choice that is not obvious from the code structure
|
|
1390
|
+
- Any decision that involves a tradeoff (performance vs. simplicity, security vs. UX)
|
|
1391
|
+
- Any decision that was reached after considering alternatives
|
|
1392
|
+
- Any decision that future engineers (or AI sessions) might be tempted to "fix"
|
|
1393
|
+
- Any change to the architectural constitution itself
|
|
1394
|
+
|
|
1395
|
+
### ADR Directory
|
|
1396
|
+
- Path: `docs/adrs/` (zero-padded, kebab-case: `ADR-0001-short-title.md`)
|
|
1397
|
+
- ADRs are immutable once Accepted. To change a decision: write a new ADR that supersedes the old one.
|
|
1398
|
+
- The old ADR is updated only to add `Superseded by ADR-NNNN` to its status.
|
|
1399
|
+
|
|
1400
|
+
### ADR Stubs — Emit in P1
|
|
1401
|
+
When starting a new project, emit ADR stub files as **fenced code blocks** in the first
|
|
1402
|
+
response alongside `prisma/schema.prisma`, `tsconfig.json`, and `package.json`.
|
|
1403
|
+
ADRs referenced only in a README but not written as files are not present in the project.
|
|
1404
|
+
The model cannot reference a file that does not exist. Emit the file.
|
|
1405
|
+
|
|
1406
|
+
**Minimum ADRs to emit in P1** (adapt titles to the actual stack chosen):
|
|
1407
|
+
- `docs/adrs/ADR-0001-stack.md` — language, runtime, framework, ORM selection and rationale
|
|
1408
|
+
- `docs/adrs/ADR-0002-authentication.md` — auth strategy (JWT/session), hashing algorithm and why
|
|
1409
|
+
- `docs/adrs/ADR-0003-architecture.md` — layered/hexagonal architecture decision and boundary rules
|
|
1410
|
+
|
|
1411
|
+
Each ADR stub must contain real content in `Status`, `Context`, `Decision`, and `Consequences`
|
|
1412
|
+
fields — not placeholder text. A stub that says "TBD" is not an ADR.
|
|
1413
|
+
|
|
1414
|
+
**ADR reference check:** If your README mentions `docs/adrs/ADR-0001-stack.md`, that file
|
|
1415
|
+
must appear as a fenced code block in the same response. A reference to a non-emitted file
|
|
1416
|
+
is an Auditable violation — it creates the appearance of traceability without the substance.
|
|
1417
|
+
|
|
1418
|
+
Also emit **`CHANGELOG.md`** in P1 with initial content documenting the P1 decisions:
|
|
1419
|
+
```markdown
|
|
1420
|
+
# Changelog
|
|
1421
|
+
All notable changes to this project will be documented here.
|
|
1422
|
+
Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
|
|
1423
|
+
|
|
1424
|
+
## [Unreleased]
|
|
1425
|
+
### Added
|
|
1426
|
+
- Initial project scaffold: layered architecture, Prisma schema, repository interfaces
|
|
1427
|
+
- Authentication: JWT + Argon2 (see ADR-0002)
|
|
1428
|
+
- Dependency registry: docs/approved-packages.md with audit baseline
|
|
1429
|
+
- CI pipeline: lint, type-check, test, npm audit, mutation gate
|
|
1430
|
+
- Pre-commit hooks: tsc, lint, audit, test gates
|
|
1431
|
+
```
|
|
1432
|
+
A CHANGELOG that exists only as "we will add one" is not Auditable. Write the file.
|
|
1433
|
+
Document the P1 decisions immediately — the first entry is not a release entry, it is the
|
|
1434
|
+
architectural record of what was built in this session.
|
|
1435
|
+
|
|
1436
|
+
### Session Protocol
|
|
1437
|
+
Every session begins by reading the open ADRs. The status of each ADR is the authoritative
|
|
1438
|
+
record of what is intentional. A session that modifies an ADR-governed boundary without
|
|
1439
|
+
first reading the ADR has produced drift, regardless of whether the code compiles.
|
|
1440
|
+
|
|
1441
|
+
- id: use-case-triple-derivation
|
|
1442
|
+
tier: recommended
|
|
1443
|
+
title: "Use Case Triple Derivation"
|
|
1444
|
+
content: |
|
|
1445
|
+
## Use Cases — Triple Derivation
|
|
1446
|
+
|
|
1447
|
+
A use case is not a requirements artifact produced before implementation and superseded by it.
|
|
1448
|
+
In a generative specification it is a multi-purpose production rule: a single, precise
|
|
1449
|
+
description of an interaction from which three artifacts derive independently and without
|
|
1450
|
+
redundancy.
|
|
1451
|
+
|
|
1452
|
+
### The Three Derivations
|
|
1453
|
+
1. **Implementation contract** — The use case names the actor, precondition, trigger, and
|
|
1454
|
+
postcondition with enough precision to be unambiguous. This is the specification the
|
|
1455
|
+
service layer is written against. When the AI reads a well-formed use case before
|
|
1456
|
+
generating the corresponding service method, it has what a human architect would
|
|
1457
|
+
communicate in a design review.
|
|
1458
|
+
|
|
1459
|
+
2. **Acceptance test** — The use case and the test scenario are the same artifact expressed
|
|
1460
|
+
in different dialects. A Playwright E2E test for a checkout flow is the checkout use case
|
|
1461
|
+
transcribed into executable form. A Cucumber scenario in Given-When-Then is the use case
|
|
1462
|
+
in declarative test notation. When the use case is precise, the test writes itself.
|
|
1463
|
+
**When the test is hard to write, the use case is underspecified.** The test difficulty
|
|
1464
|
+
is the diagnostic for underspecification.
|
|
1465
|
+
|
|
1466
|
+
3. **User documentation** — A use case narrated to a non-technical reader (actor, goal,
|
|
1467
|
+
precondition, sequence, expected outcome, error cases) is a user manual section.
|
|
1468
|
+
The content is identical. The framing is different. A specification with complete use
|
|
1469
|
+
cases does not need a separate documentation writing pass — it needs a rendering pass.
|
|
1470
|
+
|
|
1471
|
+
### Use Case Format (minimal)
|
|
1472
|
+
```markdown
|
|
1473
|
+
## UC-NNN: [Action] [Domain Object]
|
|
1474
|
+
|
|
1475
|
+
**Actor**: [who initiates]
|
|
1476
|
+
**Precondition**: [what must be true before]
|
|
1477
|
+
**Trigger**: [what event or action starts the flow]
|
|
1478
|
+
**Main Flow**:
|
|
1479
|
+
1. [Step one]
|
|
1480
|
+
2. [Step two]
|
|
1481
|
+
**Postcondition**: [what is true after success]
|
|
1482
|
+
**Error Cases**:
|
|
1483
|
+
- [Condition]: [System response]
|
|
1484
|
+
**Acceptance Criteria** (machine-checkable):
|
|
1485
|
+
- [ ] [Criterion 1]
|
|
1486
|
+
- [ ] [Criterion 2]
|
|
1487
|
+
```
|
|
1488
|
+
|
|
1489
|
+
### The Diagnostic Rule
|
|
1490
|
+
Before writing any service method, write the use case first. If you cannot state the
|
|
1491
|
+
precondition and postcondition precisely, you do not yet understand the behavior well enough
|
|
1492
|
+
to implement it correctly. The implementation will be wrong. The use case forces the
|
|
1493
|
+
understanding the implementation requires.
|
|
1494
|
+
|
|
1495
|
+
- id: living-documentation
|
|
1496
|
+
tier: recommended
|
|
1497
|
+
title: "Living Documentation"
|
|
1498
|
+
content: |
|
|
1499
|
+
## Living Documentation — Derived, Not Maintained
|
|
1500
|
+
|
|
1501
|
+
Documentation maintained separately from the code it describes is structurally certain
|
|
1502
|
+
to drift. An API reference written by hand becomes wrong the moment the signature changes.
|
|
1503
|
+
A system overview written at architecture time becomes misleading the moment the first
|
|
1504
|
+
refactor lands.
|
|
1505
|
+
|
|
1506
|
+
The failure is structural, not motivational. The documentation and the code share no source
|
|
1507
|
+
of truth. Drift is the natural consequence, not a failure of discipline.
|
|
1508
|
+
|
|
1509
|
+
### The Generative Specification Resolution
|
|
1510
|
+
Documentation is a derivation from the same artifacts the AI reads — which means it cannot
|
|
1511
|
+
be wrong in a way the code is right, because they share a source.
|
|
1512
|
+
|
|
1513
|
+
| Documentation type | Derivation source | Tooling |
|
|
1514
|
+
|---|---|---|
|
|
1515
|
+
| **API reference** | TypeScript type annotations + Zod schemas → OpenAPI/Swagger | `swagger-jsdoc`, `zod-to-openapi`, `ts-rest` |
|
|
1516
|
+
| **Function/class docs** | Inline JSDoc / docstrings, auto-published | TypeDoc, pdoc, mkdocs |
|
|
1517
|
+
| **Component catalog** | Component spec files | Storybook |
|
|
1518
|
+
| **README sections** | Centralized spec files, not narrative paragraphs | Custom scripts, code-gen templates |
|
|
1519
|
+
| **Database schema docs** | Prisma schema / migration files | `prisma-docs-generator` |
|
|
1520
|
+
| **Event catalog** | Event type definitions | AsyncAPI |
|
|
1521
|
+
| **Architecture diagrams** | Code structure → diagram | Structurizr, Mermaid auto-gen |
|
|
1522
|
+
|
|
1523
|
+
### Rules
|
|
1524
|
+
- Never write documentation that paraphrases code. If the doc says what the code says,
|
|
1525
|
+
one of them is redundant — and the code wins on recency.
|
|
1526
|
+
- Inline documentation (JSDoc/docstrings) belongs at the declaration, not in a separate file.
|
|
1527
|
+
- A README section that duplicates a type definition is a liability. Point to the type.
|
|
1528
|
+
- Documentation is a derivation step in the CI pipeline, not a separate task.
|
|
1529
|
+
|
|
1530
|
+
### Polyglot Systems
|
|
1531
|
+
The argument is sharpest when the system spans multiple languages, runtimes, or paradigms.
|
|
1532
|
+
Without a specification that holds naming contracts and behavioral contracts at the layer
|
|
1533
|
+
where they cross language lines, the system fragments. Cross-language interface contracts
|
|
1534
|
+
must be stated explicitly in language-neutral terms — the architectural constitution that
|
|
1535
|
+
both runtimes read.
|
|
1536
|
+
|
|
1537
|
+
- id: agentic-self-refinement
|
|
1538
|
+
tier: recommended
|
|
1539
|
+
title: "Agentic Self-Refinement"
|
|
1540
|
+
content: |
|
|
1541
|
+
## Agentic Self-Refinement
|
|
1542
|
+
|
|
1543
|
+
Wherever desired output can be specified and actual output can be observed, the agent
|
|
1544
|
+
can close a feedback loop on its own execution without human intervention between cycles.
|
|
1545
|
+
The structure is identical regardless of domain: desired state → generate → evaluate
|
|
1546
|
+
against spec-defined acceptance criteria → adjust parameters or session context → regenerate.
|
|
1547
|
+
|
|
1548
|
+
### The Loop Structure
|
|
1549
|
+
```
|
|
1550
|
+
SPECIFY → GENERATE → EVALUATE (against acceptance criteria)
|
|
1551
|
+
↑ |
|
|
1552
|
+
└──── ADJUST ────────┘
|
|
1553
|
+
(if criteria not met)
|
|
1554
|
+
```
|
|
1555
|
+
|
|
1556
|
+
The loop terminates when acceptance criteria are satisfied or retry budget is exhausted.
|
|
1557
|
+
The retry budget is itself a constraint in the specification.
|
|
1558
|
+
|
|
1559
|
+
### Applications by Domain
|
|
1560
|
+
| Domain | Generate | Evaluate | Adjust |
|
|
1561
|
+
|---|---|---|---|
|
|
1562
|
+
| **Code** | Service method | Tests pass / coverage / mutation score | Refactor implementation |
|
|
1563
|
+
| **Visual assets** | Sprite/image | Symmetry, orientation, background checks | Regenerate with refined prompt |
|
|
1564
|
+
| **Audio assets** | Sound / music | LUFS, frequency profile, artifact detection | Regenerate with adjusted parameters |
|
|
1565
|
+
| **Infrastructure** | Cloud resources | Health checks, policy compliance | Reconfigure and redeploy |
|
|
1566
|
+
| **Hyperparameter optimization** | Model training run | Win rate, drawdown, Sharpe threshold | Adjust classifier weights, retry |
|
|
1567
|
+
| **Session continuity** | Prior session output | Specification conformance on resume | Adjust strategy before proceeding |
|
|
1568
|
+
|
|
1569
|
+
### Session Continuity Pattern (Status.md)
|
|
1570
|
+
The Status.md file is the simplest form of agentic self-evaluation. A subsequent session
|
|
1571
|
+
begins not from a blank context but from a specification-informed account of what the
|
|
1572
|
+
prior session achieved, where it stopped, and what it tried. The agent evaluates its
|
|
1573
|
+
own prior output against the specification before beginning new work.
|
|
1574
|
+
- End of every session: update Status.md with completed work, current state, open questions.
|
|
1575
|
+
- Start of every session: read Status.md and open ADRs before any implementation.
|
|
1576
|
+
- The Auditable property requires both: that the record exists, and that the next session
|
|
1577
|
+
begins by reading it.
|
|
1578
|
+
|
|
1579
|
+
### Wrong History Pattern (Anti-Pattern)
|
|
1580
|
+
An audit trail that exists but is not read as state is equivalent to an absent audit trail.
|
|
1581
|
+
If the resume logic calculates from scratch rather than reading persisted state, the prior
|
|
1582
|
+
session's work is invisible — despite full persistence. The artifact was not absent; it was
|
|
1583
|
+
not consulted. Both conditions are violations of the Auditable property.
|
|
1584
|
+
|
|
1585
|
+
- id: wrong-specification-risk
|
|
1586
|
+
tier: recommended
|
|
1587
|
+
title: "Wrong Specification Risk"
|
|
1588
|
+
content: |
|
|
1589
|
+
## Wrong Specification Risk
|
|
1590
|
+
|
|
1591
|
+
The most important risk of generative specification is not an underspecified system — it
|
|
1592
|
+
is a *wrongly* specified one. A faithful AI executing a flawed architectural constitution
|
|
1593
|
+
will produce flawed code at scale, with high confidence and no complaint. The specification
|
|
1594
|
+
being a well-formed grammar does not guarantee it is the *right* grammar.
|
|
1595
|
+
|
|
1596
|
+
### Mitigation 1: Specification Verification Before Code
|
|
1597
|
+
The specification should face the same verification discipline as the implementation.
|
|
1598
|
+
Before any code is written:
|
|
1599
|
+
- Write concrete behavioral outcomes and make them checkable (acceptance criteria, ADRs
|
|
1600
|
+
with stated consequences).
|
|
1601
|
+
- If the stated rationale for a decision does not survive being written down (the "would
|
|
1602
|
+
I defend this in a code review?" test), the decision is not sound.
|
|
1603
|
+
- If the use case cannot be stated with a clear precondition and postcondition, the
|
|
1604
|
+
requirement is not understood well enough to specify correctly.
|
|
1605
|
+
|
|
1606
|
+
### Mitigation 2: Living Specification
|
|
1607
|
+
The architectural constitution is a living document, revised through the same atomic
|
|
1608
|
+
commit discipline as the code it governs.
|
|
1609
|
+
- An architectural constitution written at project inception and never revisited is a
|
|
1610
|
+
static grammar for a living system.
|
|
1611
|
+
- The ADR record documents when and why the grammar must change — making changes
|
|
1612
|
+
visible, intentional, and recoverable.
|
|
1613
|
+
- A specification change follows the same protocol as a code change: one ADR, one
|
|
1614
|
+
commit, one clear reason.
|
|
1615
|
+
|
|
1616
|
+
### Diagnostic Signs of a Wrong Specification
|
|
1617
|
+
- The AI produces code that compiles, passes tests, and violates architectural intent.
|
|
1618
|
+
(Tests are not testing architecture; the architectural constitution is not specific enough.)
|
|
1619
|
+
- The same class of mistake recurs across sessions.
|
|
1620
|
+
(The correction belongs in the architectural constitution, not the session prompt.)
|
|
1621
|
+
- The AI "improves" a known intentional decision.
|
|
1622
|
+
(The ADR is missing or was not included in the session context.)
|
|
1623
|
+
- Two modules with different responsibilities share a boundary that is not explicitly stated.
|
|
1624
|
+
(The Bounded property is violated; the constitution needs explicit module boundaries.)
|
|
1625
|
+
|
|
1626
|
+
- id: gs-five-memory-types
|
|
1627
|
+
tier: core
|
|
1628
|
+
title: "GS — Five Memory Types"
|
|
1629
|
+
content: |
|
|
1630
|
+
## Generative Specification: The Five Memory Types
|
|
1631
|
+
|
|
1632
|
+
An AI assistant has no persistent memory across sessions. The methodology distributes
|
|
1633
|
+
memory across five artifact classes, each serving a distinct cognitive function. Every
|
|
1634
|
+
artifact in a well-formed specification belongs to exactly one type. When an artifact
|
|
1635
|
+
is ambiguous about which type it serves, it is trying to do too much and will do none well.
|
|
1636
|
+
|
|
1637
|
+
| Memory Type | Cognitive Function | Primary Artifacts |
|
|
1638
|
+
|---|---|---|
|
|
1639
|
+
| **Semantic** | What the system *is* — identity, contracts, constraints | `CLAUDE.md`, tech spec, domain models, glossary |
|
|
1640
|
+
| **Procedural** | *How* things are done — execution rules, pipelines, bound prompts | `DEVELOPMENT_PROMPTS.md`, roadmap, CI/CD spec, commit hooks |
|
|
1641
|
+
| **Episodic** | What *happened* — decisions, sessions completed, history | ADRs, `Status.md`, session summaries, git commit log |
|
|
1642
|
+
| **Relationship** | *How things connect* — topology, flows, protocols | C4 diagrams, sequence diagrams, state machines, use cases |
|
|
1643
|
+
| **Working** | What is *active now* — current task, loaded context, scope | Session prompt, loaded artifacts, clarification state |
|
|
1644
|
+
|
|
1645
|
+
### Missing Types = Compounding Failure
|
|
1646
|
+
- **Semantic absent** → no grammar; output is locally correct and globally incoherent.
|
|
1647
|
+
- **Procedural absent** → each session starts from scratch; nothing is reproducible.
|
|
1648
|
+
- **Episodic absent** → decisions are repeated or overwritten; intentional choices become drift.
|
|
1649
|
+
- **Relationship absent** → inter-component contracts are implicit; integration points drift.
|
|
1650
|
+
- **Working absent (not loaded)** → the current session inherits no context; practitioner re-narrates everything.
|
|
1651
|
+
|
|
1652
|
+
A project missing all five types is using interactive prompting with no structural discipline.
|
|
1653
|
+
Use the five types as a diagnostic before beginning any session on an inherited project.
|
|
1654
|
+
|
|
1655
|
+
- id: gs-status-format
|
|
1656
|
+
tier: core
|
|
1657
|
+
title: "GS — Status.md Format"
|
|
1658
|
+
content: |
|
|
1659
|
+
## Status.md — Required Format
|
|
1660
|
+
|
|
1661
|
+
Status.md is the episodic artifact closest to working memory. Updated at the close of
|
|
1662
|
+
every session, without exception. The "Next" section is the handoff: specific enough
|
|
1663
|
+
that an agent could begin from it alone, without any narration.
|
|
1664
|
+
|
|
1665
|
+
```markdown
|
|
1666
|
+
# [Project Name] — Status
|
|
1667
|
+
|
|
1668
|
+
**Last updated:** YYYY-MM-DD
|
|
1669
|
+
**Current version / branch:**
|
|
1670
|
+
|
|
1671
|
+
## Completed (this session)
|
|
1672
|
+
- [What was done, with commit hashes where relevant]
|
|
1673
|
+
|
|
1674
|
+
## In Progress
|
|
1675
|
+
- [Partial state — what the immediate next step is]
|
|
1676
|
+
|
|
1677
|
+
## Next
|
|
1678
|
+
- [The immediate next action — specific enough to begin from this line alone]
|
|
1679
|
+
- Example: "Implement `updateConnectionStatus` in `src/connections/service.ts`,
|
|
1680
|
+
write tests for the three state transition paths, verify against `/connections/:id/status`"
|
|
1681
|
+
|
|
1682
|
+
## Decisions made (this session)
|
|
1683
|
+
- [Any choice not yet in an ADR — these are ADR candidates]
|
|
1684
|
+
|
|
1685
|
+
## Blockers / Dependencies
|
|
1686
|
+
- [What is waiting on an external input or a parallel workstream]
|
|
1687
|
+
```
|
|
1688
|
+
|
|
1689
|
+
A vague "Next" entry ("continue working on the feature") forces the next session to
|
|
1690
|
+
reconstruct intent. A specific "Next" entry enables a cold start from the artifact alone.
|
|
1691
|
+
The "Next" section is the primary quality measure of Status.md.
|
|
1692
|
+
|