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
@@ -13,7 +13,12 @@ Upstream artifacts include, at minimum:
13
13
  - `10_Plan.md` and other owner-phase planning outputs
14
14
  - Legacy spec-pack SSOT files when present: `spec.md`, `delta.md`, `plan.md`, `traceability-matrix.md`, `scenario.feature`, `case-catalogue.md`, and numbered pack files (for example `01_Spec.md`..`18_delta.md`)
15
15
  - contracts and schema decisions owned by earlier phases
16
- - outputs of discussion/sdd/review stages
16
+ - outputs of the sdd and review stages. A **discussion pack is NOT upstream
17
+ SSOT** — it is non-normative discovery material, and `.qfai/specs/**` is the
18
+ behaviour and design SSOT it feeds. A defect found in one downstream is fixed
19
+ in the SDD-owned artifact, the discrepancy recorded in delta/evidence. This
20
+ reclassifies ONLY the pack: genuine upstream is still repaired upstream-first.
21
+
17
22
  - **test or production artifacts another spec's completed implement run
18
23
  certifies** — a file named in another `tdd/test-list.md`'s `Test file` column
19
24
  on a `done` row. Changing one is not forbidden (the codebase is not
@@ -25,8 +30,9 @@ Upstream artifacts include, at minimum:
25
30
 
26
31
  One file inside `.qfai/specs/**` is carved out of that last line:
27
32
  `<spec-id>/tdd/test-list.md`, and only its `Status` / `DR-ID` / `Evidence`
28
- cells. See `#allowed-exceptions-minimal-whitelist`. Its **rows** — which obligations exist and
29
- what each covers — remain upstream.
33
+ cells unconditionally, plus its `Test file` and `Selector` cells under the two
34
+ machine-checkable conditions in `#allowed-exceptions-minimal-whitelist`. Its
35
+ **rows** — which obligations exist and what each covers — remain upstream.
30
36
 
31
37
  **Every artifact in this list requires an owner rerun by definition.** There is
32
38
  no downstream test for "is an owner rerun required here?" — being on this list
@@ -40,10 +46,24 @@ case required reading the agent roster and reasoning backwards from it.
40
46
 
41
47
  - `.qfai/evidence/**` append/update
42
48
  - `.qfai/specs/<spec-id>/tdd/test-list.md` — the `Status`, `DR-ID` and
43
- `Evidence` cells only, append/update by `/qfai-implement`. Every other column
44
- of that file, and every other file under `.qfai/specs/**`, stays upstream
45
- SSOT: adding, removing or re-scoping a row is an upstream change and takes the
49
+ `Evidence` cells unconditionally, append/update by `/qfai-implement`, plus two
50
+ cells that are writable **only** while a stated condition holds:
51
+ - the `Test file` cell, only while the seeded value is empty or a dash
52
+ placeholder;
53
+ - the `Selector` cell, only while the seeded value does not resolve against
54
+ the row's named test file — the validator's own `selectorResolves`
55
+ predicate is false.
56
+
57
+ Both conditions are machine-checkable, so a reviewer verifies the precondition
58
+ instead of taking the writing stage's word for it, and both are one-way: once
59
+ the condition that authorised the write has ceased to hold — a `Test file` that
60
+ names a path, a `Selector` that resolves — rewriting it is no longer covered.
61
+ Every other
62
+ column of that file — `TC-Refs`, `Layer`, `US-Refs`, `CON-API-Refs` — and
63
+ every other file under `.qfai/specs/**`, stays upstream SSOT: adding, removing
64
+ or re-scoping a row is an upstream change and takes the
46
65
  `#when-drift-is-detected` path.
66
+
47
67
  - **creating** a governance record under `.qfai/decisions/` — a Change Request
48
68
  (`CR-YYYYMMDD-NNNN-<slug>.md`, per `#when-drift-is-detected` step 2) or an
49
69
  anomaly Decision Record (`DR-<id>-<slug>.md`, where `<id>` follows the
@@ -56,7 +76,7 @@ Any exception beyond this list requires explicit user approval.
56
76
  `/qfai-implement` must write `tdd/test-list.md` after every phase transition,
57
77
  and the file lives inside `.qfai/specs/**`. The protocol never classified it in
58
78
  either direction, but `#core-rule`'s list is explicitly open-ended ("at minimum")
59
- and sweeps in "outputs of discussion/sdd/review stages" — and the ledger's schema
79
+ and sweeps in "outputs of the sdd and review stages" — and the ledger's schema
60
80
  is documented in `skills/qfai-sdd/references/spec-traceability-rules.md`, an
61
81
  SDD-stage reference. On the natural reading the ledger _is_ an sdd-stage output,
62
82
  so "Downstream skills must not patch upstream SSOT directly" applied to it.
@@ -81,6 +101,46 @@ So an agent obeying the protocol could not satisfy gate item 10, and an agent
81
101
  satisfying it was in drift. The entry above names the file and the three cells
82
102
  unconditionally, which is what removes the choice.
83
103
 
104
+ ### Why `Test file` and `Selector` are conditional
105
+
106
+ The deadlock that put the ledger on this list recurs one and two columns over,
107
+ and two shipped validator rules are what create it:
108
+
109
+ - `TDDLIST_TEST_FILE_MISSING` fires at **error** severity for a row whose
110
+ `Test file` cell is empty or a dash placeholder, once its `Status` is `green`,
111
+ `refactor`, `review-fix` or `done`.
112
+ - `TDDLIST_SELECTOR_UNRESOLVED` fires when the `Selector` cell's text is not
113
+ found in the named test file, and its own remediation text says to update the
114
+ selector. The per-row checkpoint command is `<runner> <Test file> -t
115
+ '<Selector>'`, so an unresolved selector also produces a run that selects
116
+ nothing while exiting 0.
117
+
118
+ A row is seeded with a descriptive selector and, commonly, no test file: the
119
+ path is a downstream decision, and the test's title does not exist until the
120
+ micro-cycle authors it. So the writing stage cannot hold the status the first
121
+ three cells **do** authorise without also writing a cell they do **not** — and
122
+ the earlier status it would otherwise have to keep is false, because the row has
123
+ already passed that phase. Seeding both cells upstream does not resolve it
124
+ either: it would require inventing titles that implementers then match exactly,
125
+ inverting the direction of authority between the spec and the test.
126
+
127
+ The conditions are what keep this narrow. They authorise **filling a placeholder
128
+ and repairing an unresolvable selector**, never rewriting a cell that already
129
+ resolves, and never touching the columns that carry the row's obligation
130
+ identity. Decomposing an existing obligation across rows stays in remit for the
131
+ executing stage; minting a new obligation id does not, and that line is
132
+ unchanged.
133
+
134
+ One limit is worth stating, because the `Selector` condition is narrower than it
135
+ reads. `selectorResolves` is deliberately lenient: it accepts verbatim
136
+ containment, then containment of the selector's last identifier-shaped token. So
137
+ a `Selector` that is materially wrong — one that misdescribes which obligations
138
+ its row covers — but happens to share a trailing token with its test file still
139
+ **resolves**, the condition is false, and this carve-out does **not** authorise
140
+ repairing it. That is the conservative direction and it is intended: only a
141
+ selector the runner's own file could not match is repairable here, and a merely
142
+ misdescribing one stays an upstream change.
143
+
84
144
  ### Why the Decision Record is on this list
85
145
 
86
146
  A downstream stage cannot always avoid needing one. `qfai-implement` Phase Red
@@ -277,17 +337,36 @@ is a defect.
277
337
  - Every reviewer finding declares a `Traces to:` value. See
278
338
  `shared-skill-delegation-baseline.md#finding-provenance-must` for the response schema. Legal
279
339
  values:
280
- - an upstream obligation (`AC-*`, `BR-*`, `TC-*`, `CON-*`) or a named constitution/catalog rule;
340
+ - an upstream obligation (`AC-*`, `BR-*`, `TC-*`, `CON-*`) or a named constitution/catalog rule
341
+ **that governs the product's behaviour**;
281
342
  - `defect:correctness`, `defect:security`, or `defect:code-quality` — the deliverable-defect
282
343
  classes above, each of which MUST carry the concrete evidence in the changed artifacts that
283
344
  demonstrates it;
345
+ - `record:<CODE>` — a defect in the run's own record rather than in the product;
284
346
  - `none` — reviewer-originated scope.
285
- - The first two are **blocking** and gate `done`.
347
+ - The first two are **blocking** and gate `done`. `record:*` and `none` are not.
348
+ - `Traces to: record:<CODE>` is a record defect: the ledger, a round block, an evidence anchor or
349
+ the provenance prose is wrong while the product is not. It MUST be recorded as `advisory`, MUST
350
+ NOT be `blocking`, and settles in the spec's record-defect queue (`#the-record-defect-queue`)
351
+ rather than by re-running the row. `record:unchecked` is a bug report against `validateTddList`,
352
+ not against the item — a record rule worth a round is worth a validator code.
353
+ - **A record that misrepresents the run is not a record defect.** Evidence copied from a previous
354
+ round or a sibling row, an evidence anchor resolving to a run other than the one it names, and a
355
+ false `Authored/edited under review` attestation do not merely mis-state the work — they claim
356
+ work that was not done, or independence the reviewer did not have. `agents/qa-gatekeeper.md`
357
+ rejects the first two outright and
358
+ `shared-skill-delegation-baseline.md#reviewer-response-template` forbids a `PASS` on the third,
359
+ so classifying them `record:*` would let an advisory-only review return `PASS` and release
360
+ `done` over the very evidence the gate exists to reject. They stay **blocking** as
361
+ `defect:code-quality` and MUST NOT be filed as `record:*`. `record:*` covers a record that is
362
+ honestly produced and merely wrong — a tier missing from an Evidence cell, a `Satisfied-by`
363
+ naming the wrong sibling row, an unlabelled round block.
286
364
  - `Traces to: none` is reviewer-originated scope. It is **drift**, and it is **not satisfiable
287
365
  downstream**: encoding it as production code plus a hard test assertion is the same violation as
288
366
  patching upstream SSOT, inverted. It MUST be recorded as `advisory`, MUST NOT be `blocking`, and
289
367
  is routed to the Change Request / Open Question path — never to the implementer.
290
- - Routing an advisory finding:
368
+ - Routing a `none` advisory (a `record:*` advisory takes `#the-record-defect-queue` instead — the
369
+ Change Request path adjudicates product obligations and cannot repair a record):
291
370
  1. The reviewer records it in its response under `Advisory / Change Request proposals`, with
292
371
  enough context for the owner phase to adjudicate. The reviewer does **not** write it into
293
372
  `08_Open-questions.md`: that file is upstream SSOT (see `#core-rule`) and is owned by
@@ -308,10 +387,94 @@ is a defect.
308
387
  Completing against an obligation that is known to be under revision would ship a knowingly
309
388
  inconsistent SSOT.
310
389
 
390
+ ### The record-defect queue
391
+
392
+ Making `record:*` advisory removes the round it used to force. It does not remove the defect, so
393
+ the class is only honest if the defect lands somewhere with an owner and is consumed. That place is
394
+ one queue per spec, and it is defined by a destination, an owner, an entry shape and a drain.
395
+
396
+ - **Where.** A `## Record defects` section in the evidence file the reviewing stage's **own
397
+ completion contract** names. For a `/qfai-implement` review that is
398
+ `.qfai/evidence/implement-<spec-id>.md` when that file exists, otherwise
399
+ `.qfai/evidence/atdd-<spec-id>.md` — the same file rule the spec-level checkpoint boundary uses,
400
+ so a spec never has this queue in two places. **Do not derive the path from a
401
+ `<stage>-<spec-id>.md` pattern.** Each stage names its own evidence file and not every one of
402
+ them is spec-scoped — `/qfai-configure` writes `.qfai/evidence/configure-<run-id>.md`, one per
403
+ run, and has no `configure-<spec-id>.md` at all — so the pattern named files no stage creates.
404
+ Never `08_Open-questions.md`: that file is upstream SSOT owned by `/qfai-sdd` (see
405
+ `#core-rule`), and a record defect is not a product obligation.
406
+ - **The class needs a drain, so a stage whose completion contract has none does not use it.** Every
407
+ stage sharing `shared-skill-delegation-baseline.md` reads the provenance rules, but an entry is
408
+ only worth filing where something consumes it, and the queue above is defined as much by the
409
+ drain as by the destination. The test is textual and local: **that stage's own completion
410
+ conditions must require this queue drained before it declares completion.** `/qfai-implement`
411
+ states it (`skills/qfai-implement/SKILL.md#spec-completion-conditions`), and no other stage's
412
+ completion conditions mention the queue at all — so `/qfai-sdd`, `/qfai-atdd`, `/qfai-configure`,
413
+ `/qfai-verify`, `/qfai-discussion` and `/web-research` reviewers MUST NOT classify a finding
414
+ `record:*`; it keeps the class it would have had, blocking under the rule it names. A stage gains
415
+ the class by adding the drain to its completion conditions, never by being named here. A class
416
+ whose entries are written where nothing drains them is the round-dropped-and-defect-dropped
417
+ outcome this queue exists to prevent, and it is worse in the stages that never gained the queue
418
+ than the round ever was.
419
+ - **Who.** The reviewer records the finding in its response as an advisory, as for any advisory.
420
+ The **orchestrator** that dispatched the review appends it to the queue when the round closes —
421
+ the same role that owns the ledger. A finding that stays in the reviewer response and never
422
+ reaches the queue is an unrouted advisory, which the review gate already forbids.
423
+ - **Entry.** One line per defect: the `<CODE>`, the row or artifact it is against, what the record
424
+ says against what the run actually did, and the round it came from. That is what makes it
425
+ repairable later by someone who did not watch the round.
426
+ - **Drain, at the spec boundary.** Before spec-level completion is declared, every open entry is
427
+ **repaired in place**: the record is corrected to what the run did, with no row re-run and no
428
+ status change. Repair is the only close. When the rule the entry names is one no validator
429
+ checks, the entry **also** produces a validator bug report per the `record:unchecked` ratchet
430
+ above — that report tracks the missing check and does not stand in for the repair. Closing an
431
+ entry on the report alone leaves the wrong record exactly as wrong as it was, with the round
432
+ that found it already spent: a missing tier stays missing, and the item stays complete. The two
433
+ are different obligations against different backlogs. Completion is not declared while an entry
434
+ is open. This gates the **spec** boundary only: a `record:*` finding still never holds an
435
+ individual row out of `done`, which is the whole point of the class.
436
+ - **When the record cannot be repaired honestly.** Repair means writing what the run actually did,
437
+ which needs the round's artifacts to still say what that was. Where they do not — nothing
438
+ reconciles the entry with any run — the finding was never a record defect: what is missing is
439
+ not a correct record of the work but any evidence the work happened, which is the integrity case
440
+ above. Reclassify it as `defect:code-quality`, blocking, and take the ordinary REVISE path.
441
+ There is no third exit: an entry closes on a corrected record or on a blocking finding.
442
+ - **Re-attest a repair in a pack of its own; never re-run it, and never edit a sealed one.** A
443
+ defect inside a `Satisfied-by`, a round block or any other phase-authored field sits inside the
444
+ exact bytes a reviewer's `Audited evidence hash` covers, and the completion gate recomputes that
445
+ hash — so repairing in place makes a correct PASS read as stale, and skipping the recomputation
446
+ would accept evidence nobody read. Repair the record, then have a reviewer **of the role that
447
+ issued the verdict** re-read the repaired entry and emit a **record re-attestation**: the
448
+ `TDD-ID`, the same `Reviewed revision`, the same `Result`, a recomputed `Audited evidence hash`,
449
+ and the queue entry's `<CODE>`.
450
+ - **The re-attestation is a new review pack, and the pack it supersedes is left untouched.** A
451
+ verdict lives in a `review-<timestamp>/` pack fixed by a `Review pack seal` the completion gate
452
+ recomputes, so replacing that verdict's `Audited evidence hash` line where it is stored breaks
453
+ the seal by construction, and replacing only the evidence file's copy leaves the sealed reviewer
454
+ response carrying a hash nothing agrees with. Write the re-attestation as its own
455
+ `review-<timestamp>/` pack, sealed by the same procedure. The superseded verdict keeps the hash
456
+ it recorded — it was correct over the bytes it read — and its pack keeps recomputing. The
457
+ evidence entry records `Record re-attestation` beside the verdict it supersedes, with its own
458
+ `Record re-attestation pack` and `Record re-attestation pack seal`; the completion gate
459
+ recomputes the superseding hash and both seals, which is what makes the re-attestation an
460
+ artifact a validator can see rather than an untraceable edit. No code runs, no row changes
461
+ status, and it spends no round — it opens none, so it is not a `Round N:` pack. The revision a
462
+ verdict names excludes `.qfai/evidence/**`, so by construction nothing outside the record moved.
463
+ **A repair that would move the revision is not a record repair**: it is a change to the
464
+ deliverable and takes the ordinary path. A repaired entry whose verdict carries no
465
+ re-attestation is still an open entry.
466
+
467
+ An unconsumed queue would make the class worse than what it replaced: the round is gone and the
468
+ defect is gone with it. The drain is what pays for dropping the round.
469
+
311
470
  ### Which evidence is committed
312
471
 
313
- - **Regenerable** — stage evidence (`.qfai/evidence/<stage>-<spec-id>.md`),
314
- run logs, reports. Reproducible by rerunning the owner skill; not committed.
472
+ - **Durable per-item TDD evidence** — `.qfai/evidence/implement-<spec-id>.md`
473
+ and `.qfai/evidence/atdd-<spec-id>.md`. Ledger `Evidence` cells point to
474
+ anchors in these files, and validation resolves those anchors on a fresh
475
+ clone, so the managed `.gitignore` block re-includes and commits them.
476
+ - **Regenerable** — other stage logs, run logs, and reports. Reproducible by
477
+ rerunning the owner skill; not committed.
315
478
  - **Governance record** — Change Requests (`.qfai/decisions/CR-*.md`) and
316
479
  durable decision records (`.qfai/evidence/decisions/*.json`). They carry
317
480
  user approval and cannot be regenerated, so they are committed. The managed
@@ -325,8 +488,8 @@ is a defect.
325
488
  — diffs the branch against `baseBranch` and emits `QFAI-DRIFT-001` (`error`)
326
489
  for every changed file under `paths.contractsDir`, under `_policies/`, or
327
490
  matching a protected spec-pack filename. A Change Request at `Status:
328
- approved` that **names the changed path** silences it; an `open` CR does not,
329
- because an open CR authorises nothing. The check does not run in the `sdd`
491
+ approved` whose **`## Impact scope` names the changed path** silences it — not
492
+ a path named elsewhere in it, not a contract ID, and never an `open` CR. The check does not run in the `sdd`
330
493
  profile: `/qfai-sdd` owns these files.
331
494
  - Downstream reviewers must not originate binding obligations that upstream SSOT does not contain.
332
495
  - If approval is not available, stay in STOP state **for that CR's blocked set**
@@ -0,0 +1,121 @@
1
+ # Review Convergence
2
+
3
+ How a review round ends, and what may follow it. Referenced from
4
+ `shared-skill-delegation-baseline.md#round-budget-and-convergence-must`,
5
+ which owns the delegation rules these sit beside.
6
+
7
+ ### Round budget (MUST)
8
+
9
+ - **Two rounds per reviewer per artifact.** Round 1 is the initial review;
10
+ round 2 reviews the fixes. **The budget is spent the moment round 2 returns
11
+ `REVISE`**: the orchestrator MUST NOT start a third review, and MUST stop and
12
+ escalate to the user with the open findings, the fixes already applied, and a
13
+ recommendation. The decision point is round 2's verdict, never a prediction
14
+ about a review that must not run.
15
+ - Escalation is not failure. The artifact stays at its current status and the
16
+ user decides: accept with the finding recorded as an Open Question, apply a
17
+ named fix, or drop the item from scope.
18
+ - **Completion after escalation.** The user's decision is the exception to
19
+ "no DONE until all blocking reviewers `PASS`", so the escalation has an exit:
20
+ - _Accept as Open Question_ or _drop from scope_ — the artifact may reach
21
+ DONE with the finding recorded; the reviewer's outstanding `REVISE` is
22
+ superseded by the recorded user decision. Cite the decision where the
23
+ stage records decisions (`*_delta.md` / `07_Decisions.md` / a Change
24
+ Request).
25
+ - _Apply a named fix_ — one **verification review** of exactly that fix is
26
+ permitted and does not consume budget (it is round 2b, not round 3). Its
27
+ remit is the named fix only. It may not raise findings unrelated to that
28
+ fix, but a defect the fix **introduced or exposed** is in remit and MUST be
29
+ reported rather than passed over: verifying only the named lines and
30
+ returning `PASS` while a regression sits next to them is a false `PASS`.
31
+ Such a finding escalates immediately (see the severity floor below) and
32
+ still does not start a round 3. The review returns `PASS` or escalates
33
+ again.
34
+ - **One 2b per artifact, total.** The verification review is free of budget,
35
+ not unbounded: a second escalation on the same artifact MUST NOT be
36
+ answered with another _apply a named fix_ + 2b cycle. Without this cap the
37
+ two rules compose into a loop — 2b costs nothing, and escalating again is
38
+ always allowed — so the gate has no guaranteed end. At the second
39
+ escalation the user is offered only _accept as Open Question_ or _drop the
40
+ item from scope_. The severity floor below then withholds _accept as Open
41
+ Question_ for its classes, so for those findings the intersection of the
42
+ two rules leaves _drop the item from scope_ alone — which is the state
43
+ **Corrective review** below exists to give an exit.
44
+ - **Severity floor on the exit.** _Accept as Open Question_ is NOT available
45
+ for a finding that names a concrete security defect, data loss or
46
+ corruption, or a correctness defect that would break a released contract.
47
+ Present the user only _apply a named fix_ or _drop the item from scope_ for
48
+ those, and say why the third option is withheld. Without this the general
49
+ exit is a route around "deferring such a finding to an Open Question so a
50
+ `PASS` can be returned is prohibited" — one that needs no lateness and no
51
+ reviewer consent, only a user click.
52
+ - **Corrective review (the one exit the floor leaves open).** The two rules
53
+ above compose into a dead end, and it is reachable: a Round 2b that
54
+ correctly reports a defect the named fix INTRODUCED or EXPOSED escalates a
55
+ second time, at which point the 2b cap withholds _apply a named fix_ and
56
+ the severity floor withholds _accept as Open Question_ — so for a security,
57
+ data-loss or released-contract-correctness finding the only remaining
58
+ option is _drop the item from scope_. Fixing the defect and keeping the
59
+ requirement has no path: the fix cannot be verified, and the artifact
60
+ stays at `REVISE` forever. Round 2b doing its job is what puts the stage
61
+ there.
62
+
63
+ When that state is reached AND the user chooses to fix rather than drop,
64
+ the stage MAY open **one corrective review artifact**. It is not a third
65
+ round and not a budget reset; it is a separate artifact with a remit
66
+ narrower than any round, and it is bounded so that the two rules above
67
+ cannot compose through it either.
68
+
69
+ Required before the review runs — all of it, in the stage's evidence:
70
+ 1. the originating artifact, and the Round 2b finding verbatim;
71
+ 2. the user's decision, recorded where the stage records decisions
72
+ (`*_delta.md` / `07_Decisions.md` / a Change Request);
73
+ 3. what was changed to fix it;
74
+ 4. the before and after revision of every artifact the fix touched, as
75
+ digests a reader can re-derive rather than as a round name.
76
+
77
+ Constraints on the review itself:
78
+ - **Remit is the finding and the named fix, nothing else.** Narrower than a
79
+ round: a corrective reviewer may not re-open the artifact generally. An
80
+ unrelated finding goes to the owning stage's delta or a Change Request
81
+ under the convergence rules, and does NOT extend this review.
82
+ - **One independent review, once.** Recorded as `Round: corrective` — not
83
+ `2c`, and not a numbered round, because a number invites a successor.
84
+ - **`PASS` supersedes the Round 2b finding** on the originating artifact
85
+ and returns the stage to the review gates it had not yet reached. It does
86
+ not retro-`PASS` anything else.
87
+ - **`REVISE` is terminal.** The stage stops with the finding recorded. No
88
+ second corrective artifact, no further review, and no route back to
89
+ _apply a named fix_. This is the guaranteed end the 2b cap exists to
90
+ provide, moved one step later rather than removed.
91
+ - **The floor and the Open Question prohibition are unchanged.** A
92
+ corrective review cannot return `PASS` over a live security, data-loss or
93
+ released-contract defect, and the finding cannot be deferred to an Open
94
+ Question at any point in this path.
95
+ - **A discussion pack is not an input to this.** It is non-normative
96
+ reference material, so a corrective review neither repairs one nor treats
97
+ one as the upstream to fix.
98
+
99
+ - The round number MUST be recorded on each reviewer response
100
+ (`Round:` in the shared response template).
101
+
102
+ ### Convergence (MUST)
103
+
104
+ - A finding first raised in round N > 1 MUST state why it was not raisable in
105
+ round N-1 — the fix introduced it, or the fix exposed it. A finding that was
106
+ raisable in round 1 and was not raised is **out of budget**: record it as an
107
+ Open Question or a `*_delta.md` Decision Record for the owning stage, do not
108
+ block on it.
109
+ - A reviewer MUST NOT open a new blocking _class_ of finding after the artifact
110
+ under review has been declared stable. New classes go to the owning stage.
111
+ - **Severity overrides lateness.** The out-of-budget rule is about review
112
+ discipline, not about shipping known harm. A late finding that names a
113
+ concrete security defect, data loss or corruption, or a correctness defect
114
+ that would break a released contract is **not** deferrable: the orchestrator
115
+ stops and escalates to the user immediately, exactly as it does when the
116
+ round budget is spent. It is still not a third round — no further review is
117
+ started, the finding goes straight to the user with its evidence. Deferring
118
+ such a finding to an Open Question so a `PASS` can be returned is prohibited.
119
+ That prohibition does not depend on lateness or on who proposes the deferral:
120
+ the escalation exit in the round budget withholds _Accept as Open Question_
121
+ for this same class, so a user choice cannot supersede it either.