qfai 1.10.0 → 1.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/README.md +95 -25
  2. package/assets/init/.qfai/assistant/README.md +27 -0
  3. package/assets/init/.qfai/assistant/agents/completion-reviewer.md +17 -1
  4. package/assets/init/.qfai/assistant/agents/delivery-planner.md +8 -0
  5. package/assets/init/.qfai/assistant/agents/implementation-reviewer.md +12 -1
  6. package/assets/init/.qfai/assistant/agents/orchestrator.md +2 -2
  7. package/assets/init/.qfai/assistant/agents/product-experience-architect.md +2 -1
  8. package/assets/init/.qfai/assistant/agents/product-surface-reviewer.md +1 -1
  9. package/assets/init/.qfai/assistant/agents/qa-gatekeeper.md +99 -14
  10. package/assets/init/.qfai/assistant/agents/test-design-analyst.md +4 -1
  11. package/assets/init/.qfai/assistant/catalog/cli-ux-guidelines.md +3 -0
  12. package/assets/init/.qfai/assistant/catalog/test-layers-ci-lanes.md +60 -0
  13. package/assets/init/.qfai/assistant/catalog/test-layers.md +169 -87
  14. package/assets/init/.qfai/assistant/catalog/worklog-entry.schema.md +4 -3
  15. package/assets/init/.qfai/assistant/constitution/agent-selection.md +7 -1
  16. package/assets/init/.qfai/assistant/constitution/communication.md +1 -1
  17. package/assets/init/.qfai/assistant/constitution/constitution.md +8 -2
  18. package/assets/init/.qfai/assistant/constitution/drift-protocol.md +177 -14
  19. package/assets/init/.qfai/assistant/constitution/review-convergence.md +121 -0
  20. package/assets/init/.qfai/assistant/constitution/shared-skill-delegation-baseline.md +205 -89
  21. package/assets/init/.qfai/assistant/constitution/shared-skill-operating-baseline.md +59 -5
  22. package/assets/init/.qfai/assistant/manifest/agent-catalog.yml +145 -21
  23. package/assets/init/.qfai/assistant/manifest/agent-routing.yml +69 -3
  24. package/assets/init/.qfai/assistant/skills/qfai-atdd/SKILL.md +131 -74
  25. package/assets/init/.qfai/assistant/skills/qfai-atdd/references/credential-reuse.md +146 -0
  26. package/assets/init/.qfai/assistant/skills/qfai-atdd/references/red-provenance.md +498 -0
  27. package/assets/init/.qfai/assistant/skills/qfai-atdd/references/review-fix-rounds.md +128 -0
  28. package/assets/init/.qfai/assistant/skills/qfai-atdd/references/scaffolding.md +71 -0
  29. package/assets/init/.qfai/assistant/skills/qfai-atdd/references/shared-test-artifacts.md +124 -0
  30. package/assets/init/.qfai/assistant/skills/qfai-atdd/references/stale-manifest.md +34 -0
  31. package/assets/init/.qfai/assistant/skills/qfai-atdd/references/test-case-depth-checklist.md +38 -1
  32. package/assets/init/.qfai/assistant/skills/qfai-configure/SKILL.md +4 -3
  33. package/assets/init/.qfai/assistant/skills/qfai-discussion/SKILL.md +10 -8
  34. package/assets/init/.qfai/assistant/skills/qfai-discussion/references/discussion-completion-matrix.md +23 -2
  35. package/assets/init/.qfai/assistant/skills/qfai-discussion/references/review-cycle-playbook.md +16 -1
  36. package/assets/init/.qfai/assistant/skills/qfai-discussion/references/ui-bearing-playbook.md +47 -11
  37. package/assets/init/.qfai/assistant/skills/qfai-discussion/references/ui_ux/trend_scan_playbook.md +1 -1
  38. package/assets/init/.qfai/assistant/skills/qfai-discussion/references/ui_ux_best_practices.md +6 -4
  39. package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/01_Context.md +2 -2
  40. package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/03_Story-Workshop.md +1 -1
  41. package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/04_Sources.md +40 -6
  42. package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/14_Review-Request.md +7 -7
  43. package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/review/Rxx_reviewer.md +3 -3
  44. package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/review/review_request.md +4 -3
  45. package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/review/summary.json +3 -0
  46. package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/uiux/00_index.md +14 -5
  47. package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/uiux/40_screen_contracts.md +17 -1
  48. package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/uiux/50_review_input_bundle.md +13 -8
  49. package/assets/init/.qfai/assistant/skills/qfai-implement/SKILL.md +83 -84
  50. package/assets/init/.qfai/assistant/skills/qfai-implement/references/checkpoint-verification.md +339 -39
  51. package/assets/init/.qfai/assistant/skills/qfai-implement/references/cross-spec-ownership.md +1 -1
  52. package/assets/init/.qfai/assistant/skills/qfai-implement/references/evidence-revision.md +348 -15
  53. package/assets/init/.qfai/assistant/skills/qfai-implement/references/execution-ledger.md +203 -32
  54. package/assets/init/.qfai/assistant/skills/qfai-implement/references/final-checklist.md +159 -12
  55. package/assets/init/.qfai/assistant/skills/qfai-implement/references/finding-classification.md +70 -5
  56. package/assets/init/.qfai/assistant/skills/qfai-implement/references/ledger-preconditions.md +55 -14
  57. package/assets/init/.qfai/assistant/skills/qfai-implement/references/parallelization-policy.md +92 -3
  58. package/assets/init/.qfai/assistant/skills/qfai-implement/references/red-not-observable.md +48 -6
  59. package/assets/init/.qfai/assistant/skills/qfai-implement/references/relevant-test-suite.md +13 -1
  60. package/assets/init/.qfai/assistant/skills/qfai-implement/references/review-artifact-layout.md +71 -9
  61. package/assets/init/.qfai/assistant/skills/qfai-implement/references/round-evidence.md +31 -7
  62. package/assets/init/.qfai/assistant/skills/qfai-implement/references/upstream-artifact-ordering.md +33 -0
  63. package/assets/init/.qfai/assistant/skills/qfai-implement/references/volume-policy.md +19 -12
  64. package/assets/init/.qfai/assistant/skills/qfai-prototyping/SKILL.md +76 -8
  65. package/assets/init/.qfai/assistant/skills/qfai-prototyping/references/design-md-spec.md +20 -0
  66. package/assets/init/.qfai/assistant/skills/qfai-prototyping/references/evidence-requirements.md +7 -4
  67. package/assets/init/.qfai/assistant/skills/qfai-prototyping/references/generator-prompt.md +83 -22
  68. package/assets/init/.qfai/assistant/skills/qfai-prototyping/references/reviewer-prompt.md +29 -4
  69. package/assets/init/.qfai/assistant/skills/qfai-sdd/SKILL.md +134 -20
  70. package/assets/init/.qfai/assistant/skills/qfai-sdd/references/contract-artifact-rules.md +31 -3
  71. package/assets/init/.qfai/assistant/skills/qfai-sdd/references/review-cycle-playbook.md +22 -1
  72. package/assets/init/.qfai/assistant/skills/qfai-sdd/references/sdd-execution-playbook.md +41 -5
  73. package/assets/init/.qfai/assistant/skills/qfai-sdd/references/sdd-phase-checklists.md +16 -4
  74. package/assets/init/.qfai/assistant/skills/qfai-sdd/references/sdd-triage.md +77 -7
  75. package/assets/init/.qfai/assistant/skills/qfai-sdd/references/spec-traceability-rules.md +60 -11
  76. package/assets/init/.qfai/assistant/skills/qfai-sdd/references/ui-design-contract-normalization.md +9 -3
  77. package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/change-request.md +14 -1
  78. package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/contracts/ui-contract.sample.yaml +13 -3
  79. package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/evidence/sdd-spec.md +5 -1
  80. package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/report/preflight_summary.md +3 -2
  81. package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/_policies/04_Business-Flow.md +4 -1
  82. package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/_policies/05_Contracts.md +12 -5
  83. package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/_policies/11_Slice-Policy.md +8 -9
  84. package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/spec/02_User-stories.md +9 -0
  85. package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/spec/tdd/test-list.md +68 -23
  86. package/assets/init/.qfai/assistant/skills/qfai-verify/SKILL.md +4 -4
  87. package/assets/init/.qfai/assistant/skills/qfai-verify/references/articles.md +1 -1
  88. package/assets/init/.qfai/assistant/skills/qfai-verify/references/validate-json-schema.md +79 -0
  89. package/assets/init/.qfai/assistant/skills/web-research/SKILL.md +3 -2
  90. package/assets/init/root/.github/workflows/qfai-tests.yml +318 -0
  91. package/assets/init/root/.github/workflows/qfai-validate.yml +327 -24
  92. package/assets/init/root/qfai.config.yaml +11 -2
  93. package/dist/cli/index.cjs +25083 -11488
  94. package/dist/cli/index.cjs.map +1 -1
  95. package/dist/cli/index.mjs +25216 -11589
  96. package/dist/cli/index.mjs.map +1 -1
  97. package/dist/index.cjs +16731 -8386
  98. package/dist/index.cjs.map +1 -1
  99. package/dist/index.d.cts +407 -17
  100. package/dist/index.d.ts +407 -17
  101. package/dist/index.mjs +16701 -8370
  102. package/dist/index.mjs.map +1 -1
  103. package/package.json +6 -1
@@ -136,73 +136,13 @@ review in this run.
136
136
  - Do not declare DONE until all routed blocking reviewers return `PASS`.
137
137
  - Every reviewer returning `FAIL` or `REVISE` must include a concrete fix proposal.
138
138
 
139
- ### Round budget (MUST)
140
-
141
- - **Two rounds per reviewer per artifact.** Round 1 is the initial review;
142
- round 2 reviews the fixes. **The budget is spent the moment round 2 returns
143
- `REVISE`**: the orchestrator MUST NOT start a third review, and MUST stop and
144
- escalate to the user with the open findings, the fixes already applied, and a
145
- recommendation. The decision point is round 2's verdict, never a prediction
146
- about a review that must not run.
147
- - Escalation is not failure. The artifact stays at its current status and the
148
- user decides: accept with the finding recorded as an Open Question, apply a
149
- named fix, or drop the item from scope.
150
- - **Completion after escalation.** The user's decision is the exception to
151
- "no DONE until all blocking reviewers `PASS`", so the escalation has an exit:
152
- - _Accept as Open Question_ or _drop from scope_ — the artifact may reach
153
- DONE with the finding recorded; the reviewer's outstanding `REVISE` is
154
- superseded by the recorded user decision. Cite the decision where the
155
- stage records decisions (`*_delta.md` / `07_Decisions.md` / a Change
156
- Request).
157
- - _Apply a named fix_ — one **verification review** of exactly that fix is
158
- permitted and does not consume budget (it is round 2b, not round 3). Its
159
- remit is the named fix only. It may not raise findings unrelated to that
160
- fix, but a defect the fix **introduced or exposed** is in remit and MUST be
161
- reported rather than passed over: verifying only the named lines and
162
- returning `PASS` while a regression sits next to them is a false `PASS`.
163
- Such a finding escalates immediately (see the severity floor below) and
164
- still does not start a round 3. The review returns `PASS` or escalates
165
- again.
166
- - **One 2b per artifact, total.** The verification review is free of budget,
167
- not unbounded: a second escalation on the same artifact MUST NOT be
168
- answered with another _apply a named fix_ + 2b cycle. Without this cap the
169
- two rules compose into a loop — 2b costs nothing, and escalating again is
170
- always allowed — so the gate has no guaranteed end. At the second
171
- escalation the user is offered only _accept as Open Question_ or _drop the
172
- item from scope_ (subject to the severity floor below); if the floor
173
- withholds both, the artifact does not reach DONE and the stage stops with
174
- the finding recorded.
175
- - **Severity floor on the exit.** _Accept as Open Question_ is NOT available
176
- for a finding that names a concrete security defect, data loss or
177
- corruption, or a correctness defect that would break a released contract.
178
- Present the user only _apply a named fix_ or _drop the item from scope_ for
179
- those, and say why the third option is withheld. Without this the general
180
- exit is a route around "deferring such a finding to an Open Question so a
181
- `PASS` can be returned is prohibited" — one that needs no lateness and no
182
- reviewer consent, only a user click.
183
- - The round number MUST be recorded on each reviewer response
184
- (`Round:` in the shared response template).
185
-
186
- ### Convergence (MUST)
187
-
188
- - A finding first raised in round N > 1 MUST state why it was not raisable in
189
- round N-1 — the fix introduced it, or the fix exposed it. A finding that was
190
- raisable in round 1 and was not raised is **out of budget**: record it as an
191
- Open Question or a `*_delta.md` Decision Record for the owning stage, do not
192
- block on it.
193
- - A reviewer MUST NOT open a new blocking _class_ of finding after the artifact
194
- under review has been declared stable. New classes go to the owning stage.
195
- - **Severity overrides lateness.** The out-of-budget rule is about review
196
- discipline, not about shipping known harm. A late finding that names a
197
- concrete security defect, data loss or corruption, or a correctness defect
198
- that would break a released contract is **not** deferrable: the orchestrator
199
- stops and escalates to the user immediately, exactly as it does when the
200
- round budget is spent. It is still not a third round — no further review is
201
- started, the finding goes straight to the user with its evidence. Deferring
202
- such a finding to an Open Question so a `PASS` can be returned is prohibited.
203
- That prohibition does not depend on lateness or on who proposes the deferral:
204
- the escalation exit in the round budget withholds _Accept as Open Question_
205
- for this same class, so a user choice cannot supersede it either.
139
+ ### Round budget and convergence (MUST)
140
+
141
+ Both live in `.qfai/assistant/constitution/review-convergence.md`: the
142
+ two-round budget, the escalation exits and their severity floor, the
143
+ one-shot corrective review, and the convergence rules that decide which
144
+ findings are still in budget. They moved there because this file reached
145
+ the shipped-asset line ceiling; the rules are unchanged by the move.
206
146
 
207
147
  ### Reviewer remit (in scope per stage)
208
148
 
@@ -229,19 +169,19 @@ in/out split is not re-derived per run.
229
169
 
230
170
  - Every finding must declare a severity (`blocking` or `advisory`) and a `Traces to:` value.
231
171
  - `Traces to:` names what the finding enforces. Legal values:
232
- - an upstream obligation — an `AC-*`, `BR-*`, `TC-*`, `CON-*` ID, or a named
233
- constitution/catalog rule;
234
- - `defect:correctness`, `defect:security`, or `defect:code-quality` — a defect demonstrable from
235
- the changed artifacts themselves, cited together with the evidence that demonstrates it. See
236
- `drift-protocol.md#defect-or-new-scope-decide-this-first`. A reviewer who can show the
237
- deliverable is wrong on its own terms does not need an `AC-*` to say so;
172
+ - an upstream obligation — an `AC-*`, `BR-*`, `TC-*`, `CON-*` ID, or a named constitution/catalog rule **that governs the product's behaviour**;
173
+ - `defect:correctness`, `defect:security`, or `defect:code-quality` — a defect demonstrable from the changed artifacts themselves, cited with the evidence that demonstrates it
174
+ (see `drift-protocol.md#defect-or-new-scope-decide-this-first`). A reviewer who can show the deliverable is wrong on its own terms does not need an `AC-*` to say so;
175
+ - `record:<CODE>` — a defect in the run's own record rather than in the product: a ledger cell, a round block, an evidence anchor, the provenance prose. `<CODE>` names the record rule;
238
176
  - `none` — reviewer-originated scope, i.e. a new product obligation upstream never asked for.
239
- - A finding whose `Traces to:` is `none` MUST be recorded as `advisory`. It cannot be `blocking`,
240
- and it cannot gate `DONE`.
241
- - An advisory finding is routed to the Change Request / Open Question path defined in
242
- `drift-protocol.md#reviewer-originated-obligations`, not to the implementer.
243
- - Only `blocking` findings — those citing an upstream obligation or a defect class — force
244
- `REVISE`.
177
+ - `record:*` and `none` MUST be recorded as `advisory`; neither can be `blocking` or gate `DONE`. A `record:*` finding never re-runs the row: the orchestrator files it in the record-defect queue the
178
+ reviewing stage's own completion contract names, and that contract is what drains it (`drift-protocol.md#the-record-defect-queue`). **The class needs a drain: only a stage whose completion conditions require that queue drained may use it — today `/qfai-implement` alone, so `/qfai-sdd`, `/qfai-atdd`, `/qfai-configure`, `/qfai-verify`, `/qfai-discussion` and `/web-research` reviewers MUST NOT, and there the finding keeps the class it would otherwise have had.** An entry closes only on a repaired record, re-attested in a new pack where a reviewer hashed it; `record:unchecked` is a bug report against `validateTddList` and never a substitute for the repair —
179
+ a record rule worth a round is worth a validator code.
180
+ - **Integrity is not record class.** Evidence copied from another round or a sibling row, an anchor resolving to a run other than the one it names, and a false
181
+ `Authored/edited under review` attestation claim work that was not done or independence the reviewer lacked. `agents/qa-gatekeeper.md` and the response rules below refuse a `PASS`
182
+ built on them, so they stay `blocking` as `defect:code-quality` and are never filed as `record:*` — which covers an honestly produced record that is merely wrong.
183
+ - A `none` advisory takes the Change Request / Open Question path (`drift-protocol.md#reviewer-originated-obligations`); a `record:*` advisory takes the queue above. Neither goes to the implementer.
184
+ - Only `blocking` findings — those citing a behaviour-governing obligation or a defect class — force `REVISE`.
245
185
 
246
186
  ### Reviewer budget exhausted
247
187
 
@@ -273,20 +213,21 @@ Constraints:
273
213
  STOP + Change Request + owner rerun per constitution/drift-protocol.md
274
214
  Output format:
275
215
  - <headings / bullet schema>
276
- Quality bar:
277
- - PASS if ...
278
- - REVISE if ...
216
+ Acceptance bar: <accept when ...> | <rework when ...> # never `PASS`/`REVISE`: that is the reviewer's vocabulary and the completion gate matches on it, so a doer told to report in it emits a verdict on its own work
279
217
  ```
280
218
 
281
219
  ## Reviewer response template
282
220
 
283
221
  ```text
222
+ Reviewer role: <sub-agent role that produced this response> # REQUIRED — a `Result:` line with no speaker is a report, not a verdict
223
+ Reviewed artifact: <path/anchor this verdict rules on> # REQUIRED — bounds the ruling; a PASS here clears nothing else
284
224
  Round: 1 | 2 | 2b
285
225
  Result: PASS | REVISE
286
- Reviewed revision: <git rev> | working-tree+<porcelain digest>
226
+ Reviewed revision: <git rev> | working-tree+<content hash>
227
+ Audited evidence hash: <content hash of the evidence read> # one line per TDD-ID on a T1 group
287
228
  Authored/edited under review: none | <artifact refs this reviewer authored or edited in this run>
288
229
  Findings:
289
- - <issue> | Severity: blocking|advisory | Traces to: <AC-*/BR-*/TC-*/CON-*/rule-name|defect:correctness|defect:security|defect:code-quality|none>
230
+ - <issue> | Severity: blocking|advisory | Traces to: <AC-*/BR-*/TC-*/CON-*/rule-name|defect:correctness|defect:security|defect:code-quality|record:<CODE>|none>
290
231
  Required fixes:
291
232
  - <action> # blocking findings only
292
233
  Advisory / Change Request proposals:
@@ -295,18 +236,193 @@ Evidence checked:
295
236
  - <refs>
296
237
  ```
297
238
 
298
- `Round` is required — the round budget above is counted from it. `2b` is the
239
+ `Round` is required — the round budget in `review-convergence.md` is counted
240
+ from it. `2b` is the
299
241
  post-escalation verification review of a user-named fix.
300
242
 
243
+ - `Audited evidence hash` is REQUIRED wherever the evidence tree is what the
244
+ verdict is about. `Reviewed revision` excludes `.qfai/evidence/**` — see below
245
+ for why it has to — so nothing else pins the RED/GREEN output this reviewer
246
+ read, or the coverage justifications it accepted: edited after a PASS they
247
+ leave the revision unchanged and the verdict reads as fresh. Hash the row's
248
+ **phase-authored** entry, meaning the entry with the reviewer-appended fields
249
+ removed — which is exactly what was read — plus
250
+ `.qfai/evidence/coverage-depth-<spec-id>.md` where the row has one, in the
251
+ same `path + NUL + blob hash` manifest form, sorted by path. **The reviewer
252
+ computes it**, on the evidence it read; an orchestrator filling it in on the
253
+ reviewer's behalf is recording something nobody audited.
254
+ - **How to compute it, exactly.** The subject is part of a file, so a
255
+ file-level manifest alone is ambiguous, and two readers hashing different
256
+ extents produce a verdict that is either always stale or never checked. One
257
+ procedure, in four steps:
258
+ 1. **Extract — the fields this observation could read, named.** Not "the
259
+ section minus what is written later": the entry keeps growing after every
260
+ observation, so subtracting a list only moved the problem to the next
261
+ field added. The RED gatekeeper hashes an entry that has no GREEN yet, the
262
+ GREEN gatekeeper one that has no `Refactor verify`, and each was stale as
263
+ soon as the phase wrote on. **Three subjects, from the row's
264
+ `### <TDD-ID>` section** of the evidence file its `Layer` owns — the
265
+ heading line through the line before the next `###` heading that names a
266
+ `TDD-` id, or the next `##` / `#` heading, or end of file, **counting only
267
+ headings outside a fenced block** (` ``` ` / `~~~`, closed at that length or
268
+ longer; a body that would close its own fence gets a longer one). Every
269
+ recorded output is fenced for this reason: a test asserting on Markdown
270
+ prints `## ...` of its own, and a boundary that took it dropped the GREEN,
271
+ the `Oracle proof` and the round evidence out of the subject. Each takes
272
+ only its own fields, in the order the contract lists them:
273
+ - **Row identity, in all three**: `TDD-ID`, `Layer`, `Test file` and
274
+ `Selector` — copied from the ledger, which the revision excludes.
275
+ Without them, changing `Selector` after a PASS to another valid test in
276
+ the same file left every hash and revision unmoved, and a verdict that
277
+ only ran the old selector stood as evidence for the new one. Mutable
278
+ bookkeeping — `Status`, `Evidence` — stays out: it moves on its own.
279
+
280
+ **The copy is checked against the ledger, not trusted** — the four
281
+ identity fields **and the obligation reference**. Hashing a value the
282
+ entry already holds proves only that the entry has not changed: edit
283
+ `Selector` in `test-list.md` after the PASS and copy, hash and revision
284
+ are all unmoved. Gate item 10 reads the four fields from
285
+ `test-list.md` and requires them to equal the copy; a difference is the
286
+ row moving under its own evidence, and the verdict is not fresh. The
287
+ obligation is on that list for the same reason: change `TC-Refs` /
288
+ `US-Refs` / `CON-API-Refs` alone after the PASS and the entry still holds
289
+ the old copy, so a verdict about one requirement stands for another.
290
+
291
+ - **RED observation**: the obligation reference the row's
292
+ `Layer` selects (`TC-ref`, or `US-ref` on `E2E` and `CON-API-ref` on
293
+ `API` — an ATDD-owned row has no `TC-ref`, so naming only that one left
294
+ its obligation outside every hash), `RED test hash`, the row's own
295
+ transient revision (`RED revision` or `Falsifiability revision`), and the
296
+ RED pair or the falsifiability trio with `RED failure mode`. **Not
297
+ `Revision`**: it names the tree the GREEN landed at and does not exist
298
+ yet, so including it made every correct RED PASS stale at GREEN.
299
+ - **GREEN observation**: the RED subject plus `Revision`, the GREEN pair,
300
+ `Oracle proof` and, where the row has one, `Replacement proof revision` —
301
+ it addresses the tree a re-taken proof ran against, which the revision
302
+ does not reach, so a subject without it let that proof be attributed to a
303
+ tree it never ran on.
304
+ - **Stage review** (a `completion-reviewer` judging a stage rather than a
305
+ row — a spec with no ATDD-owned rows is the ordinary case, and
306
+ `qfai-atdd/SKILL.md` treats zero as a legitimate count): the stage
307
+ evidence file **whole**, under its repo-relative path, plus
308
+ `.qfai/evidence/coverage-depth-<spec-id>.md` whole — **minus the
309
+ `## Final status` section**, which the P8 reviewer's own answer fills in.
310
+ Whole-file included it, so writing PASS and the confirmer's name straight
311
+ after hashing made the verdict stale on being recorded. There is no
312
+ `### <TDD-ID>` section to extract and no per-row boundary to draw, so the
313
+ rest of the file is the subject; step 2 normalizes it, steps 3 and 4 are
314
+ unchanged.
315
+ Without this the final review of such a spec either omitted a required
316
+ field or PASSed with nothing pinning the evidence it read.
317
+ - **Branch 3** (`exception`): row identity, the obligation reference the
318
+ row's `Layer` selects, the `DR-ID`, and the `DR-*` artifact it names. The
319
+ obligation is what the DR says cannot be observed, so a subject without
320
+ it let the reference be pointed at a different requirement after the PASS
321
+ — the ledger is out of the revision, and item 10's identity check covers
322
+ four fields, so nothing moved. Item 10 checks this one against the ledger
323
+ as well. There is no RED and no GREEN on this branch — the
324
+ claim is that neither could be had — so the DR **is** the evidence, and
325
+ leaving it out of every subject let the pointer be swapped after the PASS
326
+ for another existing `DR-*`, one already waived perhaps, with the
327
+ revision and the hash both unmoved. Gate item 10 also requires the
328
+ verdict to name the `DR-ID` the row currently carries.
329
+ - **Completion review** (`completion-reviewer` / `implementation-reviewer`):
330
+ the GREEN subject plus `Refactor verify command` / `result` / `revision`, the
331
+ `Shared-artifact re-verify` block when the row has one — it records the
332
+ earlier rows' re-runs and re-taken proofs, which these reviewers are the
333
+ ones who audit, so leaving it out let it be edited or deleted without
334
+ moving either hash — and, from every `### Round N` block the row
335
+ carries, that block's **phase-authored** fields only. `Round N: reviewer verdict` is written by these reviewers
336
+ after they have read the block, so taking the whole block put their own
337
+ line inside what they hashed.
338
+
339
+ A field absent at that point contributes nothing — it is not a placeholder
340
+ and not an error. Nothing written after an observation is in its subject,
341
+ which is what makes a verdict re-checkable at all: gate item 10 recomputes
342
+ each one against its own list. **When in doubt about a new field, ask which
343
+ observation could have read it**; that is the whole rule, and it is why the
344
+ subjects are named rather than derived by subtraction. **A field written
345
+ after every reviewer is in no subject at all** — the checkpoint pair, which
346
+ the revision and the pack seal both miss — so it carries a seal of its own,
347
+ taken as it is written and recomputed by the gate that reads it.
348
+
349
+ 2. **Normalize.** LF line endings; strip trailing whitespace from every line;
350
+ drop leading and trailing blank lines; end with exactly one newline.
351
+ 3. **Serialize.** One record per artifact — the repo-relative path, a NUL
352
+ byte, then the SHA-256 of that artifact's normalized bytes — sorted by
353
+ path, joined with newlines. **This is the audit hash, not the working-tree
354
+ revision**: that one has its own four steps, including the untracked
355
+ record's `kind` and `mode`, in
356
+ `../skills/qfai-implement/references/evidence-revision.md`, and restating
357
+ it here is how the two came to disagree. Two artifacts: the extracted
358
+ section, recorded under the evidence file's path, and
359
+ on a branch-3 row the `DR-*` artifact the row names, whole, under its
360
+ repo-relative path — the subject says the DR is that branch's evidence, and
361
+ a subject with no record for it is a hash that does not move when the DR
362
+ text changes; and
363
+ the part of `.qfai/evidence/coverage-depth-<spec-id>.md` that belongs to
364
+ this row's obligation — not the file whole, and matched **exactly**. A
365
+ row may legitimately carry several (`TC-Refs: TC-0001, TC-0002`), so split
366
+ the copied column on commas first and take each id in the order the column
367
+ lists them; comparing the whole column against a single-id matrix cell
368
+ matched nothing, and a row with two obligations had no matrix rows in its
369
+ subject at all. For each id: the table rows whose obligation cell equals it
370
+ (`TC-0001` does not match `TC-00011`), plus each justification paragraph
371
+ whose first line names it. A justification that names no obligation belongs to
372
+ none of them and is left out; "everything after the table" was the other
373
+ reading, and two readers taking one each computed different hashes from one
374
+ file. The matrix is one document
375
+ for the spec and a later `/qfai-atdd` run recomputes it, so hashing all of
376
+ it made every existing verdict stale when an unrelated obligation's cell
377
+ moved, and a `done` row has no re-review path to clear that. Take the table
378
+ rows whose obligation column matches, with any justification lines under
379
+ them, normalized by step 2 as well; a row whose obligation appears nowhere
380
+ in the matrix contributes nothing.
381
+ 4. **Hash.** SHA-256 of that record list; record the hex digest.
382
+
383
+ **A T1 coherent group is one pass and several rows** (`volume-policy.md`).
384
+ One hash over a representative would leave the other members' evidence free to
385
+ change after the PASS, and a private concatenation of their sections has no
386
+ defined member order or record shape for gate item 10 to reproduce. Record
387
+ **one `Audited evidence hash` per `TDD-ID` in the group**, each by these four
388
+ steps over that row's own subject, listed in the verdict beside the id it
389
+ belongs to. Nothing about a group is special then; it is the single-row rule
390
+ applied as many times as the group has members.
391
+
392
+ Gate item 10 runs the same four steps. A row with no coverage-depth file, or
393
+ none whose matrix names its obligation, has one record rather than a
394
+ placeholder — an absent artifact contributes nothing, not a name with an empty
395
+ hash.
396
+
301
397
  - `Reviewed revision` is REQUIRED. It names the state the verdict describes — a `git rev-parse HEAD`
302
- value, or `working-tree+<digest of git status --porcelain>` when the tree is uncommitted. Without
398
+ value, or `working-tree+<content hash>` when the tree is uncommitted, computed by
399
+ the four-step procedure in `../skills/qfai-implement/references/evidence-revision.md`:
400
+ collect, exclude, serialize, hash. **Do not restate it**: it was restated here as
401
+ `path + NUL + hash`, the canonical since gained the untracked record's `kind`
402
+ and `mode`, and the two spellings gave producer and reviewer different
403
+ addresses for one tree on any run with an untracked file in it — which a new
404
+ acceptance test is.
405
+ **The ledger, the evidence tree and the review pack are excluded**, exactly
406
+ as that contract says — `.qfai/specs/*/tdd/test-list.md`, `.qfai/evidence/**`
407
+ and `.qfai/review/**`. The pack is on the list because a project may
408
+ legitimately track it, and then storing R01 moves the address R02 computes,
409
+ so items 7-8 could not PASS on one revision. The phases write `test-list.md`
410
+ and `.qfai/evidence/**` between the
411
+ refactor-verify run and the reviews, so hashing all of `git diff HEAD` here
412
+ produced a `Reviewed revision` that could never equal the phase-authored
413
+ `Refactor verify revision` — and gate item 10 wants them equal. `references/evidence-revision.md` is the
414
+ field's contract and this restates it; the two have to agree or the verdict
415
+ cannot be re-checked. **Not** a
416
+ `git status --porcelain` digest: that names the changed paths and their states, so it does not
417
+ move when only the content of an already-changed file does, and a stale PASS reads as fresh.
418
+ Without
303
419
  it a verdict cannot be re-checked, cannot be invalidated by a later commit, and cannot be told
304
420
  apart from a stale one, so "stale evidence MUST NOT be reused" has nothing to compare against.
305
421
  Reviewers are dispatched against the integrated tree by design, so the tree is legitimately
306
422
  allowed to move under them: an honest, independent verdict on a tree that no longer exists is the
307
423
  normal failure this field addresses. If the tree changed mid-review, say so and name the revision
308
424
  the ruling is pinned to.
309
- - `Authored/edited under review` is REQUIRED. A response omitting it is not a valid review verdict.
425
+ - `Reviewer role`, `Reviewed artifact` and `Authored/edited under review` are REQUIRED. A response omitting any of them is not a valid review verdict and MUST NOT satisfy a completion gate — re-request it rather than reading a bare `Result:` line out of it, which is how a doer's self-assessment gets counted as a reviewer's ruling.
310
426
  - Anything other than `none` is a declared independence conflict: the verdict cannot be `PASS`,
311
427
  and the review must be handed to a non-participating reviewer (see
312
428
  `Definition: independent reviewer`).
@@ -317,8 +433,8 @@ post-escalation verification review of a user-named fix.
317
433
 
318
434
  - Reviewer responses in-flight use `Result: PASS | REVISE` (this file).
319
435
  - `summary.json` archived into review packs historically uses
320
- `status: "PASS|FAIL"` (validated by
321
- `packages/qfai/src/core/validators/reviewArtifacts.ts`).
436
+ `status: "PASS|FAIL"` (validated by the review-artifact validator
437
+ shipped inside the QFAI package, which `npx qfai validate` runs).
322
438
  - A `REVISE` verdict during iteration maps to `status: "FAIL"` when the
323
439
  final `summary.json` is written; they represent the same outcome.
324
440
  Review packs should not invent a third verdict.
@@ -26,8 +26,19 @@ It is not where the detail lives.
26
26
  the file (and anchor, when the file covers more than one topic) so the reader
27
27
  is never left guessing where the rule went.
28
28
 
29
- A hard line ceiling backs this up in the asset tests, but it is a backstop, not
30
- the rule. A skill approaching it is a signal to move a section out.
29
+ A hard line ceiling backs this up: **500 lines per assistant asset file**, for
30
+ every `.qfai/assistant/**/*.{md,yml,yaml}` file, counted as
31
+ `content.split(/\r?\n/).length` — blank lines included. `npx qfai doctor`
32
+ measures it and reports every file over the ceiling as `assets.lineBudget`. The
33
+ ceiling is a backstop, not the rule: a file approaching it is a signal to move a
34
+ section out, not to raise the number.
35
+
36
+ One shipped file is exempt, and only because it is a roster rather than prose:
37
+ `assistant/manifest/agent-catalog.yml` holds one entry per agent, mirroring
38
+ `assistant/agents/<id>.md`, so its length tracks the number of agents — whether
39
+ shipped or adjusted through `qfai-configure` — and splitting it would mean
40
+ splitting the roster itself. `npx qfai doctor` names it under `exempt` with that
41
+ reason. No prose asset has an exemption.
31
42
 
32
43
  ## User Questions (AskUserQuestion Protocol)
33
44
 
@@ -116,7 +127,7 @@ Rules:
116
127
 
117
128
  When validate, doctor, test, lint, typecheck, build, capture, or report gates fail — **or when a blocking reviewer returns `REVISE`** (the in-flight verdict; `status: "FAIL"` is only what a review pack's `summary.json` serializes — see `shared-skill-delegation-baseline.md#verdict-vocabulary`):
118
129
 
119
- - inspect exit code, logs, `validate.json`, and cited files before reporting;
130
+ - inspect exit code, logs, `validate.json`, and cited files before reporting — in `validate.json`, read `counts` for the verdict and `issues[].code` for each finding; the array is `issues`, not `findings` (keys: `.qfai/assistant/skills/qfai-verify/references/validate-json-schema.md`);
120
131
  - classify each finding as skill-owned artifact, upstream spec/contract, code/test defect, environment/tooling, or user decision;
121
132
  - fix skill-owned artifacts and code/test defects autonomously when the fix is local and non-destructive;
122
133
  - **upstream spec/contract findings: never repair.** STOP and follow `.qfai/assistant/constitution/drift-protocol.md` (Change Request + owner-skill rerun) — **even when the fix looks local and non-destructive, and even when it is one token and obviously correct**. "Local and non-destructive" is a permission for the two classes above it; it is not a test that upstream artifacts can pass. Ownership, not size, decides;
@@ -125,7 +136,7 @@ When validate, doctor, test, lint, typecheck, build, capture, or report gates fa
125
136
  - rerun the same failing gate after each fix batch, **and once with no intervening change** when the failure looks nondeterministic — see `#nondeterministic-gates` below. The confirmation rerun is bounded at one: after it the finding is classified, not re-rolled;
126
137
  - do not weaken profiles, lower `--fail-on`, waive errors, invent evidence, or skip required reviewers;
127
138
  - stop for destructive changes, **any upstream spec/contract finding**, ambiguous product/spec decisions, missing permissions/tools, or repeated no-progress failures — the stop list is closed over the classification above, so every class the agent is told to use has a defined next action;
128
- - stop on **round count** as well as on lack of progress: a reviewer gate that would enter its third round escalates to the user, even when every round has made progress. See `shared-skill-delegation-baseline.md#round-budget-must`.
139
+ - stop on **round count** as well as on lack of progress: a reviewer gate that would enter its third round escalates to the user, even when every round has made progress. See `review-convergence.md#round-budget-must`.
129
140
 
130
141
  When stopping, report: cause, attempted fixes, remaining blocker, user action, retry gate, and **the work counts — how many items are complete, how many are blocked, and by which finding**.
131
142
 
@@ -175,5 +186,48 @@ Before declaring completion, you MUST:
175
186
 
176
187
  - resolve or explicitly defer undefined or ambiguous items with rationale;
177
188
  - verify every expected artifact exists and required sections are populated;
178
- - scan generated artifacts for unresolved placeholders such as `TBD`, `TODO`, `TBA`, `TBC`, `XXX`, `???`, `OQ`, `OPEN QUESTION`, `UNDEFINED`, and `PLACEHOLDER`;
189
+ - scan generated artifacts for unresolved placeholders — `TODO`, `TBA`, `TBC`, `XXX`, `???`, `UNDEFINED`, `PLACEHOLDER`, and **undocumented** `TBD` — under the two rules below;
179
190
  - run the smallest applicable smoke check, or state "not applicable" with a short rationale.
191
+
192
+ ### What the placeholder scan does not flag
193
+
194
+ **`OQ` and `OPEN QUESTION` are exempt only as tracking structure.** Exempt: an
195
+ Open Questions register row carrying its tracking fields — ID, owner, status,
196
+ due — and the `Open Questions` heading, `OQ-ID` table header and empty-state row
197
+ that the required `Open-questions.md` files ship with while recording zero open
198
+ questions. Article II and `workflow.md` both end an unverifiable fact by
199
+ recording an Open Question, so the tracked record they prescribe must never be
200
+ reported as an unresolved placeholder. Everywhere else the two strings are still
201
+ scanned: a bare `OQ` or `OPEN QUESTION` left as a value in generated spec prose
202
+ or a contract field, or a row missing its owner, status or due date, is a hit
203
+ like any other token.
204
+
205
+ **A documented `TBD` is a compliant record.** `constitution.md` Article II and
206
+ `thinking.md` require writing `TBD` together with a note of what evidence is
207
+ missing, and `thinking.md` requires raising the matching Open Question for the
208
+ same fact. Both halves together are the finished form, not an unfinished one; do
209
+ not report it and do not delete it — deleting it destroys the record of the
210
+ missing evidence, which is the whole point of the marker. A `TBD` missing either
211
+ half — no note, or no Open Question — is a hit.
212
+
213
+ ### What a surviving hit obligates
214
+
215
+ A hit is **reported, not silently cleared**, and **cleared by a re-scan, not by
216
+ assertion**. Fix what you can, then run the scan again over the same artifacts:
217
+ _resolved_ is the verdict for a hit the re-run no longer reports, and that re-run
218
+ is its evidence. It is not available for a hit still present at that file and
219
+ line — a token still readable there is unresolved whatever the report calls it.
220
+ List every hit the re-scan still finds alongside the completion claim — file,
221
+ line, token — and state for each one whether it is deferred with rationale or
222
+ recorded as an Open Question. A completion claim that omits a surviving hit is
223
+ invalid evidence under the rules above. Completion is blocked while a surviving
224
+ hit is neither of the two.
225
+
226
+ **Severity floor on the verdict.** _Deferred with rationale_ and _recorded as an
227
+ Open Question_ are NOT available for a hit that stands in for a concrete
228
+ security defect, data loss or corruption, or a correctness defect that would
229
+ break a released contract. Such a hit is cleared only by a named fix or by
230
+ dropping the item from scope; recording it and declaring completion anyway is
231
+ prohibited, exactly as `shared-skill-delegation-baseline.md` withholds that same
232
+ exit for that same class. While neither of the two remaining verdicts applies,
233
+ completion stays blocked.