@mlmcps/ml-specs 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +15 -0
- package/LICENSE +21 -0
- package/README.md +106 -0
- package/ml-specs/.claude-plugin/plugin.json +11 -0
- package/ml-specs/.mcp.json +17 -0
- package/ml-specs/CHANGELOG.md +860 -0
- package/ml-specs/LICENSE +21 -0
- package/ml-specs/README.md +347 -0
- package/ml-specs/agents/coder.md +76 -0
- package/ml-specs/agents/developer.md +78 -0
- package/ml-specs/agents/pr-author.md +36 -0
- package/ml-specs/agents/reviewer.md +65 -0
- package/ml-specs/agents/scanner.md +66 -0
- package/ml-specs/agents/spec-author.md +91 -0
- package/ml-specs/agents/spec-reviewer.md +59 -0
- package/ml-specs/commands/code.md +29 -0
- package/ml-specs/commands/fix.md +67 -0
- package/ml-specs/commands/nfr.md +114 -0
- package/ml-specs/commands/pr.md +32 -0
- package/ml-specs/commands/repo-adopt.md +86 -0
- package/ml-specs/commands/repo-doctor.md +57 -0
- package/ml-specs/commands/repo-estate.md +79 -0
- package/ml-specs/commands/repo-impact.md +77 -0
- package/ml-specs/commands/repo-init.md +155 -0
- package/ml-specs/commands/repo-refresh.md +58 -0
- package/ml-specs/commands/repo-rollout.md +84 -0
- package/ml-specs/commands/repo-status.md +59 -0
- package/ml-specs/commands/spec-advance.md +81 -0
- package/ml-specs/commands/spec-build.md +66 -0
- package/ml-specs/commands/spec-fanout.md +64 -0
- package/ml-specs/commands/spec-review.md +24 -0
- package/ml-specs/commands/spec-verify.md +55 -0
- package/ml-specs/commands/spec.md +73 -0
- package/ml-specs/hooks/hooks.json +23 -0
- package/ml-specs/hooks/knowledge-drift.sh +43 -0
- package/ml-specs/hooks/secret-scan.sh +56 -0
- package/ml-specs/mcp/README.md +173 -0
- package/ml-specs/mcp/ml-specs-server.mjs +708 -0
- package/ml-specs/mcp/ml-specs-server.test.mjs +225 -0
- package/ml-specs/package.json +44 -0
- package/ml-specs/scripts/branch-policy.mjs +71 -0
- package/ml-specs/scripts/fix-specs.mjs +289 -0
- package/ml-specs/scripts/lib/cli.mjs +43 -0
- package/ml-specs/scripts/lib/estate.mjs +108 -0
- package/ml-specs/scripts/lib/http.mjs +73 -0
- package/ml-specs/scripts/lib/knowledge.mjs +91 -0
- package/ml-specs/scripts/lib/knowledge.test.mjs +70 -0
- package/ml-specs/scripts/lib/nfr.mjs +119 -0
- package/ml-specs/scripts/lib/nfr.test.mjs +89 -0
- package/ml-specs/scripts/lib/policy.mjs +114 -0
- package/ml-specs/scripts/lib/policy.test.mjs +139 -0
- package/ml-specs/scripts/lib/scm.mjs +189 -0
- package/ml-specs/scripts/lib/scm.test.mjs +155 -0
- package/ml-specs/scripts/lib/specs.mjs +192 -0
- package/ml-specs/scripts/lib/specs.test.mjs +69 -0
- package/ml-specs/scripts/lib/trace.mjs +90 -0
- package/ml-specs/scripts/lib/trace.test.mjs +110 -0
- package/ml-specs/scripts/lib/tracker.mjs +257 -0
- package/ml-specs/scripts/lib/tracker.test.mjs +177 -0
- package/ml-specs/scripts/nfr-compile.mjs +120 -0
- package/ml-specs/scripts/scripts.test.mjs +182 -0
- package/ml-specs/scripts/spec-brief.mjs +127 -0
- package/ml-specs/scripts/spec-dashboard.mjs +331 -0
- package/ml-specs/scripts/spec-fanout.mjs +120 -0
- package/ml-specs/scripts/spec-gate.mjs +329 -0
- package/ml-specs/scripts/spec-trace.mjs +91 -0
- package/ml-specs/scripts/survey-estate.mjs +230 -0
- package/ml-specs/scripts/tracker-sync.mjs +91 -0
- package/ml-specs/skills/knowledge-retrieval/SKILL.md +75 -0
- package/ml-specs/templates/CLAUDE.fragment.md +87 -0
- package/ml-specs/templates/ci/azure-pipelines-spec-gate.yml +64 -0
- package/ml-specs/templates/ci/knowledge-check.mjs +176 -0
- package/ml-specs/templates/ci/knowledge-layer.yml +35 -0
- package/ml-specs/templates/ci/spec-gate.yml +69 -0
- package/ml-specs/templates/docs/ARCHITECTURE.template.md +110 -0
- package/ml-specs/templates/docs/ESTATE.template.md +55 -0
- package/ml-specs/templates/docs/PATTERNS.template.md +80 -0
- package/ml-specs/templates/gitattributes +18 -0
- package/ml-specs/templates/hooks/settings.hooks.example.json +32 -0
- package/ml-specs/templates/mcp/.mcp.json +34 -0
- package/ml-specs/templates/settings.json +18 -0
- package/ml-specs/templates/specs/AGENTS.md +57 -0
- package/ml-specs/templates/specs/README.md +104 -0
- package/ml-specs/templates/specs/TEMPLATE.md +114 -0
- package/ml-specs/templates/standards/.mlskills.json +24 -0
- package/package.json +36 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# <project name> — architecture summary
|
|
2
|
+
|
|
3
|
+
> Auto-maintainable summary the coding agent reads **first** to orient before searching.
|
|
4
|
+
> Regenerate when structure/endpoints/data layer change (see "Keeping this fresh" at the bottom).
|
|
5
|
+
> Source of truth is the code; if this disagrees with the code, the code wins — fix this file.
|
|
6
|
+
>
|
|
7
|
+
> This is a **stack-neutral skeleton**. Keep the sections that apply to THIS project's stack
|
|
8
|
+
> (Java/Spring, React, Node/Express, NestJS, or any other) and delete the rest. Fill every kept
|
|
9
|
+
> section with real `file:line` references — do not leave placeholders.
|
|
10
|
+
>
|
|
11
|
+
> **Token budget: keep this under ~200 lines.** It's a *map*, not the territory — terse tables and
|
|
12
|
+
> `file:line` pointers, not prose or pasted code. If it grows past the budget, split per-context /
|
|
13
|
+
> per-package or push detail down into the code (which the agent greps on demand).
|
|
14
|
+
>
|
|
15
|
+
> **Large application? Shard it (the key scaling move).** Do NOT grow one giant file. Keep THIS
|
|
16
|
+
> file as a tiny **router**: the "What it is" blurb + the Structure table where each row links to a
|
|
17
|
+
> per-module shard `docs/architecture/<module>.md` (each its own ≤~150-line map). The agent reads
|
|
18
|
+
> this router (cheap), then loads only the ONE shard for the module a task touches. Same idea for
|
|
19
|
+
> patterns: a per-module `docs/patterns/<module>.md` when conventions differ across modules.
|
|
20
|
+
> See "Large-codebase layout" at the bottom.
|
|
21
|
+
|
|
22
|
+
## What it is
|
|
23
|
+
<1–3 sentences: what this app/service does, the stack (language, framework, build tool), and
|
|
24
|
+
the database engine. Rough size (file/LOC count) helps. If it's one of several services, say so
|
|
25
|
+
and link `docs/ESTATE.md`.>
|
|
26
|
+
|
|
27
|
+
## Structure (where to look by feature)
|
|
28
|
+
<How the code is organized. Pick the shape that matches the stack:>
|
|
29
|
+
- **Java/Spring:** bounded contexts / packages — `controller → service → domain → repository`,
|
|
30
|
+
plus `events/*` for messaging. Table of contexts with base path + one-liner.
|
|
31
|
+
- **Node (Express/NestJS):** modules/routers → controllers → services/providers → data layer;
|
|
32
|
+
middleware or guards/interceptors/pipes. Table of modules with route prefix + one-liner.
|
|
33
|
+
- **React:** routes/pages → feature components → shared components/hooks → API/data layer; where
|
|
34
|
+
state lives. Table of routes/features with one-liner.
|
|
35
|
+
|
|
36
|
+
| Area / module / route | Path | One-liner |
|
|
37
|
+
|-----------------------|------|-----------|
|
|
38
|
+
| | | |
|
|
39
|
+
|
|
40
|
+
## Data & persistence (the #1 gotcha)
|
|
41
|
+
<The database and how the code talks to it. Be specific — this is where bugs hide.>
|
|
42
|
+
- **Engine:** MySQL / PostgreSQL / MongoDB (+ any cache like Redis, object store like S3).
|
|
43
|
+
- **Access layer:**
|
|
44
|
+
- Relational: ORM (Sequelize/Prisma/TypeORM, or Spring Data JPA) — where models/entities and
|
|
45
|
+
**migrations** live; transaction style; dialect-specific bits.
|
|
46
|
+
- MongoDB: Mongoose/Spring Data Mongo schemas, validation, indexes; reactive vs blocking (Java).
|
|
47
|
+
- **Migrations:** how schema changes ship (e.g. `sequelize-cli db:migrate`, Prisma migrate, Flyway).
|
|
48
|
+
|
|
49
|
+
## Events / async / side-effects
|
|
50
|
+
<Queues, topics, jobs, webhooks, cache invalidation, email. Producer/consumer + payload + failure
|
|
51
|
+
handling. Omit if the app has none.>
|
|
52
|
+
|
|
53
|
+
## External / cross-service calls
|
|
54
|
+
| Client / proxy | Target | Purpose |
|
|
55
|
+
|----------------|--------|---------|
|
|
56
|
+
| | | |
|
|
57
|
+
<HTTP clients, Feign proxies, third-party SDKs. Note error/timeout handling. Omit if none.>
|
|
58
|
+
|
|
59
|
+
## Cross-cutting
|
|
60
|
+
- **Errors:** how errors are represented and surfaced (global handler/middleware/filter; error
|
|
61
|
+
types). Don't invent ad-hoc error shapes.
|
|
62
|
+
- **Auth:** in-app (JWT/passport/guards) or delegated to a gateway? Say which.
|
|
63
|
+
- **Config:** env vars / `.env` / config server / profiles.
|
|
64
|
+
- **Quality gates:** lint/format/typecheck and test commands (see CLAUDE.md).
|
|
65
|
+
|
|
66
|
+
## Large-codebase layout (sharded — fill the Structure table above with these links)
|
|
67
|
+
For a big app, this file is just the router; the detail lives in per-module shards loaded on demand:
|
|
68
|
+
```
|
|
69
|
+
docs/
|
|
70
|
+
ARCHITECTURE.md # THIS router: blurb + Structure table + the contract index below
|
|
71
|
+
architecture/
|
|
72
|
+
<module-a>.md # ≤~150 lines: structure, data, events, calls + a "Depends on/Used by" header
|
|
73
|
+
<module-b>.md
|
|
74
|
+
patterns/ # only if conventions differ per module
|
|
75
|
+
<module-a>.md
|
|
76
|
+
```
|
|
77
|
+
The agent's path: read `ARCHITECTURE.md` (router) → open the ONE shard for the module the task
|
|
78
|
+
touches → grep within that module for exact lines. It never loads modules it isn't working on.
|
|
79
|
+
|
|
80
|
+
### When modules are interlinked (edges, not just nodes)
|
|
81
|
+
Sharding by module only works if you also capture the **contracts between modules** — otherwise a
|
|
82
|
+
change that ripples across modules misses the other side. So:
|
|
83
|
+
|
|
84
|
+
- **Every shard starts with a `## Depends on / Used by` header** listing its edges — the modules it
|
|
85
|
+
calls and is called by, each as a one-line contract pointer (`event/API/shared type → file:line`).
|
|
86
|
+
This is the cheap, always-small part; it's what makes the graph navigable.
|
|
87
|
+
- **Module contract index (below)** is the join table: the shared contracts (events, shared
|
|
88
|
+
DTOs/types, shared DB tables, internal APIs) and which modules produce/consume each.
|
|
89
|
+
- **Load the dependency closure, bounded:** for a task on module X, load X's full shard **plus only
|
|
90
|
+
the `Depends on / Used by` + relevant contract section of its direct neighbors** — not the
|
|
91
|
+
neighbors' full shards. That's 1-hop: enough to honor the contract, still bounded.
|
|
92
|
+
- **If "everything depends on everything"** that's coupling worth surfacing, not hiding. Keep a
|
|
93
|
+
single always-loaded **`docs/architecture/_core.md`** for the truly shared contracts, and let the
|
|
94
|
+
**spec** own the cross-module contract explicitly (template §4.1/4.3/4.4). Tightly-coupled specs
|
|
95
|
+
must be **sequenced, not parallelized** (see `specs/AGENTS.md`).
|
|
96
|
+
|
|
97
|
+
## Module contract index (the join table — keep in the router)
|
|
98
|
+
> The shared edges, so a change designs against both sides. One row per shared contract.
|
|
99
|
+
|
|
100
|
+
| Contract (event / API / shared type / table) | Produced by | Consumed by | Defined at |
|
|
101
|
+
|-----------------------------------------------|-------------|-------------|------------|
|
|
102
|
+
| | | | `file:line` |
|
|
103
|
+
|
|
104
|
+
## Keeping this fresh
|
|
105
|
+
Regenerate (or `/repo-refresh`) after changes to routes/endpoints/controllers, the data model or
|
|
106
|
+
migrations, event listeners, or external clients. Refresh only the shard(s) that changed — not the
|
|
107
|
+
whole set. Use the project's own search (the right grep/glob for the stack), e.g. controllers/route
|
|
108
|
+
definitions, `@SqsListener`/queue consumers, ORM model & migration dirs, external-client/proxy
|
|
109
|
+
definitions. This file (+ `docs/ESTATE.md` if part of an estate) is the retrieval index; a stale
|
|
110
|
+
summary is worse than none.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# <estate name> — service & contract index
|
|
2
|
+
|
|
3
|
+
> Estate-level retrieval index for the coding agent. When a change crosses a service boundary
|
|
4
|
+
> (an event, an HTTP/RPC call, a shared table), this is where the agent learns **the other side of
|
|
5
|
+
> the contract** without cloning and grepping every repo. Generated and refreshed by `/repo-estate`.
|
|
6
|
+
>
|
|
7
|
+
> Keep it under ~200 lines — it's an index, not documentation. One copy per service repo, kept in
|
|
8
|
+
> sync (or hosted centrally and symlinked). Mark anything not confirmed against real code
|
|
9
|
+
> `(inferred)` so the agent re-checks it instead of trusting it.
|
|
10
|
+
|
|
11
|
+
## Service registry
|
|
12
|
+
|
|
13
|
+
One row per service in the estate. `Summary doc` points at that repo's own `docs/ARCHITECTURE.md`
|
|
14
|
+
(the deep detail lives there, not here). Use `_TBD_` for peers not onboarded yet — an honest gap is
|
|
15
|
+
better than a guess.
|
|
16
|
+
|
|
17
|
+
| Service | Owns | Stack | Summary doc |
|
|
18
|
+
|---------|------|-------|-------------|
|
|
19
|
+
| <this-service> | <the domain nouns it is the source of truth for> | <language / framework / datastore> | `<this-service>/docs/ARCHITECTURE.md` |
|
|
20
|
+
| <peer-service> | <domain> | <stack, or `_TBD_`> | `_TBD_` |
|
|
21
|
+
|
|
22
|
+
## Cross-service contract index (who calls / publishes / consumes what)
|
|
23
|
+
|
|
24
|
+
The point of this file. Every row is an **edge** between two services — the agent reads it to find
|
|
25
|
+
the peer's side before designing a change.
|
|
26
|
+
|
|
27
|
+
### Synchronous (HTTP / RPC / gRPC / Feign)
|
|
28
|
+
|
|
29
|
+
| Caller | Callee | Via | What | Evidence |
|
|
30
|
+
|--------|--------|-----|------|----------|
|
|
31
|
+
| <service> | <peer> | <client class / module name> | <what it asks for> | `path/to/Client.ext:42` |
|
|
32
|
+
|
|
33
|
+
### Asynchronous (events / queues / topics)
|
|
34
|
+
|
|
35
|
+
| Event / queue / topic | Producer | Consumer | Notes | Evidence |
|
|
36
|
+
|-----------------------|----------|----------|-------|----------|
|
|
37
|
+
| `<event-name>` | <service> | <service> (`<listener class>`) | <payload gist, ordering/idempotency> | `path/to/Listener.ext:17` |
|
|
38
|
+
|
|
39
|
+
> Queue/topic names often resolve from config rather than literals — note where
|
|
40
|
+
> (`<config key or config server path>`). Update this table whenever a listener or a published
|
|
41
|
+
> topic is added.
|
|
42
|
+
|
|
43
|
+
### Shared data & packages (optional — delete if none)
|
|
44
|
+
|
|
45
|
+
| Shared thing | Owner | Used by | Notes |
|
|
46
|
+
|--------------|-------|---------|-------|
|
|
47
|
+
| <table / collection / shared library / published type> | <service> | <services> | <coupling risk, migration order> |
|
|
48
|
+
|
|
49
|
+
## How to use this for retrieval
|
|
50
|
+
|
|
51
|
+
1. Read this repo's own `docs/ARCHITECTURE.md` first (in-repo orientation).
|
|
52
|
+
2. Only if the task touches an event, a cross-service call, or shared data: find the edge in the
|
|
53
|
+
contract index above, then open the peer's summary doc — design the change against **both**
|
|
54
|
+
sides of the contract, and note the deploy order in the spec's §7 Rollout.
|
|
55
|
+
3. Only then do agentic search (`Explore` / grep) for the exact lines.
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# <project name> — code patterns & conventions
|
|
2
|
+
|
|
3
|
+
> Learned from the existing codebase by `/repo-init`. This is the agent's "house style" memory:
|
|
4
|
+
> how THIS project actually writes code, so new code matches what's already there. Every pattern
|
|
5
|
+
> below must cite a real example (`path/to/File.ext:line`). The code is the source of truth — if a
|
|
6
|
+
> pattern here drifts from reality, fix this file.
|
|
7
|
+
>
|
|
8
|
+
> Keep only the rows that apply to this stack; delete the rest. Be concrete, not generic
|
|
9
|
+
> ("controllers return `Mono<ResponseEntity<Dto>>` and never throw raw" beats "uses MVC").
|
|
10
|
+
>
|
|
11
|
+
> **Token budget: keep this under ~200 lines.** This loads into context whenever code is written.
|
|
12
|
+
> Cite `file:line` examples — do NOT paste code blocks. One bullet per pattern. In a monorepo,
|
|
13
|
+
> give each package its own short section (or its own `PATTERNS.md`) rather than one fat file.
|
|
14
|
+
>
|
|
15
|
+
> **Mark confidence.** A pattern with 3+ consistent examples is the rule — state it plainly. A
|
|
16
|
+
> pattern seen once or guessed, prefix `(inferred)` so the agent re-checks it against the code
|
|
17
|
+
> before relying on it. A wrong pattern stated as law is worse than an omission. Never invent a
|
|
18
|
+
> convention to fill a section — delete the section instead.
|
|
19
|
+
|
|
20
|
+
## Stack snapshot
|
|
21
|
+
- **Language / framework:** <e.g. TypeScript + NestJS 10 / Java 17 + Spring Boot 3 / React 18 + Vite>
|
|
22
|
+
- **Build / package manager:** <Maven · Gradle · npm · yarn · pnpm> (from lockfile)
|
|
23
|
+
- **Database / ORM:** <PostgreSQL + Prisma · MySQL + Sequelize · MongoDB + Mongoose · Spring Data>
|
|
24
|
+
- **Test stack:** <JUnit · Jest · Vitest · Supertest · @nestjs/testing · Playwright>
|
|
25
|
+
- **Lint / format / typecheck:** <ESLint + Prettier · `tsc --noEmit` · Checkstyle/Spotless>
|
|
26
|
+
|
|
27
|
+
## Directory layout
|
|
28
|
+
<The real tree the agent should mirror when adding files. One line per significant dir + what lives there.>
|
|
29
|
+
```
|
|
30
|
+
src/
|
|
31
|
+
... # <what goes here>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Naming conventions
|
|
35
|
+
- **Files:** <e.g. `kebab-case.ts`, one component per file; `*.controller.ts` / `*.service.ts`>
|
|
36
|
+
- **Types/classes/components:** <`PascalCase`; React components `PascalCase.tsx`>
|
|
37
|
+
- **Functions/vars:** <`camelCase`>; **constants:** <`SCREAMING_SNAKE`>
|
|
38
|
+
- **Tests:** <`*.spec.ts` next to source / `*Test.java` / `__tests__/`>
|
|
39
|
+
- Example: `path/File.ext:line`
|
|
40
|
+
|
|
41
|
+
## How a feature is structured (the layered flow)
|
|
42
|
+
<Trace one real feature end to end so the agent can copy the shape. e.g.>
|
|
43
|
+
- Entry: <route/controller> — `path:line`
|
|
44
|
+
- Business logic: <service/provider> — `path:line`
|
|
45
|
+
- Data access: <repository/model/ORM> — `path:line`
|
|
46
|
+
- Input/output shape: <DTO/schema/validation> — `path:line`
|
|
47
|
+
|
|
48
|
+
## Data access & migrations
|
|
49
|
+
- How models/entities are defined — `path:line`
|
|
50
|
+
- How queries/transactions are written (ORM calls, not raw SQL unless shown) — `path:line`
|
|
51
|
+
- How schema changes ship (migration dir + command, e.g. `sequelize-cli db:migrate`) — `path:line`
|
|
52
|
+
|
|
53
|
+
## API / interface contracts
|
|
54
|
+
- Request validation: <Zod / class-validator / Joi / Bean Validation> — `path:line`
|
|
55
|
+
- Response shape & serialization (DTOs, never leak entities) — `path:line`
|
|
56
|
+
- Status codes / pagination / common envelope, if any — `path:line`
|
|
57
|
+
|
|
58
|
+
## Error handling
|
|
59
|
+
- Error types and where they're thrown — `path:line`
|
|
60
|
+
- Central handler/middleware/filter that maps them to responses — `path:line`
|
|
61
|
+
- Rule: <e.g. "throw typed errors, never build ad-hoc error bodies in controllers">
|
|
62
|
+
|
|
63
|
+
## Validation, config & secrets
|
|
64
|
+
- Config/env access pattern (`.env`, config service, `@ConfigService`) — `path:line`
|
|
65
|
+
- Never hard-code secrets; how the project reads them — `path:line`
|
|
66
|
+
|
|
67
|
+
## Logging & observability
|
|
68
|
+
- Logger used and how it's invoked — `path:line`
|
|
69
|
+
|
|
70
|
+
## Testing patterns
|
|
71
|
+
- Unit test shape (arrange/act/assert, mocking style) — `path:line`
|
|
72
|
+
- Integration test shape (test DB, fixtures, Supertest/`@nestjs/testing`) — `path:line`
|
|
73
|
+
- Functional/E2E shape (HTTP black-box against the running app; Playwright/Cypress UI flows;
|
|
74
|
+
how the app/DB is started for the run) — `path:line`
|
|
75
|
+
- Test command(s): unit/integration `<npm test, mvn test, …>`; functional/E2E
|
|
76
|
+
`<npm run test:e2e, mvn verify, npx playwright test, …>`; full final-acceptance run
|
|
77
|
+
`<the command that runs everything end to end>`
|
|
78
|
+
|
|
79
|
+
## Don'ts (project-specific anti-patterns observed/avoided)
|
|
80
|
+
- <e.g. "no `any` — strict TS", "no raw SQL", "no new `.block()` calls", "no direct entity returns">
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Normalize line endings: store LF in the repo, check out LF on all platforms.
|
|
2
|
+
# Prevents the whole-repo CRLF/LF "phantom diff" churn.
|
|
3
|
+
* text=auto eol=lf
|
|
4
|
+
|
|
5
|
+
# Keep Windows scripts as CRLF
|
|
6
|
+
*.bat text eol=crlf
|
|
7
|
+
*.cmd text eol=crlf
|
|
8
|
+
|
|
9
|
+
# Treat known binaries as binary (no EOL conversion, no diff)
|
|
10
|
+
*.jar binary
|
|
11
|
+
*.png binary
|
|
12
|
+
*.jpg binary
|
|
13
|
+
*.jpeg binary
|
|
14
|
+
*.gif binary
|
|
15
|
+
*.ico binary
|
|
16
|
+
*.pdf binary
|
|
17
|
+
*.zip binary
|
|
18
|
+
*.gz binary
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"//": "OPTIONAL example hooks — the PROJECT-SPECIFIC ones the plugin cannot ship for you,",
|
|
3
|
+
"//1": "because it can't know your format/lint/test commands. Copy what you want into this",
|
|
4
|
+
"//2": "repo's .claude/settings.json and REPLACE the commands with the real ones. Hooks run",
|
|
5
|
+
"//3": "automatically, so keep them fast and non-destructive. Delete this file after wiring up.",
|
|
6
|
+
|
|
7
|
+
"//4": "ALREADY SHIPPED BY THE PLUGIN — do not copy these, they are active on install:",
|
|
8
|
+
"//5": " SessionStart → knowledge-layer drift warning (silent unless drifted)",
|
|
9
|
+
"//6": " PreToolUse → staged-diff secret scan (blocks the commit; allowlist at",
|
|
10
|
+
"//7": " .claude/secret-allowlist.txt). See ml-specs/hooks/.",
|
|
11
|
+
|
|
12
|
+
"hooks": {
|
|
13
|
+
"//PostToolUse": "Auto-format / lint the file just edited. Pick the matcher + command for your stack.",
|
|
14
|
+
"PostToolUse": [
|
|
15
|
+
{
|
|
16
|
+
"matcher": "Edit|Write",
|
|
17
|
+
"//note": "JS/TS example — run prettier on changed files. Swap for your formatter (spotlessApply, black, gofmt…).",
|
|
18
|
+
"hooks": [
|
|
19
|
+
{ "type": "command", "command": "npx --no-install prettier --write \"$CLAUDE_FILE_PATHS\" 2>/dev/null || true" }
|
|
20
|
+
]
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"//Stop": "Remind to run the quality gates before finishing. Replace with the real test command.",
|
|
24
|
+
"Stop": [
|
|
25
|
+
{
|
|
26
|
+
"hooks": [
|
|
27
|
+
{ "type": "command", "command": "echo 'Reminder: run the project test + lint + typecheck before opening a PR.'" }
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"//": "Project-scoped MCP config. Copy to the REPO ROOT as .mcp.json and commit it, so every",
|
|
3
|
+
"//1": "teammate and every MCP-speaking tool (Claude Code, Cursor, a custom agent) gets the same",
|
|
4
|
+
"//2": "read-only tools over this repo.",
|
|
5
|
+
"//3": "",
|
|
6
|
+
"//4": "Replace <ABSOLUTE PATH TO> below with wherever ml-claude-plugins is checked out. If the",
|
|
7
|
+
"//5": "ml-specs plugin is installed, ${CLAUDE_PLUGIN_ROOT} resolves inside Claude Code — but a",
|
|
8
|
+
"//6": "non-Claude client won't expand it, so an absolute path is the portable choice.",
|
|
9
|
+
"//7": "",
|
|
10
|
+
"//8": "--root . means the server reads THIS repo. Nothing either server exposes writes anything.",
|
|
11
|
+
"//9": "",
|
|
12
|
+
"//10": "ml-skills is the ARCHITECTURE STANDARDS half: the rules a spec's contract and the code",
|
|
13
|
+
"//11": "implementing it are held to. It is OPTIONAL — delete the block if you are not using it —",
|
|
14
|
+
"//12": "but if you keep it, keep it working: the spec loop reports when the standards could not be",
|
|
15
|
+
"//13": "consulted rather than passing quietly, because an unrun check is not a clean one.",
|
|
16
|
+
"mcpServers": {
|
|
17
|
+
"ml-specs": {
|
|
18
|
+
"command": "node",
|
|
19
|
+
"args": [
|
|
20
|
+
"<ABSOLUTE PATH TO>/ml-claude-plugins/ml-specs/mcp/ml-specs-server.mjs",
|
|
21
|
+
"--root",
|
|
22
|
+
"."
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
"ml-skills": {
|
|
26
|
+
"command": "node",
|
|
27
|
+
"args": [
|
|
28
|
+
"<ABSOLUTE PATH TO>/ml-skills/server.mjs",
|
|
29
|
+
"--root",
|
|
30
|
+
"."
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"//": "Committed project settings for Claude Code. Copy to the REPO ROOT as .claude/settings.json",
|
|
3
|
+
"//1": "and commit it: every teammate who clones the repo gets this with no per-machine setup, and",
|
|
4
|
+
"//2": "personal overrides still live in .claude/settings.local.json, which this does not touch.",
|
|
5
|
+
"//3": "",
|
|
6
|
+
"//4": "attribution — commits and PRs name the humans who own the change. An empty string suppresses",
|
|
7
|
+
"//5": "that trailer entirely, so no assistant is ever recorded as co-author. This is enforced by",
|
|
8
|
+
"//6": "Claude Code itself rather than being an instruction a model has to remember, which is why it",
|
|
9
|
+
"//7": "belongs here and not only in CLAUDE.md.",
|
|
10
|
+
"//8": "",
|
|
11
|
+
"//9": "Why it matters beyond one commit: a squash merge aggregates Co-Authored-By trailers from",
|
|
12
|
+
"//10": "EVERY commit on the branch, so a single stray line added early resurfaces on the merge",
|
|
13
|
+
"//11": "commit long after, crediting a tool instead of the people who did the work.",
|
|
14
|
+
"attribution": {
|
|
15
|
+
"commit": "",
|
|
16
|
+
"pr": ""
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# The SDD agent team
|
|
2
|
+
|
|
3
|
+
Spec-driven development as a team of subagents, mapped to the loop:
|
|
4
|
+
|
|
5
|
+
| Agent | Phase | Command | Tools | Job |
|
|
6
|
+
|-------|-------|---------|-------|-----|
|
|
7
|
+
| `spec-author` | SPECIFY | `/spec` | read + Write | Ticket → reviewable spec under `specs/`. No code. Stops and returns blocking contract questions rather than guessing them. |
|
|
8
|
+
| `spec-reviewer` | SPECIFY | `/spec-review` | read-only + Bash | Adversarially checks the **draft spec** before a human reads it — contracts, testable criteria, ripple. Fresh context, so it sees what the author can't. |
|
|
9
|
+
| `developer` | IMPLEMENT | `/spec-build` | read + Edit/Write + Bash | Builds ONE approved spec, test-first. |
|
|
10
|
+
| `reviewer` | VERIFY | `/spec-verify` | read-only + Bash | Adversarially checks the impl against the spec's acceptance criteria; runs the final-acceptance suite. |
|
|
11
|
+
| `pr-author` | VERIFY | `/pr` | read-only + Bash | Completed spec + diff → PR title/body with the criteria as a checklist. |
|
|
12
|
+
|
|
13
|
+
The two reviewers are deliberately separate: `spec-reviewer` reviews the **paper** (before code
|
|
14
|
+
exists, where a fix is a sentence), `reviewer` reviews the **code** against that paper.
|
|
15
|
+
|
|
16
|
+
Definitions live in `.claude/agents/`. Invoke one by asking for it ("use the developer
|
|
17
|
+
agent to build specs/0001-…"), or let Claude pick by description.
|
|
18
|
+
|
|
19
|
+
## "Three developers working" = parallel implement, isolated
|
|
20
|
+
|
|
21
|
+
The team had three developers building features concurrently. To mirror that, run **three
|
|
22
|
+
`developer` agents in parallel — one spec each — and give each its own git worktree**
|
|
23
|
+
so their edits never collide:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
┌─ spec-author → specs/0001-a.md ─┐
|
|
27
|
+
├─ spec-author → specs/0002-b.md ─┤ (human reviews/approves the specs)
|
|
28
|
+
└─ spec-author → specs/0003-c.md ─┘
|
|
29
|
+
│ approved
|
|
30
|
+
▼
|
|
31
|
+
┌─ developer (worktree A) builds 0001 ─┐
|
|
32
|
+
├─ developer (worktree B) builds 0002 ─┤ run concurrently
|
|
33
|
+
└─ developer (worktree C) builds 0003 ─┘
|
|
34
|
+
│ each returns diff + test results
|
|
35
|
+
▼
|
|
36
|
+
┌─ reviewer verifies 0001 ─┐
|
|
37
|
+
├─ reviewer verifies 0002 ─┤ verify per spec
|
|
38
|
+
└─ reviewer verifies 0003 ─┘
|
|
39
|
+
│
|
|
40
|
+
▼ human merges the approved branches
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Why worktree isolation matters
|
|
44
|
+
Three agents editing the same checkout would clobber each other. Each `developer` runs
|
|
45
|
+
in its own git worktree (a separate working copy on its own branch), so the three streams
|
|
46
|
+
are independent and merge cleanly — exactly like three developers on three branches.
|
|
47
|
+
|
|
48
|
+
**Important:** parallelize across *independent* specs. If two specs touch the same files
|
|
49
|
+
(e.g. both edit `CouponService`), sequence them instead — paper conflicts are cheaper than
|
|
50
|
+
merge conflicts.
|
|
51
|
+
|
|
52
|
+
## How to kick it off
|
|
53
|
+
- One ticket: `/spec DLA-1234 …` → review → `/spec-advance … Approved` → `/spec-build specs/NNNN-….md`
|
|
54
|
+
→ `/spec-verify` → `/pr`.
|
|
55
|
+
- A batch (the 3-developer pattern): ask Claude to "spec these 3 tickets, then build them in
|
|
56
|
+
parallel with isolated worktrees, then review each against its spec." Claude orchestrates
|
|
57
|
+
the fan-out. For larger batches this is worth running as a structured multi-agent workflow.
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Spec-Driven Development (SDD)
|
|
2
|
+
|
|
3
|
+
Every non-trivial change starts with a **spec** — a reviewable document that defines
|
|
4
|
+
*what* and *why* before any *how* is written. The spec is the contract Claude implements
|
|
5
|
+
against, and the artifact a human reviews **before** code exists.
|
|
6
|
+
|
|
7
|
+
> One-line / trivial fixes don't need a spec. Anything touching an API, a data model,
|
|
8
|
+
> an event, cross-service behavior, or more than ~one file does.
|
|
9
|
+
|
|
10
|
+
## The loop
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
1. SPECIFY → 2. PLAN → 3. IMPLEMENT → 4. VERIFY
|
|
14
|
+
(write spec) (approve) (code + tests) (review + CI)
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
1. **Specify** — `/spec <ticket-or-description>`
|
|
18
|
+
Claude explores the relevant code, then does two things **before** the spec reaches you:
|
|
19
|
+
|
|
20
|
+
- **Asks you the blocking questions up front**, batched, as concrete options with a
|
|
21
|
+
recommendation. A question is blocking if its answer would change a contract (API shape, data
|
|
22
|
+
model, error codes, scope, compatibility). Answering four of these in one pass is cheap;
|
|
23
|
+
discovering them one revision at a time is not.
|
|
24
|
+
- **Runs an adversarial pass over its own draft** (the `spec-reviewer` agent, fresh context)
|
|
25
|
+
and fixes what it finds — contract gaps, untestable criteria, unnamed ripple. Hole-finding is
|
|
26
|
+
the agent's job, not yours.
|
|
27
|
+
|
|
28
|
+
Then it writes `specs/NNNN-slug.md` and hands it to you to review and approve. **No
|
|
29
|
+
implementation code is written in this step.** The spec is the source of truth.
|
|
30
|
+
|
|
31
|
+
You should be approving, not QA-ing. If a review keeps turning up holes, that's a bug in the
|
|
32
|
+
loop — not a reason to review harder.
|
|
33
|
+
|
|
34
|
+
`/spec-review specs/NNNN-slug.md` runs that same adversarial pass on demand. `/spec` already
|
|
35
|
+
does it, so reach for the command when a spec was hand-written, heavily edited, or came from
|
|
36
|
+
someone else.
|
|
37
|
+
|
|
38
|
+
**If you send a spec back:** Claude records what changed in the spec's **Revisions** table, so
|
|
39
|
+
round two is a diff read rather than another full read.
|
|
40
|
+
|
|
41
|
+
2. **Plan** — Claude proposes an implementation plan from the approved spec (plan mode).
|
|
42
|
+
You approve before edits begin.
|
|
43
|
+
|
|
44
|
+
3. **Implement** — `/spec-build specs/NNNN-slug.md`
|
|
45
|
+
Claude implements **strictly against the spec's acceptance criteria**, writing a test
|
|
46
|
+
for each criterion using this project's framework (Java `*Test.java`/`*IT.java`; React/Node
|
|
47
|
+
Jest/Vitest + Testing Library / Supertest / `@nestjs/testing`). Every user-facing or
|
|
48
|
+
contract-level criterion also gets a **functional/E2E test** (HTTP black-box, or Playwright/
|
|
49
|
+
Cypress UI flow), and Claude runs them. Anything not in the spec is out of scope — if a gap
|
|
50
|
+
surfaces, update the spec first, then continue.
|
|
51
|
+
|
|
52
|
+
4. **Verify** — `/spec-verify specs/NNNN-slug.md`
|
|
53
|
+
The `reviewer` agent judges the implementation against the spec's acceptance criteria with
|
|
54
|
+
fresh context, and runs the **final acceptance** pass (spec section 6.1): the project's *full*
|
|
55
|
+
test suite, including the functional/E2E tests, green end to end — not just the new tests. Then
|
|
56
|
+
`/code-review` (and `/security-review` where relevant) and the normal CI pipeline — those check
|
|
57
|
+
the diff for bugs, which is a different question from "does it match the spec". Run both.
|
|
58
|
+
|
|
59
|
+
Then `/spec-advance specs/NNNN-slug.md Verified`, and `/pr specs/NNNN-slug.md` for the PR text
|
|
60
|
+
with the acceptance criteria as a review checklist.
|
|
61
|
+
|
|
62
|
+
## Lifecycle
|
|
63
|
+
|
|
64
|
+
A spec's Status is a claim about reality, so **`/spec-advance` is the only thing that writes it**,
|
|
65
|
+
and each transition has to show its evidence:
|
|
66
|
+
|
|
67
|
+
| Status | Means | Gate to reach it |
|
|
68
|
+
|--------|-------|------------------|
|
|
69
|
+
| `Draft` | Written, not agreed | — (`/spec` creates it here) |
|
|
70
|
+
| `Approved` | The contract is agreed; build it | Human approval + no blocking question left in §8 |
|
|
71
|
+
| `Implemented` | Code + tests exist for every criterion | Every AC checked, every §6 test named **exists on disk** |
|
|
72
|
+
| `Verified` | It actually works | Clean `/spec-verify` + §6.1 full suite green |
|
|
73
|
+
| `Archived` | Merged and closed out | Branch merged → `git mv` to `specs/archive/NNNN-slug.md` |
|
|
74
|
+
|
|
75
|
+
If the evidence isn't there, the transition is refused — that's the feature. Moving *backwards*
|
|
76
|
+
(the contract changed mid-build) is fine and needs no gate, but it must add a **Revisions** row.
|
|
77
|
+
`/repo-status` shows where everything sits; `/repo-doctor` flags statuses the repo can't back up.
|
|
78
|
+
|
|
79
|
+
## Conventions
|
|
80
|
+
|
|
81
|
+
- Specs are numbered sequentially: `specs/0001-add-coupon-expiry.md`, `specs/0002-...md`. Archiving
|
|
82
|
+
moves the file to `specs/archive/` but **keeps its number** — numbers are never reused.
|
|
83
|
+
- **The number comes from every branch, not your working tree.** Two people speccing in parallel
|
|
84
|
+
will otherwise both take the next number and collide at merge — a conflict in a filename, which
|
|
85
|
+
git resolves badly. `/spec` does this for you; by hand it's:
|
|
86
|
+
```
|
|
87
|
+
git fetch --quiet && git log --all --pretty=format: --name-only --diff-filter=A -- 'specs/[0-9]*' | sort -u
|
|
88
|
+
```
|
|
89
|
+
If a collision does land, renumber the *later* spec and update its branch name — don't merge two
|
|
90
|
+
specs onto one number.
|
|
91
|
+
- Keep the spec in the **same PR/branch** as the implementation — it documents intent and
|
|
92
|
+
lives next to the code it describes.
|
|
93
|
+
- A spec is "done" (`Verified`) when every acceptance criterion has a passing test — including a
|
|
94
|
+
functional/E2E test for each user-facing/contract-level criterion — and the project's full test
|
|
95
|
+
suite passes end to end (the final-acceptance run, spec section 6.1).
|
|
96
|
+
- Update the spec if reality diverges; a stale spec is worse than none.
|
|
97
|
+
|
|
98
|
+
## Why this works across many repos and stacks
|
|
99
|
+
|
|
100
|
+
The same template + the same `/spec` and `/spec-build` commands work in every repo, whatever
|
|
101
|
+
the stack (Java, React, Node/Express, NestJS) and database (MySQL, PostgreSQL, MongoDB). The
|
|
102
|
+
spec captures the contract — API/interface, data model, events, and any cross-service calls —
|
|
103
|
+
explicitly, so changes that ripple between modules or services are designed on paper before
|
|
104
|
+
they're coded.
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Spec: <short title>
|
|
2
|
+
|
|
3
|
+
| | |
|
|
4
|
+
|---|---|
|
|
5
|
+
| **Ticket** | XXX-0000 |
|
|
6
|
+
| **Project / service** | <repo or service name> |
|
|
7
|
+
| **Stack** | <e.g. Java/Spring, React, Node/Express, NestJS — fill from the repo> |
|
|
8
|
+
| **Status** | Draft \| Approved \| Implemented \| Verified \| Archived |
|
|
9
|
+
| **Branch** | <branch this is built on — set by `/spec-advance`; `—` until work starts> |
|
|
10
|
+
| **Author** | <name> |
|
|
11
|
+
| **Date** | YYYY-MM-DD |
|
|
12
|
+
|
|
13
|
+
> Status is written by `/spec-advance`, which checks the evidence each transition requires
|
|
14
|
+
> (see `specs/README.md`). Don't hand-edit it — a status nobody checked is worth nothing.
|
|
15
|
+
|
|
16
|
+
## Revisions
|
|
17
|
+
<Skip this section entirely if the spec was approved first pass — it exists only to bound
|
|
18
|
+
re-review. Add one row per revision, newest first, so a reviewer re-reads what moved instead of
|
|
19
|
+
re-reading the whole spec.>
|
|
20
|
+
|
|
21
|
+
| # | What changed | Why | Sections |
|
|
22
|
+
|---|--------------|-----|----------|
|
|
23
|
+
| 2 | <e.g. 409 → 422 on expired coupon> | <reviewer: 409 implies a conflict that doesn't exist> | 4.1, AC3 |
|
|
24
|
+
| 1 | <initial draft> | — | — |
|
|
25
|
+
|
|
26
|
+
## 1. Problem / Goal
|
|
27
|
+
<What user/business problem are we solving, and why now? 2–4 sentences. No solution here.>
|
|
28
|
+
|
|
29
|
+
## 2. Scope
|
|
30
|
+
**In scope**
|
|
31
|
+
- <bullet>
|
|
32
|
+
|
|
33
|
+
**Non-goals** (explicitly NOT doing)
|
|
34
|
+
- <bullet>
|
|
35
|
+
|
|
36
|
+
## 3. Current behavior
|
|
37
|
+
<How does the relevant part work today? Reference real code: `path/to/File.ext:42`. If new, say "new".>
|
|
38
|
+
|
|
39
|
+
## 4. Proposed change
|
|
40
|
+
> Fill only the subsections that apply to this change and this stack. Delete the rest.
|
|
41
|
+
|
|
42
|
+
### 4.1 API / interface contract
|
|
43
|
+
<The contract this change exposes or consumes. Pick what fits:>
|
|
44
|
+
- **HTTP API** (Java controller, Express route, NestJS controller): method + path, request shape,
|
|
45
|
+
response shape, status codes, error cases.
|
|
46
|
+
- **UI component / module** (React): component name, props in/out, state, events/callbacks,
|
|
47
|
+
the data it fetches and from where.
|
|
48
|
+
- **Library/function**: signature, inputs, outputs, errors thrown.
|
|
49
|
+
|
|
50
|
+
| Method/Type | Path / name | Request / props | Response / return | Notes |
|
|
51
|
+
|-------------|-------------|-----------------|-------------------|-------|
|
|
52
|
+
| | | | | |
|
|
53
|
+
|
|
54
|
+
### 4.2 Data / state model
|
|
55
|
+
<Pick the row(s) that apply:>
|
|
56
|
+
- **Relational (MySQL/PostgreSQL):** new/changed tables, columns, types, indexes, constraints,
|
|
57
|
+
and the **migration** (never hand-edited schema). Note transactions where multiple writes
|
|
58
|
+
must be atomic. Mind dialect specifics (Postgres `SERIAL`/`RETURNING` vs MySQL `AUTO_INCREMENT`).
|
|
59
|
+
- **Document (MongoDB):** new/changed collections, document shape, schema/validation, indexes,
|
|
60
|
+
and any migration/backfill of existing documents.
|
|
61
|
+
- **Client state (React):** new/changed state shape, where it lives (component, store, cache),
|
|
62
|
+
and how it's derived/invalidated.
|
|
63
|
+
|
|
64
|
+
### 4.3 Events / side-effects
|
|
65
|
+
<Async messages, queues/topics, jobs, webhooks, cache invalidation, emails — payload shape,
|
|
66
|
+
idempotency, and failure handling. Omit if none.>
|
|
67
|
+
|
|
68
|
+
### 4.4 External / cross-service / integration calls
|
|
69
|
+
<Outbound calls to other services or third parties (HTTP client, Feign, SDK). For each: what's
|
|
70
|
+
called, the contract assumed, and failure/timeout behavior. Omit if none.>
|
|
71
|
+
|
|
72
|
+
### 4.5 Config / feature flags / env
|
|
73
|
+
<New config keys, environment variables (`.env`), feature flags to gate rollout, profiles affected.>
|
|
74
|
+
|
|
75
|
+
## 5. Acceptance criteria
|
|
76
|
+
<Testable Given/When/Then statements. These become the tests AND the review checklist.>
|
|
77
|
+
|
|
78
|
+
- [ ] **AC1** — Given <state>, when <action>, then <observable outcome>.
|
|
79
|
+
- [ ] **AC2** — ...
|
|
80
|
+
|
|
81
|
+
## 6. Test plan
|
|
82
|
+
<Map each AC to at least one test using THIS project's framework. Pick the level that actually
|
|
83
|
+
proves the AC — don't over- or under-test:>
|
|
84
|
+
- **unit** — pure logic in isolation (Java `*Test.java`; Jest/Vitest).
|
|
85
|
+
- **integration** — module + its real collaborators / DB (Java `*IT.java`; Supertest, `@nestjs/testing`).
|
|
86
|
+
- **functional / E2E** — the behavior end to end from the outside, the way a user or caller hits it
|
|
87
|
+
(HTTP black-box against the running service; UI flows via Playwright/Cypress). **Every
|
|
88
|
+
user-facing or contract-level AC needs at least one functional/E2E test**, not just a unit test.
|
|
89
|
+
|
|
90
|
+
| AC | Test type (unit / integration / functional-e2e) | Test file / class / method |
|
|
91
|
+
|----|-------------------------------------------------|----------------------------|
|
|
92
|
+
| AC1 | unit | |
|
|
93
|
+
|
|
94
|
+
### 6.1 Final acceptance (gate before `Verified`)
|
|
95
|
+
The spec is **not** `Verified` until the project's **full** test suite — including the
|
|
96
|
+
functional/E2E tests above — runs green end to end (not just the newly-added tests). List the
|
|
97
|
+
command(s) that constitute that final run and any seed/fixtures/services they need:
|
|
98
|
+
|
|
99
|
+
- Full suite: `<e.g. npm test && npm run test:e2e / mvn verify / pytest && pytest -m e2e>`
|
|
100
|
+
- Preconditions: `<test DB seeded, service running, env vars — or "none">`
|
|
101
|
+
|
|
102
|
+
## 7. Rollout & risks
|
|
103
|
+
<Deploy order if cross-service, backward compatibility, data migration risk, rollback plan,
|
|
104
|
+
and mitigations.>
|
|
105
|
+
|
|
106
|
+
## 8. Open questions / follow-ups
|
|
107
|
+
<**Non-blocking items only** — things whose answer changes nothing in this spec: a later
|
|
108
|
+
optimization, a question for another team, a deferred follow-up. If an answer would change the API
|
|
109
|
+
shape, data model, error/status codes, scope boundary, or backward compatibility, it is
|
|
110
|
+
**blocking**: it must be answered *before* this spec is written, not parked here. A blocking
|
|
111
|
+
question in this section is a bug — it turns one human review into a review, a revision, and a
|
|
112
|
+
re-read. Empty is the healthy state.>
|
|
113
|
+
|
|
114
|
+
- <bullet>
|