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.
- package/README.md +48 -2
- package/assets/init/.qfai/assistant/agents/acceptance-test-engineer.md +1 -0
- package/assets/init/.qfai/assistant/agents/backend-engineer.md +1 -0
- package/assets/init/.qfai/assistant/agents/completion-reviewer.md +13 -2
- package/assets/init/.qfai/assistant/agents/delivery-planner.md +9 -0
- package/assets/init/.qfai/assistant/agents/frontend-engineer.md +1 -0
- package/assets/init/.qfai/assistant/agents/implementation-reviewer.md +6 -0
- package/assets/init/.qfai/assistant/agents/orchestrator.md +2 -2
- package/assets/init/.qfai/assistant/agents/qa-gatekeeper.md +96 -3
- package/assets/init/.qfai/assistant/agents/test-design-analyst.md +20 -3
- package/assets/init/.qfai/assistant/catalog/cli-ux-guidelines.md +2 -2
- package/assets/init/.qfai/assistant/catalog/spec_required_files.json +2 -1
- package/assets/init/.qfai/assistant/catalog/test-layers.md +355 -14
- package/assets/init/.qfai/assistant/catalog/worklog-entry.schema.md +165 -0
- package/assets/init/.qfai/assistant/constitution/communication.md +1 -1
- package/assets/init/.qfai/assistant/constitution/drift-protocol.md +304 -10
- package/assets/init/.qfai/assistant/constitution/quality.md +35 -5
- package/assets/init/.qfai/assistant/constitution/requirements-decomposition.md +37 -0
- package/assets/init/.qfai/assistant/constitution/shared-skill-delegation-baseline.md +244 -8
- package/assets/init/.qfai/assistant/constitution/shared-skill-operating-baseline.md +122 -5
- package/assets/init/.qfai/assistant/constitution/workflow.md +53 -7
- package/assets/init/.qfai/assistant/manifest/agent-catalog.yml +316 -945
- package/assets/init/.qfai/assistant/manifest/agent-routing.yml +50 -4
- package/assets/init/.qfai/assistant/manifest/review-profiles.yml +9 -0
- package/assets/init/.qfai/assistant/process/migrations/v1.4.27-atdd-alignment.md +1 -1
- package/assets/init/.qfai/assistant/skills/qfai-atdd/SKILL.md +61 -21
- package/assets/init/.qfai/assistant/skills/qfai-atdd/references/test-case-depth-checklist.md +23 -4
- package/assets/init/.qfai/assistant/skills/qfai-configure/SKILL.md +15 -7
- package/assets/init/.qfai/assistant/skills/qfai-discussion/SKILL.md +8 -4
- package/assets/init/.qfai/assistant/skills/qfai-discussion/references/design-md-brand-catalog.md +2 -2
- package/assets/init/.qfai/assistant/skills/qfai-discussion/references/discussion-completion-matrix.md +17 -7
- package/assets/init/.qfai/assistant/skills/qfai-discussion/references/rcp_footer.md +10 -4
- package/assets/init/.qfai/assistant/skills/qfai-discussion/references/review-cycle-playbook.md +1 -1
- package/assets/init/.qfai/assistant/skills/qfai-discussion/references/ui-bearing-playbook.md +4 -4
- package/assets/init/.qfai/assistant/skills/qfai-discussion/references/ui_ux/review_audit_playbook.md +1 -1
- package/assets/init/.qfai/assistant/skills/qfai-discussion/references/ui_ux/trend_scan_playbook.md +1 -1
- package/assets/init/.qfai/assistant/skills/qfai-discussion/references/ui_ux_best_practices.md +17 -7
- package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/01_Context.md +1 -1
- package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/02_Inception-Deck.md +1 -1
- package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/03_Story-Workshop.md +11 -3
- package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/05_Scope.md +5 -2
- package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/07_NFR.md +1 -1
- package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/09_Constraints.md +7 -4
- package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/10_Policy.md +1 -1
- package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/11_OQ-Register.md +1 -1
- package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/12_OQ-Resolution-Log.md +1 -1
- package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/14_Review-Request.md +14 -7
- package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/99_delta.md +1 -1
- package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/review/Rxx_reviewer.md +16 -7
- package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/review/review_request.md +9 -6
- package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/uiux/40_screen_contracts.md +3 -2
- package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/uiux/50_review_input_bundle.md +4 -2
- package/assets/init/.qfai/assistant/skills/qfai-implement/SKILL.md +250 -128
- package/assets/init/.qfai/assistant/skills/qfai-implement/references/change-request-reset.md +93 -0
- package/assets/init/.qfai/assistant/skills/qfai-implement/references/checkpoint-verification.md +106 -0
- package/assets/init/.qfai/assistant/skills/qfai-implement/references/cross-spec-ownership.md +73 -0
- package/assets/init/.qfai/assistant/skills/qfai-implement/references/evidence-revision.md +77 -0
- package/assets/init/.qfai/assistant/skills/qfai-implement/references/execution-ledger.md +303 -0
- package/assets/init/.qfai/assistant/skills/qfai-implement/references/final-checklist.md +19 -0
- package/assets/init/.qfai/assistant/skills/qfai-implement/references/finding-classification.md +49 -0
- package/assets/init/.qfai/assistant/skills/qfai-implement/references/ledger-preconditions.md +55 -0
- package/assets/init/.qfai/assistant/skills/qfai-implement/references/oracle-strength.md +81 -0
- package/assets/init/.qfai/assistant/skills/qfai-implement/references/parallelization-policy.md +235 -0
- package/assets/init/.qfai/assistant/skills/qfai-implement/references/red-admissibility.md +91 -0
- package/assets/init/.qfai/assistant/skills/qfai-implement/references/red-not-observable.md +70 -0
- package/assets/init/.qfai/assistant/skills/qfai-implement/references/relevant-test-suite.md +87 -0
- package/assets/init/.qfai/assistant/skills/qfai-implement/references/review-artifact-layout.md +31 -0
- package/assets/init/.qfai/assistant/skills/qfai-implement/references/round-evidence.md +102 -0
- package/assets/init/.qfai/assistant/skills/qfai-implement/references/selector-granularity.md +24 -0
- package/assets/init/.qfai/assistant/skills/qfai-implement/references/volume-policy.md +149 -0
- package/assets/init/.qfai/assistant/skills/qfai-prototyping/SKILL.md +35 -18
- package/assets/init/.qfai/assistant/skills/qfai-prototyping/references/evidence-requirements.md +1 -1
- package/assets/init/.qfai/assistant/skills/qfai-prototyping/references/generator-prompt.md +106 -7
- package/assets/init/.qfai/assistant/skills/qfai-prototyping/references/handoff.md +40 -11
- package/assets/init/.qfai/assistant/skills/qfai-prototyping/references/iteration-loop.md +48 -1
- package/assets/init/.qfai/assistant/skills/qfai-prototyping/templates/DESIGN.md.sample +6 -0
- package/assets/init/.qfai/assistant/skills/qfai-sdd/SKILL.md +82 -22
- package/assets/init/.qfai/assistant/skills/qfai-sdd/references/contract-artifact-rules.md +148 -0
- package/assets/init/.qfai/assistant/skills/qfai-sdd/references/rcp_footer.md +10 -4
- package/assets/init/.qfai/assistant/skills/qfai-sdd/references/review-cycle-playbook.md +1 -1
- package/assets/init/.qfai/assistant/skills/qfai-sdd/references/sdd-execution-playbook.md +4 -2
- package/assets/init/.qfai/assistant/skills/qfai-sdd/references/sdd-phase-checklists.md +18 -0
- package/assets/init/.qfai/assistant/skills/qfai-sdd/references/sdd-quality-gate.md +44 -3
- package/assets/init/.qfai/assistant/skills/qfai-sdd/references/sdd-triage.md +60 -7
- package/assets/init/.qfai/assistant/skills/qfai-sdd/references/spec-traceability-rules.md +157 -5
- package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/change-request.md +125 -0
- package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/contracts/db-contract.sample.sql +6 -0
- package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/evidence/sdd-spec.md +92 -0
- package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/_policies/01_Objective.md +27 -0
- package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/_policies/02_Initiative.md +30 -0
- package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/_policies/05_Contracts.md +16 -6
- package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/_policies/06_Glossary.md +19 -0
- package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/_policies/07_Constraints.md +25 -0
- package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/_policies/08_Decisions.md +22 -2
- package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/_policies/11_Slice-Policy.md +37 -10
- package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/spec/02_User-stories.md +20 -0
- package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/spec/03_Acceptance-Criteria.md +19 -0
- package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/spec/04_Business-Rules.md +32 -3
- package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/spec/06_Test-Cases.md +56 -0
- package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/spec/07_Decisions.md +29 -2
- package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/spec/10_Plan.md +41 -0
- package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/spec/16_Traceability-ledger.md +58 -0
- package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/spec/tdd/test-list.md +56 -0
- package/assets/init/.qfai/assistant/skills/qfai-verify/SKILL.md +57 -102
- package/assets/init/.qfai/assistant/skills/qfai-verify/references/articles.md +24 -0
- package/assets/init/.qfai/assistant/skills/qfai-verify/references/context-load.md +22 -0
- package/assets/init/.qfai/assistant/skills/qfai-verify/references/verify-output-contract.md +48 -0
- package/assets/init/.qfai/assistant/skills/qfai-verify/templates/verify-evidence.md +48 -0
- package/assets/init/.qfai/assistant/skills/web-research/SKILL.md +25 -7
- package/assets/init/.qfai/waivers.yml +11 -5
- package/assets/init/root/DESIGN.md +6 -0
- package/assets/init/root/qfai.config.yaml +15 -12
- package/dist/cli/index.cjs +11023 -7139
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.mjs +10963 -7080
- package/dist/cli/index.mjs.map +1 -1
- package/dist/index.cjs +8782 -5257
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +280 -8
- package/dist/index.d.ts +280 -8
- package/dist/index.mjs +11776 -8264
- package/dist/index.mjs.map +1 -1
- 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` / `
|
|
28
|
-
-
|
|
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 `
|
|
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
|
|
13
|
-
7. **Phase
|
|
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
|
|
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.
|
|
22
|
-
|
|
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
|
|
44
|
-
| SPLIT | - | One spec carries >1 capability; split into N specs
|
|
45
|
-
| MERGE | - | Multiple specs converge on one capability; collapse them
|
|
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
|
|
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
|
-
-
|
|
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
|
-
|
|
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
|
|