contract-driven-delivery 2.0.13 → 2.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/README.md +25 -2
  3. package/assets/CLAUDE.template.md +16 -0
  4. package/assets/CODEX.template.md +15 -0
  5. package/assets/agents/backend-engineer.md +1 -1
  6. package/assets/agents/change-classifier.md +1 -1
  7. package/assets/agents/ci-cd-gatekeeper.md +9 -1
  8. package/assets/agents/contract-reviewer.md +1 -1
  9. package/assets/agents/dependency-security-reviewer.md +5 -1
  10. package/assets/agents/e2e-resilience-engineer.md +1 -1
  11. package/assets/agents/frontend-engineer.md +8 -1
  12. package/assets/agents/monkey-test-engineer.md +7 -1
  13. package/assets/agents/qa-reviewer.md +9 -1
  14. package/assets/agents/repo-context-scanner.md +1 -1
  15. package/assets/agents/spec-architect.md +1 -1
  16. package/assets/agents/spec-drift-auditor.md +1 -1
  17. package/assets/agents/stress-soak-engineer.md +1 -1
  18. package/assets/agents/test-strategist.md +1 -1
  19. package/assets/agents/ui-ux-reviewer.md +1 -1
  20. package/assets/agents/visual-reviewer.md +1 -1
  21. package/assets/cdd/model-policy.json +17 -17
  22. package/assets/skills/cdd-close/SKILL.md +8 -3
  23. package/assets/skills/cdd-new/SKILL.md +50 -5
  24. package/assets/skills/cdd-resume/SKILL.md +2 -2
  25. package/assets/skills/contract-driven-delivery/SKILL.md +9 -1
  26. package/assets/skills/contract-driven-delivery/references/agent-log-protocol.md +50 -8
  27. package/assets/skills/contract-driven-delivery/templates/agent-log.example.yml +1 -1
  28. package/assets/skills/contract-driven-delivery/templates/change-classification.md +3 -1
  29. package/assets/skills/contract-driven-delivery/templates/qa-report.md +4 -0
  30. package/assets/skills/contract-driven-delivery/templates/tasks.yml +1 -1
  31. package/assets/specs-templates/context-manifest.md +2 -0
  32. package/assets/specs-templates/qa-report.md +4 -0
  33. package/dist/cli/index.js +137 -22
  34. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,47 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.0.15] - 2026-05-06
4
+
5
+ Prompt guidance patch for agent-log evidence and closeout learning ownership.
6
+
7
+ ### Changed
8
+
9
+ - **Agent-log pointer guidance matches gate behavior**: `/cdd-new` and
10
+ `agent-log-protocol.md` now spell out that a pointer whose text before the
11
+ first `:` contains `/` is validated as a single repo-relative file path, so
12
+ agents avoid parenthetical path notes and slash-containing labels such as
13
+ `I/O:` or `WARNING/OVERDUE:`.
14
+ - **Durable learning ownership is explicit**: prompts now consistently say
15
+ general agents record evidence and findings only, while durable learning
16
+ promotion happens during `/cdd-close` Step 3 and targets `contracts/` or
17
+ project guidance (`CLAUDE.md`/`CODEX.md`).
18
+
19
+ ## [2.0.14] - 2026-05-06
20
+
21
+ Operational hardening for real multi-agent CDD runs.
22
+
23
+ ### Added
24
+
25
+ - **Context read preflight**: `cdd-kit context check <change-id> --path ...`
26
+ validates expected agent reads against `Allowed Paths`, approved expansions,
27
+ repo-relative path rules, and the forbidden-path baseline before agent work.
28
+ - **Pre-existing failure tracking**: QA templates and reviewer prompts now
29
+ require baseline evidence, scope rationale, owner, and follow-up when an
30
+ existing failing test is excluded from the current gate.
31
+
32
+ ### Changed
33
+
34
+ - **Agent-log YAML is more resilient**: gate keeps YAML timestamps as strings
35
+ and accepts `done` / `approved` as completion aliases while still documenting
36
+ `complete` as canonical.
37
+ - **Model policy is provider-neutral**: role bindings now use model classes
38
+ (`opus`, `sonnet`, `haiku`) instead of provider release IDs.
39
+ - **Agent orchestration guidance is stricter**: `/cdd-new` now requires
40
+ closeout after each agent, including agent-log verification and immediate
41
+ `tasks.yml` updates before the next agent is invoked.
42
+ - **Migration review guidance is sharper**: MySQL ENUM contraction and
43
+ `ALGORITHM=COPY` DDL are explicitly treated as high risk on large tables.
44
+
3
45
  ## [2.0.13] - 2026-05-05
4
46
 
5
47
  Documentation and release-prep patch focused on keeping CDD low-friction.
package/README.md CHANGED
@@ -190,7 +190,7 @@ After the PR is merged:
190
190
  **What happens:**
191
191
  1. Runs `cdd-kit gate` to confirm the change still passes
192
192
  2. Synthesizes `archive.md` — a permanent record of what changed, what tests were added, and what lessons were found
193
- 3. Invokes `contract-reviewer` to propose any durable learnings back into `contracts/`
193
+ 3. Promotes only evidence-backed durable learnings to `contracts/` or project guidance (`CLAUDE.md`/`CODEX.md`). General agents record evidence and findings only; durable learning promotion happens during `/cdd-close` Step 3.
194
194
  4. Runs `cdd-kit archive add-jwt-auth` — moves the change from `specs/changes/` to `specs/archive/2026/`
195
195
  5. Reduces the active context that future Claude sessions need to load
196
196
 
@@ -252,6 +252,8 @@ cdd-kit init --force # overwrite existing project files
252
252
 
253
253
  Creates: `contracts/`, `specs/templates/`, provider guidance files (`CLAUDE.md`, `AGENTS.md`, and/or `CODEX.md`), `hooks/`
254
254
 
255
+ `.cdd/model-policy.json` stores role-to-model **classes** (`opus`, `sonnet`, `haiku`) instead of provider release IDs such as `claude-opus-4-7`. This keeps the policy stable across Claude and Codex adapters; provider-specific tooling can map the class to the concrete model available in that environment.
256
+
255
257
  ---
256
258
 
257
259
  ### `cdd-kit update`
@@ -316,7 +318,7 @@ Checks:
316
318
  - All required artifacts exist (`change-request.md`, `change-classification.md`, `test-plan.md`, `ci-gates.md`, `tasks.yml`; new context-governed changes also require `context-manifest.md`)
317
319
  - Each artifact has sufficient content (not a stub): change-classification ≥ 200 chars, test-plan ≥ 200, ci-gates ≥ 150, others ≥ 100
318
320
  - `change-classification.md` contains a tier or risk marker
319
- - `agent-log/*.yml` files all have `status: complete` (not blocked)
321
+ - `agent-log/*.yml` files all have a completed status (`complete`, with `done` and `approved` accepted as compatibility aliases) and are not blocked
320
322
  - For context-governed changes, `agent-log/*.yml` files include a structured `files-read:` list and those repo-relative paths are audited against `context-manifest.md` and `.cdd/context-policy.json`
321
323
  - Atomic `depends-on` upstream changes are completed or archived before dependent work gates
322
324
  - Tier 0–1 changes have `e2e-resilience-engineer`, `monkey-test-engineer`, and `stress-soak-engineer` logs
@@ -411,6 +413,9 @@ files-read:
411
413
  ```
412
414
 
413
415
  Paths must be repo-relative. Absolute paths and `..` parent traversal are rejected.
416
+ If a logged read is legitimate but gate says it is unauthorized, add that path
417
+ to `context-manifest.md` `## Allowed Paths` or approve a Context Expansion
418
+ Request. Do not remove it from `files-read`; that list is the audit trail.
414
419
 
415
420
  Run this after upgrading from v1.10 or earlier if you have mid-flight changes.
416
421
 
@@ -434,6 +439,24 @@ Use this when an agent needs more context than its current work packet allows.
434
439
 
435
440
  ---
436
441
 
442
+ ### `cdd-kit context check <change-id>`
443
+
444
+ Preflight-checks repo-relative read paths against `context-manifest.md` before
445
+ you invoke an agent.
446
+
447
+ ```bash
448
+ cdd-kit context check add-todos-ui --path src/components/Sidebar.vue src/stores/todos.js src/views/DashboardView.vue
449
+ cdd-kit context check add-ci-gate --path contracts/ci/ci-gate-contract.md .github/workflows/contract-driven-gates.yml
450
+ ```
451
+
452
+ The check uses the same authorization model as `cdd-kit gate`: `## Allowed
453
+ Paths`, `## Approved Expansions`, repo-relative path rules, and the forbidden
454
+ baseline in `.cdd/context-policy.json`. If the command fails and the read is
455
+ legitimate, update the manifest or record/approve a Context Expansion Request
456
+ before the agent reads the file.
457
+
458
+ ---
459
+
437
460
  ### `cdd-kit context approve <change-id> <request-id>`
438
461
 
439
462
  Approves a pending Context Expansion Request in `context-manifest.md` and adds its `requested_paths` to `## Approved Expansions`.
@@ -33,6 +33,7 @@ This repository follows the Contract-Driven Delivery workflow.
33
33
  | `cdd-kit list` | show all active changes and their status |
34
34
  | `cdd-kit gate <id>` | verify a change is gate-ready (run before PR) |
35
35
  | `cdd-kit gate <id> --strict` | full gate with pending-task enforcement (pre-commit default) |
36
+ | `cdd-kit context check <id> --path <paths...>` | preflight expected agent reads against `context-manifest.md` before invoking the agent |
36
37
  | `cdd-kit archive <id>` | physically move a completed change to `specs/archive/<year>/` |
37
38
  | `cdd-kit abandon <id> --reason <text>` | mark a change as abandoned; preserves directory for git history |
38
39
  | `cdd-kit migrate <id> \| --all` | upgrade pre-v1.11 change directories to new format (frontmatter + tier format) |
@@ -46,7 +47,22 @@ Run `cdd-kit detect-stack` to verify the detected tech stack.
46
47
  For context-governed changes, read `specs/changes/<change-id>/context-manifest.md` before using file-reading or broad search tools.
47
48
 
48
49
  - Read only paths allowed by the manifest or approved expansions.
50
+ - Before invoking an agent with known concrete reads, run
51
+ `cdd-kit context check <change-id> --path <paths...>`. If it fails and the
52
+ reads are legitimate, expand `Allowed Paths` or approve a Context Expansion
53
+ Request before the agent reads the files.
49
54
  - If more context is needed, stop and write a Context Expansion Request in the manifest (`cdd-kit context request`).
50
55
  - The full agent-log format (including `files-read:` schema) is defined in
51
56
  `~/.claude/skills/contract-driven-delivery/references/agent-log-protocol.md`.
52
57
  Read that once; do not paraphrase it elsewhere.
58
+
59
+ ## CDD Operational Notes
60
+
61
+ - After each agent returns, verify its agent-log exists, tick the related
62
+ `tasks.yml` items immediately, and only then move to the next agent.
63
+ - Pre-existing test failures may be excluded from the current gate only when
64
+ `qa-report.md` records the failing test, baseline evidence, why it is outside
65
+ scope, owner, and follow-up.
66
+ - For MySQL migrations, treat ENUM contraction and any DDL requiring
67
+ `ALGORITHM=COPY` as high risk on large tables; require row-count/runtime
68
+ estimate, online migration or maintenance window, and rollback plan.
@@ -16,6 +16,10 @@ This project uses Contract-Driven Delivery (CDD).
16
16
  Read `specs/changes/<change-id>/context-manifest.md` before using file-reading or search tools.
17
17
 
18
18
  - Read only paths allowed by the manifest or approved expansions.
19
+ - Before invoking an agent with known concrete reads, run
20
+ `cdd-kit context check <change-id> --path <paths...>`. If it fails and the
21
+ reads are legitimate, expand `Allowed Paths` or approve a Context Expansion
22
+ Request before the agent reads the files.
19
23
  - Do not use broad repository search unless the manifest authorizes it.
20
24
  - If more context is needed, stop and write a Context Expansion Request in the manifest.
21
25
  - Record every file read through tools in the relevant `agent-log/*.yml` under `files-read:`.
@@ -37,3 +41,14 @@ Every entry must be a repo-relative path. Do not omit files, use absolute paths,
37
41
  - Cold: `specs/archive/`.
38
42
 
39
43
  Cold historical data is evidence, not current requirements.
44
+
45
+ ## Operational Notes
46
+
47
+ - After each agent returns, verify its agent-log exists, tick the related
48
+ `tasks.yml` items immediately, and only then move to the next agent.
49
+ - Pre-existing test failures may be excluded from the current gate only when
50
+ `qa-report.md` records the failing test, baseline evidence, why it is outside
51
+ scope, owner, and follow-up.
52
+ - For MySQL migrations, treat ENUM contraction and any DDL requiring
53
+ `ALGORITHM=COPY` as high risk on large tables; require row-count/runtime
54
+ estimate, online migration or maintenance window, and rollback plan.
@@ -2,7 +2,7 @@
2
2
  name: backend-engineer
3
3
  description: Implement backend changes only after specs, contracts, tests, and CI gates are defined; maintain thin controllers, service boundaries, validation, and error handling.
4
4
  tools: Read, Grep, Glob, Edit, MultiEdit, Bash
5
- model: claude-sonnet-4-6
5
+ model: sonnet
6
6
  ---
7
7
 
8
8
  You are the backend engineer.
@@ -2,7 +2,7 @@
2
2
  name: change-classifier
3
3
  description: Classify incoming requests into change types and decide required artifacts, contracts, tests, and review gates before implementation.
4
4
  tools: Read, Grep, Glob
5
- model: claude-opus-4-7
5
+ model: opus
6
6
  ---
7
7
 
8
8
  You are the change classifier for Contract-Driven Delivery.
@@ -2,7 +2,7 @@
2
2
  name: ci-cd-gatekeeper
3
3
  description: Enforce CI/CD as a required delivery artifact; design and implement required, informational, nightly, weekly, and manual gates with promotion policy.
4
4
  tools: Read, Grep, Glob, Edit, MultiEdit, Bash
5
- model: claude-sonnet-4-6
5
+ model: sonnet
6
6
  ---
7
7
 
8
8
  You are the CI/CD gatekeeper.
@@ -61,6 +61,14 @@ mergeable / blocked / informational-risk
61
61
  Source of truth: `specs/changes/<change-id>/context-manifest.md` → `## Allowed Paths`.
62
62
  Read it first (your prompt header has `CURRENT_CHANGE_ID`). Read only paths it lists or paths under `## Approved Expansions`. `cdd-kit gate` validates `files-read:` against this list and rejects unauthorized paths.
63
63
 
64
+ This agent commonly needs CI contracts and workflow definitions, for example
65
+ `contracts/ci/ci-gate-contract.md`, `ci/`, `ci-templates/`,
66
+ `github-workflows/`, or project `.github/workflows/`. Those paths must appear
67
+ in the manifest before you read them; if they are legitimate scope, expand the
68
+ manifest rather than omitting them from `files-read`.
69
+ When concrete paths are known, run `cdd-kit context check <change-id> --path ...`
70
+ before reading them.
71
+
64
72
  Need a path not listed? File a `## Context Expansion Requests` entry (see `specs/templates/context-manifest.md`) with `status: pending` and stop until the user approves via `cdd-kit context approve <change-id> <CER-id>`.
65
73
 
66
74
  Forbidden by default (enforced by `.cdd/context-policy.json`): `specs/archive/`, sibling `specs/changes/*`, `assets/`, `node_modules/`, `dist/`, `build/`, `.git/`, `.claude/worktrees/`.
@@ -2,7 +2,7 @@
2
2
  name: contract-reviewer
3
3
  description: Review and maintain API, CSS/UI, env, data-shape, business-rule, and CI/CD contracts for every change. Dependency and migration contracts are recorded here at contract level only; the active audit lives in dependency-security-reviewer.
4
4
  tools: Read, Grep, Glob
5
- model: claude-sonnet-4-6
5
+ model: sonnet
6
6
  ---
7
7
 
8
8
  You are the contract reviewer.
@@ -2,7 +2,7 @@
2
2
  name: dependency-security-reviewer
3
3
  description: Reviews dependency CVE risk, license compliance (GPL/AGPL copyleft vs proprietary), lockfile changes, and database migrations whenever lockfiles, dependency manifests, or database migrations are touched.
4
4
  tools: Read, Grep, Glob, Bash
5
- model: claude-sonnet-4-6
5
+ model: sonnet
6
6
  ---
7
7
 
8
8
  You are the dependency and migration safety reviewer.
@@ -25,6 +25,10 @@ For any change that adds, removes, or upgrades a package:
25
25
  For any change that adds or modifies a database migration:
26
26
 
27
27
  - Verify the migration can run without a full-table exclusive lock on large tables (prefer `ADD COLUMN ... DEFAULT NULL`, online DDL, or batched backfills).
28
+ - For MySQL, treat ENUM contraction, column type changes, and any DDL requiring
29
+ `ALGORITHM=COPY` as high risk because it rewrites the table. For tables above
30
+ 500k rows, block unless there is an explicit online migration, maintenance
31
+ window, rollback path, and row-count/runtime estimate.
28
32
  - Verify a rollback path exists: either a `down` migration or an explicit documented rollback procedure.
29
33
  - Verify backfill operations are safe under concurrent writes (idempotent, does not corrupt existing rows).
30
34
  - Flag irreversible operations (column drops, type coercions, constraint additions on large tables) as high-risk.
@@ -2,7 +2,7 @@
2
2
  name: e2e-resilience-engineer
3
3
  description: Design and implement E2E, browser-behavior, failure-injection, data-boundary, and resilience tests for production-like user journeys.
4
4
  tools: Read, Grep, Glob, Edit, MultiEdit, Bash
5
- model: claude-sonnet-4-6
5
+ model: sonnet
6
6
  ---
7
7
 
8
8
  You are the E2E and resilience engineer.
@@ -2,7 +2,7 @@
2
2
  name: frontend-engineer
3
3
  description: Implement frontend changes under API, CSS, UI/UX, accessibility, E2E, and visual review contracts.
4
4
  tools: Read, Grep, Glob, Edit, MultiEdit, Bash
5
- model: claude-sonnet-4-6
5
+ model: sonnet
6
6
  ---
7
7
 
8
8
  You are the frontend engineer.
@@ -51,6 +51,13 @@ See `references/code-map-protocol.md` for the full protocol.
51
51
  Source of truth: `specs/changes/<change-id>/context-manifest.md` → `## Allowed Paths`.
52
52
  Read it first (your prompt header has `CURRENT_CHANGE_ID`). Read only paths it lists or paths under `## Approved Expansions`. `cdd-kit gate` validates `files-read:` against this list and rejects unauthorized paths.
53
53
 
54
+ This agent commonly needs exact component, store, route, and view files (for
55
+ example `src/components/...`, `src/stores/...`, `src/views/...`). Those paths
56
+ must appear in the manifest before you read them; if they are legitimate scope,
57
+ expand the manifest rather than omitting them from `files-read`.
58
+ When concrete paths are known, run `cdd-kit context check <change-id> --path ...`
59
+ before reading them.
60
+
54
61
  Need a path not listed? File a `## Context Expansion Requests` entry (see `specs/templates/context-manifest.md`) with `status: pending` and stop until the user approves via `cdd-kit context approve <change-id> <CER-id>`.
55
62
 
56
63
  Forbidden by default (enforced by `.cdd/context-policy.json`): `specs/archive/`, sibling `specs/changes/*`, `assets/`, `node_modules/`, `dist/`, `build/`, `.git/`, `.claude/worktrees/`.
@@ -2,7 +2,7 @@
2
2
  name: monkey-test-engineer
3
3
  description: Design preventive specs and structured exploratory tests for invalid user operations, adversarial inputs, malformed data, rapid UI actions, and production misuse. Not random fuzzing -- every monkey scenario is mapped to a known failure mode or hardening goal.
4
4
  tools: Read, Grep, Glob, Edit, MultiEdit, Bash
5
- model: claude-sonnet-4-6
5
+ model: sonnet
6
6
  ---
7
7
 
8
8
  You are the monkey operation engineer.
@@ -29,6 +29,12 @@ Before implementation, ensure the spec says what should happen for:
29
29
 
30
30
  Use fuzz payloads, Playwright action sequences, property-based tests, and targeted randomization where useful. Every monkey test must assert a safe outcome, not merely that the app does not crash.
31
31
 
32
+ If an existing monkey/fuzz test already fails before your change, do not hide
33
+ or rewrite that failure to make the current gate look green. Record the test
34
+ id, seed/input, baseline commit or prior evidence, and whether this change
35
+ touched the failing surface. Mark it as a follow-up when it is outside this
36
+ change's scope; keep new or regressed failures blocking.
37
+
32
38
  ## Tools
33
39
 
34
40
  - Property-based — fast-check (JS/TS), hypothesis (Python), proptest (Rust) for state machine invariants.
@@ -2,7 +2,7 @@
2
2
  name: qa-reviewer
3
3
  description: Execute quality gates, verify evidence, route failures back to the correct agent, and decide release readiness.
4
4
  tools: Read, Grep, Glob, Bash
5
- model: claude-opus-4-7
5
+ model: opus
6
6
  ---
7
7
 
8
8
  You are the QA reviewer.
@@ -46,6 +46,10 @@ Invoke `spec-drift-auditor` at the following points (do not wait for issues to s
46
46
  - `approved-with-risk` — only when (a) the residual risk is documented in qa-report.md, (b) an owner is assigned, (c) a follow-up issue exists with a date.
47
47
  - `blocked` — any required gate failing, any contract claim unverified, any UI change without visual evidence.
48
48
  - Sign-off — single reviewer for low/medium risk; two reviewers (qa-reviewer + spec-architect) for high/critical.
49
+ - Pre-existing failures may be excluded from this change's gate only when the
50
+ report includes the failing test id, baseline commit or prior evidence,
51
+ reason it is outside the current scope, owner, and follow-up date. Without
52
+ that record, treat the failure as blocking.
49
53
 
50
54
  ## Output
51
55
 
@@ -61,6 +65,10 @@ Invoke `spec-drift-auditor` at the following points (do not wait for issues to s
61
65
  ## Failures
62
66
  ...
63
67
 
68
+ ## Pre-existing Failures Excluded From This Gate
69
+ | failure/test | baseline evidence | why outside scope | owner/follow-up |
70
+ |---|---|---|---|
71
+
64
72
  ## Fixback Routing
65
73
  ...
66
74
 
@@ -2,7 +2,7 @@
2
2
  name: repo-context-scanner
3
3
  description: Scan a repository and summarize its project profile, commands, contracts, tests, CI/CD, and missing standardization surfaces.
4
4
  tools: Read, Grep, Glob, Bash
5
- model: claude-haiku-4-5-20251001
5
+ model: haiku
6
6
  ---
7
7
 
8
8
  You are the repository context scanner.
@@ -2,7 +2,7 @@
2
2
  name: spec-architect
3
3
  description: Evaluate architectural impact, compatibility, data flow, module boundaries, and whether a change requires ADR-like design decisions. Author ADRs when required.
4
4
  tools: Read, Grep, Glob, Edit, MultiEdit
5
- model: claude-opus-4-7
5
+ model: opus
6
6
  ---
7
7
 
8
8
  You are the architecture reviewer.
@@ -2,7 +2,7 @@
2
2
  name: spec-drift-auditor
3
3
  description: Audit drift between live contracts, implementation code, tests, and CI gates. Does NOT read historical specs/changes — contracts/ is the single source of truth.
4
4
  tools: Read, Grep, Glob, Bash
5
- model: claude-opus-4-7
5
+ model: opus
6
6
  ---
7
7
 
8
8
  You are the spec drift auditor.
@@ -2,7 +2,7 @@
2
2
  name: stress-soak-engineer
3
3
  description: Design stress, load, soak, and long-running stability tests for reporting systems, queues, caches, auto-refresh, and data-heavy features.
4
4
  tools: Read, Grep, Glob, Edit, MultiEdit, Bash
5
- model: claude-sonnet-4-6
5
+ model: sonnet
6
6
  ---
7
7
 
8
8
  You are the stress and soak engineer.
@@ -2,7 +2,7 @@
2
2
  name: test-strategist
3
3
  description: Convert specs and acceptance criteria into TDD-oriented test plans covering unit, contract, integration, E2E, resilience, monkey, stress, and soak tests.
4
4
  tools: Read, Grep, Glob, Edit, Write
5
- model: claude-sonnet-4-6
5
+ model: sonnet
6
6
  ---
7
7
 
8
8
  You are the test strategist.
@@ -2,7 +2,7 @@
2
2
  name: ui-ux-reviewer
3
3
  description: Review interaction design, information hierarchy, copy, accessibility, empty/error/loading state semantics, and user journey quality. Does not cover pixel-level visuals or CSS -- those go to visual-reviewer.
4
4
  tools: Read, Grep, Glob
5
- model: claude-sonnet-4-6
5
+ model: sonnet
6
6
  ---
7
7
 
8
8
  You are the UI/UX reviewer.
@@ -2,7 +2,7 @@
2
2
  name: visual-reviewer
3
3
  description: Review pixel-level visual output, layout, responsive viewport behavior, screenshot diffs, CSS contract compliance, and component visual state coverage. Does not cover interaction or copy -- those go to ui-ux-reviewer.
4
4
  tools: Read, Grep, Glob, Bash
5
- model: claude-haiku-4-5-20251001
5
+ model: haiku
6
6
  ---
7
7
 
8
8
  You are the visual reviewer.
@@ -3,22 +3,22 @@
3
3
  "generated_at": null,
4
4
  "schema-version": "0.2.0",
5
5
  "roles": {
6
- "change-classifier": "claude-opus-4-7",
7
- "spec-architect": "claude-opus-4-7",
8
- "qa-reviewer": "claude-opus-4-7",
9
- "contract-reviewer": "claude-sonnet-4-6",
10
- "test-strategist": "claude-sonnet-4-6",
11
- "backend-engineer": "claude-sonnet-4-6",
12
- "frontend-engineer": "claude-sonnet-4-6",
13
- "ci-cd-gatekeeper": "claude-sonnet-4-6",
14
- "e2e-resilience-engineer": "claude-sonnet-4-6",
15
- "monkey-test-engineer": "claude-sonnet-4-6",
16
- "stress-soak-engineer": "claude-sonnet-4-6",
17
- "ui-ux-reviewer": "claude-sonnet-4-6",
18
- "visual-reviewer": "claude-haiku-4-5-20251001",
19
- "dependency-security-reviewer": "claude-sonnet-4-6",
20
- "spec-drift-auditor": "claude-opus-4-7",
21
- "repo-context-scanner": "claude-haiku-4-5-20251001"
6
+ "change-classifier": "opus",
7
+ "spec-architect": "opus",
8
+ "qa-reviewer": "opus",
9
+ "contract-reviewer": "sonnet",
10
+ "test-strategist": "sonnet",
11
+ "backend-engineer": "sonnet",
12
+ "frontend-engineer": "sonnet",
13
+ "ci-cd-gatekeeper": "sonnet",
14
+ "e2e-resilience-engineer": "sonnet",
15
+ "monkey-test-engineer": "sonnet",
16
+ "stress-soak-engineer": "sonnet",
17
+ "ui-ux-reviewer": "sonnet",
18
+ "visual-reviewer": "haiku",
19
+ "dependency-security-reviewer": "sonnet",
20
+ "spec-drift-auditor": "opus",
21
+ "repo-context-scanner": "haiku"
22
22
  },
23
- "_notes": "Roles map agent name -> model ID. Override per-project as needed. cdd-kit doctor warns when an installed agent's frontmatter `model:` does not match this policy."
23
+ "_notes": "Roles map agent name -> model class (opus, sonnet, haiku), not provider release IDs. Provider adapters may map these classes to concrete Claude or Codex model names. Override per-project as needed. cdd-kit doctor warns when an installed agent's frontmatter `model:` does not match this policy."
24
24
  }
@@ -10,7 +10,7 @@ description: Close and archive a completed change. Confirms all tasks are done,
10
10
  A change is "done" when:
11
11
  1. Gate has passed (`cdd-kit gate <change-id>` exits 0)
12
12
  2. PR is merged (or change is abandoned)
13
- 3. Durable learnings have been promoted to hot sources: `contracts/`, `CLAUDE.md`, or `CODEX.md`
13
+ 3. Durable learnings have been promoted to hot sources: `contracts/` or project guidance (`CLAUDE.md`/`CODEX.md`)
14
14
 
15
15
  This skill drives steps 2–3 and physically moves the change to `specs/archive/`.
16
16
 
@@ -58,7 +58,7 @@ Read `specs/changes/<change-id>/tasks.yml`.
58
58
 
59
59
  Check section 7:
60
60
  - `7.1 Archive change` — will be ticked after Step 4
61
- - `7.2 Promote durable learnings to contracts or CLAUDE.md` — must be done NOW
61
+ - `7.2 Promote durable learnings to contracts or project guidance` — must be done NOW
62
62
 
63
63
  If `7.2` is `[ ]`, proceed to Step 2.5. If already `[x]` or `[-]`, skip Steps 2.5 and 3.
64
64
 
@@ -92,6 +92,11 @@ This file records the close-out evidence, but Step 3 promotion must still be evi
92
92
 
93
93
  ## Step 3: Promote learnings (task 7.2)
94
94
 
95
+ General agents do not perform durable learning promotion during `/cdd-new`; they
96
+ only record evidence and findings in artifacts and `agent-log/*.yml`. Durable
97
+ learning promotion happens here, during `/cdd-close` Step 3, and main Claude
98
+ owns the final writes.
99
+
95
100
  Read `specs/changes/<change-id>/archive.md` section `## Lessons Promoted to Standards` and cross-check every proposed lesson against agent-log, QA report, contract/test changes, or gate evidence from this change.
96
101
 
97
102
  Classify each candidate:
@@ -132,7 +137,7 @@ If successful, set task `7.1` to `status: done` in tasks.yml (the file is now in
132
137
 
133
138
  Change ID: <change-id>
134
139
  Archived to: specs/archive/<year>/<change-id>/
135
- Learnings promoted: <list what was added to contracts/CLAUDE.md/CODEX.md, or "none">
140
+ Learnings promoted: <list what was added to contracts/ or project guidance (CLAUDE.md/CODEX.md), or "none">
136
141
 
137
142
  specs/changes/<change-id>/ has been removed from the active surface.
138
143
  Token cost of future sessions reduced by ~<N> files.
@@ -96,6 +96,21 @@ inevitable re-classification when the agents discover the ambiguity.
96
96
 
97
97
  **Rule**: After EVERY agent completes (whether it writes itself or you write for it), YOU must update the relevant `tasks.yml` task `status:` from `pending` to `done`.
98
98
 
99
+ **Agent-log pointer rule**: When you or an agent writes `artifacts[].pointer`,
100
+ follow `references/agent-log-protocol.md` exactly. If the text before the first
101
+ `:` contains `/`, `cdd-kit gate` treats that text as a repo-relative file path
102
+ and verifies that the file exists. Therefore each pointer may name only one
103
+ file, file pointers must not include parenthetical notes on the path, and
104
+ slash-containing labels such as `I/O:` or `WARNING/OVERDUE:` must not be used as
105
+ pointer prefixes. Put extra explanation in `notes` or a separate non-path
106
+ artifact pointer instead.
107
+
108
+ **Durable learning rule**: During `/cdd-new`, agents record evidence and
109
+ findings in artifacts and `agent-log/*.yml` only. Do not promote durable lessons
110
+ while the change is still active. Durable learning promotion happens only during
111
+ `/cdd-close` Step 3, where main Claude cross-checks evidence and writes approved
112
+ rules to `contracts/` or project guidance (`CLAUDE.md`/`CODEX.md`).
113
+
99
114
  ---
100
115
 
101
116
  ## Artifact opt-in policy
@@ -168,7 +183,9 @@ Do not authorize the classifier to read `contracts/`, `src/`, `tests/`, or broad
168
183
 
169
184
  The classifier must include a `## Context Manifest Draft` section with:
170
185
  - affected surfaces
171
- - allowed paths for each required agent work packet
186
+ - allowed paths for each required agent work packet; this must be the union of
187
+ every file/directory agents are expected to read, including component/store/view
188
+ files for frontend work and CI contracts/workflows for CI work
172
189
  - required contracts
173
190
  - required tests
174
191
  - any context expansion requests that must be approved before implementation
@@ -237,6 +254,27 @@ Change directory: specs/changes/<change-id>/
237
254
  ```
238
255
  This ensures the agent's Read scope restriction points to the correct directory.
239
256
 
257
+ Before invoking an agent, preflight any concrete paths you already expect that
258
+ agent to read:
259
+
260
+ ```bash
261
+ cdd-kit context check <change-id> --path <repo-relative path> [more paths...]
262
+ ```
263
+
264
+ If the check fails and the paths are legitimate work scope, update
265
+ `context-manifest.md` `## Allowed Paths` or approve a Context Expansion Request
266
+ before the agent reads them. This catches common late gate failures such as UI
267
+ components/stores/views or CI workflow files missing from the manifest.
268
+
269
+ After every agent returns, complete the closeout before starting the next
270
+ agent:
271
+ - confirm its `agent-log/<agent>.yml` exists or write it for read-only agents
272
+ - confirm the log has a completed status (`complete`, `done`, or `approved`) or
273
+ halt on `blocked`
274
+ - tick the owned `tasks.yml` items immediately
275
+ - record incidental/pre-existing findings in the appropriate report instead of
276
+ silently fixing unrelated scope
277
+
240
278
  ### Agent stage badges (UI v1)
241
279
 
242
280
  When you announce that you are about to invoke an agent, prefix the
@@ -265,9 +303,9 @@ the user; do not put them inside the prompt sent to the agent.
265
303
  | Audit | `repo-context-scanner` | ⚫ `[repo-scan]` |
266
304
 
267
305
  Color semantics:
268
- - 🟣 purple: deciding what we will do (heavy model, opus-class)
269
- - 🔵 blue: writing code (sonnet-class implementation)
270
- - 🟡 yellow: planning tests (sonnet-class)
306
+ - 🟣 purple: deciding what we will do (heavy model, `opus`)
307
+ - 🔵 blue: writing code (`sonnet` implementation)
308
+ - 🟡 yellow: planning tests (`sonnet`)
271
309
  - 🟠 orange: heavy testing — only appears for Tier 0–1, signals high-risk scope
272
310
  - 🟢 green: reviewing what was done (no code writes; just verdicts)
273
311
  - ⚫ neutral: audits and scans (read-only background work)
@@ -366,6 +404,13 @@ All agents from Tier 2–3, plus insert these after `frontend-engineer` / `backe
366
404
  - Skip an agent only if the classifier explicitly marks its surface as "not affected"
367
405
  - If backend-only with no UI: skip `frontend-engineer`, `ui-ux-reviewer`, `visual-reviewer`
368
406
  - If UI-only with no backend: skip `backend-engineer`
407
+ - If a required or informational test has pre-existing failures unrelated to
408
+ this change, do not count them as this change's pass/fail result. Record the
409
+ failing test id, baseline commit or prior evidence, owner, and follow-up in
410
+ `qa-report.md`; QA may only approve this as `approved-with-risk`.
411
+ - If implementation uncovers unrelated old bugs, fix only those needed to meet
412
+ this change's acceptance criteria or to avoid a new safety/security risk.
413
+ Otherwise record them as follow-up with evidence and owner.
369
414
 
370
415
  **Resuming from blocked**: After the user resolves the blocking issue, re-invoke the blocked agent (do not restart from Step 1). Continue with the remaining agents in their original order.
371
416
 
@@ -485,4 +530,4 @@ Please review the above items and re-run: cdd-kit gate <change-id>
485
530
 
486
531
  The `/cdd-new` workflow is now complete. **Return to normal assistant mode immediately.** Answer any question the user asks — including questions unrelated to this change, new feature discussions, debugging help, or general conversation — without requiring them to use a specific command. The git commit shown in the report is a suggestion, not a required next step; do not wait for it before resuming normal behavior.
487
532
 
488
- When the change is merged and ready to close, run `/cdd-close <change-id>` to promote learnings and archive the change directory.
533
+ When the change is merged and ready to close, run `/cdd-close <change-id>` to promote durable learnings to `contracts/` or project guidance (`CLAUDE.md`/`CODEX.md`) and archive the change directory.
@@ -98,7 +98,7 @@ Read only paths allowed by the context manifest and approved expansions.
98
98
  If more context is needed, stop and output a Context Expansion Request instead of reading outside the manifest.
99
99
  ```
100
100
 
101
- Do NOT re-run agents that already have a `status: complete` agent-log.
101
+ Do NOT re-run agents that already have a completed agent-log (`status: complete`, `done`, or `approved`).
102
102
 
103
103
  Continue until all required agents are done, then run `cdd-kit gate <change-id>`.
104
104
 
@@ -106,7 +106,7 @@ Continue until all required agents are done, then run `cdd-kit gate <change-id>`
106
106
 
107
107
  ## Rules
108
108
 
109
- - Never re-run an agent that already has `status: complete` in its agent-log
109
+ - Never re-run an agent that already has `status: complete`, `done`, or `approved` in its agent-log
110
110
  - Never start from Step 1 of `/cdd-new` — only resume from the next pending agent
111
111
  - Never use broad search to reconstruct state; resume from `tasks.yml`, `context-manifest.md`, and `agent-log/`
112
112
  - Never continue past pending Context Expansion Requests
@@ -41,6 +41,11 @@ Use this skill to turn software requests into traceable, testable, CI/CD-gated c
41
41
  - Each engineer must read the matching standard before authoring tests: e2e-resilience-engineer → references/e2e-standard.md, monkey-test-engineer → references/monkey-operation-standard.md, stress-soak-engineer → references/stress-soak-standard.md.
42
42
  6. Implement through the right role.
43
43
  - Backend/frontend work must follow contracts and tests.
44
+ - Before invoking an agent with known concrete read paths, run
45
+ `cdd-kit context check <change-id> --path <paths...>` and expand the
46
+ manifest before the agent reads legitimate missing paths.
47
+ - After each agent finishes, verify its agent-log exists and tick the
48
+ related `tasks.yml` items before starting the next agent.
44
49
  - UI changes require UI/UX and visual review.
45
50
  - Invoke ui-ux-reviewer for interaction, copy, accessibility, and information hierarchy review whenever UI changes.
46
51
  - Invoke visual-reviewer for layout, responsive, CSS contract, and screenshot diff review whenever UI changes.
@@ -52,7 +57,10 @@ Use this skill to turn software requests into traceable, testable, CI/CD-gated c
52
57
  - Invoke ci-cd-gatekeeper to design and enforce the gate plan.
53
58
  8. Archive and audit drift.
54
59
  - Use `references/spec-drift-policy.md`.
55
- - Durable learnings must be promoted back to contracts or CLAUDE.md.
60
+ - General agents record evidence and findings only; durable learning
61
+ promotion happens only during `/cdd-close` Step 3.
62
+ - Durable learnings must be promoted back to `contracts/` or project
63
+ guidance (`CLAUDE.md`/`CODEX.md`).
56
64
  - `spec-drift-auditor` must run before every release to main and weekly during active multi-iteration development.
57
65
 
58
66
  ## Required gates by risk
@@ -24,7 +24,7 @@ The file is pure YAML (no markdown wrapping, no checklist).
24
24
  ```yaml
25
25
  change-id: <id>
26
26
  agent: <agent-name>
27
- timestamp: <ISO 8601 UTC, e.g. 2026-04-27T14:30:00Z>
27
+ timestamp: "<ISO 8601 date-time, e.g. 2026-04-27T14:30:00Z>"
28
28
  status: complete # complete | needs-review | blocked
29
29
  files-read:
30
30
  - <repo-relative path>
@@ -42,8 +42,8 @@ notes: <optional free-form>
42
42
  |---|---|---|
43
43
  | `change-id` | yes | must equal the parent change directory name |
44
44
  | `agent` | yes | canonical agent name (matches the agent's filename) |
45
- | `timestamp` | yes | ISO 8601 UTC; used by spec-drift-auditor for ordering |
46
- | `status` | yes | exactly one of `complete` \| `needs-review` \| `blocked` |
45
+ | `timestamp` | yes | ISO 8601 date-time string; quote it to avoid YAML timestamp coercion in non-cdd tools. UTC `Z` is preferred; numeric offsets such as `+08:00` are accepted. |
46
+ | `status` | yes | canonical values are `complete` \| `needs-review` \| `blocked`; `done` and `approved` are accepted by gate as compatibility aliases for `complete` |
47
47
  | `files-read` | conditional | required for context-governed changes (see below) |
48
48
  | `artifacts` | yes | array of `{type, pointer}` objects, ≥ 1 item |
49
49
  | `next-action` | yes | when `status: blocked`, ≥ 10 chars and not `none` |
@@ -60,6 +60,12 @@ files-read:
60
60
  - specs/changes/<change-id>/
61
61
  ```
62
62
 
63
+ If `cdd-kit gate` reports `read unauthorized path`, do not delete that
64
+ `files-read` entry to silence the gate. If the read was legitimate work scope,
65
+ add the repo-relative path to `context-manifest.md` under `## Allowed Paths` or
66
+ approve a Context Expansion Request. `files-read` is the audit trail; the
67
+ manifest is the authorization boundary.
68
+
63
69
  #### `artifacts`
64
70
 
65
71
  Concrete pointers only. Allowed forms:
@@ -69,6 +75,22 @@ Concrete pointers only. Allowed forms:
69
75
  - `cdd-kit gate <id>: 0 errors`
70
76
  - `contracts/api/api-contract.md#endpoints`
71
77
 
78
+ Gate path-existence rule: unless gate is run with `--lax`, any pointer whose
79
+ text before the first `:` contains `/` is treated as a repo-relative file path
80
+ and that file must exist. This makes path-like pointers useful, but it also
81
+ means:
82
+
83
+ - One pointer names one file only. Use separate `artifacts` items for multiple
84
+ files.
85
+ - Do not attach parenthetical notes to a file path, e.g. use
86
+ `src/api/users.ts:45-67`, not `src/api/users.ts (updated):45-67`.
87
+ - Do not start a pointer with slash-containing prose labels such as `I/O:` or
88
+ `WARNING/OVERDUE:`; gate will try to validate `I/O` or `WARNING/OVERDUE` as a
89
+ path. Write those labels in `notes` or after a non-path command/result
90
+ pointer.
91
+ - `n/a (<reason>)` is exempt from path validation and is allowed for genuinely
92
+ inapplicable required artifact types.
93
+
72
94
  Never `verified`, `OK`, `done`, or unscoped prose.
73
95
 
74
96
  #### `next-action`
@@ -77,6 +99,14 @@ When `status: blocked`, this must be ≥ 10 chars, must not be `none`, `tbd`,
77
99
  `investigate further`, or `n/a`, and must name the actual next step a human
78
100
  can act on. When `status: complete`, `none` is acceptable.
79
101
 
102
+ #### `status`
103
+
104
+ Use `status: complete` for a finished agent-log. `tasks.yml` task entries use
105
+ `status: done`, and review language may say "approved", but agent-log
106
+ completion is canonically `complete`. `cdd-kit gate` accepts `done` and
107
+ `approved` as compatibility aliases so these common mix-ups do not block
108
+ delivery.
109
+
80
110
  ## Per-agent additional artifact requirements
81
111
 
82
112
  Each agent prompt lists its own `### Required artifacts for this agent`. The
@@ -104,8 +134,13 @@ verify each item:
104
134
  - [ ] **All required keys exist**: `change-id`, `agent`, `timestamp`,
105
135
  `status`, `artifacts`, `next-action` (plus `files-read` for
106
136
  context-governed changes).
107
- - [ ] **`status` is one of**: `complete`, `needs-review`, `blocked` — not
108
- `done`, `OK`, `pending`, `wip`, or anything else.
137
+ - [ ] **`timestamp` is quoted** and uses ISO 8601 date-time form. Prefer
138
+ UTC `Z`, e.g. `timestamp: "2026-04-27T14:30:00Z"`. Numeric offsets
139
+ such as `timestamp: "2026-05-05T00:00:00+08:00"` are valid.
140
+ - [ ] **`status` is one of**: `complete`, `needs-review`, `blocked`.
141
+ Prefer `complete` for finished logs; `done` and `approved` are accepted
142
+ only as compatibility aliases. Do not use `OK`, `pending`, `wip`, or
143
+ anything else.
109
144
  - [ ] **Every `artifacts` item is a `{type, pointer}` mapping** with a
110
145
  concrete pointer:
111
146
  - GOOD: `{ type: tests-added, pointer: "tests/foo.test.ts::should reject empty body" }`
@@ -114,7 +149,12 @@ verify each item:
114
149
  - BAD: `{ type: tests-added, pointer: verified }`
115
150
  - BAD: `{ type: files-changed, pointer: yes }`
116
151
  - BAD: `{ type: contract, pointer: OK }`
152
+ - BAD: `{ type: files-changed, pointer: "src/api/users.ts (updated):45-67" }`
153
+ - BAD: `{ type: test-output, pointer: "I/O: warning reproduced" }`
154
+ - BAD: `{ type: test-output, pointer: "WARNING/OVERDUE: manual follow-up" }`
117
155
  Reject any line whose pointer would not let a reviewer click through.
156
+ If the text before the first `:` contains `/`, confirm it is exactly one
157
+ existing repo-relative file path with no parenthetical note.
118
158
  - [ ] **If `status: blocked`**, `next-action` is ≥ 10 chars, is NOT `none`,
119
159
  `investigate further`, `tbd`, or `n/a`, and names the actual next step
120
160
  a human can act on.
@@ -137,11 +177,13 @@ ship a known-bad log and rely on the gate to catch it.
137
177
  3. `status` is missing or has an unknown value.
138
178
  4. `status: blocked` without a concrete `next-action`.
139
179
  5. `files-read` is missing for a context-governed change, or contains an
140
- absolute path / `..` segment / forbidden path.
180
+ absolute path / `..` segment / forbidden path / path outside manifest
181
+ `Allowed Paths` and `Approved Expansions`.
141
182
  6. Any `artifacts` item is missing `type` or `pointer`, or the array is empty.
142
183
  7. A required per-agent artifact `type` declared in the agent prompt is missing.
143
- 8. With `--strict`: any `artifacts` pointer that looks like a path but does
144
- not exist on disk; or any runtime-logged read not declared in `files-read`.
184
+ 8. Unless gate is run with `--lax`: any `artifacts` pointer whose text before
185
+ the first `:` contains `/` but does not exist on disk; or any
186
+ runtime-logged read not declared in `files-read`.
145
187
 
146
188
  ## Why this lives in references/
147
189
 
@@ -1,6 +1,6 @@
1
1
  change-id: feat-001
2
2
  agent: backend-engineer
3
- timestamp: 2026-04-27T14:30:00Z
3
+ timestamp: "2026-04-27T14:30:00Z"
4
4
  status: complete
5
5
  files-read:
6
6
  - contracts/api/api-contract.md
@@ -75,7 +75,9 @@ Always required: change-request.md, change-classification.md, test-plan.md, ci-g
75
75
  -
76
76
 
77
77
  ### Allowed Paths
78
- <!-- Union of ALL paths any agent will read. Add change-specific paths below the defaults. -->
78
+ <!-- Union of ALL paths any agent will read. Add change-specific paths below the defaults.
79
+ Include component/store/view files for frontend work and CI contracts/workflows for CI work
80
+ when those files are legitimate work scope. Gate compares agent-log files-read against this list. -->
79
81
  - specs/changes/<change-id>/
80
82
  - specs/context/project-map.md
81
83
  - specs/context/contracts-index.md
@@ -18,6 +18,10 @@
18
18
 
19
19
  ## Known Risks
20
20
 
21
+ ## Pre-existing Failures Excluded From This Gate
22
+ | failure/test | baseline evidence | why outside scope | owner/follow-up |
23
+ |---|---|---|---|
24
+
21
25
  ## Failures and Fixback Routing
22
26
  | failure | evidence | owner | required fix |
23
27
  |---|---|---|---|
@@ -36,4 +36,4 @@ tasks:
36
36
  - { id: "6.3", section: Verification, title: "Informational gates", status: pending }
37
37
  - { id: "6.4", section: Verification, title: "Nightly/weekly/manual gates if required", status: pending }
38
38
  - { id: "7.1", section: Archive, title: "Archive change", status: pending }
39
- - { id: "7.2", section: Archive, title: "Promote durable learnings to contracts or CLAUDE.md", status: pending }
39
+ - { id: "7.2", section: Archive, title: "Promote durable learnings to contracts or project guidance", status: pending }
@@ -10,6 +10,8 @@ and is automatically applied by `cdd-kit gate` — do not duplicate it here.
10
10
  ## Allowed Paths
11
11
  <!-- UNION of all repo-relative paths (or globs) any agent may read for this change.
12
12
  cdd-kit gate validates every agent's files-read log against this list.
13
+ If an agent legitimately read a path, add that path here; do not remove it
14
+ from files-read just to pass gate.
13
15
  Be specific — wide globs (e.g. src/) defeat read-scope governance.
14
16
  Always include the three defaults below; add change-specific paths beneath them. -->
15
17
  - specs/changes/<change-id>/
@@ -18,6 +18,10 @@
18
18
 
19
19
  ## Known Risks
20
20
 
21
+ ## Pre-existing Failures Excluded From This Gate
22
+ | failure/test | baseline evidence | why outside scope | owner/follow-up |
23
+ |---|---|---|---|
24
+
21
25
  ## Failures and Fixback Routing
22
26
  | failure | evidence | owner | required fix |
23
27
  |---|---|---|---|
package/dist/cli/index.js CHANGED
@@ -9881,22 +9881,22 @@ async function attemptAutoFixes(cwd, report) {
9881
9881
  const merged = {
9882
9882
  ...existing,
9883
9883
  roles: {
9884
- "change-classifier": "claude-opus-4-7",
9885
- "spec-architect": "claude-opus-4-7",
9886
- "qa-reviewer": "claude-opus-4-7",
9887
- "contract-reviewer": "claude-sonnet-4-6",
9888
- "test-strategist": "claude-sonnet-4-6",
9889
- "backend-engineer": "claude-sonnet-4-6",
9890
- "frontend-engineer": "claude-sonnet-4-6",
9891
- "ci-cd-gatekeeper": "claude-sonnet-4-6",
9892
- "e2e-resilience-engineer": "claude-sonnet-4-6",
9893
- "monkey-test-engineer": "claude-sonnet-4-6",
9894
- "stress-soak-engineer": "claude-sonnet-4-6",
9895
- "ui-ux-reviewer": "claude-sonnet-4-6",
9896
- "visual-reviewer": "claude-haiku-4-5-20251001",
9897
- "dependency-security-reviewer": "claude-sonnet-4-6",
9898
- "spec-drift-auditor": "claude-opus-4-7",
9899
- "repo-context-scanner": "claude-haiku-4-5-20251001"
9884
+ "change-classifier": "opus",
9885
+ "spec-architect": "opus",
9886
+ "qa-reviewer": "opus",
9887
+ "contract-reviewer": "sonnet",
9888
+ "test-strategist": "sonnet",
9889
+ "backend-engineer": "sonnet",
9890
+ "frontend-engineer": "sonnet",
9891
+ "ci-cd-gatekeeper": "sonnet",
9892
+ "e2e-resilience-engineer": "sonnet",
9893
+ "monkey-test-engineer": "sonnet",
9894
+ "stress-soak-engineer": "sonnet",
9895
+ "ui-ux-reviewer": "sonnet",
9896
+ "visual-reviewer": "haiku",
9897
+ "dependency-security-reviewer": "sonnet",
9898
+ "spec-drift-auditor": "opus",
9899
+ "repo-context-scanner": "haiku"
9900
9900
  }
9901
9901
  };
9902
9902
  const { writeFileSync: writeFileSync14 } = await import("fs");
@@ -10321,6 +10321,7 @@ var context_exports = {};
10321
10321
  __export(context_exports, {
10322
10322
  approveAllPending: () => approveAllPending,
10323
10323
  approveContextExpansion: () => approveContextExpansion,
10324
+ checkContextPaths: () => checkContextPaths,
10324
10325
  listContextExpansions: () => listContextExpansions,
10325
10326
  rejectAllPending: () => rejectAllPending,
10326
10327
  rejectContextExpansion: () => rejectContextExpansion,
@@ -10328,6 +10329,7 @@ __export(context_exports, {
10328
10329
  });
10329
10330
  import { existsSync as existsSync22, readFileSync as readFileSync26, writeFileSync as writeFileSync13 } from "fs";
10330
10331
  import { join as join26 } from "path";
10332
+ import picomatch3 from "picomatch";
10331
10333
  function normalizePath(path) {
10332
10334
  return path.replace(/\\/g, "/").replace(/^\.\//, "").trim();
10333
10335
  }
@@ -10356,9 +10358,57 @@ function writeManifest(changeId, content) {
10356
10358
  `, "utf8");
10357
10359
  }
10358
10360
  function sectionBody(content, heading) {
10359
- const match = content.match(new RegExp(`## ${heading}\\s*\\n([\\s\\S]*?)(?=\\n## |$)`));
10361
+ const match = stripHtmlComments2(content).match(new RegExp(`## ${heading}\\s*\\n([\\s\\S]*?)(?=\\n## |$)`));
10360
10362
  return match?.[1] ?? "";
10361
10363
  }
10364
+ function stripHtmlComments2(text) {
10365
+ return text.replace(/<!--[\s\S]*?-->/g, "");
10366
+ }
10367
+ function parseListSection2(content, heading) {
10368
+ return sectionBody(content, heading).split(/\r?\n/).map((line) => line.replace(/^\s*-\s*/, "").trim()).filter((item) => item && item !== "-" && item.toLowerCase() !== "none").map(normalizePath);
10369
+ }
10370
+ function pathMatches2(relPath, patterns, currentChangeId) {
10371
+ const normalized = normalizePath(relPath);
10372
+ return patterns.some((rawPattern) => {
10373
+ const pattern = normalizePath(rawPattern).replace(/\/+$/, "");
10374
+ if (!pattern)
10375
+ return false;
10376
+ if (pattern === "specs/changes/*" && currentChangeId) {
10377
+ const current = `specs/changes/${currentChangeId}`;
10378
+ if (normalized === current || normalized.startsWith(`${current}/`))
10379
+ return false;
10380
+ return normalized.startsWith("specs/changes/");
10381
+ }
10382
+ if (/[*?[{]/.test(pattern)) {
10383
+ if (picomatch3.isMatch(normalized, pattern, { dot: true, nocase: false }))
10384
+ return true;
10385
+ if (pattern.endsWith("/**")) {
10386
+ const base = pattern.slice(0, -3);
10387
+ if (normalized === base)
10388
+ return true;
10389
+ }
10390
+ return false;
10391
+ }
10392
+ return normalized === pattern || normalized.startsWith(`${pattern}/`);
10393
+ });
10394
+ }
10395
+ function loadContextPolicy2() {
10396
+ const policyPath = join26(process.cwd(), ".cdd", "context-policy.json");
10397
+ if (!existsSync22(policyPath))
10398
+ return { forbiddenPaths: DEFAULT_FORBIDDEN_PATHS };
10399
+ try {
10400
+ const custom = JSON.parse(readFileSync26(policyPath, "utf8"));
10401
+ return {
10402
+ forbiddenPaths: Array.from(/* @__PURE__ */ new Set([
10403
+ ...DEFAULT_FORBIDDEN_PATHS,
10404
+ ...custom.forbiddenPaths ?? []
10405
+ ]))
10406
+ };
10407
+ } catch {
10408
+ log.warn("could not parse .cdd/context-policy.json; using default context policy");
10409
+ return { forbiddenPaths: DEFAULT_FORBIDDEN_PATHS };
10410
+ }
10411
+ }
10362
10412
  function parseRequests(content) {
10363
10413
  const body = sectionBody(content, "Context Expansion Requests");
10364
10414
  if (!body.trim())
@@ -10496,6 +10546,47 @@ async function listContextExpansions(changeId, json = false) {
10496
10546
  log.dim(` ${path}`);
10497
10547
  }
10498
10548
  }
10549
+ async function checkContextPaths(changeId, paths, json = false) {
10550
+ if (paths.length === 0) {
10551
+ log.error("at least one --path value is required");
10552
+ process.exit(1);
10553
+ }
10554
+ const content = readManifest(changeId);
10555
+ const allowedPaths = parseListSection2(content, "Allowed Paths");
10556
+ const approvedExpansions = parseListSection2(content, "Approved Expansions");
10557
+ const policy = loadContextPolicy2();
10558
+ const normalizedPaths = [...new Set(paths.map(normalizePath).filter(Boolean))];
10559
+ const results = normalizedPaths.map((path) => {
10560
+ const validationError = validateRepoRelativePath(path);
10561
+ const forbidden = !validationError && pathMatches2(path, policy.forbiddenPaths, changeId);
10562
+ const authorized = !validationError && !forbidden && (pathMatches2(path, allowedPaths) || pathMatches2(path, approvedExpansions));
10563
+ let reason = "authorized";
10564
+ if (validationError)
10565
+ reason = validationError;
10566
+ else if (forbidden)
10567
+ reason = "forbidden by .cdd/context-policy.json baseline";
10568
+ else if (!authorized)
10569
+ reason = "not in context-manifest Allowed Paths or Approved Expansions";
10570
+ return { path, authorized, reason };
10571
+ });
10572
+ if (json) {
10573
+ console.log(JSON.stringify({ changeId, results }, null, 2));
10574
+ } else {
10575
+ for (const result of results) {
10576
+ if (result.authorized)
10577
+ log.ok(`authorized: ${result.path}`);
10578
+ else
10579
+ log.error(`unauthorized: ${result.path} (${result.reason})`);
10580
+ }
10581
+ const unauthorized = results.filter((r) => !r.authorized).map((r) => r.path);
10582
+ if (unauthorized.length > 0) {
10583
+ log.info(`If these reads are legitimate, add them to specs/changes/${changeId}/context-manifest.md Allowed Paths or request expansion:`);
10584
+ log.info(` cdd-kit context request ${changeId} CER-<id> --path ${unauthorized.join(" ")} --reason "<why needed>"`);
10585
+ }
10586
+ }
10587
+ if (results.some((result) => !result.authorized))
10588
+ process.exit(1);
10589
+ }
10499
10590
  function applyApproval(content, request) {
10500
10591
  for (const path of request.paths) {
10501
10592
  const validationError = validateRepoRelativePath(path);
@@ -10569,10 +10660,21 @@ async function rejectAllPending(changeId) {
10569
10660
  writeManifest(changeId, content);
10570
10661
  log.ok(`rejected ${pending.length} pending context expansion request(s) for ${changeId}`);
10571
10662
  }
10663
+ var DEFAULT_FORBIDDEN_PATHS;
10572
10664
  var init_context = __esm({
10573
10665
  "src/commands/context.ts"() {
10574
10666
  "use strict";
10575
10667
  init_logger();
10668
+ DEFAULT_FORBIDDEN_PATHS = [
10669
+ ".claude/worktrees/**",
10670
+ ".git/**",
10671
+ "node_modules/**",
10672
+ "dist/**",
10673
+ "build/**",
10674
+ "assets/**",
10675
+ "specs/archive/**",
10676
+ "specs/changes/*"
10677
+ ];
10576
10678
  }
10577
10679
  });
10578
10680
 
@@ -11243,7 +11345,7 @@ var agentLogSchema = {
11243
11345
  "change-id": { type: "string", pattern: "^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$" },
11244
11346
  timestamp: { type: "string", format: "date-time" },
11245
11347
  agent: { type: "string", minLength: 1 },
11246
- status: { type: "string", enum: ["complete", "needs-review", "blocked"] },
11348
+ status: { type: "string", enum: ["complete", "done", "approved", "needs-review", "blocked"] },
11247
11349
  "files-read": { type: "array", items: { type: "string", minLength: 1 } },
11248
11350
  artifacts: {
11249
11351
  type: "array",
@@ -11469,7 +11571,7 @@ function loadContextPolicy(cwd) {
11469
11571
  function loadYamlFile(path) {
11470
11572
  try {
11471
11573
  const raw = readFileSync16(path, "utf8");
11472
- return { data: yaml2.load(raw), parseError: null };
11574
+ return { data: yaml2.load(raw, { schema: yaml2.JSON_SCHEMA }), parseError: null };
11473
11575
  } catch (err) {
11474
11576
  return { data: null, parseError: err.message };
11475
11577
  }
@@ -11786,9 +11888,18 @@ async function gate(changeId, opts = {}) {
11786
11888
  let statusReported = false;
11787
11889
  if (!ok) {
11788
11890
  for (const e of validateAgentLog.errors ?? []) {
11789
- if (e.keyword === "required" && e.params.missingProperty === "status" || e.instancePath === "/status" && e.keyword === "enum") {
11891
+ if (e.keyword === "required" && e.params.missingProperty === "status") {
11790
11892
  if (!statusReported) {
11791
- errors.push(`agent-log/${f}: missing or invalid "status:" line (must be complete | needs-review | blocked)`);
11893
+ errors.push(`agent-log/${f}: missing required "status:" line (expected complete | needs-review | blocked; aliases accepted: done, approved)`);
11894
+ statusReported = true;
11895
+ }
11896
+ continue;
11897
+ }
11898
+ if (e.instancePath === "/status" && e.keyword === "enum") {
11899
+ if (!statusReported) {
11900
+ const rawStatus = data.status;
11901
+ const shownStatus = typeof rawStatus === "string" ? rawStatus : JSON.stringify(rawStatus);
11902
+ errors.push(`agent-log/${f}: invalid "status:" value ${shownStatus ?? "<missing>"} (expected complete | needs-review | blocked; aliases accepted: done, approved)`);
11792
11903
  statusReported = true;
11793
11904
  }
11794
11905
  continue;
@@ -11837,7 +11948,7 @@ async function gate(changeId, opts = {}) {
11837
11948
  errors.push(`agent-log/${f}: read forbidden path -> ${p}`);
11838
11949
  }
11839
11950
  if (hasManifest && allowedPaths.length > 0 && !pathMatches(p, allowedPaths) && !pathMatches(p, approvedExpansions)) {
11840
- errors.push(`agent-log/${f}: read unauthorized path -> ${p} (not in allowed paths or approved expansions)`);
11951
+ errors.push(`agent-log/${f}: read unauthorized path -> ${p} (not in context-manifest Allowed Paths or Approved Expansions; if legitimate, add it to the manifest instead of deleting it from files-read)`);
11841
11952
  }
11842
11953
  }
11843
11954
  const runtimeLog = join16(cwd, ".cdd", "runtime", `${changeId}-files-read.jsonl`);
@@ -12140,4 +12251,8 @@ context.command("list <change-id>").description("List Context Expansion Requests
12140
12251
  const { listContextExpansions: listContextExpansions2 } = await Promise.resolve().then(() => (init_context(), context_exports));
12141
12252
  await listContextExpansions2(changeId, opts.json);
12142
12253
  });
12254
+ context.command("check <change-id>").description("Preflight-check repo-relative read paths against context-manifest Allowed Paths").requiredOption("--path <paths...>", "Repo-relative path(s) an agent is expected to read").option("--json", "Print machine-readable JSON", false).action(async (changeId, opts) => {
12255
+ const { checkContextPaths: checkContextPaths2 } = await Promise.resolve().then(() => (init_context(), context_exports));
12256
+ await checkContextPaths2(changeId, opts.path, opts.json);
12257
+ });
12143
12258
  program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "contract-driven-delivery",
3
- "version": "2.0.13",
3
+ "version": "2.0.15",
4
4
  "description": "Contract-driven delivery kit for AI coding agents with deterministic context indexes, manifest-backed read-scope governance, and orchestrated contracts-first delivery.",
5
5
  "keywords": [
6
6
  "contract-driven",