qfai 1.10.0 → 1.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/README.md +95 -25
  2. package/assets/init/.qfai/assistant/README.md +27 -0
  3. package/assets/init/.qfai/assistant/agents/completion-reviewer.md +17 -1
  4. package/assets/init/.qfai/assistant/agents/delivery-planner.md +8 -0
  5. package/assets/init/.qfai/assistant/agents/implementation-reviewer.md +12 -1
  6. package/assets/init/.qfai/assistant/agents/orchestrator.md +2 -2
  7. package/assets/init/.qfai/assistant/agents/product-experience-architect.md +2 -1
  8. package/assets/init/.qfai/assistant/agents/product-surface-reviewer.md +1 -1
  9. package/assets/init/.qfai/assistant/agents/qa-gatekeeper.md +99 -14
  10. package/assets/init/.qfai/assistant/agents/test-design-analyst.md +4 -1
  11. package/assets/init/.qfai/assistant/catalog/cli-ux-guidelines.md +3 -0
  12. package/assets/init/.qfai/assistant/catalog/test-layers-ci-lanes.md +60 -0
  13. package/assets/init/.qfai/assistant/catalog/test-layers.md +169 -87
  14. package/assets/init/.qfai/assistant/catalog/worklog-entry.schema.md +4 -3
  15. package/assets/init/.qfai/assistant/constitution/agent-selection.md +7 -1
  16. package/assets/init/.qfai/assistant/constitution/communication.md +1 -1
  17. package/assets/init/.qfai/assistant/constitution/constitution.md +8 -2
  18. package/assets/init/.qfai/assistant/constitution/drift-protocol.md +177 -14
  19. package/assets/init/.qfai/assistant/constitution/review-convergence.md +121 -0
  20. package/assets/init/.qfai/assistant/constitution/shared-skill-delegation-baseline.md +205 -89
  21. package/assets/init/.qfai/assistant/constitution/shared-skill-operating-baseline.md +59 -5
  22. package/assets/init/.qfai/assistant/manifest/agent-catalog.yml +145 -21
  23. package/assets/init/.qfai/assistant/manifest/agent-routing.yml +69 -3
  24. package/assets/init/.qfai/assistant/skills/qfai-atdd/SKILL.md +131 -74
  25. package/assets/init/.qfai/assistant/skills/qfai-atdd/references/credential-reuse.md +146 -0
  26. package/assets/init/.qfai/assistant/skills/qfai-atdd/references/red-provenance.md +498 -0
  27. package/assets/init/.qfai/assistant/skills/qfai-atdd/references/review-fix-rounds.md +128 -0
  28. package/assets/init/.qfai/assistant/skills/qfai-atdd/references/scaffolding.md +71 -0
  29. package/assets/init/.qfai/assistant/skills/qfai-atdd/references/shared-test-artifacts.md +124 -0
  30. package/assets/init/.qfai/assistant/skills/qfai-atdd/references/stale-manifest.md +34 -0
  31. package/assets/init/.qfai/assistant/skills/qfai-atdd/references/test-case-depth-checklist.md +38 -1
  32. package/assets/init/.qfai/assistant/skills/qfai-configure/SKILL.md +4 -3
  33. package/assets/init/.qfai/assistant/skills/qfai-discussion/SKILL.md +10 -8
  34. package/assets/init/.qfai/assistant/skills/qfai-discussion/references/discussion-completion-matrix.md +23 -2
  35. package/assets/init/.qfai/assistant/skills/qfai-discussion/references/review-cycle-playbook.md +16 -1
  36. package/assets/init/.qfai/assistant/skills/qfai-discussion/references/ui-bearing-playbook.md +47 -11
  37. package/assets/init/.qfai/assistant/skills/qfai-discussion/references/ui_ux/trend_scan_playbook.md +1 -1
  38. package/assets/init/.qfai/assistant/skills/qfai-discussion/references/ui_ux_best_practices.md +6 -4
  39. package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/01_Context.md +2 -2
  40. package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/03_Story-Workshop.md +1 -1
  41. package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/04_Sources.md +40 -6
  42. package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/14_Review-Request.md +7 -7
  43. package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/review/Rxx_reviewer.md +3 -3
  44. package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/review/review_request.md +4 -3
  45. package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/review/summary.json +3 -0
  46. package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/uiux/00_index.md +14 -5
  47. package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/uiux/40_screen_contracts.md +17 -1
  48. package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/uiux/50_review_input_bundle.md +13 -8
  49. package/assets/init/.qfai/assistant/skills/qfai-implement/SKILL.md +83 -84
  50. package/assets/init/.qfai/assistant/skills/qfai-implement/references/checkpoint-verification.md +339 -39
  51. package/assets/init/.qfai/assistant/skills/qfai-implement/references/cross-spec-ownership.md +1 -1
  52. package/assets/init/.qfai/assistant/skills/qfai-implement/references/evidence-revision.md +348 -15
  53. package/assets/init/.qfai/assistant/skills/qfai-implement/references/execution-ledger.md +203 -32
  54. package/assets/init/.qfai/assistant/skills/qfai-implement/references/final-checklist.md +159 -12
  55. package/assets/init/.qfai/assistant/skills/qfai-implement/references/finding-classification.md +70 -5
  56. package/assets/init/.qfai/assistant/skills/qfai-implement/references/ledger-preconditions.md +55 -14
  57. package/assets/init/.qfai/assistant/skills/qfai-implement/references/parallelization-policy.md +92 -3
  58. package/assets/init/.qfai/assistant/skills/qfai-implement/references/red-not-observable.md +48 -6
  59. package/assets/init/.qfai/assistant/skills/qfai-implement/references/relevant-test-suite.md +13 -1
  60. package/assets/init/.qfai/assistant/skills/qfai-implement/references/review-artifact-layout.md +71 -9
  61. package/assets/init/.qfai/assistant/skills/qfai-implement/references/round-evidence.md +31 -7
  62. package/assets/init/.qfai/assistant/skills/qfai-implement/references/upstream-artifact-ordering.md +33 -0
  63. package/assets/init/.qfai/assistant/skills/qfai-implement/references/volume-policy.md +19 -12
  64. package/assets/init/.qfai/assistant/skills/qfai-prototyping/SKILL.md +76 -8
  65. package/assets/init/.qfai/assistant/skills/qfai-prototyping/references/design-md-spec.md +20 -0
  66. package/assets/init/.qfai/assistant/skills/qfai-prototyping/references/evidence-requirements.md +7 -4
  67. package/assets/init/.qfai/assistant/skills/qfai-prototyping/references/generator-prompt.md +83 -22
  68. package/assets/init/.qfai/assistant/skills/qfai-prototyping/references/reviewer-prompt.md +29 -4
  69. package/assets/init/.qfai/assistant/skills/qfai-sdd/SKILL.md +134 -20
  70. package/assets/init/.qfai/assistant/skills/qfai-sdd/references/contract-artifact-rules.md +31 -3
  71. package/assets/init/.qfai/assistant/skills/qfai-sdd/references/review-cycle-playbook.md +22 -1
  72. package/assets/init/.qfai/assistant/skills/qfai-sdd/references/sdd-execution-playbook.md +41 -5
  73. package/assets/init/.qfai/assistant/skills/qfai-sdd/references/sdd-phase-checklists.md +16 -4
  74. package/assets/init/.qfai/assistant/skills/qfai-sdd/references/sdd-triage.md +77 -7
  75. package/assets/init/.qfai/assistant/skills/qfai-sdd/references/spec-traceability-rules.md +60 -11
  76. package/assets/init/.qfai/assistant/skills/qfai-sdd/references/ui-design-contract-normalization.md +9 -3
  77. package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/change-request.md +14 -1
  78. package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/contracts/ui-contract.sample.yaml +13 -3
  79. package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/evidence/sdd-spec.md +5 -1
  80. package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/report/preflight_summary.md +3 -2
  81. package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/_policies/04_Business-Flow.md +4 -1
  82. package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/_policies/05_Contracts.md +12 -5
  83. package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/_policies/11_Slice-Policy.md +8 -9
  84. package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/spec/02_User-stories.md +9 -0
  85. package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/spec/tdd/test-list.md +68 -23
  86. package/assets/init/.qfai/assistant/skills/qfai-verify/SKILL.md +4 -4
  87. package/assets/init/.qfai/assistant/skills/qfai-verify/references/articles.md +1 -1
  88. package/assets/init/.qfai/assistant/skills/qfai-verify/references/validate-json-schema.md +79 -0
  89. package/assets/init/.qfai/assistant/skills/web-research/SKILL.md +3 -2
  90. package/assets/init/root/.github/workflows/qfai-tests.yml +318 -0
  91. package/assets/init/root/.github/workflows/qfai-validate.yml +327 -24
  92. package/assets/init/root/qfai.config.yaml +11 -2
  93. package/dist/cli/index.cjs +25083 -11488
  94. package/dist/cli/index.cjs.map +1 -1
  95. package/dist/cli/index.mjs +25216 -11589
  96. package/dist/cli/index.mjs.map +1 -1
  97. package/dist/index.cjs +16731 -8386
  98. package/dist/index.cjs.map +1 -1
  99. package/dist/index.d.cts +407 -17
  100. package/dist/index.d.ts +407 -17
  101. package/dist/index.mjs +16701 -8370
  102. package/dist/index.mjs.map +1 -1
  103. package/package.json +6 -1
@@ -0,0 +1,60 @@
1
+ # Test layers to CI lanes
2
+
3
+ A crosswalk between the test layers in [`test-layers.md`](./test-layers.md) and the CI lanes
4
+ the shipped workflows run. It exists so that "which job runs my L3 tests" has one answer a
5
+ reader can find, instead of being rediscovered from a workflow file each time.
6
+
7
+ **The layer policy loader does not read this file.** (Written without a hyphen on purpose: the
8
+ loader extracts anything matching `layer-<word>` from the file it parses, and while it does not
9
+ parse this one, a catalog-directory file carrying such a token is a hazard waiting for the day
10
+ someone widens the loader to scan the directory.) It resolves `catalog/test-layers.md` by
11
+ exact path and reads nothing else in this directory, so nothing written here can widen or
12
+ narrow the layer vocabulary. That is deliberate: this document is a map, and a map that could
13
+ change the territory would be a second source of truth for something that already has one. If
14
+ you need to change what layers exist, change `test-layers.md` — this file follows.
15
+
16
+ ## The mapping
17
+
18
+ | Layer | What it exercises | Shipped CI lane |
19
+ | -------------- | --------------------------------------------- | --------------- |
20
+ | L1 Unit | one module, no I/O | `unit` |
21
+ | L2 Component | one component and its immediate collaborators | `component` |
22
+ | L3 Integration | several modules across a real boundary | `integration` |
23
+ | L4 API | a running interface, contract-first | `api` |
24
+ | L5 E2E | the product as a user reaches it | `e2e` |
25
+
26
+ Two lanes in the shipped workflow are not layers and have no row above:
27
+
28
+ - **`detection`** decides which of the lanes above need to run for a given change, and
29
+ publishes that decision as job outputs. It is infrastructure, not a test level.
30
+ - **`verdict`** aggregates the lanes into the single status a branch-protection rule can name.
31
+ It runs unconditionally so that a run where every lane was skipped is still distinguishable
32
+ from a run where nothing was verified.
33
+
34
+ ## Lane names are a project's choice
35
+
36
+ The names in the third column are the ones the shipped workflow uses. They are not a contract:
37
+ a project that calls its integration lane `service-tests` is not violating anything, and this
38
+ table is not a rename list. What matters is that each layer a project uses has some lane that
39
+ runs it, and that the lane's name stays put once branch protection refers to it — a check name
40
+ is a repository setting, and renaming one silently makes a required check unsatisfiable.
41
+
42
+ ## Per-level routing is not enforced
43
+
44
+ `test-layers.md` marks per-level annotation routing as a target state and says plainly: not
45
+ enforced, do not follow yet. This document does not change that and does not activate it. The
46
+ live traceability gate reads one directory for annotations, and it is the gate — not this
47
+ table — that decides where an annotation counts.
48
+
49
+ So: read this file to find out which lane runs a layer. Do not read it as instructions about
50
+ where anything belongs in the tree. That question is settled by the gate's own scope, and by
51
+ `test-layers.md` for the vocabulary.
52
+
53
+ ## Keeping this file honest
54
+
55
+ - Every layer code here also appears in `test-layers.md`'s crosswalk. If you add a layer there
56
+ and not here, this table is incomplete; if you add one here and not there, you have invented
57
+ a layer nothing enforces.
58
+ - The lane column describes the shipped workflow. If the shipped workflow's job set changes,
59
+ this table is stale, and stale is worse than absent for a document whose only job is to save
60
+ someone a lookup.
@@ -2,6 +2,10 @@
2
2
 
3
3
  This document is the SSOT for ATDD test-layer semantics and completion gates.
4
4
 
5
+ For which CI lane runs which layer, see the sibling map
6
+ [`test-layers-ci-lanes.md`](./test-layers-ci-lanes.md). That file is a crosswalk only — the policy
7
+ loader reads this file and not that one, so nothing there can change the vocabulary declared below.
8
+
5
9
  ## Layer vocabulary crosswalk (normative)
6
10
 
7
11
  qfai spells the same layer four ways across shipped artifacts. This table is
@@ -31,27 +35,30 @@ Rules:
31
35
  - L1 and L2 have no mandated directory: unit and component tests live wherever
32
36
  the project's own convention puts them. Only L3-L5 are directory-pinned, and
33
37
  only those directories are scanned by the ATDD traceability rules.
34
- - **A `TC-*` row's `Level` is L1-L3.** The ATDD annotation hard gate routes an
35
- obligation by its ID, not by its `Level`: `US-*` is answered from
36
- `<testsDir>/e2e/**` (`QFAI-ATDD-111`), `TC-*` from
37
- `<testsDir>/integration/**` (`QFAI-ATDD-112`) and `CON-API-*` from
38
- `<testsDir>/api/**` (`QFAI-ATDD-113`) and `CON-DB-*` from
39
- `<testsDir>/integration/**` (`QFAI-ATDD-115`), while a `TC-*` reference inside
40
- `<testsDir>/api/**` or `<testsDir>/e2e/**` is rejected outright
41
- (`QFAI-ATDD-121` / `QFAI-ATDD-122`). L4's goal is `CON-API-*` and L5's is
42
- `US-*` (see the layer definitions below), so an oracle that lands at L4 or L5
43
- means the obligation is misfiled: record it as `CON-API-*` or `US-*` rather
44
- than as a `TC-*` row no test directory can carry.
38
+ - **A `TC-*` row's `Level` is L1-L3.** Of those, only L3 owes an ATDD
39
+ annotation: L1 and L2 have no mandated directory, so `QFAI-ATDD-112` does not
40
+ apply to them and `QFAI-ATDD-117` (`info`) names them instead. Their gate is
41
+ `tdd/test-list.md` / `TDDLIST_TC_NOT_COVERED`, under `/qfai-implement`.
42
+ `US-*` is answered from `<testsDir>/e2e/**` (`QFAI-ATDD-111`), `CON-API-*`
43
+ from `<testsDir>/api/**` (`QFAI-ATDD-113`) and `CON-DB-*` from
44
+ `<testsDir>/integration/**` (`QFAI-ATDD-115`) — those three are fixed by the
45
+ ID type. A `TC-*` is answered from the directory **its own declared `Level`**
46
+ names, which for a correctly filed row is `<testsDir>/integration/**`; see
47
+ [Annotation routing](#annotation-routing) for the full table and the
48
+ misplacement rules. L4's goal is `CON-API-*` and L5's is `US-*` (see the
49
+ layer definitions below), so an oracle that lands at L4 or L5 means the
50
+ obligation is misfiled: record it as `CON-API-*` or `US-*` rather than
51
+ leaving a `TC-*` row at a layer whose goal is another ID type.
45
52
  - The two code-side word lists (`tddHelpers.ts#UNIT_COMPONENT_LAYERS` /
46
53
  `#NON_COVERAGE_LAYERS`) accept both the code and the word form for the same
47
54
  layer; they MUST stay in step with this table.
48
55
 
49
56
  ## How this file is consumed
50
57
 
51
- The layer set below is read by `core/layerPolicy.ts` and is the SSOT for two
52
- checks: `QFAI-EX-005` on the legacy spec-pack layout, and `QFAI-EX-105` on the
53
- layered layout `npx qfai init` produces. Until both consumed it, the file was
54
- read, reported on, and then ignored on every modern project.
58
+ This file is the SSOT for the layer set below: `npx qfai validate` reads the layers
59
+ from here and applies them to two checks — `QFAI-EX-005` on the legacy spec-pack
60
+ layout, and `QFAI-EX-105` on the layered layout `npx qfai init` produces. Until both
61
+ consumed it, the file was read, reported on, and then ignored on every modern project.
55
62
 
56
63
  - A file that yields no layers raises `QFAI-SPACK-090` (error) rather than
57
64
  silently widening to the built-in set.
@@ -73,7 +80,7 @@ writer targets a declared layer instead.
73
80
  - Scope: pure decision logic — a single module's inputs and return values, with
74
81
  no port collaboration and no real infrastructure.
75
82
  - Goal: verify `TC-*` obligations whose oracle observes inputs and outputs only.
76
- - Location rule: `tests/unit/**`.
83
+ - Convention: `tests/unit/**`. L1 has no mandated directory and owes no ATDD annotation — see the crosswalk and "Unit and Component owe no ATDD annotation".
77
84
 
78
85
  ### L2 Component
79
86
 
@@ -81,25 +88,25 @@ writer targets a declared layer instead.
81
88
  with no real infrastructure.
82
89
  - Goal: verify `TC-*` obligations whose oracle observes the interaction with a
83
90
  port rather than infrastructure state.
84
- - Location rule: `tests/component/**`.
91
+ - Convention: `tests/component/**`. L2 has no mandated directory and owes no ATDD annotation — see the crosswalk and "Unit and Component owe no ATDD annotation".
85
92
 
86
93
  ### L3 Integration
87
94
 
88
95
  - Scope: real infrastructure integration (for example DB/queue/filesystem) within service boundaries.
89
96
  - Goal: verify `TC-*` obligations from specs.
90
- - Location rule: `tests/integration/**`.
97
+ - Location rule: `<testsDir>/integration/**`.
91
98
 
92
99
  ### L4 API
93
100
 
94
101
  - Scope: service-boundary contracts (HTTP/gRPC/etc), auth, and error contracts.
95
102
  - Goal: verify `CON-API-*` obligations from contracts.
96
- - Location rule: `tests/api/**`.
103
+ - Location rule: `<testsDir>/api/**`.
97
104
 
98
105
  ### L5 E2E
99
106
 
100
107
  - Scope: representative full-system journeys across UI/API/data.
101
108
  - Goal: verify `US-*` obligations from specs.
102
- - Location rule: `tests/e2e/**`.
109
+ - Location rule: `<testsDir>/e2e/**`.
103
110
 
104
111
  ## Layer derivation procedure (normative)
105
112
 
@@ -137,8 +144,23 @@ falsifying-oracle rule:
137
144
  observable at two layers, it is two obligations: write one TC per oracle and
138
145
  give each its own `Level`.
139
146
 
140
- - A multi-valued `Level` cell (`L3/L5`) is **illegal**. Nothing consumes it and
141
- no validator can route it.
147
+ - A multi-valued `Level` cell (`L3/L5`, `L1/L2`, `L1, L3`) is **illegal**. It
148
+ matches no entry in the crosswalk, so no rule can read a layer out of it.
149
+ - **What a reader does with one: split the row.** One TC per oracle, each with
150
+ its own single `Level`. Nothing else is a fix — in particular, do not record
151
+ a normalization that "drops one half": no tool performs one, and a note
152
+ saying an `L3/L5` row "normalizes to `L3`" is a claim about a value that only
153
+ `06_Test-Cases.md` can make.
154
+ - **What the validators do with one, until it is split.** They neither guess
155
+ nor let it through:
156
+ - `QFAI-ATDD-112` routes the TC to the same place a TC with no declared
157
+ `Level` goes — `<testsDir>/integration/**` — and keeps the obligation.
158
+ Unreadable is deliberately not "excused": if a cell qfai cannot read
159
+ discharged the obligation, `L1/L2` would be a one-keystroke way to delete
160
+ any TC from the gate. That default is where the obligation is _reported_,
161
+ not where the obligation _belongs_.
162
+ - `TDDLIST_UNKNOWN_LEVEL` (`warning`) names the cell, and the TC stays a
163
+ coverage target, so `tdd/test-list.md` still owes it a row.
142
164
  - If splitting is genuinely impossible, escalate through the Drift Protocol
143
165
  rather than inventing a combined value.
144
166
 
@@ -158,15 +180,40 @@ L4" applies only when the service-boundary values are themselves what the
158
180
  parent BR owns. Inverting this is what collapses a designed pyramid into an
159
181
  all-integration suite.
160
182
 
161
- ### Annotation routing is by ID type, not by `Level`
162
-
163
- The derived `Level` records which oracle owns the obligation. It does **not**
164
- move the traceability annotation. The [ATDD annotation hard gate](#atdd-annotation-hard-gate)
165
- routes by obligation ID: `US-*` is answered from `tests/e2e/**`
166
- (`QFAI-ATDD-111`), `TC-*` from `tests/integration/**` (`QFAI-ATDD-112`), and
167
- `CON-API-*` from `tests/api/**` (`QFAI-ATDD-113`); a `TC-*` reference inside
168
- `tests/api/**` or `tests/e2e/**` is rejected outright (`QFAI-ATDD-121` /
169
- `QFAI-ATDD-122`). Two consequences bind every `TC-*` row:
183
+ ### Annotation routing
184
+
185
+ The derived `Level` records which oracle owns the obligation, and the [ATDD annotation hard
186
+ gate](#atdd-annotation-hard-gate) routes each obligation ID to exactly one directory. `US-*` is
187
+ answered from `<testsDir>/e2e/**` (`QFAI-ATDD-111`) and `CON-API-*` from `<testsDir>/api/**`
188
+ (`QFAI-ATDD-113`); those two are fixed by the ID type. A `TC-*` is answered from the directory **its
189
+ own declared `Level`** names (`QFAI-ATDD-112`):
190
+
191
+ | `Level` | Answered from |
192
+ | ----------------------------- | ----------------------------------- |
193
+ | `L1`/`Unit` | no ATDD obligation |
194
+ | `L2`/`Component` | no ATDD obligation |
195
+ | `L3`/`Integration` | `<testsDir>/integration/**` |
196
+ | `L4`/`API` | `<testsDir>/api/**` (note) |
197
+ | `L5`/`E2E` | `<testsDir>/e2e/**` (note) |
198
+ | none declared | `<testsDir>/integration/**` |
199
+ | anything else — typo, `L3/L5` | `<testsDir>/integration/**` (note2) |
200
+
201
+ **(note)** A `TC-*` **should not be** at L4 or L5 — the first bullet below says
202
+ why and what to do instead. The gate routes it there rather than rejecting it so
203
+ a misfiled row is reported once, by the rule that names the real cause, instead
204
+ of twice as "uncovered in integration" and "forbidden in api".
205
+
206
+ **(note2)** A `Level` the crosswalk does not list — a typo, a project's own
207
+ word, or the illegal multi-valued cell — falls to the same default as an
208
+ undeclared one, and keeps its obligation. The default is the conservative
209
+ answer to a cell qfai cannot read, never a supported spelling: fix the cell
210
+ (see [Obligation spanning more than one layer](#obligation-spanning-more-than-one-layer)).
211
+ `TDDLIST_UNKNOWN_LEVEL` (`warning`) names such a cell on the ledger side.
212
+
213
+ Exactly one directory, never two: an annotation outside the one its `Level` names is both uncovered
214
+ and rejected (`QFAI-ATDD-121` / `QFAI-ATDD-122` / `QFAI-ATDD-123`), and the rejection is symmetric —
215
+ an annotation left in `<testsDir>/integration/**` after its TC moved to `L4`/`L5` is rejected the
216
+ same way an early one in `<testsDir>/api/**` is. Two consequences bind every `TC-*` row:
170
217
 
171
218
  - **A `TC-*` row's `Level` stays within L1–L3.** L4's goal is `CON-API-*` and
172
219
  L5's goal is `US-*` (see the layer definitions above), so an oracle that
@@ -185,22 +232,29 @@ routes by obligation ID: `US-*` is answered from `tests/e2e/**`
185
232
  parent BR keeps a spec-side obligation, split the row instead: keep a `TC-*`
186
233
  for the part the BR owns — by step 2 that part derives to L1–L3 — and re-file
187
234
  only the boundary assertion as `CON-API-*` / `US-*`.
188
- - **An L1/L2 `Level` does not relax `QFAI-ATDD-112`, and the gate does not
189
- change the `Level`.** The two are independent: the `Level` records what the
190
- oracle observes and is derived before any test exists, while the
191
- `QFAI:SPEC-XXXX:TC-YYYY` annotation is still owed to `tests/integration/**`.
192
- Never rewrite a derived L1/L2 to L3 because no integration trace exists yet —
193
- that would make the recorded oracle depend on implementation order and hide
194
- the unit/component work `/qfai-implement` selects. The missing annotation is
195
- an open ATDD obligation to satisfy, not evidence that the `Level` was wrong.
196
-
197
- ## TestKind resolution (single source)
198
-
199
- - `tests/unit/**` -> Unit
200
- - `tests/component/**` -> Component
201
- - `tests/e2e/**` -> E2E
202
- - `tests/api/**` -> API
203
- - `tests/integration/**` -> Integration
235
+ - **An L1/L2 `Level` carries no `QFAI-ATDD-112` obligation, and the gate does
236
+ not change the `Level`.** The two are independent: the `Level` records what
237
+ the oracle observes and is derived before any test exists, while
238
+ `QFAI-ATDD-112` asks only about the layers ATDD owns. Never rewrite a derived
239
+ L1/L2 to L3 to make a gate quieter — that would make the recorded oracle
240
+ depend on implementation order and hide the unit/component work
241
+ `/qfai-implement` selects. An L1/L2 row's obligation is discharged through
242
+ `tdd/test-list.md` and `TDDLIST_TC_NOT_COVERED`, not through an annotation in
243
+ a directory ATDD scans.
244
+
245
+ ## Directory → AtddTestKind (code-side, derived from the crosswalk)
246
+
247
+ Derived from `## Layer vocabulary crosswalk (normative)`, which is the
248
+ authority for this mapping. This list only restates the three kinds the ATDD
249
+ scan can resolve:
250
+
251
+ - `<testsDir>/integration/**` -> Integration
252
+ - `<testsDir>/api/**` -> API
253
+ - `<testsDir>/e2e/**` -> E2E
254
+
255
+ L1 Unit and L2 Component resolve to no kind. They follow project convention, no
256
+ directory maps to them, and none of them is scanned — see the crosswalk rules
257
+ and `**Unit and Component owe no ATDD annotation.**` above.
204
258
 
205
259
  ## Annotation schema (code-side)
206
260
 
@@ -219,7 +273,7 @@ routes by obligation ID: `US-*` is answered from `tests/e2e/**`
219
273
 
220
274
  - E2E obligations:
221
275
  - Every `US-*` in a **user-facing** spec must be referenced at least once from
222
- `tests/e2e/**`. "User-facing" is the same surface **union**
276
+ `<testsDir>/e2e/**`. "User-facing" is the same surface **union**
223
277
  `/qfai-prototyping` enforces. Any one of these signals puts a spec in it:
224
278
  - frontmatter `surface_type: ui-bearing` in `01_Spec.md`;
225
279
  - a matching UI contract `.qfai/contracts/ui/<spec-id>*.yaml` — a project
@@ -233,40 +287,59 @@ routes by obligation ID: `US-*` is answered from `tests/e2e/**`
233
287
  - Scoping applies only when the project declares at least one UI-bearing
234
288
  spec. A project that has never declared a surface has not opted into
235
289
  surface typing, so the obligation stays project-wide for it.
290
+ - **Deferral.** A story whose acceptance cannot be observed at E2E in the current slice defers with a `- x-qfai-status: planned` meta line inside its own `US-XXXX` block (a `##`-or-deeper heading, or its catalog list entry) in `02_User-stories.md` — the same token the two contract kinds use. It leaves `QFAI-ATDD-111` and is reported as `QFAI-ATDD-118` (`info`); remove the marker when the slice is implemented. It counts only inside the story block it is written in, so one above the first `US-XXXX` heading defers nothing — one line must not drop the obligation for a whole file. It removes the test obligation, not the declaration. A deferred `US-*` stays a known ID, so an early E2E test is counted, not an unknown reference. This is per story, unlike the surface-type scoping above, a whole-spec property that would erase the siblings too.
236
291
  - Do not create an E2E tree whose only purpose is to receive annotations.
237
292
  That is the "convert all obligations into E2E" anti-pattern below.
238
293
  - Use `QFAI:SPEC-XXXX:US-YYYY` annotations.
239
294
 
240
295
  - Integration obligations (enforced today):
241
- - Every `TC-*` in specs must be referenced at least once from the directory
242
- its declared `Level` routes to: L3/Integration -> `tests/integration/**`,
243
- L4/API -> `tests/api/**`, L5/E2E -> `tests/e2e/**`. A TC with no declared
244
- `Level` defaults to `tests/integration/**`. This is what `QFAI-ATDD-112`
245
- checks. - Use `QFAI:SPEC-XXXX:TC-YYYY` annotations.
246
- - `tests/api/**` and `tests/e2e/**` must not carry `TC-*` annotations
247
- (`QFAI-ATDD-121` / `QFAI-ATDD-122`), so an L4 obligation is discharged as a
248
- `CON-API-*` reference, never as a `TC-*` one.
249
- - Every declared `CON-DB-*` must be referenced at least once from
250
- `tests/integration/**` (`QFAI-ATDD-115`). Use `QFAI:CON-DB-XXXX`
251
- annotations. L3 owns this because a DB contract is only exercised against
252
- real infrastructure, which is L3's declared scope; a `CON-DB` reference
253
- from `tests/e2e/**` is not counted, or an end-to-end assertion that never
254
- touches the schema could close the obligation. A contract outside the
255
- current slice defers with a `-- x-qfai-status: planned` comment line,
256
- reported at `info` by `QFAI-ATDD-116` so the deferral stays visible.
257
-
258
- - Per-level routing (target state — **not enforced, do not follow yet**):
259
- - The intended end state is one required location per declared `Level`:
260
- L1 -> `tests/unit/**`, L2 -> `tests/component/**`,
261
- L3 -> `tests/integration/**`. L4 stays `CON-API-*` in `tests/api/**` and
262
- L5 stays `US-*` in `tests/e2e/**`.
263
- - **This is not live.** `buildAtddTestGlobs` scans only
264
- `tests/{e2e,api,integration}`, so an annotation placed in `tests/unit/**`
265
- or `tests/component/**` is invisible to the scanner and `QFAI-ATDD-112`
266
- still reports the TC as uncovered. Until the scanner and `QFAI-ATDD-112`
267
- resolve per-TC, keep discharging every `TC-*` in `tests/integration/**`.
296
+ - Every `TC-*` in specs must be referenced at least once from the directory its declared `Level`
297
+ routes to: L3/Integration -> `<testsDir>/integration/**`, L4/API -> `<testsDir>/api/**`, L5/E2E
298
+ -> `<testsDir>/e2e/**`. A TC with no declared `Level` defaults to `<testsDir>/integration/**`.
299
+ **L1/Unit and L2/Component owe no reference at all** — see "Unit and Component owe no ATDD
300
+ annotation" below. This is what `QFAI-ATDD-112` checks.
301
+ - Use `QFAI:SPEC-XXXX:TC-YYYY` annotations.
302
+ - A `TC-*` annotation outside the directory its declared `Level` names is rejected
303
+ (`QFAI-ATDD-121` / `QFAI-ATDD-122` / `QFAI-ATDD-123`). The rule is `Level`-relative, not a
304
+ blanket ban: a `TC-*` in `<testsDir>/api/**` is rejected **unless** that TC declares `L4`/`API`,
305
+ and in `<testsDir>/e2e/**` unless it declares `L5`/`E2E` — an annotation matching its own
306
+ `Level` is what discharges the obligation there. A `TC-*` should not be at L4 or L5 in the first
307
+ place (see "Annotation routing"): re-file that obligation as `CON-API-*` or `US-*`. But while
308
+ the row exists at that `Level`, its annotation belongs in the one directory the `Level` names,
309
+ and putting it anywhere else leaves the TC uncovered as well as forbidden.
310
+ - Every declared `CON-DB-*` must be referenced at least once from `<testsDir>/integration/**`
311
+ (`QFAI-ATDD-115`). Use `QFAI:CON-DB-XXXX` annotations. L3 owns this because a DB contract is
312
+ only exercised against real infrastructure, which is L3's declared scope; a `CON-DB` reference
313
+ from `<testsDir>/e2e/**` is not counted, or an end-to-end assertion that never touches the
314
+ schema could close the obligation. A contract outside the current slice defers with a
315
+ `-- x-qfai-status: planned` comment line, reported at `info` by `QFAI-ATDD-116` so the
316
+ deferral stays visible.
317
+
318
+ - **Unit and Component owe no ATDD annotation.** A `TC-*` whose declared
319
+ `Level` is L1 or L2 is outside `QFAI-ATDD-112` entirely: it is not required
320
+ in any directory, and an annotation for it inside a scanned directory is not
321
+ a violation either. `QFAI-ATDD-117` (`info`) names the excluded TCs on every
322
+ run so the exclusion is visible rather than silent.
323
+ - This is the only reading consistent with the rest of the package.
324
+ `qfai-atdd/SKILL.md` puts Unit and Component out of its scope, and the
325
+ crosswalk above gives L1/L2 no mandated directory — only L3-L5 are
326
+ directory-pinned and only those three roots are scanned.
327
+ - Previously L1/L2 fell through to `<testsDir>/integration/**` — the fallback for
328
+ a spec with no `Level` column at all — so every declared Unit and Component
329
+ TC was an `error` demanding an annotation in a directory this file says is
330
+ not its home. `QFAI-WAIVER-002` refuses waivers on `error` rules, so a
331
+ project that filed unit tests where L1's own entry says to had no exit, and
332
+ the only validator-clean path was duplicating every annotation into
333
+ `<testsDir>/integration/**` — the all-integration collapse named under
334
+ Anti-patterns below.
335
+ - **They are still gated, by the other stage.** Every coverage-target `TC-*`
336
+ owes a `tdd/test-list.md` row, and `TDDLIST_TC_NOT_COVERED` (`error`)
337
+ reports a missing one. L1/L2 belong to `/qfai-implement`, which is the
338
+ stage that writes unit and component tests.
339
+
340
+ - **An annotation carrier is not a test.** The scan reads `.feature` and `.md` too, and a file's kind is read from its body: a `.feature` with a `Scenario:` declares a test, a `.md` never does, and a `.test.ts` holding only the annotation is the same ledger renamed. An obligation no carrier declares a test for clears `QFAI-ATDD-111` / `-112` / `-113` / `-115` with nothing behind it, so `QFAI-ATDD-119` (`info`) names it — a legitimate placeholder that must not read as coverage. A repo-wide gate reads `missing.<kind>` **and** `coveredByCarrierOnly` in `summary.json`, never `missing` alone; a `--spec` gate reads the narrowed `QFAI-ATDD-119` in `validate.spec-<id>.json`, because `summary.json` is repo-wide under every scope. A skipped test still counts as declared, and the partition is suppressed, not empty, when `scan.truncated` says the scan was cut short.
268
341
  - API obligations:
269
- - Every declared `CON-API-*` must be referenced at least once from `tests/api/**`.
342
+ - Every declared `CON-API-*` must be referenced at least once from `<testsDir>/api/**`.
270
343
  - Use `QFAI:CON-API-XXXX` annotations.
271
344
  - **Deferral.** `/qfai-sdd` authors contracts in Phase 0 (Contracts-first) and
272
345
  slices them in Phase 2, so a contract legitimately exists before its slice
@@ -284,26 +357,28 @@ routes by obligation ID: `US-*` is answered from `tests/e2e/**`
284
357
  under `deferred.conApi`, so an empty `missing.conApi` can be told apart
285
358
  from a project where every contract is still planned.
286
359
  - Forbidden references:
287
- - `tests/api/**` must not include `QFAI:SPEC-XXXX:TC-YYYY` **for a TC whose
360
+ - `<testsDir>/api/**` must not include `QFAI:SPEC-XXXX:TC-YYYY` **for a TC whose
288
361
  declared `Level` is not L4/API**. A TC that declares an API-level
289
- obligation belongs in `tests/api/**`, and its annotation there counts as
362
+ obligation belongs in `<testsDir>/api/**`, and its annotation there counts as
290
363
  coverage. The rule exists to stop obligations drifting into the wrong
291
364
  layer, not to make the correct layer unusable.
292
- - `tests/e2e/**` must not include `QFAI:SPEC-XXXX:TC-YYYY` **for a TC whose
365
+ - `<testsDir>/e2e/**` must not include `QFAI:SPEC-XXXX:TC-YYYY` **for a TC whose
293
366
  declared `Level` is not L5/E2E**. Same reason as above: the routing rule
294
367
  and the forbidden rule must agree, or the layer the routing selects
295
368
  becomes unusable.
296
- - `tests/integration/**` must not include `QFAI:SPEC-XXXX:TC-YYYY` **for a TC
369
+ - `<testsDir>/integration/**` must not include `QFAI:SPEC-XXXX:TC-YYYY` **for a TC
297
370
  whose declared `Level` is not L3/Integration** (`QFAI-ATDD-123`). The rule
298
371
  is symmetric so "exactly one directory" holds in both directions: an
299
372
  annotation left behind here after the TC moved to L4/L5 is as wrong as one
300
- filed early into `tests/api/**`.
373
+ filed early into `<testsDir>/api/**`.
301
374
  - Unknown references (`US/TC/CON-API` not declared) are errors.
302
375
  - A `TC-*` annotation outside the directory its `Level` routes to is a
303
- misplacement, whichever directory it lands in — including the two new
304
- locations `tests/unit/**` and `tests/component/**`.
376
+ misplacement, whichever directory it lands in. **This applies to L3-L5 only.**
377
+ L1 and L2 route nowhere — they carry no ATDD annotation obligation at all — so
378
+ an annotation for one is neither required nor misplaced, in
379
+ `tests/unit/**`, `tests/component/**` or anywhere else.
305
380
  - AC annotations are not required in code; AC coverage is treated as indirect through TC coverage.
306
- - `QFAI:CON-API-*` in `tests/e2e/**` is not forbidden, but contract guarantee belongs to API tests.
381
+ - `QFAI:CON-API-*` in `<testsDir>/e2e/**` is not forbidden, but contract guarantee belongs to API tests.
307
382
 
308
383
  ## Test-file granularity
309
384
 
@@ -396,10 +471,9 @@ Treat these as review signals in the same class as volume floors — worth a fin
396
471
  - a very low `test_` functions per file ratio in a module that carries many obligations
397
472
  - a single selector whose recorded runtime grows monotonically across RED rounds
398
473
 
399
- ## Test stub detection (QFAI-TEST-001 / QFAI-TEST-002)
474
+ ## Test stub detection (QFAI-TEST-001 / -002 / -003)
400
475
 
401
- `QFAI-TEST-001` (error) reports the silent-placeholder construct of each
402
- supported stack:
476
+ `QFAI-TEST-001` (error) reports the silent-placeholder construct of each supported stack:
403
477
 
404
478
  | Extensions | Construct |
405
479
  | -------------------- | ------------------------------------------------------------------- |
@@ -411,6 +485,14 @@ supported stack:
411
485
  | `.rb` | a line starting `skip` / `pending` |
412
486
  | `.cs` | `[Ignore` / `Skip = "` |
413
487
 
488
+ `QFAI-TEST-003` (warning) is the JS/TS `.skip` family — `it.skip(` / `test.skip(` /
489
+ `describe.skip(`, chained `.each` spellings included. It is its own rule, not a graded-down
490
+ `QFAI-TEST-001`: a waiver is judged against the highest severity its rule produced in the run,
491
+ so sharing one code would let a single `.todo` promote the pair to `error` and take the
492
+ per-path waiver in `.qfai/waivers.yml` away from every `.skip`. The fix differs too — a `.skip`
493
+ keeps its body (it is what `npx qfai atdd scaffold` emits for a skeleton awaiting
494
+ implementation), so drop the modifier rather than delete the test.
495
+
414
496
  `QFAI-TEST-002` (info) names any extension the scan opened that has no dialect.
415
497
  Without it a clean run on an unsupported stack is indistinguishable from a
416
498
  checked one — the detector used to be JS-only while file selection was
@@ -3,9 +3,10 @@
3
3
  - Contract scope: frontmatter and body schema for `.qfai/steering/*.md` entries
4
4
  - Owners: the validate stage (schema enforcement), the implement stage (primary writer) and the Reviewer-Gate stage (consumer)
5
5
  - Used-by: All implementation/review-phase skills, `npx qfai validate`, Reviewer subagents
6
- - SSOT modules:
7
- - `packages/qfai/src/core/worklog/parseEntry.ts` (pure parser: `string → Result<Entry, SchemaError>`)
8
- - `packages/qfai/src/core/worklog/validateLinks.ts` (link-integrity check)
6
+ - SSOT modules (shipped inside the QFAI package, run by `npx qfai validate`):
7
+ - the work-log entry parser (`string → Result<Entry, SchemaError>`)
8
+ - the work-log link-integrity check
9
+ - The field checks, enums and required headings are compiled into the CLI, not read from this file: this document is their reference, so editing it does not change what `validate` accepts. Report a divergence as a QFAI bug instead of customizing the schema here.
9
10
 
10
11
  ## Storage model
11
12
 
@@ -15,9 +15,15 @@ version: 2.0.0
15
15
 
16
16
  # エージェント選択ガイド(QFAI Toolkit)
17
17
 
18
- QFAI のサブエージェントは、**agent-catalog + agent-routing + review-profiles** を SSOT とする。
18
+ QFAI のサブエージェントの**選定**は、**agent-catalog + agent-routing + review-profiles** を SSOT とする。
19
19
  選定は「成果物の種類」と「phase の役割」で行い、skill 本文の直感では決めない。
20
20
 
21
+ ただしエージェントの**本文(mission / responsibilities / stop conditions 等)**の SSOT は
22
+ `.qfai/assistant/agents/<id>.md` である。`agent-catalog.yml` の `developer_instructions`
23
+ はそこから導出される派生コピーであり、そこに新しい内容を書き起こさない。本文を変更するときは
24
+ markdown 側を編集し、その `## Mission` 見出し以降をそのままブロックへ写して一致させる
25
+ (乖離もブロックの欠落も `QFAI-AGENT-014` が警告する)。
26
+
21
27
  ## 中核原則
22
28
 
23
29
  - 司令塔は常に `orchestrator`
@@ -35,7 +35,7 @@ When an agent needs to ask the user a question, the following rules apply (see a
35
35
 
36
36
  All SKILL.md files MUST include a
37
37
  `## User Questions (AskUserQuestion Protocol)` section with MUST-level wording.
38
- SSOT: `packages/qfai/assets/init/.qfai/assistant/skills/*/SKILL.md`.
38
+ SSOT: the skill templates shipped inside the QFAI package.
39
39
  Deployed copy (updated by `npx qfai init`): `.qfai/assistant/skills/*/SKILL.md`.
40
40
 
41
41
  ## Error handling
@@ -1,7 +1,7 @@
1
1
  # QFAI Constitution (Non‑Negotiable)
2
2
 
3
3
  This document defines **non‑negotiable operating rules** for QFAI agents and subagents.
4
- It is inspired by proven “constitution / articles / guardrails” patterns in existing SDD toolchains, but tailored to QFAI’s minimal workflow.
4
+ It is inspired by proven “constitution / articles / guardrails” patterns in existing SDD toolchains, but adapted to QFAI’s minimal workflow.
5
5
 
6
6
  ---
7
7
 
@@ -160,10 +160,16 @@ This article survives context compaction because `constitution.md` is a P1 reloa
160
160
 
161
161
  All temporary files, scratch scripts, and intermediate build artifacts **MUST** be placed under the repository‑root `tmp/` directory.
162
162
 
163
+ Scope: this article is about files written **into the working tree** — scratch
164
+ scripts, intermediate build artifacts, downloaded fixtures, notes. A sandbox a
165
+ test creates with `mkdtemp` under the OS temporary directory is **not** covered:
166
+ it lives outside the repository, so it cannot put a file in any of the
167
+ directories Rule 1 protects, and the test that created it removes it.
168
+
163
169
  Rules:
164
170
 
165
171
  1. **Never** create temporary files in the repository root, `src/`, `.qfai/specs/`, or any other production/artifact directory.
166
172
  2. Use `tmp/` (repository root) as the sole staging area. Create subdirectories as needed (e.g., `tmp/glossary/`, `tmp/build/`).
167
173
  3. `tmp/` MUST be listed in `.gitignore` so temporary files are never committed.
168
174
  4. Clean up `tmp/` contents when the task that created them is complete.
169
- 5. If a temporary file is found outside `tmp/`, treat it as a defect and move or delete it immediately.
175
+ 5. If a temporary file is found outside `tmp/` **in the working tree**, treat it as a defect and move or delete it immediately. A test's `mkdtemp` sandbox is not one — see Scope above.