qfai 1.9.2 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/README.md +48 -2
  2. package/assets/init/.qfai/assistant/agents/acceptance-test-engineer.md +1 -0
  3. package/assets/init/.qfai/assistant/agents/backend-engineer.md +1 -0
  4. package/assets/init/.qfai/assistant/agents/completion-reviewer.md +13 -2
  5. package/assets/init/.qfai/assistant/agents/delivery-planner.md +9 -0
  6. package/assets/init/.qfai/assistant/agents/frontend-engineer.md +1 -0
  7. package/assets/init/.qfai/assistant/agents/implementation-reviewer.md +6 -0
  8. package/assets/init/.qfai/assistant/agents/orchestrator.md +2 -2
  9. package/assets/init/.qfai/assistant/agents/qa-gatekeeper.md +96 -3
  10. package/assets/init/.qfai/assistant/agents/test-design-analyst.md +20 -3
  11. package/assets/init/.qfai/assistant/catalog/cli-ux-guidelines.md +2 -2
  12. package/assets/init/.qfai/assistant/catalog/spec_required_files.json +2 -1
  13. package/assets/init/.qfai/assistant/catalog/test-layers.md +355 -14
  14. package/assets/init/.qfai/assistant/catalog/worklog-entry.schema.md +165 -0
  15. package/assets/init/.qfai/assistant/constitution/communication.md +1 -1
  16. package/assets/init/.qfai/assistant/constitution/drift-protocol.md +304 -10
  17. package/assets/init/.qfai/assistant/constitution/quality.md +35 -5
  18. package/assets/init/.qfai/assistant/constitution/requirements-decomposition.md +37 -0
  19. package/assets/init/.qfai/assistant/constitution/shared-skill-delegation-baseline.md +244 -8
  20. package/assets/init/.qfai/assistant/constitution/shared-skill-operating-baseline.md +122 -5
  21. package/assets/init/.qfai/assistant/constitution/workflow.md +53 -7
  22. package/assets/init/.qfai/assistant/manifest/agent-catalog.yml +316 -945
  23. package/assets/init/.qfai/assistant/manifest/agent-routing.yml +50 -4
  24. package/assets/init/.qfai/assistant/manifest/review-profiles.yml +9 -0
  25. package/assets/init/.qfai/assistant/process/migrations/v1.4.27-atdd-alignment.md +1 -1
  26. package/assets/init/.qfai/assistant/skills/qfai-atdd/SKILL.md +61 -21
  27. package/assets/init/.qfai/assistant/skills/qfai-atdd/references/test-case-depth-checklist.md +23 -4
  28. package/assets/init/.qfai/assistant/skills/qfai-configure/SKILL.md +15 -7
  29. package/assets/init/.qfai/assistant/skills/qfai-discussion/SKILL.md +8 -4
  30. package/assets/init/.qfai/assistant/skills/qfai-discussion/references/design-md-brand-catalog.md +2 -2
  31. package/assets/init/.qfai/assistant/skills/qfai-discussion/references/discussion-completion-matrix.md +17 -7
  32. package/assets/init/.qfai/assistant/skills/qfai-discussion/references/rcp_footer.md +10 -4
  33. package/assets/init/.qfai/assistant/skills/qfai-discussion/references/review-cycle-playbook.md +1 -1
  34. package/assets/init/.qfai/assistant/skills/qfai-discussion/references/ui-bearing-playbook.md +4 -4
  35. package/assets/init/.qfai/assistant/skills/qfai-discussion/references/ui_ux/review_audit_playbook.md +1 -1
  36. package/assets/init/.qfai/assistant/skills/qfai-discussion/references/ui_ux/trend_scan_playbook.md +1 -1
  37. package/assets/init/.qfai/assistant/skills/qfai-discussion/references/ui_ux_best_practices.md +17 -7
  38. package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/01_Context.md +1 -1
  39. package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/02_Inception-Deck.md +1 -1
  40. package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/03_Story-Workshop.md +11 -3
  41. package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/05_Scope.md +5 -2
  42. package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/07_NFR.md +1 -1
  43. package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/09_Constraints.md +7 -4
  44. package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/10_Policy.md +1 -1
  45. package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/11_OQ-Register.md +1 -1
  46. package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/12_OQ-Resolution-Log.md +1 -1
  47. package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/14_Review-Request.md +14 -7
  48. package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/99_delta.md +1 -1
  49. package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/review/Rxx_reviewer.md +16 -7
  50. package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/review/review_request.md +9 -6
  51. package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/uiux/40_screen_contracts.md +3 -2
  52. package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/uiux/50_review_input_bundle.md +4 -2
  53. package/assets/init/.qfai/assistant/skills/qfai-implement/SKILL.md +250 -128
  54. package/assets/init/.qfai/assistant/skills/qfai-implement/references/change-request-reset.md +93 -0
  55. package/assets/init/.qfai/assistant/skills/qfai-implement/references/checkpoint-verification.md +106 -0
  56. package/assets/init/.qfai/assistant/skills/qfai-implement/references/cross-spec-ownership.md +73 -0
  57. package/assets/init/.qfai/assistant/skills/qfai-implement/references/evidence-revision.md +77 -0
  58. package/assets/init/.qfai/assistant/skills/qfai-implement/references/execution-ledger.md +303 -0
  59. package/assets/init/.qfai/assistant/skills/qfai-implement/references/final-checklist.md +19 -0
  60. package/assets/init/.qfai/assistant/skills/qfai-implement/references/finding-classification.md +49 -0
  61. package/assets/init/.qfai/assistant/skills/qfai-implement/references/ledger-preconditions.md +55 -0
  62. package/assets/init/.qfai/assistant/skills/qfai-implement/references/oracle-strength.md +81 -0
  63. package/assets/init/.qfai/assistant/skills/qfai-implement/references/parallelization-policy.md +235 -0
  64. package/assets/init/.qfai/assistant/skills/qfai-implement/references/red-admissibility.md +91 -0
  65. package/assets/init/.qfai/assistant/skills/qfai-implement/references/red-not-observable.md +70 -0
  66. package/assets/init/.qfai/assistant/skills/qfai-implement/references/relevant-test-suite.md +87 -0
  67. package/assets/init/.qfai/assistant/skills/qfai-implement/references/review-artifact-layout.md +31 -0
  68. package/assets/init/.qfai/assistant/skills/qfai-implement/references/round-evidence.md +102 -0
  69. package/assets/init/.qfai/assistant/skills/qfai-implement/references/selector-granularity.md +24 -0
  70. package/assets/init/.qfai/assistant/skills/qfai-implement/references/volume-policy.md +149 -0
  71. package/assets/init/.qfai/assistant/skills/qfai-prototyping/SKILL.md +35 -18
  72. package/assets/init/.qfai/assistant/skills/qfai-prototyping/references/evidence-requirements.md +1 -1
  73. package/assets/init/.qfai/assistant/skills/qfai-prototyping/references/generator-prompt.md +106 -7
  74. package/assets/init/.qfai/assistant/skills/qfai-prototyping/references/handoff.md +40 -11
  75. package/assets/init/.qfai/assistant/skills/qfai-prototyping/references/iteration-loop.md +48 -1
  76. package/assets/init/.qfai/assistant/skills/qfai-prototyping/templates/DESIGN.md.sample +6 -0
  77. package/assets/init/.qfai/assistant/skills/qfai-sdd/SKILL.md +82 -22
  78. package/assets/init/.qfai/assistant/skills/qfai-sdd/references/contract-artifact-rules.md +148 -0
  79. package/assets/init/.qfai/assistant/skills/qfai-sdd/references/rcp_footer.md +10 -4
  80. package/assets/init/.qfai/assistant/skills/qfai-sdd/references/review-cycle-playbook.md +1 -1
  81. package/assets/init/.qfai/assistant/skills/qfai-sdd/references/sdd-execution-playbook.md +4 -2
  82. package/assets/init/.qfai/assistant/skills/qfai-sdd/references/sdd-phase-checklists.md +18 -0
  83. package/assets/init/.qfai/assistant/skills/qfai-sdd/references/sdd-quality-gate.md +44 -3
  84. package/assets/init/.qfai/assistant/skills/qfai-sdd/references/sdd-triage.md +60 -7
  85. package/assets/init/.qfai/assistant/skills/qfai-sdd/references/spec-traceability-rules.md +157 -5
  86. package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/change-request.md +125 -0
  87. package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/contracts/db-contract.sample.sql +6 -0
  88. package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/evidence/sdd-spec.md +92 -0
  89. package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/_policies/01_Objective.md +27 -0
  90. package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/_policies/02_Initiative.md +30 -0
  91. package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/_policies/05_Contracts.md +16 -6
  92. package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/_policies/06_Glossary.md +19 -0
  93. package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/_policies/07_Constraints.md +25 -0
  94. package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/_policies/08_Decisions.md +22 -2
  95. package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/_policies/11_Slice-Policy.md +37 -10
  96. package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/spec/02_User-stories.md +20 -0
  97. package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/spec/03_Acceptance-Criteria.md +19 -0
  98. package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/spec/04_Business-Rules.md +32 -3
  99. package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/spec/06_Test-Cases.md +56 -0
  100. package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/spec/07_Decisions.md +29 -2
  101. package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/spec/10_Plan.md +41 -0
  102. package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/spec/16_Traceability-ledger.md +58 -0
  103. package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/spec/tdd/test-list.md +56 -0
  104. package/assets/init/.qfai/assistant/skills/qfai-verify/SKILL.md +57 -102
  105. package/assets/init/.qfai/assistant/skills/qfai-verify/references/articles.md +24 -0
  106. package/assets/init/.qfai/assistant/skills/qfai-verify/references/context-load.md +22 -0
  107. package/assets/init/.qfai/assistant/skills/qfai-verify/references/verify-output-contract.md +48 -0
  108. package/assets/init/.qfai/assistant/skills/qfai-verify/templates/verify-evidence.md +48 -0
  109. package/assets/init/.qfai/assistant/skills/web-research/SKILL.md +25 -7
  110. package/assets/init/.qfai/waivers.yml +11 -5
  111. package/assets/init/root/DESIGN.md +6 -0
  112. package/assets/init/root/qfai.config.yaml +15 -12
  113. package/dist/cli/index.cjs +11023 -7139
  114. package/dist/cli/index.cjs.map +1 -1
  115. package/dist/cli/index.mjs +10963 -7080
  116. package/dist/cli/index.mjs.map +1 -1
  117. package/dist/index.cjs +8782 -5257
  118. package/dist/index.cjs.map +1 -1
  119. package/dist/index.d.cts +280 -8
  120. package/dist/index.d.ts +280 -8
  121. package/dist/index.mjs +11776 -8264
  122. package/dist/index.mjs.map +1 -1
  123. package/package.json +18 -19
@@ -20,11 +20,159 @@ Discussion UI/UX files are upstream discovery artifacts. `/qfai-sdd` normalizes
20
20
  - `api/`, `db/`, and `ui/` contracts must declare `QFAI-CONTRACT-ID` at the top.
21
21
  - Use prefixes `CON-API-*`, `CON-DB-*`, and `CON-UI-*`.
22
22
  - `design/` files do not require `QFAI-CONTRACT-ID`, but they are execution-time SSOT for UI-bearing work.
23
+ - **Declare apply-order dependencies.** `QFAI-CONTRACT-011` makes a second
24
+ `QFAI-CONTRACT-ID` in one file a hard `error`, so any schema larger than one
25
+ table necessarily becomes N cross-referencing files. State the resulting
26
+ composition rather than leaving every consumer to reconstruct it from the DDL:
27
+ - `db/`: a comment line `-- Depends on: CON-DB-0002, CON-DB-0003` (or `-`)
28
+ - `api/` / `ui/`: `x-qfai-depends-on: [CON-API-0002]`, flow or block form
29
+ - Mirror the same list in `_policies/05_Contracts.md`'s `Depends On` column.
30
+ - **Apply order only.** A reference resolved at run time — a deferred foreign
31
+ key, an endpoint another calls during a request — is not an apply-order
32
+ dependency and must not be listed. The apply graph is acyclic by
33
+ construction; the runtime graph legitimately is not, and conflating them
34
+ makes the declaration unusable for ordering.
35
+ - `QFAI-CONTRACT-014` (error) reports a declared dependency naming a contract
36
+ that does not exist. Getting the set wrong is otherwise silent: the wrong
37
+ subset still applies cleanly and the tests still pass, against a schema
38
+ missing the tables under test.
39
+ - **Target schema is the applier's, not the contract's.** A `db/` contract
40
+ declares unqualified object names and is applied into whatever schema the
41
+ runner selects (`SET search_path`, `USE`, the connection's default). Do not
42
+ hard-code a schema qualifier: a contract that names one cannot be applied into
43
+ a per-test or per-tenant schema, which is what the integration layer needs.
23
44
  - Breaking changes require delta notes.
24
45
  - `_policies/05_Contracts.md` is the contract index; it must align with `.qfai/contracts/**` and must not become behavior SSOT.
25
46
 
47
+ ## What validation checks in a `.sql` contract
48
+
49
+ Scope is **apply-ability, not semantic correctness**. `.sql` used to be the only
50
+ contract kind the validator never parsed — the "this contract does not parse" check
51
+ guarding UI and API files was unreachable for it — so a DB contract that cannot
52
+ run passed `npx qfai validate --profile sdd --fail-on error`. It now has a structural lane:
53
+
54
+ | Finding | Fires when | Severity |
55
+ | ------------------- | ----------------------------------------------------------------------------- | -------- |
56
+ | `QFAI-CONTRACT-021` | an unterminated string, comment or dollar-quoted body, or unbalanced `(` | error |
57
+ | `QFAI-DB-002` | one file creates the same object twice — only the last definition is in force | error |
58
+
59
+ `QFAI-DB-002` covers tables, views, indexes, functions, procedures, types and
60
+ domains. **Triggers are excluded**: a trigger name is unique per table, not per
61
+ schema, so two same-named triggers on different tables are correct SQL and
62
+ reporting them would be a false positive on valid input.
63
+ | `QFAI-DB-001` | a dangerous statement (`DROP TABLE`, `TRUNCATE`, …) | warning |
64
+
65
+ The statement splitter honours SQL quoting, so a `;` inside a literal, a
66
+ comment, a `$$ … $$` body or parentheses does not end a statement.
67
+
68
+ **Not checked**: nothing here type-checks a query, resolves a column, or
69
+ verifies the schema against the API contract. A green run means the file could
70
+ be handed to a database and does not contradict itself about what it defines —
71
+ it does not mean the schema is right. Cross-contract agreement remains the
72
+ authoring obligation below.
73
+
74
+ ## Cross-contract Reconciliation (MUST)
75
+
76
+ Contracts are validated per file; agreement _between_ contracts is an authoring obligation.
77
+
78
+ - Every terminal state, status enum value, and error code an API contract mandates MUST have a
79
+ representable counterpart in the paired DB contract. An outcome the API requires but the DB
80
+ domain (`CHECK (... IN (...))`, `CREATE TYPE ... AS ENUM`, inline `ENUM(...)`) cannot store is a
81
+ contradiction, not an implementation detail.
82
+ - Failure and rejection paths count. If the API consumes a transaction on a validation failure,
83
+ the DB must have an honest terminal value for that failure — do not reuse a success state whose
84
+ own preconditions cannot hold on failure, and do not relabel a rejection as an expiry.
85
+ - Resolve the contradiction in the contracts, in Phase 0. Never resolve it downstream by
86
+ fabricating values that satisfy both.
87
+ - Record the pairing you reconciled in `_policies/05_Contracts.md` so the scope is declared rather
88
+ than guessed.
89
+
90
+ `QFAI-CONTRACT-040` mechanizes the state/status-domain part of this rule at `warning` severity. It
91
+ is a partial check: error codes, response-status sets, and non-enum domains are still reconciled by
92
+ the author and the reviewer gate.
93
+
94
+ ## Executability (MUST)
95
+
96
+ A contract this file calls "downstream execution truth" has to have been
97
+ executed. Everything else qfai asserts about a `db/` contract — one
98
+ correctly-prefixed unique ID, four dangerous-SQL patterns at `warning` — is
99
+ satisfied by a file that cannot run.
100
+
101
+ - **Apply every `db/` contract to a scratch database.** Applying cleanly is the
102
+ floor, not the gate: contracts that apply without a single error still fail at
103
+ runtime, because the failure is a resolution error inside a PL/pgSQL body,
104
+ not a syntax error.
105
+ - **Drive every declared write path at least twice.** The second traversal is
106
+ what exercises head-advance and expected-version guards; a single pass proves
107
+ the first insert and nothing after it. Defects that appear only on traversal
108
+ two are a normal share of the total, not an exotic case.
109
+ - **Record it** in `.qfai/evidence/sdd-<spec-id>.md` as a line of the form:
110
+
111
+ ```
112
+ - Executability: CON-DB-NNNN — applied to scratch DB; every declared write path driven twice; <command> / <result>
113
+ ```
114
+
115
+ `QFAI-CONTRACT-031` (`warning`) reports a `db/` contract with no such line. It
116
+ is a **presence check**: it does not execute SQL and makes no claim about
117
+ correctness. Neither a syntax-level parse nor a structural comparison would
118
+ have caught the observed defects, so a cheap record of "this was actually
119
+ driven" is what the omission needs.
120
+
121
+ The cost of skipping this is not paid in Phase 0. It is paid inside a TDD
122
+ micro-cycle, by an implementer who is forbidden from fixing the contract and has
123
+ to stop the batch.
124
+
125
+ ## Obligation Reconciliation (MUST) — Phase 2c
126
+
127
+ Cross-contract reconciliation above compares contracts to each other. This
128
+ compares contracts to the **obligations written after them**.
129
+
130
+ Phase 0 authors contracts. `BR` / `AC` / `TC` are written in Phase 2. The
131
+ contract is therefore frozen before the obligations that must ride on it exist,
132
+ and "Contracts-first" is only defensible if something later checks that the
133
+ obligations are realizable. That check is this one, and it runs in **Phase 2c**,
134
+ after Phase 2b and before Phase 3 Plan finalize — early enough that a contract
135
+ change still flows into the plan and the delta.
136
+
137
+ For every `BR` / `AC` produced in Phase 2:
138
+
139
+ - **Name the contract that realizes it.** An obligation whose realizing
140
+ contract cannot be named is not reconciled; it is unowned.
141
+ - **Resolve every persisted attribute the obligation names to a concrete column,
142
+ field or enum member in that contract.** "Attribute" means anything the
143
+ obligation requires the system to store, distinguish or report on — an axis of
144
+ attribution, a status the obligation branches on, a value it aggregates by.
145
+ - **Reachability counts, not adjacency.** When the attribute lives in a
146
+ different relation, state the join that reaches it. If no join reaches it, the
147
+ obligation is unrealizable however valid both contracts are.
148
+ - **Vocabulary mixing is the usual cause, and it does not look like a typo.**
149
+ An obligation that mixes the vocabulary of two contracts designed for
150
+ different purposes — an operational ledger and an evidentiary one — reads
151
+ perfectly and cannot be satisfied by either. Two internally valid, mutually
152
+ consistent contracts is exactly the state in which this defect survives.
153
+ - Record the outcome per obligation, not per spec: which contract, which
154
+ columns/fields, and the join when one is needed.
155
+
156
+ **A failure here is resolved in the contract or in the obligation, in this
157
+ phase.** Both are owned by `/qfai-sdd`, so amending either is not drift — but
158
+ carrying the mismatch downstream is, because the implementer who eventually
159
+ meets it cannot fix either side.
160
+
161
+ Execution-based checking does not substitute for this. An obligation whose
162
+ attributes are missing produces a declared path that **succeeds** when driven:
163
+ the query returns rows, the endpoint answers, the suite is green. Failure
164
+ surfaces defects; this class is concealed by success, and only a reading of the
165
+ obligation against the contract finds it.
166
+
26
167
  ## Checklist
27
168
 
28
169
  - Contract IDs exist and are unique.
29
170
  - Specs reference only existing contract IDs.
30
171
  - Design contracts are sufficient for prototyping, ATDD, and implementation without discussion-pack fallback.
172
+ - Every `db/` contract has been applied to a scratch database and every declared write path driven
173
+ **at least twice**, with the command and result recorded in `.qfai/evidence/sdd-<spec-id>.md`
174
+ (`QFAI-CONTRACT-031`).
175
+ - Every API-mandated terminal state / status value / error code is representable in the paired DB contract.
176
+ - Every `BR` / `AC` names a realizing contract, and every persisted attribute it names resolves to a
177
+ column, field or enum member there — reachable directly or by a stated join (Phase 2c).
178
+ - `QFAI-CONTRACT-040` findings are resolved or explicitly triaged, not carried forward.
@@ -24,15 +24,21 @@
24
24
  - `architecture-reviewer`
25
25
  - `product-surface-reviewer`
26
26
  - `qa-gatekeeper`
27
- - 各レビューは `PASS` / `FAIL` を返す
28
- - `FAIL` が出たら、失敗 reviewer と修正影響を受ける reviewer のみ再実行する
27
+ - 各レビューは `PASS` / `REVISE` を返す(in-flight のレビュアー応答の語彙。SSOT は
28
+ `.qfai/assistant/constitution/shared-skill-delegation-baseline.md` の `## Reviewer response template`)
29
+ - `REVISE` は review pack の `summary.json` を書き出す際に `status: "FAIL"` へ対応付けられる(同ファイルの
30
+ `### Verdict vocabulary` を参照)。第3の判定値を作らないこと
31
+ - `REVISE` が出たら、失敗 reviewer と修正影響を受ける reviewer のみ再実行する
29
32
 
30
33
  ---
31
34
 
32
35
  ## Validate Hard Gate(必須)
33
36
 
34
- - 各 review cycle で `qfai validate --profile sdd --fail-on error --format github` を実行していること
35
- - `.qfai/report/validate.log` が存在し、最新の成果物に対応していること
37
+ - 各 review cycle で `npx qfai validate --profile sdd --fail-on error --format github` を実行していること
38
+ - `<paths.outDir>/validate.log`(既定 `.qfai/report/validate.log`)が存在し、最新の成果物に対応していること
39
+ - このファイルは `npx qfai validate` が実行のたびに自動で書き出す。`| tee` などのシェルリダイレクトは不要(PowerShell では動作しないため使用しない)
40
+ - `<paths.outDir>` は `qfai.config.yaml` の `paths.outDir`。既定以外に変更したプロジェクトでは `<paths.outDir>/validate.log` と `<paths.outDir>/run-*/` を見ること
41
+ - 最新性は `validate.log` の `run_log:` 行が最新の `run-*/` を指しているかで確認する
36
42
 
37
43
  ---
38
44
 
@@ -14,7 +14,7 @@ Use this file when you need the detailed review-cycle mechanics for `/qfai-sdd`.
14
14
  2. Build one review pack for the current cycle only.
15
15
  3. Apply the footer SSOT without rewriting it locally.
16
16
  4. Collect verdicts.
17
- 5. If any blocking reviewer returns `FAIL`, fix only the affected scope and rerun the failed reviewer plus any reviewer whose scope changed.
17
+ 5. If any blocking reviewer returns `REVISE`, fix only the affected scope and rerun that reviewer plus any reviewer whose scope changed. `REVISE` is the in-flight verdict (`.qfai/assistant/constitution/shared-skill-delegation-baseline.md#reviewer-response-template`); it becomes `status: "FAIL"` only when the pack's `summary.json` is written.
18
18
  6. Mark the cycle fixed only when all routed blocking reviewers return `PASS`.
19
19
 
20
20
  ## Required Outputs
@@ -9,8 +9,10 @@ Use this file for the detailed sequencing rules behind `/qfai-sdd`.
9
9
  3. **Phase 0 - Contracts-first**
10
10
  4. **Phase 1 - Outline**
11
11
  5. **Phase 2 - Slice** (per spec)
12
- 6. **Phase 3 - Plan finalize** (per spec)
13
- 7. **Phase 4 - Delta update** (per spec)
12
+ 6. **Phase 2b - Seed `tdd/test-list.md`** (per spec)
13
+ 7. **Phase 2c - Obligation reconciliation** (per spec)
14
+ 8. **Phase 3 - Plan finalize** (per spec)
15
+ 9. **Phase 4 - Delta update** (per spec)
14
16
 
15
17
  ## Stage 0: Preflight
16
18
 
@@ -40,6 +40,24 @@ Use these checklists as the detailed operational guide for `/qfai-sdd`.
40
40
  - Ensure `01_Spec.md` remains the execution Primary SSOT.
41
41
  - Stop if slice gate fails.
42
42
 
43
+ ## Phase 2b: Seed `tdd/test-list.md`
44
+
45
+ - Copy `templates/specs/spec/tdd/test-list.md` when `<spec-id>/tdd/test-list.md` does not exist.
46
+ - Add one row per coverage-target TC from `06_Test-Cases.md`, `Status = todo`.
47
+ - Delta only: an unchanged TC's row keeps its `TDD-ID`, `Status`, `Test file`, `Selector`, `DR-ID` and `Evidence`.
48
+ - Reconcile changed and removed TCs: return a changed TC's row to `todo` under the upstream-reset rule (driving `CR-*` / `DR-*` in `DR-ID`), and retire the row of a TC deleted upstream or no longer a coverage target. Never leave a stale `done` row nor a selectable row for a TC that no longer exists.
49
+ - Keep the ledger table the first markdown table in the file.
50
+ - An empty table is a valid outcome when the spec declares no coverage-target TC.
51
+
52
+ ## Phase 2c: Obligation reconciliation
53
+
54
+ - For every `BR` / `AC` this run produced, name the contract under `.qfai/contracts/**` that realizes it.
55
+ - Resolve every persisted attribute the obligation names to a column, field or enum member in that contract.
56
+ - When the attribute lives in another relation, state the join that reaches it. No join reaching it means the obligation is unrealizable, however valid both contracts are.
57
+ - Fix the contract or the obligation in this phase — both are owned by `/qfai-sdd`, and a mismatch carried downstream reaches an implementer who can fix neither.
58
+ - Record the outcome per obligation, not per spec.
59
+ - Full rule: `contract-artifact-rules.md#obligation-reconciliation-must--phase-2c`.
60
+
43
61
  ## Phase 3: Plan finalize
44
62
 
45
63
  - Create or update `<spec-id>/10_Plan.md`.
@@ -22,17 +22,58 @@ Use this file for the full quality gate checklist behind `/qfai-sdd`.
22
22
  - UPDATE rows carry a Sub-op of APPEND / MODIFY / REMOVE.
23
23
  - CREATE / DELETE / SPLIT / MERGE / SUPERSEDE and UPDATE:REMOVE rows record an `Approved By` value.
24
24
 
25
+ ## Contract Checks
26
+
27
+ Phase 0 is a mandatory output of this skill, so its own artifacts belong on this page.
28
+
29
+ - Every `api/`, `db/` and `ui/` contract declares a unique, correctly-prefixed `QFAI-CONTRACT-ID`.
30
+ - Every `db/` contract has been **applied to a scratch database**, and every declared write path
31
+ **driven at least twice** — the second traversal is what exercises head-advance and
32
+ expected-version guards. Applying cleanly is the floor, not the gate: a contract that applies
33
+ without error still fails at runtime, because the failure is a resolution error inside a PL/pgSQL
34
+ body rather than a syntax error.
35
+ - The command and result are recorded in `.qfai/evidence/sdd-<spec-id>.md`; `QFAI-CONTRACT-031`
36
+ (`warning`) reports a `db/` contract with no such record.
37
+ - `QFAI-DB-001` dangerous-SQL warnings are resolved or explicitly triaged.
38
+ - Full rule: `references/contract-artifact-rules.md#executability-must`.
39
+
40
+ ## Cross-contract Checks
41
+
42
+ - Every terminal state, status enum value, and error code an API contract mandates has a
43
+ representable counterpart in the paired DB contract (`references/contract-artifact-rules.md#cross-contract-reconciliation-must`).
44
+ - Failure / rejection paths in particular: the DB has an honest terminal value for each API-mandated
45
+ failure outcome, rather than a success state whose preconditions cannot hold on failure.
46
+ - The reconciled API↔DB pairing is recorded in `_policies/05_Contracts.md`.
47
+ - `QFAI-CONTRACT-040` warnings are resolved or explicitly triaged before sign-off.
48
+
25
49
  ## Traceability Checks
26
50
 
27
- - `US -> AC -> BR -> EX -> TC` edges exist.
51
+ - `US -> AC -> BR -> EX -> TC` edges exist. Check this against `.qfai/report/run-*/traceability.json`,
52
+ which is built from the parsed spec pack on every run, clean or failing. Table-layout specs
53
+ (`05_Examples.md` + `06_Test-Cases.md`) carry `BR_TO_AC`, `EX_TO_BR`, `TC_TO_AC` and `TC_TO_EX`
54
+ edges; the older `Examples.feature` layouts carry `AC_TO_US`, `BR_TO_AC` and either
55
+ `EX_TO_BR` / `TC_TO_EX` or `SC_TO_AC` / `CASE_TO_SC`. `EX_TO_AC` also appears: in v1417 an
56
+ `EX` may hang off an `AC` directly rather than off a `BR`, and the graph builder emits both
57
+ edge kinds — it is a normal edge type, not an unknown one. An empty `edges` array on a spec
58
+ pack that has specs is a finding, not a tool limitation.
28
59
  - `05_Examples.md` includes `EX-ID` and `BR-Ref`.
29
- - `06_Test-Cases.md` includes `TC-ID`, `EX-Ref`, `AC-Refs`, and `Type`.
60
+ - `06_Test-Cases.md` includes `TC-ID`, `Level`, `EX-Ref`, `AC-Refs`, and `Type`. `Level` holds exactly one code from `.qfai/assistant/catalog/test-layers.md#layer-definitions`, which defines all five (`L1`-`L5`); the template's list is a reading aid pointing back at it.
30
61
  - Error or boundary coverage is present, not only normal-path coverage.
62
+ - **The chain does not terminate at `TC`.** Every `BR` / `AC` names the contract that realizes it,
63
+ and every persisted attribute it names resolves to a column, field or enum member in that
64
+ contract — directly or by a stated join. Phase 0 authors contracts before these obligations
65
+ exist, so an obligation the contract cannot express passes every other check on this page: the
66
+ SQL is valid, the `US -> AC -> BR -> EX -> TC` edges are complete, `npx qfai validate` is clean.
67
+ Driving the declared path succeeds, so execution-based checking does not find it either. See
68
+ `references/contract-artifact-rules.md#obligation-reconciliation-must--phase-2c`.
31
69
 
32
70
  ## Validation Checks
33
71
 
34
- - `qfai validate --profile sdd --fail-on error --format github | tee .qfai/report/validate.log`
72
+ - `npx qfai validate --profile sdd --fail-on error --format github`
35
73
  - `error=0`
74
+ - `<paths.outDir>/validate.log` (`.qfai/report/validate.log` by default) — written automatically by the
75
+ command above (no `tee` redirect); its `run_log:` line points at the `run-*/` directory of that run.
76
+ A project that changed `paths.outDir` in `qfai.config.yaml` finds both under its configured directory
36
77
  - `.qfai/report/specs-coverage/spec-*.md` reviewed
37
78
  - Density-smell warnings triaged
38
79
 
@@ -18,8 +18,16 @@ Concretely, before persisting any Triage row:
18
18
  and `04_Business-Rules.md`. The classifier output is a _proposal_; the
19
19
  final decision must be informed by reading the candidate spec body.
20
20
  2. Pick the spec whose scope most closely absorbs the new requirement.
21
- 3. Append a new BR/AC/EX/TC there. If the spec is over the size threshold,
22
- propose **SPLIT**, never CREATE-as-shortcut.
21
+ 3. Append a new BR/AC/EX/TC there. Never CREATE-as-shortcut. A spec over the
22
+ size threshold is a **signal, not an operation**: record the breach in the
23
+ row's `Rationale` — for a MERGE row, every breaching target — and start a
24
+ capability-ownership review. Propose **SPLIT** only if that review shows the
25
+ spec genuinely owns more than one `CAP-NNNN`; if it owns exactly one, the
26
+ operation already selected is unchanged (MERGE stays MERGE, APPEND stays
27
+ APPEND) and the reasoned non-split is recorded. A count-driven SPLIT of a
28
+ single-capability spec is illegal — `validateSpecSplitByCapability` raises
29
+ `QFAI-SPLIT-102` / `QFAI-SPLIT-104` at `error`, so it has no legal end
30
+ state. See `_policies/11_Slice-Policy.md` step 4.
23
31
  4. Only when no active spec's scope can absorb the requirement, AND the
24
32
  underlying capability is itself new, propose **CREATE**. Add the new
25
33
  `CAP-NNNN` to `_policies/03_Capabilities.md` _first_, then cite it in
@@ -37,14 +45,53 @@ shares the most subject tokens. CREATE is emitted only when there is
37
45
  | Operation | Sub-op | When to choose | Approval |
38
46
  | --------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
39
47
  | CREATE | - | New subject; no active spec owns the capability | Required |
40
- | UPDATE | APPEND | Add new US/AC/BR/EX/TC to an active spec (no semantic change) | - |
41
- | UPDATE | MODIFY | Change the meaning of an existing US/AC/BR/EX/TC | - |
48
+ | UPDATE | APPEND | Add new US/AC/BR/EX/TC to an active spec (no semantic change). Item-level only. With UPDATE:MODIFY this is also how an item is decomposed into N siblings — see Operation scope below | - |
49
+ | UPDATE | MODIFY | Change the meaning of an existing US/AC/BR/EX/TC. Item-level only | - |
42
50
  | UPDATE | REMOVE | Delete an existing US/AC/BR/EX/TC (cuts downstream refs) | Required |
43
- | DELETE | - | Subject was removed from the product; the spec itself goes away | Required |
44
- | SPLIT | - | One spec carries >1 capability; split into N specs | Required |
45
- | MERGE | - | Multiple specs converge on one capability; collapse them | Required |
51
+ | DELETE | - | Subject was removed from the product; the spec itself goes away. **Spec-scoped only** — deleting one item is UPDATE:REMOVE (QFAI-TRIAGE-007) | Required |
52
+ | SPLIT | - | One spec carries >1 capability; split into N specs. **Spec-scoped only** — never use it to split an item (QFAI-TRIAGE-007) | Required |
53
+ | MERGE | - | Multiple specs converge on one capability; collapse them. **Spec-scoped only** (QFAI-TRIAGE-007) | Required |
46
54
  | SUPERSEDE | - | Responsibilities move to a new spec; flip status, keep history. Also covers single-spec **RENAME** (subject change at the same ID is normally UPDATE:MODIFY; if the spec ID itself must change while scope stays the same — i.e. **RENUMBER** — emit SUPERSEDE: create the new ID, mark the old as superseded). MERGE handles multi-spec consolidation. | Required |
47
55
 
56
+ ### Operation scope (spec-level vs item-level)
57
+
58
+ `SPLIT`, `MERGE`, `SUPERSEDE` and `DELETE` operate on a **whole spec
59
+ directory**. `UPDATE:APPEND / MODIFY / REMOVE` operate on **items inside one
60
+ spec**. There is no operation for decomposing one `US/AC/BR/EX/TC` into N
61
+ siblings within the same spec — that is encoded as `UPDATE:MODIFY` (narrow the
62
+ original) plus one `UPDATE:APPEND` row per new sibling.
63
+
64
+ Do not reach for `SPLIT` to mean "split this business rule": `SPLIT` asserts
65
+ that the spec itself must become N specs, which
66
+ `validateSpecSplitByCapability` then enforces as one `CAP-NNNN` per spec.
67
+ Likewise do not reach for `DELETE` to remove one item — that is
68
+ `UPDATE:REMOVE`.
69
+
70
+ `QFAI-TRIAGE-007` (error) rejects a `SPLIT` / `MERGE` / `SUPERSEDE` / `DELETE`
71
+ row whose `Subject` names an item ID **as the operation's object**. The object
72
+ is decided structurally, by **brackets, not by word order**: an item ID inside
73
+ `(...)` / `(...)` / `[...]` / `【...】` is a citation, and any item ID outside
74
+ brackets is what the operation acts on.
75
+
76
+ - `delete BR-0006-0004 from spec-0006` -> bare item: rejected. Co-occurring
77
+ with a spec name is not an exemption.
78
+ - `in spec-0006, delete BR-0006-0004` -> bare item: rejected. Naming the spec
79
+ first does not help — there it is only the item's location, which is why word
80
+ order cannot decide the object.
81
+ - `split spec-0006 (motivated by BR-0006-0004)` -> item bracketed: accepted.
82
+ - `separate CAP-0003 (driven by BR-0006-0004)` -> item bracketed: accepted.
83
+
84
+ So a genuinely spec-level row names only its `spec-NNNN` / `CAP-NNNN` target
85
+ outside brackets and puts the motivating item inside them. Item IDs are matched
86
+ with the shared digit semantics of `specPackIds.ts`, so `BR-1` and `TC-12345`
87
+ are caught alongside the canonical 4-digit form.
88
+
89
+ Because `UPDATE:MODIFY` and `UPDATE:APPEND` are approval-free by operation
90
+ type, an item decomposition carries no approval-required row. Record the
91
+ conservation statement — which obligations existed before, which exist after,
92
+ and that none were added or dropped — in the `Rationale` column of the
93
+ `UPDATE:MODIFY` row so a reviewer can check it.
94
+
48
95
  ## Inputs
49
96
 
50
97
  1. Latest discussion-pack `06_REQ.md` / `07_NFR.md` / `99_delta.md`.
@@ -122,6 +169,12 @@ ops), `Rationale` (recommended for every row).
122
169
  (APPEND / MODIFY / REMOVE).
123
170
  - `QFAI-TRIAGE-005` (error): approval-required Operation has no
124
171
  `Approved By` value.
172
+ - `QFAI-TRIAGE-007` (error): `SPLIT` / `MERGE` / `SUPERSEDE` / `DELETE` row
173
+ whose `Subject` names a `US/AC/BR/EX/TC` ID as the operation's object. All
174
+ four are spec-scoped: item decomposition is `UPDATE:MODIFY` +
175
+ `UPDATE:APPEND`, and deleting one item is `UPDATE:REMOVE`.
176
+ `QFAI-TRIAGE-003` is a membership check on the Operation label and provably
177
+ cannot catch this.
125
178
  - `QFAI-TRIAGE-006` (error): CREATE row without a `CAP-NNNN` reference
126
179
  in the Rationale column, or referencing a CAP that is not registered
127
180
  in `_policies/03_Capabilities.md`. This is the structural gate that
@@ -4,7 +4,7 @@ Use this file when working on traceability-heavy parts of `/qfai-sdd`.
4
4
 
5
5
  ## Required Layered Layout
6
6
 
7
- `qfai validate` treats specs as a layered package:
7
+ `npx qfai validate` treats specs as a layered package:
8
8
 
9
9
  - Shared policies: `.qfai/specs/_policies/**`
10
10
  - Capability specs: `.qfai/specs/spec-*/**`
@@ -72,21 +72,173 @@ ID reference direction (the value of `Refs:` columns) must be lower-to-upper onl
72
72
  - `US-0001` -> Parent: `CAP-0001`
73
73
  - `AC-0001` -> defined in `03_Acceptance-Criteria.md`
74
74
  - `BR-0001` -> `AC-Refs` in `04_Business-Rules.md`
75
+ - `BR-0001` -> `Contract-Refs` in `04_Business-Rules.md` (comma-separated
76
+ `CON-*` IDs; `-` when the rule binds no contract). Contract IDs recorded
77
+ only in `Notes` are untraced.
75
78
  - `EX-0001` -> `BR-Ref` in `05_Examples.md`
76
79
  - `TC-0001` -> `EX-Ref` and `AC-Refs` in `06_Test-Cases.md`
77
- - `_policies/**` must not contain lower-layer IDs (`US/AC/BR/EX/TC`) or per-spec references.
80
+ - `_policies/**` must not **define or own** lower-layer items. Concretely: no
81
+ traceability edge in `_policies/**` may name a lower-layer ID — no `Parent:`,
82
+ `Refs:`, `AC-Refs`, `BR-Ref` or `EX-Ref` value, and no heading that declares a
83
+ `US/AC/BR/EX/TC` item.
84
+ - **How this is enforced today is broader than that intent.** `QFAI-LAYER-100`
85
+ and `TRACE_SHARED_SCOPE_VIOLATION` are a token scan: they match any
86
+ `US/AC/BR/EX/TC-NNNN` anywhere in a `_policies/**` file, not only in an
87
+ ownership or definition position. Outside the Triage carve-out below, a plain
88
+ prose citation is therefore reported too. Treat the ownership/definition rule
89
+ as the _intent_ and the token scan as the _current mechanism_; when you need
90
+ to name a lower-layer item in `_policies/**`, put it in the Triage table rows,
91
+ which is the one place the scan skips.
92
+ - _Citing_ a lower-layer ID or a `spec-NNNN` inside the **Triage table rows** of
93
+ `_policies/10_delta.md` is explicitly allowed. `sdd-triage.md` requires
94
+ cross-spec and policy-only Triage rows to be persisted there, and
95
+ `QFAI-TRIAGE-002` makes `Existing Spec` (a `spec-NNNN` value) a required
96
+ column — so the `Existing Spec`, `Approved By` and `Rationale` cells must be
97
+ able to name what actually changed, verbatim. `QFAI-LAYER-100` and
98
+ `TRACE_SHARED_SCOPE_VIOLATION` skip those rows for this reason.
99
+ - The carve-out is exactly that narrow, so it cannot be used as an escape
100
+ hatch:
101
+ - **file** — `_policies/10_delta.md` only. A `## Triage` heading anywhere
102
+ else under `_policies/**` (`11_Slice-Policy.md`, `01_Objective.md`, ...)
103
+ gets no exemption.
104
+ - **heading** — the canonical `## Triage` H2 only, matching what
105
+ `QFAI-TRIAGE-001..007` validate. `# Triage`, `### Triage` and
106
+ `## Triage notes` are not exempt.
107
+ - **line shape** — markdown table rows only. A heading that declares an item
108
+ (`### AC-0001-0001`) or a traceability edge (`- Parent: US-0001-0001`)
109
+ inside the Triage section is still a violation, because it defines or owns
110
+ rather than cites.
111
+ - **table identity** — the mandated Triage table only. A second table under
112
+ `## Triage` is exempt only when its header carries the full canonical
113
+ column set (`Source`, `Subject`, `Existing Spec`, `Operation`, `Sub-op`,
114
+ `Approved By`, `Rationale`); order may differ, since the Triage validators
115
+ resolve columns by name. A table reusing only one or two of those names
116
+ earns no exemption.
117
+ - **column** — within an exempt table, only cells under a canonical column
118
+ are skipped. An author-added column (`Parent`, `Refs`, ...) keeps its cells
119
+ visible to the scan.
120
+ - Discussion-layer IDs (`DUS-001`, `DAC-001-01`, `DTC-1`, `DSC-001`) are a different
121
+ namespace and are explicitly allowed in `_policies/**` and in `Source` fields. They are
122
+ how provenance back to the discussion pack stays machine-checkable; do not rewrite them
123
+ into prose to satisfy the rule above.
124
+ - A `Source` value is always the pair `<pack-id>#<discussion-id>`, e.g.
125
+ `discussion-20260415101112123#DUS-001`. The pack half is not optional: pack IDs are the
126
+ only thing that makes a discussion ID unique, because every pack restarts its numbering at
127
+ `DUS-001` / `DAC-001-01`. A spec that two packs have updated therefore carries two `Source`
128
+ values that differ only in the pack half.
129
+ - `Source` is recorded once per item, in the required artifact: the `- Source:` line of each
130
+ `## US-NNNN` block in `02_User-stories.md`, and the `# Source:` comment inside each AC's
131
+ Gherkin block in `03_Acceptance-Criteria.md`. The optional `AC Catalog` table carries no
132
+ `Source` column, so there is no second copy to drift.
133
+
134
+ ### Item granularity
135
+
136
+ Depth expectations answer how many layers; item granularity answers how big one
137
+ item may be. It is defined in
138
+ `.qfai/assistant/constitution/requirements-decomposition.md#item-granularity-acbrextc`
139
+ and signalled by `QFAI-DENSITY-005`.
78
140
 
79
141
  ## TDD Execution Ledger
80
142
 
81
143
  Each `.qfai/specs/<spec-id>/tdd/test-list.md` is the execution ledger for the TDD micro-cycle.
82
144
 
83
145
  - Required columns: TDD-ID, TC-Refs, Layer, Test file, Selector, Status, DR-ID, Evidence
84
- - Coverage is measured as unit/component TC references from `06_Test-Cases.md` appearing in TC-Refs.
146
+ - Optional columns: `US-Refs`, `CON-API-Refs`, `Blocked-By`. `Blocked-By` names what a
147
+ `blocked` row is waiting on and is required on those rows.
148
+ - Legal `Status` values: `todo`, `blocked`, `red`, `green`, `refactor`, `review-fix`,
149
+ `done`, `exception`. `blocked` is completion-prohibiting and is never selected by
150
+ Phase Red.
151
+ - **Ownership split.** `/qfai-sdd` owns the rows — which obligations exist and what each
152
+ covers. `/qfai-implement` owns the `Status`, `DR-ID` and `Evidence` cells and nothing else.
153
+ This is the one carve-out in `constitution/drift-protocol.md#allowed-exceptions-minimal-whitelist`; adding,
154
+ removing or re-scoping a row is an upstream change and takes the Change Request path.
155
+ - `Evidence` is a **pointer**: the one-word RED/GREEN outcome plus an anchor into
156
+ `.qfai/evidence/implement-<spec-id>.md`. A GFM cell is one physical line and ends at
157
+ every unescaped `|`, so it cannot hold command output. Encoding rules and the cell
158
+ contract: `qfai-implement/references/execution-ledger.md#evidence-cell-contract`.
159
+ - Optional columns detail: `US-Refs`, `CON-API-Refs` — the E2E and API obligations a
160
+ row implements. Required when the row carries one, since `TC-*` annotations
161
+ are forbidden in `tests/e2e/**` and `tests/api/**`.
162
+ - TC coverage reads **`TC-*` tokens only**. `US-*` and `CON-API-*` IDs are
163
+ explicitly inert to it — recording one does not raise or lower TC coverage.
164
+ - Legal `Layer` values: `Unit`, `Component`, `Integration`, `API`, `E2E`.
165
+ Legal obligation kinds per layer: `TC-*` on Unit / Component / Integration,
166
+ `US-*` on E2E, `CON-API-*` on API.
167
+ - `Selector` may hold one entry, a comma-separated list, or a glob pattern. It is not limited to a single test function.
168
+ - `TC-Refs` is many-to-many with `TDD-ID`: one `TC-*` may be decomposed across several TDD rows, and each of those rows carries that `TC-*`.
169
+ - A matrix-shaped `TC-*` (many rejection reasons, a status-code matrix, several independent state transitions) MUST be split across multiple TDD rows before RED begins — one falsifying oracle per row, one row per independently observable boundary. Do not accumulate unrelated boundaries behind a single selector; doing so invalidates the RED observation, because only the first failing assert is ever observed.
170
+ - Coverage is measured as unit/component TC references from `06_Test-Cases.md`
171
+ appearing in TC-Refs. That measures which TCs need a `tdd/test-list.md` row;
172
+ it says nothing about where the test file lives. Every `TC-*` — including
173
+ unit/component ones — is still discharged in `tests/integration/**` for
174
+ `QFAI-ATDD-112` until the scanner supports the per-level routing described as
175
+ a target state in `catalog/test-layers.md`.
85
176
  - If `06_Test-Cases.md` has no test-case classification column, every TC is treated as a coverage target.
86
- - `Status=exception` requires a non-empty DR-ID.
87
- - `Status` in `green`, `refactor`, or `done` requires an existing Test file resolved from project root.
177
+ - `Status=exception` requires a non-empty DR-ID. An `exception` row is not a
178
+ dead end: a Drift Protocol sweep may reset it to `todo` like any other status
179
+ when the rerun changed the obligation it was raised against.
180
+ - `Status` in `green`, `refactor`, or `done` requires an existing Test file
181
+ resolved from project root. The upstream reset does not relax this: a swept
182
+ row returns to `todo`, where no file is required, and writes its test in the
183
+ following `red` phase.
184
+ - **The converse also holds.** A `todo` row whose Test file exists _and_ whose
185
+ `Selector` resolves inside it is a stale ledger row, not a not-started one
186
+ (`TDDLIST_STALE_STATUS`, `warning`). Stated in one direction only, the rule
187
+ could catch the ledger over-reporting and never under-reporting — and
188
+ under-reporting is what actually happens, because work lands from parallel
189
+ worktrees and the ledger is reconciled by hand afterwards. A stale `todo` and
190
+ a genuinely not-started row are indistinguishable to every downstream
191
+ consumer, including the completion gate that reads the ledger. A project that
192
+ declares test paths and selectors up front waives `TDDLIST-005`.
193
+ - `Selector` is read, not merely required: on a row claiming completion it must
194
+ resolve inside the named Test file (`TDDLIST_SELECTOR_UNRESOLVED`, `warning`).
195
+ Resolution is a containment check over the selector text and its last
196
+ identifier token, not a runner-specific parse; waive `TDDLIST-006` for a
197
+ selector form it cannot resolve.
198
+ - `DR-ID` carries Decision Record (`DR-*`) **and** Change Request (`CR-*`)
199
+ references, so it carries the approval that authorised an upstream reset, not
200
+ only `Status = exception`. A row reset by a Drift Protocol sweep records the
201
+ approved `CR-*` / `DR-*` ID there and **retains it through `red`, `green`,
202
+ `refactor` and `done`** — the ledger is the audit trail for why a completed
203
+ row was reopened. Change Requests live at
204
+ `.qfai/decisions/CR-YYYYMMDD-NNNN-<slug>.md` (`CR-\d{8}-\d{4}`).
205
+ - `Layer` must be consistent with `Test file`: an `Integration` row may not
206
+ point into `tests/e2e/**` or `tests/api/**`, and vice versa.
207
+ - More than one `TDD-*` row MAY reference the same `TC-*` — a TC split across
208
+ several test modules is legitimate. `TDD-ID` uniqueness is the only
209
+ identity constraint.
88
210
  - `TDD-ID` must match `TDD-NNNN` and be unique within the spec.
89
211
  - Missing `tdd/test-list.md` is a warning; missing DR-ID/Evidence columns is an error.
212
+ - The `Evidence` **cell** is checked too, not only the header: on a row at
213
+ `green` / `refactor` / `review-fix` / `done`, an empty-or-dash cell is
214
+ `TDDLIST_EVIDENCE_EMPTY` and a verdict with no command is
215
+ `TDDLIST_EVIDENCE_STATUS_ONLY`, both at `error`.
216
+
217
+ ## Traceability Ledger (`16_Traceability-ledger.md`)
218
+
219
+ Optional per-spec artifact linking `BR-*` / `AC-*` to the implementation file that realizes them.
220
+ Template: `templates/specs/spec/16_Traceability-ledger.md`.
221
+
222
+ - It is **optional**. Without it `npx qfai validate` emits `QFAI-TRACE-002` (`warning`) and skips the
223
+ implementation-integrity check; the spec is still valid.
224
+ - With it, `QFAI-TRACE-001` (`error`) fires when a spec's `03_Acceptance-Criteria.md` or
225
+ `04_Business-Rules.md` changed on the branch but a linked implementation file did not.
226
+ - Schema for the **layered** layout — the first Markdown table is the one read; header needs ≥3
227
+ columns, one named `Implementation File`:
228
+
229
+ | BR/AC | Implementation File | Test File |
230
+ | ------- | ------------------- | --------- |
231
+ | AC-0001 | src/… | tests/… |
232
+
233
+ First cell must be a `BR-NNNN` / `AC-NNNN` ID; second cell one repo-root-relative path (no globs,
234
+ no `./`). One row per BR/AC ↔ file pair. Extra trailing columns are ignored.
235
+
236
+ - The legacy **spec-pack** layout uses the same filename with a different schema
237
+ (`trace_id, obj_id, init_id, cap_id, flow_id, us_id, ac_id, ex_ids, tc_ids`, checked by
238
+ `QFAI-LEDGER-001`). That check runs only on spec-pack layouts — the two schemas never apply to the
239
+ same file. Do not merge them.
240
+ - Authored and refreshed by `/qfai-sdd` in the same change as the BR/AC it links. It is upstream
241
+ SSOT; downstream skills must not edit it.
90
242
 
91
243
  ## Depth Expectations
92
244