qfai 2.1.0 → 2.1.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 (184) hide show
  1. package/README.md +327 -55
  2. package/assets/defaults/agent-routing/qfai-triage.yml +9 -0
  3. package/assets/defaults/workflows/change-tooling.yml +0 -4
  4. package/assets/defaults/workflows/run-owned-cleanup.yml +12 -0
  5. package/assets/init/.claude/settings.json +27 -9
  6. package/assets/init/.codex/hooks.json +20 -8
  7. package/assets/init/.qfai/assistant/agent/frontend-engineer.md +5 -0
  8. package/assets/init/.qfai/assistant/agent/implementation-reviewer.md +14 -1
  9. package/assets/init/.qfai/assistant/agent/product-experience-architect.md +4 -0
  10. package/assets/init/.qfai/assistant/agent/product-surface-reviewer.md +7 -0
  11. package/assets/init/.qfai/assistant/agent/qa-gatekeeper.md +29 -0
  12. package/assets/init/.qfai/assistant/agent/requirements-analyst.md +8 -0
  13. package/assets/init/.qfai/assistant/rule/communication.md +18 -8
  14. package/assets/init/.qfai/assistant/rule/constitution.md +5 -4
  15. package/assets/init/.qfai/assistant/rule/drift-protocol.md +72 -5
  16. package/assets/init/.qfai/assistant/rule/references/asset-authoring.md +72 -0
  17. package/assets/init/.qfai/assistant/rule/references/context-summary.md +30 -0
  18. package/assets/init/.qfai/assistant/rule/references/gate-failure-autorepair.md +42 -0
  19. package/assets/init/.qfai/assistant/rule/references/griller-recommendations.md +23 -0
  20. package/assets/init/.qfai/assistant/rule/references/host-backstops.md +60 -0
  21. package/assets/init/.qfai/assistant/rule/references/placeholder-scan.md +25 -0
  22. package/assets/init/.qfai/assistant/rule/references/reviewer-findings.md +41 -0
  23. package/assets/init/.qfai/assistant/rule/references/reviewer-remit.md +35 -0
  24. package/assets/init/.qfai/assistant/rule/references/worker-edit-boundary.md +48 -0
  25. package/assets/init/.qfai/assistant/rule/shared-skill-delegation-baseline.md +39 -162
  26. package/assets/init/.qfai/assistant/rule/shared-skill-operating-baseline.md +14 -145
  27. package/assets/init/.qfai/assistant/rule/stage-cost.md +1 -1
  28. package/assets/init/.qfai/assistant/rule/test-layers.md +42 -0
  29. package/assets/init/.qfai/assistant/rule/ui-definition-protocol.md +6 -1
  30. package/assets/init/.qfai/assistant/skill/qfai-configure/SKILL.md +11 -45
  31. package/assets/init/.qfai/assistant/skill/qfai-configure/references/principles.md +25 -0
  32. package/assets/init/.qfai/assistant/skill/qfai-discussion/SKILL.md +1 -1
  33. package/assets/init/.qfai/assistant/skill/qfai-discussion/references/discussion-completion-matrix.md +12 -9
  34. package/assets/init/.qfai/assistant/skill/qfai-discussion/references/ui-bearing-playbook.md +2 -4
  35. package/assets/init/.qfai/assistant/skill/qfai-discussion/references/ui_ux/platform_baselines.md +11 -0
  36. package/assets/init/.qfai/assistant/skill/qfai-discussion/references/ui_ux/review_audit_playbook.md +11 -0
  37. package/assets/init/.qfai/assistant/skill/qfai-discussion/references/ui_ux_best_practices.md +13 -42
  38. package/assets/init/.qfai/assistant/skill/qfai-discussion/templates/uiux/00_index.md +0 -16
  39. package/assets/init/.qfai/assistant/skill/qfai-grill/SKILL.md +1 -1
  40. package/assets/init/.qfai/assistant/skill/qfai-grilling/SKILL.md +16 -88
  41. package/assets/init/.qfai/assistant/skill/qfai-grilling/references/delegated-session.md +58 -0
  42. package/assets/init/.qfai/assistant/skill/qfai-grilling/references/session-record.md +42 -0
  43. package/assets/init/.qfai/assistant/skill/qfai-implement/SKILL.md +17 -4
  44. package/assets/init/.qfai/assistant/skill/qfai-implement/references/credential-reuse.md +9 -0
  45. package/assets/init/.qfai/assistant/skill/qfai-implement/references/cross-spec-ownership.md +41 -0
  46. package/assets/init/.qfai/assistant/skill/qfai-implement/references/oracle-strength.md +6 -1
  47. package/assets/init/.qfai/assistant/skill/qfai-implement/references/parallelization-policy.md +9 -1
  48. package/assets/init/.qfai/assistant/skill/qfai-implement/references/red-admissibility.md +47 -1
  49. package/assets/init/.qfai/assistant/skill/qfai-implement/references/ui-affecting.md +4 -3
  50. package/assets/init/.qfai/assistant/skill/qfai-maintain/SKILL.md +4 -4
  51. package/assets/init/.qfai/assistant/skill/qfai-migration-v1-to-v2/SKILL.md +16 -10
  52. package/assets/init/.qfai/assistant/skill/qfai-migration-v1-to-v2/references/migration-guide.md +10 -260
  53. package/assets/init/.qfai/assistant/skill/qfai-migration-v1-to-v2/references/migration-placement.md +273 -0
  54. package/assets/init/.qfai/assistant/skill/qfai-prototyping/SKILL.md +5 -4
  55. package/assets/init/.qfai/assistant/skill/qfai-prototyping/references/design-md-spec.md +14 -5
  56. package/assets/init/.qfai/assistant/skill/qfai-prototyping/references/generator-prompt.md +10 -0
  57. package/assets/init/.qfai/assistant/skill/qfai-prototyping/references/handoff.md +1 -1
  58. package/assets/init/.qfai/assistant/skill/qfai-prototyping/references/iteration-loop.md +3 -4
  59. package/assets/init/.qfai/assistant/skill/qfai-prototyping/references/review-payload-schema.md +12 -5
  60. package/assets/init/.qfai/assistant/skill/qfai-prototyping/references/reviewer-prompt.md +33 -4
  61. package/assets/init/.qfai/assistant/skill/qfai-run/SKILL.md +34 -36
  62. package/assets/init/.qfai/assistant/skill/qfai-run/references/evidence-delivery.md +322 -0
  63. package/assets/init/.qfai/assistant/skill/qfai-run/references/extraction.md +67 -24
  64. package/assets/init/.qfai/assistant/skill/qfai-run/references/operator-screens.md +246 -5
  65. package/assets/init/.qfai/assistant/skill/qfai-run/references/plan.md +29 -5
  66. package/assets/init/.qfai/assistant/skill/qfai-run/references/stage-points.md +43 -0
  67. package/assets/init/.qfai/assistant/skill/qfai-sdd/SKILL.md +5 -4
  68. package/assets/init/.qfai/assistant/skill/qfai-sdd/references/concrete-abstract-cycle.md +10 -1
  69. package/assets/init/.qfai/assistant/skill/qfai-sdd/references/contract-artifact-rules.md +22 -9
  70. package/assets/init/.qfai/assistant/skill/qfai-sdd/references/design-anti-patterns.md +41 -6
  71. package/assets/init/.qfai/assistant/skill/qfai-sdd/references/design-md-authoring.md +11 -5
  72. package/assets/init/.qfai/assistant/skill/qfai-sdd/references/design-md-brand-catalog.md +17 -2
  73. package/assets/init/.qfai/assistant/skill/qfai-sdd/references/requirements-decomposition.md +10 -2
  74. package/assets/init/.qfai/assistant/skill/qfai-sdd/references/sdd-execution-playbook.md +34 -9
  75. package/assets/init/.qfai/assistant/skill/qfai-sdd/references/sdd-phase-checklists.md +4 -4
  76. package/assets/init/.qfai/assistant/skill/qfai-sdd/references/sdd-quality-gate.md +2 -2
  77. package/assets/init/.qfai/assistant/skill/qfai-sdd/references/sdd-triage.md +177 -7
  78. package/assets/init/.qfai/assistant/skill/qfai-sdd/references/spec-traceability-rules.md +29 -5
  79. package/assets/init/.qfai/assistant/skill/qfai-sdd/references/ui-contract-guide.md +130 -1
  80. package/assets/init/.qfai/assistant/skill/qfai-sdd/references/ui-design-contract-normalization.md +4 -30
  81. package/assets/init/.qfai/assistant/skill/qfai-sdd/templates/change-request.md +39 -2
  82. package/assets/init/.qfai/assistant/skill/qfai-sdd/templates/contracts/db-contract.sample.sql +2 -2
  83. package/assets/init/.qfai/assistant/skill/qfai-sdd/templates/contracts/ui-contract.sample.yaml +52 -5
  84. package/assets/init/.qfai/assistant/skill/qfai-sdd/templates/spec/03_contract/cli/cli-NNNN-title.md +2 -2
  85. package/assets/init/.qfai/assistant/skill/qfai-sdd/templates/spec/03_contract/tech.md +1 -1
  86. package/assets/init/.qfai/assistant/skill/qfai-sdd/templates/spec/decisions.md +7 -0
  87. package/assets/init/.qfai/assistant/skill/qfai-triage/SKILL.md +30 -20
  88. package/assets/init/.qfai/assistant/skill/qfai-verify/SKILL.md +6 -5
  89. package/assets/init/.qfai/assistant/skill/qfai-verify/references/context-load.md +9 -6
  90. package/assets/init/.qfai/assistant/skill/qfai-verify/references/verify-output-contract.md +92 -13
  91. package/assets/init/.qfai/assistant/skill/web-research/SKILL.md +37 -31
  92. package/assets/init/.qfai/assistant/skill/web-research/mcp-templates/brave-search/config.toml +2 -4
  93. package/assets/init/.qfai/assistant/skill/web-research/mcp-templates/brave-search/mcp-config.json +9 -5
  94. package/assets/init/.qfai/assistant/skill/web-research/mcp-templates/firecrawl/.mcp.json +1 -2
  95. package/assets/init/.qfai/assistant/skill/web-research/mcp-templates/firecrawl/config.toml +3 -3
  96. package/assets/init/.qfai/assistant/skill/web-research/mcp-templates/firecrawl/mcp-config.json +11 -8
  97. package/assets/init/.qfai/assistant/skill/web-research/mcp-templates/playwright/config.toml +1 -1
  98. package/assets/init/.qfai/assistant/skill/web-research/mcp-templates/playwright/mcp-config.json +7 -3
  99. package/assets/init/.qfai/assistant/step/common-design-md/STEP.md +17 -7
  100. package/assets/init/.qfai/assistant/step/common-gate-run/STEP.md +126 -13
  101. package/assets/init/.qfai/assistant/step/common-review-cycle/STEP.md +3 -2
  102. package/assets/init/.qfai/assistant/step/discussion-pack/STEP.md +1 -0
  103. package/assets/init/.qfai/assistant/step/discussion-research/STEP.md +2 -0
  104. package/assets/init/.qfai/assistant/step/discussion-uiux/STEP.md +12 -4
  105. package/assets/init/.qfai/assistant/step/implement-backport/STEP.md +1 -1
  106. package/assets/init/.qfai/assistant/step/implement-benchmark/STEP.md +7 -4
  107. package/assets/init/.qfai/assistant/step/implement-dep-bump/STEP.md +11 -1
  108. package/assets/init/.qfai/assistant/step/implement-diagnose/STEP.md +2 -0
  109. package/assets/init/.qfai/assistant/step/implement-oracle-parity/STEP.md +2 -2
  110. package/assets/init/.qfai/assistant/step/implement-quarantine/STEP.md +3 -3
  111. package/assets/init/.qfai/assistant/step/implement-refactor/STEP.md +2 -2
  112. package/assets/init/.qfai/assistant/step/implement-regression-fix/STEP.md +4 -3
  113. package/assets/init/.qfai/assistant/step/implement-retire/STEP.md +6 -3
  114. package/assets/init/.qfai/assistant/step/implement-revert/STEP.md +4 -3
  115. package/assets/init/.qfai/assistant/step/implement-scaffold/STEP.md +3 -3
  116. package/assets/init/.qfai/assistant/step/implement-seam/STEP.md +9 -6
  117. package/assets/init/.qfai/assistant/step/implement-stress-harness/STEP.md +1 -1
  118. package/assets/init/.qfai/assistant/step/implement-sweep/STEP.md +4 -3
  119. package/assets/init/.qfai/assistant/step/implement-tdd/STEP.md +42 -6
  120. package/assets/init/.qfai/assistant/step/implement-test-fix/STEP.md +2 -0
  121. package/assets/init/.qfai/assistant/step/implement-tooling/STEP.md +22 -2
  122. package/assets/init/.qfai/assistant/step/maintain-edit/STEP.md +18 -14
  123. package/assets/init/.qfai/assistant/step/prototyping-grill/STEP.md +4 -3
  124. package/assets/init/.qfai/assistant/step/prototyping-loop/STEP.md +4 -0
  125. package/assets/init/.qfai/assistant/step/prototyping-preflight/STEP.md +1 -3
  126. package/assets/init/.qfai/assistant/step/sdd-contract/STEP.md +11 -0
  127. package/assets/init/.qfai/assistant/step/sdd-flow/STEP.md +4 -0
  128. package/assets/init/.qfai/assistant/step/sdd-gate/STEP.md +4 -0
  129. package/assets/init/.qfai/assistant/step/sdd-story/STEP.md +10 -0
  130. package/assets/init/.qfai/assistant/step/sdd-triage/STEP.md +37 -11
  131. package/assets/init/.qfai/assistant/step/triage-answer/STEP.md +5 -4
  132. package/assets/init/.qfai/assistant/step/triage-close/STEP.md +33 -23
  133. package/assets/init/.qfai/assistant/step/triage-cluster/STEP.md +5 -3
  134. package/assets/init/.qfai/assistant/step/triage-decompose/STEP.md +2 -0
  135. package/assets/init/.qfai/assistant/step/triage-dedupe/STEP.md +4 -0
  136. package/assets/init/.qfai/assistant/step/triage-handoff/STEP.md +13 -4
  137. package/assets/init/.qfai/assistant/step/triage-investigate/STEP.md +8 -5
  138. package/assets/init/.qfai/assistant/step/triage-owned-cleanup/STEP.md +86 -0
  139. package/assets/init/.qfai/assistant/step/triage-request-info/STEP.md +2 -0
  140. package/assets/init/.qfai/assistant/step/triage-security-intake/STEP.md +6 -3
  141. package/assets/init/.qfai/assistant/step/verify-change-note/STEP.md +9 -5
  142. package/assets/init/.qfai/assistant/step/verify-commit/STEP.md +39 -6
  143. package/assets/init/.qfai/assistant/step/verify-external/STEP.md +5 -2
  144. package/assets/init/.qfai/assistant/step/verify-qfai-gate/STEP.md +10 -2
  145. package/assets/init/.qfai/assistant/step/verify-release-notes/STEP.md +1 -0
  146. package/assets/init/.qfai/assistant/step/verify-repeat-run/STEP.md +7 -5
  147. package/assets/init/.qfai/assistant/step/verify-repo-gate/STEP.md +136 -28
  148. package/assets/init/.qfai/waivers.yml +1 -1
  149. package/assets/init/root/.agents/rules/ai-readable-markdown.md +98 -0
  150. package/assets/init/root/.agents/rules/api-budget.md +191 -13
  151. package/assets/init/root/.agents/rules/documentation-clarity.md +192 -35
  152. package/assets/init/root/.agents/rules/grilling.md +4 -4
  153. package/assets/init/root/.agents/rules/interface-clarity.md +5 -5
  154. package/assets/init/root/.agents/rules/minimal-implementation.md +11 -3
  155. package/assets/init/root/.agents/rules/reminders.json +27 -14
  156. package/assets/init/root/.agents/rules/session-feedback.md +136 -0
  157. package/assets/init/root/.agents/rules/temporary-files.md +47 -5
  158. package/assets/init/root/.agents/rules/untrusted-content.md +3 -3
  159. package/assets/init/root/.agents/rules/user-questions.md +74 -36
  160. package/assets/init/root/.gitattributes +9 -0
  161. package/assets/init/root/.github/workflows/qfai-docs.yml +44 -12
  162. package/assets/init/root/.github/workflows/qfai-tests.yml +58 -15
  163. package/assets/init/root/.github/workflows/qfai-validate.yml +49 -42
  164. package/assets/init/root/AGENTS.md +23 -21
  165. package/assets/mdschema/story/03_contract/tech.mdschema.yml +7 -3
  166. package/assets/sandbox-templates/default-deny.yaml +9 -5
  167. package/assets/schemas/workflow/extraction.schema.json +85 -5
  168. package/assets/schemas/workflow/plan.schema.json +9 -2
  169. package/assets/scripts/check-mdschema.mjs +172 -5
  170. package/assets/uix-rev/comparison-review.md +1 -1
  171. package/assets/uix-rev/contracts-review.md +1 -2
  172. package/dist/cli/index.cjs +6499 -7688
  173. package/dist/cli/index.cjs.map +1 -1
  174. package/dist/cli/index.mjs +6449 -7641
  175. package/dist/cli/index.mjs.map +1 -1
  176. package/dist/index.cjs +5548 -7823
  177. package/dist/index.cjs.map +1 -1
  178. package/dist/index.d.cts +40 -666
  179. package/dist/index.d.ts +40 -666
  180. package/dist/index.mjs +5397 -7648
  181. package/dist/index.mjs.map +1 -1
  182. package/docs/MIGRATION-2.0.0.md +1 -1
  183. package/package.json +5 -7
  184. package/assets/init/root/CLAUDE.md +0 -45
@@ -18,9 +18,8 @@
18
18
  ```
19
19
 
20
20
  The orchestrator writes the reviewer's payload for each `(UI contract, screen)` pair beside the
21
- per-iteration `review.json` summary, from the first iteration on (schema:
22
- `references/review-payload-schema.md`, aggregation rule:
23
- `references/reviewer-prompt.md`). That holds for a single-contract run as much
21
+ per-iteration `review.json` summary, from the first iteration on (the payload schema and the aggregation rule are
22
+ in the reviewer references the loop step names). That holds for a single-contract run as much
24
23
  as for a multi-contract one.
25
24
 
26
25
  The reviewer operates Playwright live. A screenshot or HTML snapshot is an
@@ -55,7 +54,7 @@ prototype. It is neutral with respect to AI behavior.
55
54
  ## Produced after the loop
56
55
 
57
56
  - `.qfai/prototype/final/index.html` and `.qfai/prototype/final/handoff.json`.
58
- See `handoff.md`.
57
+ The `prototyping-handoff` step defines its fields.
59
58
 
60
59
  ## Brand identity
61
60
 
@@ -7,9 +7,17 @@ and the user reads what it finds before confirming the prototype.
7
7
  The schema is **closed**: any key not listed below is rejected. The
8
8
  orchestrator checks each payload against it before writing it, and asks the
9
9
  reviewer again for one that does not conform before the prototype is put to
10
- the user. A near-miss (extra key, misspelled field, legacy flat key) fails the
10
+ the user. A near-miss (extra key, misspelled field) fails the
11
11
  whole file.
12
12
 
13
+ ## Contents
14
+
15
+ - Path
16
+ - Shape (11 required top-level fields)
17
+ - Field rules
18
+ - Not accepted
19
+ - `sessionStatus` and the retry policy
20
+
13
21
  ## Path
14
22
 
15
23
  ```text
@@ -23,8 +31,8 @@ per-(UI contract × screen) artifact written for a review — no `.html`, no
23
31
  `.png`, no `.interaction.json`.
24
32
 
25
33
  The Reviewer's other result is the per-iteration summary
26
- `iter-NN/review.json` (one per iteration, a different shape — see
27
- `references/reviewer-prompt.md`). It is not a per-screen artifact and
34
+ `iter-NN/review.json` (one per iteration, a different shape, set by
35
+ the reviewer prompt). It is not a per-screen artifact and
28
36
  is never read against this schema.
29
37
 
30
38
  ## Shape (11 required top-level fields)
@@ -91,8 +99,7 @@ These keys belong to the per-iteration summary, **not** to this payload.
91
99
  Writing any of them here breaks the closed schema:
92
100
 
93
101
  `iterIndex`, `reviewerId`, `proseCritique`, `pivotDirective`,
94
- `evidenceRefs`, and the retired flat `timeBudgetSoftWarning` string
95
- (use `softWarnings.timeBudget: boolean`).
102
+ and `evidenceRefs`.
96
103
 
97
104
  ## `sessionStatus` and the retry policy
98
105
 
@@ -18,12 +18,25 @@ put to the user. Explain observable defects and corrective actions in prose. A f
18
18
  score never hides a blocking finding. Do not use numeric AC-pass or
19
19
  transition-pass percentages as a substitute for the qualitative review.
20
20
 
21
+ ## Contents
22
+
23
+ - Inputs
24
+ - Outputs — two files, two schemas
25
+ - Per-iteration summary (`iter-NN/review.json`)
26
+ - The four ordinal UX axes
27
+ - Diagnostic criteria
28
+ - Applying the four axes
29
+ - What blocks
30
+ - Layout anti-pattern matching (`lap-*`)
31
+ - pivotDirective rules
32
+ - Prose critique format (at most 500 English words, or 2500 Japanese/Chinese characters)
33
+
21
34
  ## Inputs
22
35
 
23
36
  - The live prototype URL and declared `screens[]` routes from the UI contract.
24
37
  Open each route in your own Playwright session and exercise its declared
25
38
  primary tasks. Record `sessionStatus` and `retryCount` in the per-screen
26
- payload according to `references/review-payload-schema.md`.
39
+ payload according to the closed per-screen payload schema.
27
40
  - A screenshot or HTML snapshot, only when one was taken. Name any mandatory
28
41
  input you did not receive in a finding.
29
42
  - The layout anti-pattern registry the package ships.
@@ -55,7 +68,7 @@ below and are relative to the project root.
55
68
  per-UI-contract subdirectory is mandatory for every run that declares UI
56
69
  screens, including a run with one contract. Its schema is closed
57
70
  (11 required top-level fields, unknown keys rejected) and lives in
58
- `references/review-payload-schema.md`. Build it from that
71
+ the payload schema reference. Build it from that
59
72
  reference, not from the block below.
60
73
  2. **Per-iteration summary** —
61
74
  `.qfai/prototype/iter-NN/review.json`, one per iteration. Its shape is
@@ -114,7 +127,7 @@ type Review = {
114
127
 
115
128
  Fill `designMdViolations` yourself: one entry per distinct value the
116
129
  prototype uses that root `DESIGN.md` does not declare, in the categories
117
- `generator-prompt.md` lists.
130
+ the generator prompt lists.
118
131
 
119
132
  ## The four ordinal UX axes
120
133
 
@@ -155,7 +168,7 @@ count can support a finding, but cannot replace the live assessment.
155
168
  | 5 | No catalogued anti-pattern is present | `lap-*`, below |
156
169
  | 6 | Conformant, procured, restrained and consistent | below |
157
170
  | 7 | Every declared `primary_task` walks | below |
158
- | 8 | No text on the screen explains the interface | `.agents/rules/interface-clarity.md` |
171
+ | 8 | No text explains the interface, and the text shown is the contract's | `.agents/rules/interface-clarity.md` |
159
172
 
160
173
  Criteria 1 to 4 are the procurement ladder read as questions, so a screen
161
174
  cannot pass by a standard it was not built to.
@@ -201,6 +214,22 @@ Hint text survives only where a need was demonstrated, the control was
201
214
  improved first and the need remained, and it is one sentence at most. Longer
202
215
  means the question needs clarifying or splitting.
203
216
 
217
+ Compare the rendered text with the screen's UI contract in both directions. The
218
+ screen shows its `title`, the group headings of its `structure`, its labels and
219
+ the `supplements` it declares. A text shown that none of them declares is excess,
220
+ and a declared supplement that is not shown is an unmet need. The finding names
221
+ the screen, the task or state, the meaning that is duplicated or the need that is
222
+ unmet, and the text to remove or the control or structure to repair. Apply the
223
+ patterns of the section on copy that adds no meaning, which the loop step names; the
224
+ rest of the design anti-patterns list stays with the direction review.
225
+
226
+ A repair keeps what the task needs: a condition, cost, storage or transmission
227
+ destination, result, recovery step, the consequence of an action that cannot be
228
+ undone, and every label, accessible name, role and state. Moving that into a
229
+ tooltip or a placeholder is not a repair. After a repair, walk the task again at
230
+ the declared narrow and desktop widths, in the normal, empty, error, loading and
231
+ success states the screen has.
232
+
204
233
  The counts are contract-relative. A screen declaring one primary task and
205
234
  carrying forty controls is wrong; the same forty elsewhere may be right. The
206
235
  denominator is in the contract, so no global threshold has to be invented.
@@ -12,15 +12,16 @@ mode: execution-focused
12
12
 
13
13
  ## /qfai-run - Change request entry
14
14
 
15
- [DRIFT-PROTOCOL:MANDATORY]
15
+ [DRIFT-PROTOCOL:REQUIRED]
16
16
 
17
- The user states a change once. This skill reads the request into facts, asks
18
- `npx qfai workflow plan` for the plan they give, and runs its steps in order.
17
+ The CLI plans; this skill follows its steps in order.
19
18
 
20
- - The facts a request is read into: `references/extraction.md`.
21
- - The command, its input and its output: `references/plan.md`.
22
- - What the user sees, and how questions are put: `references/operator-screens.md`.
23
- - Invoke the CLI through the launcher of `.qfai/assistant/rule/shared-skill-operating-baseline.md#canonical-qfai-launcher-mandatory`.
19
+ - Read `references/extraction.md` to extract a request.
20
+ - Plan command and format: `references/plan.md`.
21
+ - Screens and questions: `references/operator-screens.md`.
22
+ - Release, decision and branch points: `references/stage-points.md`.
23
+ - Run preflight before planning, as `.qfai/assistant/rule/shared-skill-operating-baseline.md#canonical-qfai-launcher-mandatory` says.
24
+ If the launcher is missing or preflight fails, read `references/operator-screens.md` for recovery.
24
25
 
25
26
  ## What this skill never does
26
27
 
@@ -44,48 +45,42 @@ value but the three below plans nothing.
44
45
 
45
46
  ## Request kinds
46
47
 
48
+ - For independent targets under one goal, read `references/operator-screens.md`
49
+ before planning or switching during a wait.
47
50
  - A change, a question, a proposal to decide or a report to close is planned.
48
51
  A question plans a route that answers it and changes nothing. Text that is
49
52
  not a request is not planned.
53
+ - A reply with a requested answer or result resumes the same step without a new
54
+ invocation, including failure. An independent new request is planned. Read
55
+ `references/operator-screens.md` for replies.
50
56
  - `stop`: end the work at once and list every open decision as open.
51
57
  - A request naming a stage skill: invoke that skill by name.
52
58
 
53
59
  ## The work
54
60
 
55
61
  1. **Extract.** Read the request into an extraction as
56
- `references/extraction.md` sets out, and pass it to
62
+ `references/extraction.md` sets out, using its definition of acceptance.
63
+ Pass the extraction to
57
64
  `npx qfai workflow plan --in <file>`, or `--in -` on standard input.
58
65
  2. **Candidates.** When `plan` returns `candidates`, put one single-select
59
66
  question, each option saying in the user's words what that route will do,
60
67
  then run `npx qfai workflow plan --route <route>` for the chosen one.
61
- 3. **Scope.** Ask which scope to run, as `references/operator-screens.md` says; run only its stages.
68
+ 3. **Scope.** With two or more scopes, ask which to run as
69
+ `references/operator-screens.md` says, and run only its stages.
70
+ With one scope, no scopes, or a branch destination's plan, ask nothing and
71
+ run every stage.
62
72
  4. **Announce.** Before the first stage, give the goal, the chosen stages in
63
73
  order in plain words, and the files the work may change. Ask nothing. Then run
64
74
  `common-policy-check` once. On a route that changes no file, one that
65
75
  closes, answers or asks, it reads and reports and writes nothing.
66
76
  5. **Run the stages.** Run each stage in plan order, and each of its steps in
67
- order. Write any artifact yourself. Give a part to a sub-agent only to run
68
- independent parts in parallel, or for a review. At each step, handle the
69
- points the plan names for it:
70
- - **Release point.** Before a step `releasePoint` names runs, ask the user
71
- to approve the release; where it is `end`, ask once the last stage's
72
- gates have passed, then rerun them over the approval's `decisions.md`
73
- row. `verify-commit` runs after that, so the commit holds the approval. Nothing after it
74
- runs without the approval, which authorizes no push, merge, tag or publication.
75
- - **Decision point.** At a step `decisionPoints` names, put each critical
76
- decision to the user through the structured question tool before
77
- changing anything that depends on it. A decision is critical when it contradicts a
78
- specification, a contract or a recorded decision, cannot be taken back, or
79
- rests on product intent nothing written states. Take every other decision
80
- yourself, ask nothing, and list it with its reason in the final report.
81
- - **Branch point.** When a step `branchPoints` names reports an outcome
82
- paired with one route, move there; with several, to the one the step
83
- names; with `decision-table`, to the route `plan --in` gives the step's
84
- new extraction. Take the destination's plan with
85
- `npx qfai workflow plan --route <route>` at once: no later step of this
86
- route runs. Any other outcome continues the route. Before the third move
87
- and every one after it, ask the user, naming the destination in plain
88
- words; `stop` ends the work. From a scope that leaves stages out, ask before any move.
77
+ order, as `.qfai/assistant/rule/shared-skill-operating-baseline.md#running-steps-mandatory` says.
78
+ When a step is short or passes without edits, read `references/operator-screens.md`.
79
+ Write artifacts yourself or delegate independent parallel work or review.
80
+ At each step, follow its plan's points in `references/stage-points.md`:
81
+ - **Release point.** Ask the user to approve the release before the step `releasePoint` names.
82
+ - **Decision point.** Put each critical decision at a step `decisionPoints` names to the user.
83
+ - **Branch point.** Move to the destination a step `branchPoints` names, and plan it at once.
89
84
  6. **Review.** After a stage whose `review` is `spec`, `requirements-reviewer`
90
85
  reviews, with `architecture-reviewer` when a contract changed; after one
91
86
  whose `review` is `code`, `implementation-reviewer`.
@@ -102,6 +97,8 @@ value but the three below plans nothing.
102
97
  ## Under a no-question mode
103
98
 
104
99
  Nothing is asked. The plan's narrowest scope, or the first candidate and its narrowest scope, is taken and reported as an assumption.
100
+ An uncovered question-only move to tracked-file repair instead stops that target
101
+ with a report and no tracked open question, as `references/stage-points.md` says.
105
102
  A critical decision or a release point becomes one `open-questions.md` row,
106
103
  the step stops before the change that depends on it, and the report lists the
107
104
  decision as open. A third branch move, or one from a scope that leaves stages out, stops the work.
@@ -123,11 +120,7 @@ Follow `.qfai/assistant/rule/shared-skill-delegation-baseline.md`.
123
120
 
124
121
  ## Work Orders Summary
125
122
 
126
- Where parts ran in parallel, report one row per part given to a sub-agent.
127
-
128
- | Step | Role (sub-agent) | Agent instance | Task title | Input (refs) | Output (refs) | Status (PASS/REVISE/PENDING) |
129
- | ---- | ---------------- | --------------- | ----------------- | ------------- | ------------- | ---------------------------- |
130
- | 1 | `<role>` | `<instance id>` | `<part in words>` | The step file | The result | PASS/REVISE |
123
+ When parts ran in parallel, use the summary in `references/operator-screens.md`.
131
124
 
132
125
  ## Default Autopilot Policy
133
126
 
@@ -144,6 +137,11 @@ Where parts ran in parallel, report one row per part given to a sub-agent.
144
137
 
145
138
  Follow `.qfai/assistant/rule/shared-skill-operating-baseline.md#completion-contract-shared`. **Smallest applicable smoke check** (this skill's override): the gates of the `verify-qfai-gate` and `verify-repo-gate` steps the chosen scope holds; a scope holding none runs no gate, and the report says so. A gate that cannot run is UNRUN, not a pass.
146
139
 
140
+ When the request requires evidence handover before session archive, read
141
+ `references/evidence-delivery.md` and complete its receiving proof first.
142
+ Missing access keeps the handover pending and originals retained. Ordinary
143
+ completion does not require an unsolicited upload.
144
+
147
145
  project_memory:
148
146
 
149
147
  - The user names no stage after the first request.
@@ -0,0 +1,322 @@
1
+ # Evidence delivery
2
+
3
+ ## Contents
4
+
5
+ - When delivery is required
6
+ - Identity and the ignored index
7
+ - Selection and privacy
8
+ - Native preflight
9
+ - Copy and archive
10
+ - Retained storage and receipt
11
+ - Independent receiver
12
+ - Failure and proof limits
13
+
14
+ ## When delivery is required
15
+
16
+ Read this guide when a request requires evidence handover before a session is
17
+ archived. Complete that handover before archiving the session. Ordinary
18
+ completion does not require an unsolicited upload or an extra full verification
19
+ run solely to deliver evidence.
20
+
21
+ Use explicit selected regular files, an ignored human-readable index, standard
22
+ native tools and authorized retained storage. Keep originals until the named
23
+ recipient or receiving role has independently received and checked every
24
+ required item. A storage link or producer self-read is not that receipt.
25
+
26
+ This guide adds no QFAI command, exporter, storage service, machine schema or
27
+ runtime state. It does not change the plan, its gates or existing verdicts.
28
+
29
+ ## Identity and the ignored index
30
+
31
+ Write the index in an ignored location outside the selected payload and keep
32
+ its destination in the stage report or session handoff. Record:
33
+
34
+ - target, scope, repository, branch and full source revision;
35
+ - observed worktree/index state and the fingerprint of the selected input;
36
+ - actual executable and build, command with separated argv, cwd, runtime,
37
+ input and time where observed;
38
+ - each selected relative name, expected byte length and SHA-256 digest;
39
+ - original results, excluded attempts and their original result and exclusion
40
+ reason, review identity, open work, owner and resume condition;
41
+ - sharing authority, exclusions, destination, receiving role and retention.
42
+
43
+ Use native Git observations such as `git rev-parse HEAD`,
44
+ `git status --porcelain=v1 --untracked-files=all` and
45
+ `git rev-parse --git-path index` to record the source and index. Where the index
46
+ exists, record its raw-byte digest too. Recheck the revision, index and selected
47
+ input before producing the archive. A changed revision/index or stale index
48
+ entry stops delivery until the intended source and required inventory are
49
+ established again. A dirty tree is disclosed with the selected-byte snapshot;
50
+ its commit alone cannot identify the actual input or build used by an old run.
51
+
52
+ Keep trusted expected selected sizes/digests, source identity and archive digest
53
+ outside the delivered bundle. Compare the index with those expectations. A
54
+ downloaded index cannot establish its own source or digest authority. Required
55
+ selected-file or independent source/archive identity that is UNKNOWN refuses
56
+ delivery; do not fabricate it from an unverified receipt.
57
+
58
+ Historical executable, build, command or time that was not observed stays
59
+ UNKNOWN. Known evidence may still be preserved, but unknown historical execution
60
+ does not prove verification. Keep old-source PASS separate from current FAIL,
61
+ UNRUN and delegated pending checks. Retain excluded failed attempts without
62
+ changing their result. No delivery completes failed or unrun required
63
+ verification, turns pending CI into PASS or relabels a review for another head.
64
+ Existing `verify.json` fields, scope and statuses stay unchanged.
65
+
66
+ ## Selection and privacy
67
+
68
+ Select only the files needed to resume this target. Do not recursively discover
69
+ scratch, select a directory or copy a whole checkout. Give each required entry
70
+ a canonical relative name with `/` separators, a known expected byte length and
71
+ lowercase SHA-256 digest. Use a new owned staging root; keep the index and
72
+ archive outside it.
73
+
74
+ For portable names and unambiguous native listings, exclude control characters
75
+ and components ending in a dot or space. If a required original uses such a
76
+ name, review and identify a separately named copy before selecting it.
77
+
78
+ Review the selected names and contents, sharing authority and destination before
79
+ upload. Exclude credentials and unapproved private material. Record exclusions
80
+ without exposing withheld values. If a reviewed or redacted copy is needed,
81
+ identify it separately from the retained original and hash the bytes actually
82
+ delivered. Neither hashes nor the preflight detect all secrets, automatically
83
+ redact contents or establish privacy completeness.
84
+
85
+ The preflight below reads only the explicit selection. It refuses unsafe names,
86
+ missing or non-regular entries, linked root/ancestors/leaves, hardlinks,
87
+ duplicate normalized names, case collisions and wrong or changed byte identity.
88
+ It checks observations again during and after reading. These observations are
89
+ not an atomic snapshot or protection against every concurrent adversary.
90
+
91
+ ## Native preflight
92
+
93
+ Save this single block verbatim as an owned temporary `.mjs` file. Run it with
94
+ the installed Node executable and separated argv:
95
+
96
+ `node <saved-preflight.mjs> <absolute-root> <relative-name> <decimal-byte-length> <lowercase-sha256> [more triples]`
97
+
98
+ Use the same block and trusted expected triples for source, staged copy and
99
+ receiver roots. There is no collection/receiver mode and no input from stdin.
100
+ The block changes no file. Exit 0 and `Verified N selected files.` mean only
101
+ that this selection passed these checks. Exit 1 refuses it; neither result
102
+ proves sharing authority, storage access, historical execution or handover.
103
+
104
+ ```js
105
+ import fs from "node:fs";
106
+ import path from "node:path";
107
+ import { createHash } from "node:crypto";
108
+
109
+ function sameIdentity(left, right) {
110
+ return ["dev", "ino", "mode", "nlink", "size", "mtimeNs", "ctimeNs"].every(
111
+ (key) => left[key] === right[key],
112
+ );
113
+ }
114
+
115
+ function sameDirectory(left, right) {
116
+ return ["dev", "ino", "mode"].every((key) => left[key] === right[key]);
117
+ }
118
+
119
+ function main() {
120
+ const [rootArg, ...args] = process.argv.slice(2);
121
+ if (!rootArg || !path.isAbsolute(rootArg) || !args.length || args.length % 3) {
122
+ throw new Error("Use an absolute root and complete name/size/digest triples.");
123
+ }
124
+ const root = path.resolve(rootArg);
125
+ const names = new Set();
126
+ const directories = new Map();
127
+ const entries = [];
128
+
129
+ function directory(name) {
130
+ const stat = fs.lstatSync(name, { bigint: true });
131
+ if (stat.isSymbolicLink() || !stat.isDirectory()) {
132
+ throw new Error("A selected path has a linked or non-directory component.");
133
+ }
134
+ const previous = directories.get(name);
135
+ if (previous && !sameDirectory(previous, stat)) {
136
+ throw new Error("A selected directory changed.");
137
+ }
138
+ directories.set(name, stat);
139
+ }
140
+
141
+ const parents = [];
142
+ for (let current = root; ; current = path.dirname(current)) {
143
+ parents.push(current);
144
+ if (path.dirname(current) === current) break;
145
+ }
146
+ parents.reverse().forEach(directory);
147
+
148
+ for (let offset = 0; offset < args.length; offset += 3) {
149
+ const [name, sizeText, digest] = args.slice(offset, offset + 3);
150
+ const parts = name.split("/");
151
+ if (
152
+ path.isAbsolute(name) ||
153
+ /[\\:\x00-\x1f\x7f]/u.test(name) ||
154
+ parts.some((part) => !part || part === "." || part === ".." || /[. ]$/u.test(part)) ||
155
+ !/^\d+$/u.test(sizeText) ||
156
+ !Number.isSafeInteger(Number(sizeText)) ||
157
+ !/^[a-f0-9]{64}$/u.test(digest)
158
+ ) {
159
+ throw new Error("A selected name, expected size or digest is unsafe.");
160
+ }
161
+ const normalized = name.toLowerCase();
162
+ if (names.has(normalized)) {
163
+ throw new Error("Selected names are duplicated or collide by case.");
164
+ }
165
+ names.add(normalized);
166
+ let current = root;
167
+ for (const part of parts.slice(0, -1)) {
168
+ current = path.join(current, part);
169
+ directory(current);
170
+ }
171
+ const file = path.join(root, ...parts);
172
+ const stat = fs.lstatSync(file, { bigint: true });
173
+ const expectedSize = BigInt(sizeText);
174
+ if (stat.isSymbolicLink() || !stat.isFile() || stat.nlink !== 1n) {
175
+ throw new Error("A selected entry is linked, hardlinked or non-regular.");
176
+ }
177
+ if (stat.size !== expectedSize) throw new Error("A selected size changed.");
178
+ entries.push({ file, stat, expectedSize, digest });
179
+ }
180
+
181
+ function recheckDirectories() {
182
+ for (const [name, before] of directories) {
183
+ const after = fs.lstatSync(name, { bigint: true });
184
+ if (!after.isDirectory() || after.isSymbolicLink() || !sameDirectory(before, after)) {
185
+ throw new Error("A selected directory changed.");
186
+ }
187
+ }
188
+ }
189
+
190
+ const buffer = Buffer.alloc(64 * 1024);
191
+ for (const entry of entries) {
192
+ recheckDirectories();
193
+ const flags = fs.constants.O_RDONLY | (fs.constants.O_NOFOLLOW ?? 0);
194
+ const descriptor = fs.openSync(entry.file, flags);
195
+ try {
196
+ const before = fs.fstatSync(descriptor, { bigint: true });
197
+ if (!before.isFile() || before.nlink !== 1n || !sameIdentity(entry.stat, before)) {
198
+ throw new Error("A selected entry changed before reading.");
199
+ }
200
+ const hash = createHash("sha256");
201
+ let size = 0n;
202
+ for (;;) {
203
+ const count = fs.readSync(descriptor, buffer, 0, buffer.length, null);
204
+ if (!count) break;
205
+ size += BigInt(count);
206
+ if (size > entry.expectedSize) throw new Error("A selected size changed.");
207
+ hash.update(buffer.subarray(0, count));
208
+ }
209
+ const after = fs.fstatSync(descriptor, { bigint: true });
210
+ const current = fs.lstatSync(entry.file, { bigint: true });
211
+ if (
212
+ !sameIdentity(before, after) ||
213
+ !sameIdentity(before, current) ||
214
+ size !== entry.expectedSize ||
215
+ hash.digest("hex") !== entry.digest
216
+ ) {
217
+ throw new Error("Selected bytes or identity changed.");
218
+ }
219
+ recheckDirectories();
220
+ } finally {
221
+ fs.closeSync(descriptor);
222
+ }
223
+ }
224
+ recheckDirectories();
225
+ for (const entry of entries) {
226
+ if (!sameIdentity(entry.stat, fs.lstatSync(entry.file, { bigint: true }))) {
227
+ throw new Error("A selected entry changed after reading.");
228
+ }
229
+ }
230
+ console.log(`Verified ${entries.length} selected files.`);
231
+ }
232
+
233
+ try {
234
+ main();
235
+ } catch (error) {
236
+ console.error(`Evidence preflight refused: ${error.message}`);
237
+ process.exitCode = 1;
238
+ }
239
+ ```
240
+
241
+ ## Copy and archive
242
+
243
+ After source preflight succeeds, copy only those selected files to the new owned
244
+ staging root. Use a native literal-path copy or Node's `fs.copyFileSync`; create
245
+ only their listed parent directories. Do not decode, rewrite or normalize
246
+ binary data, encoding markers, LF or CRLF. Re-run the exact preflight block on
247
+ staging with the trusted source expectations immediately before native tar.
248
+ If anything changes or cannot be read, stop before archive and keep originals.
249
+
250
+ Use the installed native tar executable with separated argv, for example:
251
+
252
+ - create: `tar -cf <absolute-bundle.tar> -C <absolute-staging-root> ./<selected-name> ...`
253
+ - list: `tar -tf <absolute-bundle.tar>`
254
+ - extract: `tar -xf <absolute-bundle.tar> -C <fresh-absolute-receiver-root>`
255
+
256
+ Prefix each selected name with `./` to avoid option or archive-inclusion
257
+ interpretation. Select no directory and use no wildcard or shell interpolation.
258
+ Check the actual listing against the exact expected member set: each required
259
+ name occurs once, with no unexpected or missing member. Record the actual
260
+ executable/version, argv, cwd, platform, exit/signal and stdout/stderr. A missing
261
+ tool or failed command is not successful production. Different native tar
262
+ implementations need not produce identical archive container bytes.
263
+
264
+ Calculate the produced archive's raw-byte SHA-256 and record it with the trusted
265
+ source and selected expectations outside the archive. Archive digest identity
266
+ alone does not prove file provenance, privacy or recipient access.
267
+
268
+ ## Retained storage and receipt
269
+
270
+ Before upload, establish existing authority for this target and payload,
271
+ destination privacy, the named recipient or receiving role, required access and
272
+ retention. A visible storage link grants none of these. Use an existing
273
+ authorized retained channel; do not create a paid service or publish private raw
274
+ evidence by assumption. Preserve actual upload results and artifact identity.
275
+
276
+ The ignored receiving receipt records who received the evidence, retrieval time,
277
+ destination and artifact identity, retrieved items, independently checked source
278
+ and archive identity, every required size/digest result and missing evidence.
279
+ Keep its reference in the stage report or handoff. A required item or receipt
280
+ that is unavailable, expired, denied, incomplete or mismatched leaves handover
281
+ pending, records the blocker and resume condition, and retains originals.
282
+
283
+ ## Independent receiver
284
+
285
+ The receiver independently retrieves every required item from retained storage;
286
+ producer self-read or index visibility is insufficient. Supply trusted source,
287
+ archive digest and selected-file expectations through a separate authorized
288
+ channel. Check the archive's actual raw-byte digest and source identity against
289
+ those expectations before extraction. Refuse a mismatched or unknown archive.
290
+
291
+ Extract only this known-safe producer archive into a fresh owned receiving root.
292
+ This procedure does not safely extract arbitrary third-party archives. Check
293
+ the exact member set and re-run the same preflight on the extracted regular
294
+ files with the trusted expected triples. Compare the index's target/source and
295
+ inventory with the separately supplied expectations. Missing, duplicated,
296
+ unexpected, linked or altered members do not produce an accepted receipt.
297
+
298
+ Only the named recipient's actual complete receiving proof allows the requested
299
+ handover to complete before real session archive. Local producer checks cannot
300
+ stand in for it. Preserve unrelated receiver contents and originals when proof
301
+ fails; do not destroy or silently replace them to make the receipt pass.
302
+
303
+ ## Failure and proof limits
304
+
305
+ On unsafe selection, changed source or index, missing evidence, unknown required
306
+ identity, denied access, expiry or mismatched bytes, stop dependent delivery and
307
+ archive. Name the observed blocker, missing item, owner and resume condition.
308
+ Keep actual failure output and originals. Required verification FAIL, UNRUN or
309
+ pending remains incomplete even if some evidence was successfully delivered.
310
+
311
+ Generic capability acceptance requires actual native Linux and Windows
312
+ producers and separate Linux and Windows hosted receivers. Each receiver must
313
+ retrieve both retained producer artifacts and independently check their bytes,
314
+ digests and source identity: all four transfer directions need actual proof.
315
+ Executing only the instructions or reading one's own output is insufficient.
316
+
317
+ That controlled CI receipt proves the tested capability. It does not establish
318
+ this session's real successor access, long-term retention, a session archive or
319
+ general sharing permission. Historical metadata remains UNKNOWN where absent.
320
+ The preflight is neither an automatic secret scanner, an exporter nor an atomic
321
+ concurrent-adversary guarantee. Native archives are not a general safe restore
322
+ engine. Report these limits with the actual observations.