qfai 2.1.1 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. package/README.md +56 -36
  2. package/assets/defaults/agent-routing/qfai-implement.yml +9 -0
  3. package/assets/defaults/agent-routing/qfai-triage.yml +18 -0
  4. package/assets/defaults/workflows/answer-in-session.yml +8 -0
  5. package/assets/defaults/workflows/quarantine-flaky.yml +3 -0
  6. package/assets/defaults/workflows/repair-consistency.yml +1 -0
  7. package/assets/defaults/workflows/run-operation.yml +11 -0
  8. package/assets/defaults/workflows/run-owned-cleanup.yml +12 -0
  9. package/assets/defaults/workflows/write-procedure.yml +18 -0
  10. package/assets/graph/codegraph-native.mjs +174 -0
  11. package/assets/graph/graphify-native.py +72 -0
  12. package/assets/init/.claude/settings.json +9 -9
  13. package/assets/init/.codex/hooks.json +8 -8
  14. package/assets/init/.qfai/assistant/agent/frontend-engineer.md +5 -0
  15. package/assets/init/.qfai/assistant/agent/product-experience-architect.md +4 -0
  16. package/assets/init/.qfai/assistant/agent/product-surface-reviewer.md +7 -0
  17. package/assets/init/.qfai/assistant/agent/requirements-analyst.md +8 -0
  18. package/assets/init/.qfai/assistant/rule/communication.md +18 -8
  19. package/assets/init/.qfai/assistant/rule/constitution.md +31 -15
  20. package/assets/init/.qfai/assistant/rule/drift-protocol.md +119 -2
  21. package/assets/init/.qfai/assistant/rule/references/asset-authoring.md +6 -4
  22. package/assets/init/.qfai/assistant/rule/references/codex-delegation.md +27 -0
  23. package/assets/init/.qfai/assistant/rule/references/griller-recommendations.md +21 -9
  24. package/assets/init/.qfai/assistant/rule/references/worker-edit-boundary.md +48 -0
  25. package/assets/init/.qfai/assistant/rule/review-convergence.md +25 -12
  26. package/assets/init/.qfai/assistant/rule/shared-skill-delegation-baseline.md +16 -25
  27. package/assets/init/.qfai/assistant/rule/shared-skill-operating-baseline.md +16 -11
  28. package/assets/init/.qfai/assistant/rule/ui-definition-protocol.md +6 -1
  29. package/assets/init/.qfai/assistant/rule/workflow.md +2 -1
  30. package/assets/init/.qfai/assistant/skill/qfai-configure/SKILL.md +3 -3
  31. package/assets/init/.qfai/assistant/skill/qfai-discussion/SKILL.md +6 -0
  32. package/assets/init/.qfai/assistant/skill/qfai-discussion/references/discussion-completion-matrix.md +20 -15
  33. package/assets/init/.qfai/assistant/skill/qfai-discussion/references/ui-bearing-playbook.md +2 -4
  34. package/assets/init/.qfai/assistant/skill/qfai-discussion/references/ui_ux_best_practices.md +1 -6
  35. package/assets/init/.qfai/assistant/skill/qfai-discussion/templates/uiux/00_index.md +0 -16
  36. package/assets/init/.qfai/assistant/skill/qfai-grilling/SKILL.md +30 -20
  37. package/assets/init/.qfai/assistant/skill/qfai-grilling/references/delegated-session.md +4 -3
  38. package/assets/init/.qfai/assistant/skill/qfai-grilling/references/session-record.md +8 -2
  39. package/assets/init/.qfai/assistant/skill/qfai-implement/SKILL.md +16 -3
  40. package/assets/init/.qfai/assistant/skill/qfai-implement/references/parallelization-policy.md +9 -1
  41. package/assets/init/.qfai/assistant/skill/qfai-implement/references/red-admissibility.md +46 -0
  42. package/assets/init/.qfai/assistant/skill/qfai-implement/references/ui-affecting.md +5 -2
  43. package/assets/init/.qfai/assistant/skill/qfai-maintain/SKILL.md +3 -3
  44. package/assets/init/.qfai/assistant/skill/qfai-migration-v1-to-v2/SKILL.md +12 -6
  45. package/assets/init/.qfai/assistant/skill/qfai-migration-v1-to-v2/references/migration-guide.md +1 -265
  46. package/assets/init/.qfai/assistant/skill/qfai-migration-v1-to-v2/references/migration-placement.md +273 -0
  47. package/assets/init/.qfai/assistant/skill/qfai-prototyping/SKILL.md +4 -3
  48. package/assets/init/.qfai/assistant/skill/qfai-prototyping/references/review-payload-schema.md +2 -3
  49. package/assets/init/.qfai/assistant/skill/qfai-prototyping/references/reviewer-prompt.md +17 -1
  50. package/assets/init/.qfai/assistant/skill/qfai-run/SKILL.md +52 -37
  51. package/assets/init/.qfai/assistant/skill/qfai-run/references/codex-cloud-install.md +80 -0
  52. package/assets/init/.qfai/assistant/skill/qfai-run/references/evidence-delivery.md +322 -0
  53. package/assets/init/.qfai/assistant/skill/qfai-run/references/extraction.md +83 -49
  54. package/assets/init/.qfai/assistant/skill/qfai-run/references/operator-screens.md +226 -11
  55. package/assets/init/.qfai/assistant/skill/qfai-run/references/plan.md +6 -3
  56. package/assets/init/.qfai/assistant/skill/qfai-run/references/reached-step-observations.md +132 -0
  57. package/assets/init/.qfai/assistant/skill/qfai-run/references/stage-points.md +14 -0
  58. package/assets/init/.qfai/assistant/skill/qfai-run/scripts/codex-cloud-install.mjs +117 -0
  59. package/assets/init/.qfai/assistant/skill/qfai-sdd/SKILL.md +4 -3
  60. package/assets/init/.qfai/assistant/skill/qfai-sdd/references/contract-artifact-rules.md +1 -0
  61. package/assets/init/.qfai/assistant/skill/qfai-sdd/references/design-anti-patterns.md +23 -5
  62. package/assets/init/.qfai/assistant/skill/qfai-sdd/references/design-md-authoring.md +20 -7
  63. package/assets/init/.qfai/assistant/skill/qfai-sdd/references/requirements-decomposition.md +8 -0
  64. package/assets/init/.qfai/assistant/skill/qfai-sdd/references/sdd-execution-playbook.md +29 -4
  65. package/assets/init/.qfai/assistant/skill/qfai-sdd/references/sdd-phase-checklists.md +1 -1
  66. package/assets/init/.qfai/assistant/skill/qfai-sdd/references/sdd-pre-draft-grilling.md +4 -1
  67. package/assets/init/.qfai/assistant/skill/qfai-sdd/references/sdd-quality-gate.md +1 -1
  68. package/assets/init/.qfai/assistant/skill/qfai-sdd/references/sdd-triage.md +159 -4
  69. package/assets/init/.qfai/assistant/skill/qfai-sdd/references/spec-traceability-rules.md +14 -2
  70. package/assets/init/.qfai/assistant/skill/qfai-sdd/references/ui-contract-guide.md +146 -0
  71. package/assets/init/.qfai/assistant/skill/qfai-sdd/references/ui-design-contract-normalization.md +4 -29
  72. package/assets/init/.qfai/assistant/skill/qfai-sdd/templates/change-request.md +38 -1
  73. package/assets/init/.qfai/assistant/skill/qfai-sdd/templates/contracts/ui-contract.sample.yaml +52 -5
  74. package/assets/init/.qfai/assistant/skill/qfai-sdd/templates/spec/decisions.md +12 -0
  75. package/assets/init/.qfai/assistant/skill/qfai-triage/SKILL.md +34 -21
  76. package/assets/init/.qfai/assistant/skill/qfai-verify/SKILL.md +5 -4
  77. package/assets/init/.qfai/assistant/skill/qfai-verify/references/context-load.md +9 -6
  78. package/assets/init/.qfai/assistant/skill/qfai-verify/references/verify-output-contract.md +80 -15
  79. package/assets/init/.qfai/assistant/skill/web-research/SKILL.md +35 -21
  80. package/assets/init/.qfai/assistant/skill/web-research/mcp-templates/brave-search/config.toml +2 -4
  81. package/assets/init/.qfai/assistant/skill/web-research/mcp-templates/brave-search/mcp-config.json +9 -5
  82. package/assets/init/.qfai/assistant/skill/web-research/mcp-templates/firecrawl/.mcp.json +1 -2
  83. package/assets/init/.qfai/assistant/skill/web-research/mcp-templates/firecrawl/config.toml +3 -3
  84. package/assets/init/.qfai/assistant/skill/web-research/mcp-templates/firecrawl/mcp-config.json +11 -8
  85. package/assets/init/.qfai/assistant/skill/web-research/mcp-templates/playwright/config.toml +1 -1
  86. package/assets/init/.qfai/assistant/skill/web-research/mcp-templates/playwright/mcp-config.json +7 -3
  87. package/assets/init/.qfai/assistant/step/common-design-md/STEP.md +33 -20
  88. package/assets/init/.qfai/assistant/step/common-gate-run/STEP.md +124 -8
  89. package/assets/init/.qfai/assistant/step/common-grilling-record/STEP.md +10 -2
  90. package/assets/init/.qfai/assistant/step/common-policy-check/STEP.md +1 -0
  91. package/assets/init/.qfai/assistant/step/common-review-cycle/STEP.md +26 -9
  92. package/assets/init/.qfai/assistant/step/discussion-interview/STEP.md +15 -8
  93. package/assets/init/.qfai/assistant/step/discussion-oq/STEP.md +5 -1
  94. package/assets/init/.qfai/assistant/step/discussion-pack/STEP.md +6 -1
  95. package/assets/init/.qfai/assistant/step/discussion-research/STEP.md +2 -0
  96. package/assets/init/.qfai/assistant/step/discussion-uiux/STEP.md +6 -4
  97. package/assets/init/.qfai/assistant/step/implement-backport/STEP.md +1 -1
  98. package/assets/init/.qfai/assistant/step/implement-benchmark/STEP.md +7 -4
  99. package/assets/init/.qfai/assistant/step/implement-dep-bump/STEP.md +11 -2
  100. package/assets/init/.qfai/assistant/step/implement-diagnose/STEP.md +2 -0
  101. package/assets/init/.qfai/assistant/step/implement-oracle-parity/STEP.md +2 -2
  102. package/assets/init/.qfai/assistant/step/implement-procedure/STEP.md +69 -0
  103. package/assets/init/.qfai/assistant/step/implement-quarantine/STEP.md +24 -7
  104. package/assets/init/.qfai/assistant/step/implement-refactor/STEP.md +2 -2
  105. package/assets/init/.qfai/assistant/step/implement-regression-fix/STEP.md +7 -6
  106. package/assets/init/.qfai/assistant/step/implement-retire/STEP.md +6 -3
  107. package/assets/init/.qfai/assistant/step/implement-revert/STEP.md +4 -3
  108. package/assets/init/.qfai/assistant/step/implement-seam/STEP.md +6 -5
  109. package/assets/init/.qfai/assistant/step/implement-stress-harness/STEP.md +34 -3
  110. package/assets/init/.qfai/assistant/step/implement-sweep/STEP.md +4 -3
  111. package/assets/init/.qfai/assistant/step/implement-tdd/STEP.md +39 -5
  112. package/assets/init/.qfai/assistant/step/implement-tooling/STEP.md +22 -2
  113. package/assets/init/.qfai/assistant/step/maintain-edit/STEP.md +18 -14
  114. package/assets/init/.qfai/assistant/step/prototyping-grill/STEP.md +4 -3
  115. package/assets/init/.qfai/assistant/step/prototyping-loop/STEP.md +4 -0
  116. package/assets/init/.qfai/assistant/step/prototyping-preflight/STEP.md +9 -3
  117. package/assets/init/.qfai/assistant/step/sdd-contract/STEP.md +11 -0
  118. package/assets/init/.qfai/assistant/step/sdd-flow/STEP.md +2 -0
  119. package/assets/init/.qfai/assistant/step/sdd-story/STEP.md +10 -0
  120. package/assets/init/.qfai/assistant/step/sdd-triage/STEP.md +34 -10
  121. package/assets/init/.qfai/assistant/step/triage-answer/STEP.md +7 -6
  122. package/assets/init/.qfai/assistant/step/triage-close/STEP.md +33 -23
  123. package/assets/init/.qfai/assistant/step/triage-cluster/STEP.md +5 -3
  124. package/assets/init/.qfai/assistant/step/triage-decompose/STEP.md +2 -0
  125. package/assets/init/.qfai/assistant/step/triage-dedupe/STEP.md +4 -0
  126. package/assets/init/.qfai/assistant/step/triage-handoff/STEP.md +13 -4
  127. package/assets/init/.qfai/assistant/step/triage-investigate/STEP.md +8 -5
  128. package/assets/init/.qfai/assistant/step/triage-operate/STEP.md +50 -0
  129. package/assets/init/.qfai/assistant/step/triage-owned-cleanup/STEP.md +86 -0
  130. package/assets/init/.qfai/assistant/step/triage-request-info/STEP.md +2 -0
  131. package/assets/init/.qfai/assistant/step/triage-security-intake/STEP.md +6 -3
  132. package/assets/init/.qfai/assistant/step/verify-change-note/STEP.md +1 -0
  133. package/assets/init/.qfai/assistant/step/verify-commit/STEP.md +37 -9
  134. package/assets/init/.qfai/assistant/step/verify-external/STEP.md +5 -2
  135. package/assets/init/.qfai/assistant/step/verify-qfai-gate/STEP.md +14 -16
  136. package/assets/init/.qfai/assistant/step/verify-release-notes/STEP.md +1 -0
  137. package/assets/init/.qfai/assistant/step/verify-repeat-run/STEP.md +46 -4
  138. package/assets/init/.qfai/assistant/step/verify-repo-gate/STEP.md +133 -30
  139. package/assets/init/root/.agents/rules/ai-readable-markdown.md +2 -2
  140. package/assets/init/root/.agents/rules/api-budget.md +187 -8
  141. package/assets/init/root/.agents/rules/document-schema.md +17 -0
  142. package/assets/init/root/.agents/rules/documentation-clarity.md +163 -34
  143. package/assets/init/root/.agents/rules/graph-exploration.md +150 -0
  144. package/assets/init/root/.agents/rules/grilling.md +100 -43
  145. package/assets/init/root/.agents/rules/minimal-implementation.md +3 -3
  146. package/assets/init/root/.agents/rules/reminders.json +27 -18
  147. package/assets/init/root/.agents/rules/session-feedback.md +131 -0
  148. package/assets/init/root/.agents/rules/temporary-files.md +33 -0
  149. package/assets/init/root/.agents/rules/untrusted-content.md +2 -2
  150. package/assets/init/root/.agents/rules/user-questions.md +51 -40
  151. package/assets/init/root/.github/workflows/qfai-docs.yml +3 -3
  152. package/assets/init/root/.github/workflows/qfai-tests.yml +88 -35
  153. package/assets/init/root/.github/workflows/qfai-validate.yml +2 -2
  154. package/assets/init/root/AGENTS.md +24 -22
  155. package/assets/sandbox-templates/default-deny.yaml +9 -3
  156. package/assets/schemas/workflow/extraction.schema.json +89 -5
  157. package/assets/scripts/check-mdschema.mjs +77 -8
  158. package/assets/uix-rev/comparison-review.md +1 -1
  159. package/assets/uix-rev/contracts-review.md +1 -2
  160. package/dist/cli/index.cjs +9444 -10071
  161. package/dist/cli/index.cjs.map +1 -1
  162. package/dist/cli/index.mjs +9421 -10041
  163. package/dist/cli/index.mjs.map +1 -1
  164. package/dist/graph/cli.cjs +1568 -0
  165. package/dist/graph/cli.cjs.map +1 -0
  166. package/dist/graph/cli.d.cts +9 -0
  167. package/dist/graph/cli.d.ts +9 -0
  168. package/dist/graph/cli.mjs +1541 -0
  169. package/dist/graph/cli.mjs.map +1 -0
  170. package/dist/graph/hook.cjs +817 -0
  171. package/dist/graph/hook.cjs.map +1 -0
  172. package/dist/graph/hook.d.cts +9 -0
  173. package/dist/graph/hook.d.ts +9 -0
  174. package/dist/graph/hook.mjs +792 -0
  175. package/dist/graph/hook.mjs.map +1 -0
  176. package/dist/index.cjs +7634 -8517
  177. package/dist/index.cjs.map +1 -1
  178. package/dist/index.d.cts +146 -658
  179. package/dist/index.d.ts +146 -658
  180. package/dist/index.mjs +7462 -8318
  181. package/dist/index.mjs.map +1 -1
  182. package/dist/process-C21nTvkT.d.cts +12 -0
  183. package/dist/process-C21nTvkT.d.ts +12 -0
  184. package/package.json +4 -6
  185. package/assets/init/root/CLAUDE.md +0 -46
@@ -15,33 +15,6 @@ A cli-only target has no root `DESIGN.md`; it still normalizes
15
15
  `/qfai-prototyping` records its handoff in
16
16
  `.qfai/prototype/final/handoff.json`. SDD does not author it.
17
17
 
18
- ## Removed yaml contracts (permanent)
19
-
20
- The legacy per-aspect brand yaml contracts have been **removed**. The
21
- brand SSOT is now root `DESIGN.md` only, authored by `common-design-md`.
22
- Do not regenerate or reintroduce these files. Their content is subsumed by
23
- `DESIGN.md`:
24
-
25
- - brand archetype / voice / audience → `DESIGN.md` `brand` + `audience` +
26
- `# Brand Philosophy` body.
27
- - negative references / things-to-avoid →
28
- `audience.do_not_look_like` and the **Don't** subsection of
29
- `# Brand Philosophy`.
30
- - color / typography / spacing / radius / shadow tokens →
31
- `DESIGN.md` `visual.*` token tree.
32
-
33
- The following contracts MUST NOT be generated (the corresponding
34
- concepts do not exist in the current prototyping skill):
35
-
36
- - `evaluation-rubric.yaml` — evaluation axes are global constants; no
37
- per-project rubric.
38
- - `evaluator-calibration.yaml` — calibration is the ordinal scale plus
39
- a 200–500 word prose critique authored at review time.
40
- - `absorption-policy.yaml` — absorption / harvest concepts are not
41
- used.
42
- - `selected-direction.yaml` — winner selection is not used; the latest
43
- accepted iteration is always the artifact.
44
-
45
18
  ## Sidecar mapping
46
19
 
47
20
  The remaining UI-bearing sidecar maps to its contract as follows:
@@ -50,12 +23,14 @@ The remaining UI-bearing sidecar maps to its contract as follows:
50
23
 
51
24
  Project-specific anti-pattern notes live in `audience.do_not_look_like`
52
25
  of `DESIGN.md`. Evaluator axes are fixed by the review validation the
53
- QFAI CLI applies
54
- and are no longer authored as sidecar files.
26
+ QFAI CLI applies.
55
27
 
56
28
  ## Normalization Rules
57
29
 
58
30
  - Preserve source IDs where available.
31
+ - Normalize the sidecar's notes on displayed text into the screen's `supplements`
32
+ and `structure`, as the UI contract guide shapes them. Notes for the author or
33
+ the reviewer are not displayed text and are not copied into either key.
59
34
  - Convert prose into machine-readable arrays or objects.
60
35
  - Reject placeholder text instead of copying it into contracts.
61
36
  - Frame negative references in `audience.do_not_look_like` as
@@ -11,5 +11,42 @@ Record a change request as one row in `<paths.specsDir>/decisions.md`. The row h
11
11
  - Describe the actual contradiction and its source in `Content`. In `Approach`, state the proposed correction, affected work, and the gate that proves it is applied, inside the form stated at the top of `templates/spec/decisions.md`. Keep both cells concise enough to review as a table row.
12
12
  - Append the row only once the user approves the change, at `WIP`, and record in `Approach` who approved it, when, and the option chosen. Move it to `DONE` only after the owner rerun, affected artifacts, and validation evidence are complete. Use `SUPERSEDED (by DEC-NNNN)` when a later decision replaces the row, and `PARTLY SUPERSEDED (by DEC-NNNN)` when it replaces only part of it.
13
13
  - Append a declined change at `REJECTED`, recording in `Approach` who declined it and when. It authorizes no edit.
14
- - After appending, change only `Status`. Never rewrite `ID`, `Content`, or `Approach`, and never delete the row. A row the base holds at DONE authorizes nothing at any Status, so a later change needs a new row. If its scope or proposed correction changes, append a new decision row and supersede the old one.
14
+ - After appending, change only `Status`, apart from the drift protocol's
15
+ explicit branch-added decision renumbering or published decision prefix
16
+ recovery. Keep inherited ID, Content and Approach fixed, and never delete a
17
+ row. A row the base holds at DONE authorizes nothing at any Status, so a later
18
+ change needs a new row. If its scope or proposed correction changes, append a
19
+ new decision row and supersede the old one.
15
20
  - Keep open questions in `<paths.specsDir>/open-questions.md`. Use the same four columns there, with `OQ-NNNN` IDs and the statuses permitted by that template.
21
+
22
+ ## Published decision prefix recovery
23
+
24
+ Use the same four-cell row only after actual approval covers this specific
25
+ recovery. Read `.qfai/assistant/rule/drift-protocol.md#published-decision-prefix-recovery`
26
+ for eligibility, byte boundaries, pre-write checks and stop conditions. Generic
27
+ protocol approval and a diagnostic suggestion do not authorize a target.
28
+
29
+ - Content names the target's repository-relative file and the unique target
30
+ DEC ID. Approach records the published source commit, fixed base and unique
31
+ common ancestor, with evidence the target is absent from the latter two and
32
+ the source commit is a current-HEAD ancestor.
33
+ - Evidence names actual supporting files. Grounds records the recovery reason,
34
+ actual approval authority, old and new SHA-256 Approach digests, and the exact
35
+ approved `- Evidence: <actual file references> - Grounds: ` prefix, including
36
+ its trailing space. Use actual references in place of the placeholder.
37
+ - The old digest matches the raw published source cell; the new digest matches
38
+ the prefix plus the complete original Approach. State the single-line valid
39
+ UTF-8 cell boundary: exclude only delimiter pipes and exactly one ASCII
40
+ padding space at each end. Decode no escapes and trim or normalize nothing.
41
+ - State that original ordered, nonempty Residual risk and Rollback items are
42
+ valid. Preserve ID, Content, Status, the full original suffix and every other
43
+ row. Record the immediate pre-write uniqueness, unchanged-cell and old-digest
44
+ checks, and the required existing validation without an exemption.
45
+ - Residual risk states the remaining observation and concurrency limits.
46
+ Rollback removes only the recorded prefix when the current new digest still
47
+ matches; otherwise it preserves the row and stops. Removal restores the
48
+ original validation failure. Do not reset, amend or force push.
49
+
50
+ Inherited records, open-question rows, unavailable provenance, ambiguous byte
51
+ boundaries, duplicate IDs, stale digests and any unapproved change stop recovery.
52
+ Do not fill approval or execution fields with assumed answers or planned results.
@@ -19,6 +19,8 @@ prototype:
19
19
  purpose: customer id field on the order create form
20
20
  screens:
21
21
  - id: order_create
22
+ # The one heading of the screen. A heading beyond it is a group heading
23
+ # under `structure`.
22
24
  title: Create Order
23
25
  route: /orders/new
24
26
  # primary_tasks: at least one entry required per screen (QFAI-AUD-001).
@@ -36,6 +38,9 @@ screens:
36
38
  label: Correct a rejected field
37
39
  acceptance: the field-level error clears and submit re-enables
38
40
  - id: t3
41
+ label: Keep the order for later
42
+ acceptance: the order appears under /orders/drafts and the form keeps what was entered
43
+ - id: t4
39
44
  label: Abandon the draft
40
45
  acceptance: navigating away discards the draft and returns to /orders
41
46
  elements:
@@ -51,13 +56,55 @@ screens:
51
56
  required: true
52
57
  validations:
53
58
  - must be non-empty
54
- - id: submit_button
55
- label: Submit
56
- type: button
57
- required: true
58
- validations: []
59
59
  actions:
60
60
  - id: submit_order
61
61
  label: Submit order
62
62
  kind: submit
63
63
  effect: navigates to /orders and shows the created row
64
+ - id: save_draft
65
+ label: Save draft
66
+ kind: submit
67
+ effect: stores the order under /orders/drafts, stays on the form and keeps what was entered
68
+ - id: discard_draft
69
+ label: Discard draft
70
+ kind: navigate
71
+ effect: navigates to /orders without storing the order
72
+ # structure (optional): the groups the screen is read in, in reading order.
73
+ # `tasks` are primary_tasks ids, `members` are elements/actions ids, and
74
+ # `heading` is the displayed heading of the group; leave it out for a group
75
+ # that shows none. Without `structure` the screen shows no heading beyond
76
+ # its title. An id belongs to one group.
77
+ structure:
78
+ - id: g_customer
79
+ heading: Customer
80
+ tasks: [t1, t2]
81
+ members: [customer_id_input]
82
+ - id: g_items
83
+ heading: Items
84
+ tasks: [t1, t2]
85
+ members: [item_code_input]
86
+ - id: g_commit
87
+ tasks: [t1, t3, t4]
88
+ members: [submit_order, save_draft, discard_draft]
89
+ # supplements (required): every text the screen shows beyond its title,
90
+ # group headings and labels. Field validation messages are the exception;
91
+ # they belong to the element's `validations`. `[]` says the screen shows
92
+ # none. `near` is an elements/actions/structure id, `when` is one of
93
+ # default, empty, loading, error, success, and `why` says what the user
94
+ # could not know or do without the text, and why a label or the structure
95
+ # cannot carry it.
96
+ #
97
+ # There is no supplement that restates what "Save draft" does: the label
98
+ # says it. What the label cannot say is where the draft went and what a
99
+ # failed save means, so those two are declared.
100
+ supplements:
101
+ - id: sp_draft_saved
102
+ near: save_draft
103
+ when: success
104
+ text: Saved to Drafts
105
+ why: After the click the user cannot see where the order went; the label names the action, not the place its result is kept.
106
+ - id: sp_draft_not_saved
107
+ near: save_draft
108
+ when: error
109
+ text: Not saved. Your entries are still here. Try again.
110
+ why: A failed save leaves the user unsure whether work was lost and what to do; the label says nothing about failure.
@@ -13,6 +13,18 @@ No item is empty, and only the last two may take `none — <reason>`. What a
13
13
  kind of row must state in its Approach, such as a change request's proposed
14
14
  correction, goes inside these items. Write a `|` inside a cell as `\|`.
15
15
 
16
+ Use this form for every new row. A passing validation result does not prove
17
+ that every decision row follows it.
18
+
19
+ A release approval, with `<...>` standing for the project's values, has this
20
+ Content cell:
21
+
22
+ Release <X.Y.Z> approved by <name> on <date>, option "<label>"
23
+
24
+ and this Approach cell, written on one line and without backticks around it:
25
+
26
+ - Evidence: file:CHANGELOG.md; command:<the release checks> → <result> - Grounds: <why the checks support the release> - Residual risk: none — <reason> - Rollback: <the steps that retract the release>
27
+
16
28
  A row that records a spec change following from an earlier approval may name
17
29
  that earlier decision by its ID in `Grounds:`, in place of a new answer from
18
30
  the user. Its `Evidence:` still lists what supports the change.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: qfai-triage
3
- title: QFAI Triage (Requests that end without a change)
4
- description: "Use when invoked by name or handed a QFAI work order for a request that ends without a change to the project: a question to answer, a duplicate, missing information, a request to split, automated reports, a security report to take in, or an operation only a person can run."
3
+ title: QFAI Triage (Requests that end without a tracked change)
4
+ description: "Use when invoked by name or handed a QFAI work order for a request that ends without a tracked change: a question, a duplicate, missing information, a split, automated reports, a security report, an operation only a person can run, an operation the user named on finished work, or authorized cleanup of current-task temporary directories."
5
5
  argument-hint: "<the request, as it was reported>"
6
6
  allowed-tools: [Read, Glob, Grep, Write, Bash, TodoWrite, Task, Agent]
7
7
  roles:
@@ -24,12 +24,14 @@ steps:
24
24
  - triage-cluster
25
25
  - triage-security-intake
26
26
  - triage-handoff
27
+ - triage-owned-cleanup
28
+ - triage-operate
27
29
  - triage-close
28
30
  requires: []
29
31
  mode: execution-focused
30
32
  ---
31
33
 
32
- ## /qfai-triage - Requests that end without a change
34
+ ## /qfai-triage - Requests that end without a tracked change
33
35
 
34
36
  [DRIFT-PROTOCOL:REQUIRED]
35
37
 
@@ -37,9 +39,13 @@ Run the entry check of
37
39
  `.qfai/assistant/rule/shared-skill-operating-baseline.md#workflow-run-entry-check-mandatory`
38
40
  first.
39
41
 
40
- This skill answers, closes, splits or hands over a request, and changes no
41
- file git tracks. Work the request needs is recorded as a follow-up request,
42
- never done here.
42
+ This skill answers, closes, splits or hands over a request, or carries out an
43
+ operation the user named, and changes no file git tracks. Work the request needs is recorded as a follow-up request,
44
+ never done here except the exact current-task temporary cleanup that
45
+ `triage-owned-cleanup` permits, after rechecking existing user authority and
46
+ repository-local scope, and the named operation `triage-operate` runs. No other
47
+ triage step executes an operation, and `triage-handoff` still waits for the
48
+ person's reported result.
43
49
 
44
50
  ## Inputs
45
51
 
@@ -59,17 +65,19 @@ Invoked by name, run the steps in this order, as
59
65
  states: read `.qfai/assistant/step/<name>/STEP.md` for the current step only,
60
66
  run it, then move to the next.
61
67
 
62
- | Step | What it does | Skipped when |
63
- | ------------------------ | -------------------------------------------------------------- | -------------------------------------------------------------------------------- |
64
- | `triage-dedupe` | Finds the same or a successor item, and links it | The request neither may repeat an existing item nor rests on a premise that aged |
65
- | `triage-request-info` | Asks for the facts the request is missing | The request states every fact its handling needs |
66
- | `triage-investigate` | Reads internals, history and outside facts to find the answer | The documents and code as they stand answer the question |
67
- | `triage-answer` | Answers, citing what shows the answer | The request asks no question |
68
- | `triage-decompose` | Splits the request into child requests with their dependencies | The request is one piece of work |
69
- | `triage-cluster` | Groups automated reports by signature | The request is not a set of automated reports |
70
- | `triage-security-intake` | Takes a vulnerability report in privately | The request reports no exploitable weakness |
71
- | `triage-handoff` | Gives a person the steps of an operation only they can run | The request needs no operation that only a person can run |
72
- | `triage-close` | Records the outcome and each follow-up, and closes | Only `triage-security-intake` ran: the fix follows it, so the request stays open |
68
+ | Step | What it does | Skipped when |
69
+ | ------------------------ | -------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
70
+ | `triage-dedupe` | Finds the same or a successor item, and links it | The request neither may repeat an existing item nor rests on a premise that aged |
71
+ | `triage-request-info` | Asks for the facts the request is missing | The request states every fact its handling needs |
72
+ | `triage-investigate` | Reads internals, history and outside facts to find the answer | The documents and code as they stand answer the question |
73
+ | `triage-answer` | Answers, citing what shows the answer | The request asks no question |
74
+ | `triage-decompose` | Splits the request into child requests with their dependencies | The request is one piece of work |
75
+ | `triage-cluster` | Groups automated reports by signature | The request is not a set of automated reports |
76
+ | `triage-security-intake` | Takes a vulnerability report in privately | The request reports no exploitable weakness |
77
+ | `triage-handoff` | Gives a person the steps of an operation only they can run | The request needs no operation that only a person can run |
78
+ | `triage-owned-cleanup` | Removes authorized current-task temporary directories and verifies absence | The request is not the specific repository-local cleanup the step permits |
79
+ | `triage-operate` | Runs the operation the user named on finished work, and reports its result | The request names no operation |
80
+ | `triage-close` | Records the outcome and each follow-up, and closes | Only `triage-security-intake` ran: the fix follows it, so the request stays open |
73
81
 
74
82
  Invoked by name, the skill ends at this stage. It starts no other stage and
75
83
  routes no follow-up: a request to carry a follow-up out goes to `qfai-run`.
@@ -94,9 +102,13 @@ Follow `.qfai/assistant/rule/shared-skill-operating-baseline.md#completion-contr
94
102
  find changed when it started.
95
103
 
96
104
  The report states the outcome `triage-close` recorded and lists each follow-up
97
- request. It never says a change is done. It ends with a question listing the
98
- next actions, as `.agents/rules/user-questions.md` § 6 sets out; under a
99
- no-question mode, list them in the report instead.
105
+ request. It never says a tracked change is done. `cleaned` says only that the
106
+ named temporary targets were removed and their absence and unchanged tracked
107
+ contents and index were verified; unfinished cleanup cannot use it.
108
+ Ask for the next action only when
109
+ proceeding requires the user's answer, as `.agents/rules/user-questions.md`
110
+ § 6 sets out. A closure-only report needs no question. Under a no-question mode,
111
+ list any remaining actions instead.
100
112
 
101
113
  ## Default Autopilot Policy
102
114
 
@@ -105,6 +117,7 @@ no-question mode, list them in the report instead.
105
117
 
106
118
  project_memory:
107
119
 
108
- - Triage changes no tracked file; work it finds is a follow-up request.
120
+ - Triage changes no tracked file; only `triage-owned-cleanup` and `triage-operate` execute an operation.
121
+ - Other work it finds is a follow-up request.
109
122
  - A follow-up is recorded, never routed inside the run that found it.
110
123
  - A security report stays private until the fix is ready to disclose.
@@ -106,10 +106,11 @@ Questions about this skill's own inputs or settings stay in its own output for
106
106
  the user to answer. This skill does not write `open-questions.md`.
107
107
 
108
108
  The completion message lists each decision the agents adopted, with its
109
- reason and any disagreeing position. None of them is put as a question. The
110
- message then ends with a question listing every next action, as
111
- `.agents/rules/user-questions.md` § 6 sets out; under a no-question mode it lists
112
- them in the report instead:
109
+ reason and any disagreeing position. None of them is put as a question. Ask for
110
+ the next action only when proceeding requires the user's answer, as
111
+ `.agents/rules/user-questions.md` § 6 sets out. A completion-only report needs
112
+ no question. Under a no-question mode, list any remaining actions instead.
113
+ The applicable next actions are:
113
114
 
114
115
  - Proceed (recommended): create a PR on your hosting platform, with the
115
116
  verification report as its description.
@@ -1,9 +1,12 @@
1
1
  # Step 0 — Load context
2
2
 
3
+ `<paths.specsDir>` and `<paths.contractsDir>` are the directories `qfai.config.yaml` sets.
4
+
3
5
  1. Read relevant **project policy** (if present):
4
- - `.qfai/spec/01_policy/objective.md`
5
- - `.qfai/spec/01_policy/initiative.md`
6
- - `.qfai/spec/03_contract/tech.md`
6
+ - `<paths.specsDir>/01_policy/objective.md`
7
+ - `<paths.specsDir>/01_policy/initiative.md`
8
+ - `<paths.specsDir>/01_policy/principle.md`
9
+ - `<paths.contractsDir>/tech.md`
7
10
  - `.qfai/assistant/rule/agent-selection.md`. From
8
11
  `.qfai/assistant/rule/agent-selection.md` read the acting role's entry
9
12
  when a role needs one, not the whole file
@@ -14,9 +17,9 @@
14
17
  - `.qfai/assistant/rule/workflow.md` (or equivalent)
15
18
 
16
19
  3. Read existing artifacts for the current work item (if present):
17
- - `.qfai/spec/02_business-flow/`
18
- - `.qfai/spec/03_contract/`
19
- - `.qfai/spec/decisions.md`
20
+ - `<paths.specsDir>/02_business-flow/`
21
+ - `<paths.contractsDir>/`
22
+ - `<paths.specsDir>/decisions.md`
20
23
 
21
24
  Do not use discussion-pack artifacts as verification inputs. Verify reads normalized specs, contracts, tests and code only.
22
25
 
@@ -1,10 +1,18 @@
1
1
  # Verify Output Contract — `.qfai/report/verify.json`
2
2
 
3
- `/qfai-verify` MUST write `.qfai/report/verify.json` at the end of the run. This file is the machine-readable verdict; the stage report is the human-readable account. No `qfai` command reads it, so an absent `verify.json` does not fail `npx qfai validate`.
3
+ ## Contents
4
+
5
+ - Verdict file
6
+ - Per-gate results
7
+ - CI-only checks
8
+ - Scope
9
+ - Example and rules
4
10
 
5
- Canonical path: `.qfai/report/verify.json` (NOT `.qfai/output/`). Create the `.qfai/report/` directory if absent — it is the same directory `validate.json` is written to.
11
+ ## Verdict file
6
12
 
7
- `.qfai/output/verify.json` is the legacy location, history for projects created before the move. Never write there.
13
+ `/qfai-verify` MUST write `.qfai/report/verify.json` at the end of the run. This file is the machine-readable verdict; the stage report is the human-readable account. No `qfai` command reads it, so an absent `verify.json` does not fail `npx qfai validate`.
14
+
15
+ Canonical path: `.qfai/report/verify.json`. Create the `.qfai/report/` directory if absent — it is the same directory `validate.json` is written to.
8
16
 
9
17
  | Field | Type | Required | Meaning |
10
18
  | ------------ | ---------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
@@ -15,23 +23,72 @@ Canonical path: `.qfai/report/verify.json` (NOT `.qfai/output/`). Create the `.q
15
23
  | `summary` | string | no | One or two sentences an operator can read without opening the stage report. |
16
24
  | `gates` | array of objects | no | Per-gate results: as set out below. Advisory; no reader gates on it today. |
17
25
 
26
+ When the scope includes acceptance scaffolds or unfinished BF/AC acceptance
27
+ bodies, an optional `summary` stays one or two short sentences naming remaining
28
+ work, its owner or UNASSIGNED, and the detailed human-report reference. The
29
+ five-field detail belongs in `verify-repo-gate`'s `## Report` section, not a
30
+ new JSON field or table inside `summary`. Empty-body exemptions, verdicts and
31
+ completion rules stay unchanged.
32
+
18
33
  `status` is a closed two-value enum: `"PASS"` / `"FAIL"`. There is no `"WARN"` — a run with only `warning` / `info` findings is `"PASS"` (waivers apply to those severities only). Any `error` finding makes it `"FAIL"`.
19
34
 
20
- Each entry of `gates` is `{ name, status, command }`, plus these optional fields:
35
+ ## Per-gate results
21
36
 
22
- | Field | Type | Meaning |
23
- | ---------- | ------ | --------------------------------------------------------------------------------------------------------------------------------- |
24
- | `status` | string | `"PASS"`, `"FAIL"`, `"UNRUN"` or `"DELEGATED"`. `"UNRUN"` is a gate with no command, launcher or environment; it is never a pass. |
25
- | `baseline` | string | On a `"FAIL"`: `"same"` when the base commit fails identically, `"different"` when it does not, `"unrun"` when it cannot run. |
26
- | `reason` | string | On an `"UNRUN"` gate, or a `baseline` of `"unrun"`: what is missing. |
27
- | `check` | string | On a `"DELEGATED"` gate: the CI check that runs it. |
28
- | `ci` | string | On a `"DELEGATED"` gate: `"green"`, `"red"` or `"pending"`, the state of that check when the file is written. |
37
+ Each entry of `gates` is `{ name, status, command }`, plus these optional fields:
29
38
 
30
- A gate the project runs in CI only is recorded `"DELEGATED"` with its `check` and `ci`. A `"red"` check makes the top-level `status` `"FAIL"`. A `"pending"` one does not, and `summary` names it, so a reader sees what the run left to CI. A gate that can run here is never delegated to avoid running it.
39
+ | Field | Type | Meaning |
40
+ | ---------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
41
+ | `status` | string | `"PASS"`, `"FAIL"`, `"UNRUN"` or `"DELEGATED"`. `"UNRUN"` is a gate with no command, launcher or environment; it is never a pass. |
42
+ | `baseline` | string | On a `"FAIL"`: `"same"` when the base commit fails identically, `"different"` when it does not, `"unrun"` when it cannot run. |
43
+ | `reason` | string | On an `"UNRUN"` gate, or a `baseline` of `"unrun"`: what is missing. On a `baseline` of `"same"`: the failing test identifiers and the environment, in one or two sentences (see `verify-repo-gate`). |
44
+ | `check` | string | On a `"DELEGATED"` gate: the CI check that runs it. |
45
+ | `ci` | string | On a `"DELEGATED"` gate: `"green"`, `"red"` or `"pending"`, the state of that check when the file is written. |
46
+
47
+ ## CI-only checks
48
+
49
+ A gate the project's Standard commands declare `CI only: <check name>` is
50
+ recorded `"DELEGATED"` with its `check` and `ci` for the candidate being evaluated.
51
+ `check` names the actual CI check and `ci` its observed state.
52
+ A `"red"` check makes the top-level `status` `"FAIL"` for that candidate.
53
+ A `"pending"` one does not, and `summary` names it. A runnable local gate is
54
+ never delegated to avoid running it. Retain an observed FAIL or
55
+ UNRUN; neither becomes PASS or DELEGATED because a verification commit is wanted.
56
+
57
+ A `"PASS"` verdict with pending delegated checks supports only the existing
58
+ verification-commit allowance under a user instruction or project policy
59
+ covering that commit and its paths. It does not establish formal completion or
60
+ permission to push, create a pull request or merge. Every nondelegated gate
61
+ must pass. A delegated red check stops transport of the same unchanged candidate.
62
+ Explicit CI-only delegation covering a transport commit may instead carry actual
63
+ changes addressing that failure through the existing planned fix into a new
64
+ candidate, while HEAD still names the failed commit. Preserve the prior head,
65
+ check, run and observed result as FAIL; never relabel that evidence pending.
66
+ Report the actual fix and, after committing, the new head and resume condition.
67
+ The new candidate remains unverified until its own CI results are observed.
68
+
69
+ The stage report records the target, current head, run ID or URL when available,
70
+ check, actual outcome and counts, blocker and resume condition. No run yet means
71
+ no result; invent neither. `ci: "green"` needs actual passing evidence for that
72
+ same target and head. Missing or mismatched evidence remains pending. Formal
73
+ completion or merge waits for every required check to pass on the current head.
74
+ Keep this evidence in the stage report and `summary`; add no verdict fields or states.
31
75
 
32
76
  A gate that fails identically on the base, or did not run and is not delegated, still makes the top-level `status` `"FAIL"`. The fields let a reader tell it from a failure the run caused.
33
77
 
34
- `scope` is a closed enum. Write the one that matches the stage you were invoked for:
78
+ Keep the full CI receipt in the stage report, as
79
+ `.qfai/assistant/step/common-gate-run/STEP.md#ci-evidence` requires. A branch
80
+ overview or a confirmed closed cleanup SKIP does not replace actual verification
81
+ or turn it into a behavioral PASS. Preserve failures for the current head;
82
+ unknown identity or purpose remains unverified. The receipt adds no fields or
83
+ states to this contract.
84
+
85
+ ## Scope
86
+
87
+ `scope` is a closed enum. Write the gate set this invocation covers through
88
+ execution or an explicitly declared matching CI-only check. Delegation never
89
+ claims that the profile already ran; its check must perform the required scan
90
+ and profile. A whole-repository scope still requires full validation. Write the
91
+ one that matches the stage you were invoked for:
35
92
 
36
93
  | `scope` | Written by | validate profile |
37
94
  | ------------- | ------------------------------------------------------------------- | ----------------------------------------------- |
@@ -42,6 +99,8 @@ A gate that fails identically on the base, or did not run and is not delegated,
42
99
  There is no `implement` value: the enum is closed at these three, and a run after
43
100
  `/qfai-implement` is recorded as `full`.
44
101
 
102
+ ## Example and rules
103
+
45
104
  Minimal conforming example for the prototyping gate:
46
105
 
47
106
  ```json
@@ -56,6 +115,12 @@ Minimal conforming example for the prototyping gate:
56
115
 
57
116
  Rules:
58
117
 
59
- - Never write `"status": "PASS"` without the command outputs that justify it. A `FAIL` verdict is a legitimate output — the gate downstream is supposed to stop.
60
- - Never write a `scope` you did not actually run. Writing `"prototyping"` after a `full` run is a false verdict, not a workaround — and the reverse is just as wrong: a `--profile verify` run is `scope: "full"`, not `scope: "atdd"`, because `atdd` means the ATDD gate set only.
118
+ - A PASS gate needs actual command output or matching CI evidence. The existing
119
+ top-level pending-DELEGATED allowance supports only the covered verification
120
+ commit described above. A `FAIL` verdict is a legitimate output; downstream
121
+ work stops as its gate requires.
122
+ - Never write a `scope` this invocation does not cover by execution or its
123
+ declared matching CI-only check. Writing `"prototyping"` for a `full` gate set
124
+ is a false verdict, not a workaround. A `--profile verify` gate is
125
+ `scope: "full"`, not `scope: "atdd"`; `atdd` covers the ATDD gate set only.
61
126
  - Do not add a `version` / `schemaVersion` field. No reader validates one, and a second version series in a distributed artifact is exactly what the distributed-surface rule forbids: the npm package version is the only version this surface has.
@@ -119,8 +119,9 @@ Configuration templates: `.qfai/assistant/skill/web-research/mcp-templates/playw
119
119
 
120
120
  ### 2.4 MCP Failure Recovery
121
121
 
122
- - Crash detection threshold: **< 10 seconds** runtime indicates abnormal termination.
122
+ - Crash detection: notice an MCP server crash or a dropped connection within **10 seconds**.
123
123
  - On MCP server crash, fallback to built-in tools (WebSearch / WebFetch).
124
+ - Tell the user that the MCP server is unavailable and that the built-in tools are in use.
124
125
  - Rate limit: detect HTTP 429 responses and honour `Retry-After` header with exponential backoff.
125
126
 
126
127
  ## 3. Security
@@ -142,10 +143,11 @@ The sanitizer is idempotent: applying it twice produces byte-identical output.
142
143
  Default policy: **default-deny**.
143
144
 
144
145
  - Only domains listed in the project allowlist may be fetched.
145
- - The allowlist is defined in `qfai.config.yaml` under `webResearch.allowlist`.
146
- - Unknown domains are logged and skipped; the pipeline continues with allowed sources.
146
+ - The allowlist is a domain list in `qfai.config.yaml` under `webResearch.allowlist`, read by the agent; `qfai` does not parse it.
147
+ - Unknown domains are logged with the blocked domain and skipped; the pipeline continues with allowed sources.
147
148
  - Redirect chains are followed only while all hops remain on allowlisted domains.
148
- A redirect to a non-allowlisted domain is blocked and the fetch is rejected.
149
+ A redirect to a non-allowlisted domain is blocked at that target, the fetch is rejected,
150
+ and the redirect chain up to the blocked target is logged.
149
151
 
150
152
  ### 3.3 --yolo Flag and Security Gates
151
153
 
@@ -159,14 +161,14 @@ cannot be bypassed.
159
161
 
160
162
  Every pipeline execution produces a session log with **6 mandatory fields**:
161
163
 
162
- | Field | Description |
163
- | ------------ | --------------------------------------- |
164
- | `session_id` | Unique identifier for this research run |
165
- | `query` | The original search query |
166
- | `timestamp` | ISO-8601 start time |
167
- | `stages` | Array of stage results with timing |
168
- | `sources` | List of fetched URLs with status codes |
169
- | `citations` | Final citation entries |
164
+ | Field | Description |
165
+ | ------------ | ----------------------------------------------------------------------- |
166
+ | `session_id` | Unique identifier for this research run |
167
+ | `query` | The request and every search query issued |
168
+ | `timestamp` | ISO-8601 start time |
169
+ | `stages` | Stage results with timing, sanitization events and verification results |
170
+ | `sources` | List of fetched URLs with status codes and content hashes |
171
+ | `citations` | Final citation entries |
170
172
 
171
173
  The session log is part of the research report, not a file of its own.
172
174
 
@@ -186,6 +188,9 @@ Risk-based gating strategy:
186
188
  - **Low-risk queries**: Auto-approve. No human gate required.
187
189
  - **High-risk queries** (e.g., medical, legal, financial): Gate before cite stage.
188
190
  Human must confirm source selection and extracted claims.
191
+ - **A high-risk conclusion** is not applied to code until a human has reviewed it.
192
+ The gate blocks and shows the diff the conclusion would produce together with its citations.
193
+ A low-risk conclusion is applied without blocking.
189
194
  - `--yolo` flag is **ignored** for security gates (see Section 3.3).
190
195
 
191
196
  Risk classification is determined by query topic analysis and domain sensitivity rules.
@@ -204,7 +209,7 @@ Default TTL: **24 hours** (24h).
204
209
 
205
210
  - Entries older than TTL are marked stale and re-fetched on next access.
206
211
  - Staleness is tracked per-entry; partial cache invalidation is supported.
207
- - TTL is configurable via `qfai.config.yaml` under `webResearch.cache.ttl`.
212
+ - TTL is configurable via `qfai.config.yaml` under `webResearch.cache.ttl`, read by the agent; `qfai` does not parse it.
208
213
 
209
214
  ### 7.3 Storage
210
215
 
@@ -227,8 +232,9 @@ the session log as the coordination artifact.
227
232
 
228
233
  When the search stage returns no results:
229
234
 
230
- - Log "no sources found" to the session log.
231
- - Return a zero-result response with the original query for user review.
235
+ - Log "no web sources found" to the session log.
236
+ - Report "no web sources found" to the user together with every search query issued, for user review.
237
+ - Generate no citations: the citation block stays empty, and nothing is cited from memory or from a source that was not fetched.
232
238
  - Do not proceed to fetch/extract stages.
233
239
 
234
240
  ### 9.2 Fetch Failure Isolation
@@ -237,14 +243,19 @@ Each URL is fetched independently. A fetch failure for one URL does not
237
243
  abort the pipeline. Failed URLs are logged and excluded; the remaining
238
244
  successful fetches produce a partial result.
239
245
 
246
+ When every fetch fails, no partial result exists. Report that every fetch failed,
247
+ with the failure reason (status code or timeout) for each URL, and do not run the
248
+ extract stage.
249
+
240
250
  This isolation ensures that transient network errors or single-domain
241
251
  outages do not block the entire research pipeline.
242
252
 
243
253
  ### 9.3 Rate Limiting
244
254
 
245
255
  - Detect HTTP 429 (Too Many Requests) responses.
246
- - Read and honour the `Retry-After` header.
247
- - Apply exponential backoff with jitter for retries.
256
+ - Read and honour the `Retry-After` header: retry only after the delay it gives.
257
+ - Apply exponential backoff with jitter for further retries.
258
+ - Log each rate-limit event to the session log with the 429 status, the delay and the retry number.
248
259
 
249
260
  ## 10. Conservative Defaults
250
261
 
@@ -270,7 +281,8 @@ SKILL.md files follow a **progressive disclosure** loading strategy:
270
281
  ### 11.1 Invalid SKILL.md Handling
271
282
 
272
283
  If the YAML front-matter is **invalid** or produces a **parse error** (malformed
273
- YAML), the loader reports the error to the session log and activates
284
+ YAML), the loader reports the parse error with its details (the YAML error
285
+ message and its location) to the session log and activates
274
286
  **default behavior** as a fallback. The skill is still listed in the roster
275
287
  but operates with built-in defaults until the YAML is corrected.
276
288
 
@@ -288,15 +300,17 @@ rules apply:
288
300
 
289
301
  ## 13. Golden Task Evaluation
290
302
 
291
- **Golden task** sets are curated query-answer pairs used for regression
292
- evaluation. Each golden task is scored against 4 metrics:
303
+ **Golden task** sets are curated query-answer pairs, each with its expected
304
+ sources and citations, used for regression evaluation. Each golden task is
305
+ scored against 4 metrics:
293
306
 
294
307
  - **Citation precision** — accuracy of generated citations.
295
308
  - **Coverage** — completeness of query facet coverage.
296
309
  - **Freshness** — recency of cited sources.
297
310
  - **Security hygiene** — sanitization pass rate.
298
311
 
299
- Golden task results are reported with the evaluation run.
312
+ Each score is compared with its target in Section 5, and the scores and the
313
+ comparison are reported with the evaluation run.
300
314
 
301
315
  ## Completion Contract (Shared)
302
316
 
@@ -1,6 +1,4 @@
1
- [mcp.brave-search]
1
+ [mcp_servers.brave-search]
2
2
  command = "npx"
3
3
  args = ["-y", "@modelcontextprotocol/server-brave-search@0.6.2"]
4
-
5
- [mcp.brave-search.env]
6
- BRAVE_API_KEY = "${BRAVE_API_KEY}"
4
+ env_vars = ["BRAVE_API_KEY"]
@@ -1,9 +1,13 @@
1
1
  {
2
- "brave-search": {
3
- "command": "npx",
4
- "args": ["-y", "@modelcontextprotocol/server-brave-search@0.6.2"],
5
- "env": {
6
- "BRAVE_API_KEY": "${BRAVE_API_KEY}"
2
+ "mcpServers": {
3
+ "brave-search": {
4
+ "type": "local",
5
+ "command": "npx",
6
+ "args": ["-y", "@modelcontextprotocol/server-brave-search@0.6.2"],
7
+ "env": {
8
+ "BRAVE_API_KEY": "${BRAVE_API_KEY}"
9
+ },
10
+ "tools": ["*"]
7
11
  }
8
12
  }
9
13
  }