qfai 1.9.2 → 1.10.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.
- package/README.md +48 -2
- package/assets/init/.qfai/assistant/agents/acceptance-test-engineer.md +1 -0
- package/assets/init/.qfai/assistant/agents/backend-engineer.md +1 -0
- package/assets/init/.qfai/assistant/agents/completion-reviewer.md +13 -2
- package/assets/init/.qfai/assistant/agents/delivery-planner.md +9 -0
- package/assets/init/.qfai/assistant/agents/frontend-engineer.md +1 -0
- package/assets/init/.qfai/assistant/agents/implementation-reviewer.md +6 -0
- package/assets/init/.qfai/assistant/agents/orchestrator.md +2 -2
- package/assets/init/.qfai/assistant/agents/qa-gatekeeper.md +96 -3
- package/assets/init/.qfai/assistant/agents/test-design-analyst.md +20 -3
- package/assets/init/.qfai/assistant/catalog/cli-ux-guidelines.md +2 -2
- package/assets/init/.qfai/assistant/catalog/spec_required_files.json +2 -1
- package/assets/init/.qfai/assistant/catalog/test-layers.md +355 -14
- package/assets/init/.qfai/assistant/catalog/worklog-entry.schema.md +165 -0
- package/assets/init/.qfai/assistant/constitution/communication.md +1 -1
- package/assets/init/.qfai/assistant/constitution/drift-protocol.md +304 -10
- package/assets/init/.qfai/assistant/constitution/quality.md +35 -5
- package/assets/init/.qfai/assistant/constitution/requirements-decomposition.md +37 -0
- package/assets/init/.qfai/assistant/constitution/shared-skill-delegation-baseline.md +244 -8
- package/assets/init/.qfai/assistant/constitution/shared-skill-operating-baseline.md +122 -5
- package/assets/init/.qfai/assistant/constitution/workflow.md +53 -7
- package/assets/init/.qfai/assistant/manifest/agent-catalog.yml +316 -945
- package/assets/init/.qfai/assistant/manifest/agent-routing.yml +50 -4
- package/assets/init/.qfai/assistant/manifest/review-profiles.yml +9 -0
- package/assets/init/.qfai/assistant/process/migrations/v1.4.27-atdd-alignment.md +1 -1
- package/assets/init/.qfai/assistant/skills/qfai-atdd/SKILL.md +61 -21
- package/assets/init/.qfai/assistant/skills/qfai-atdd/references/test-case-depth-checklist.md +23 -4
- package/assets/init/.qfai/assistant/skills/qfai-configure/SKILL.md +15 -7
- package/assets/init/.qfai/assistant/skills/qfai-discussion/SKILL.md +8 -4
- package/assets/init/.qfai/assistant/skills/qfai-discussion/references/design-md-brand-catalog.md +2 -2
- package/assets/init/.qfai/assistant/skills/qfai-discussion/references/discussion-completion-matrix.md +17 -7
- package/assets/init/.qfai/assistant/skills/qfai-discussion/references/rcp_footer.md +10 -4
- package/assets/init/.qfai/assistant/skills/qfai-discussion/references/review-cycle-playbook.md +1 -1
- package/assets/init/.qfai/assistant/skills/qfai-discussion/references/ui-bearing-playbook.md +4 -4
- package/assets/init/.qfai/assistant/skills/qfai-discussion/references/ui_ux/review_audit_playbook.md +1 -1
- package/assets/init/.qfai/assistant/skills/qfai-discussion/references/ui_ux/trend_scan_playbook.md +1 -1
- package/assets/init/.qfai/assistant/skills/qfai-discussion/references/ui_ux_best_practices.md +17 -7
- package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/01_Context.md +1 -1
- package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/02_Inception-Deck.md +1 -1
- package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/03_Story-Workshop.md +11 -3
- package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/05_Scope.md +5 -2
- package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/07_NFR.md +1 -1
- package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/09_Constraints.md +7 -4
- package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/10_Policy.md +1 -1
- package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/11_OQ-Register.md +1 -1
- package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/12_OQ-Resolution-Log.md +1 -1
- package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/14_Review-Request.md +14 -7
- package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/99_delta.md +1 -1
- package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/review/Rxx_reviewer.md +16 -7
- package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/review/review_request.md +9 -6
- package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/uiux/40_screen_contracts.md +3 -2
- package/assets/init/.qfai/assistant/skills/qfai-discussion/templates/uiux/50_review_input_bundle.md +4 -2
- package/assets/init/.qfai/assistant/skills/qfai-implement/SKILL.md +250 -128
- package/assets/init/.qfai/assistant/skills/qfai-implement/references/change-request-reset.md +93 -0
- package/assets/init/.qfai/assistant/skills/qfai-implement/references/checkpoint-verification.md +106 -0
- package/assets/init/.qfai/assistant/skills/qfai-implement/references/cross-spec-ownership.md +73 -0
- package/assets/init/.qfai/assistant/skills/qfai-implement/references/evidence-revision.md +77 -0
- package/assets/init/.qfai/assistant/skills/qfai-implement/references/execution-ledger.md +303 -0
- package/assets/init/.qfai/assistant/skills/qfai-implement/references/final-checklist.md +19 -0
- package/assets/init/.qfai/assistant/skills/qfai-implement/references/finding-classification.md +49 -0
- package/assets/init/.qfai/assistant/skills/qfai-implement/references/ledger-preconditions.md +55 -0
- package/assets/init/.qfai/assistant/skills/qfai-implement/references/oracle-strength.md +81 -0
- package/assets/init/.qfai/assistant/skills/qfai-implement/references/parallelization-policy.md +235 -0
- package/assets/init/.qfai/assistant/skills/qfai-implement/references/red-admissibility.md +91 -0
- package/assets/init/.qfai/assistant/skills/qfai-implement/references/red-not-observable.md +70 -0
- package/assets/init/.qfai/assistant/skills/qfai-implement/references/relevant-test-suite.md +87 -0
- package/assets/init/.qfai/assistant/skills/qfai-implement/references/review-artifact-layout.md +31 -0
- package/assets/init/.qfai/assistant/skills/qfai-implement/references/round-evidence.md +102 -0
- package/assets/init/.qfai/assistant/skills/qfai-implement/references/selector-granularity.md +24 -0
- package/assets/init/.qfai/assistant/skills/qfai-implement/references/volume-policy.md +149 -0
- package/assets/init/.qfai/assistant/skills/qfai-prototyping/SKILL.md +35 -18
- package/assets/init/.qfai/assistant/skills/qfai-prototyping/references/evidence-requirements.md +1 -1
- package/assets/init/.qfai/assistant/skills/qfai-prototyping/references/generator-prompt.md +106 -7
- package/assets/init/.qfai/assistant/skills/qfai-prototyping/references/handoff.md +40 -11
- package/assets/init/.qfai/assistant/skills/qfai-prototyping/references/iteration-loop.md +48 -1
- package/assets/init/.qfai/assistant/skills/qfai-prototyping/templates/DESIGN.md.sample +6 -0
- package/assets/init/.qfai/assistant/skills/qfai-sdd/SKILL.md +82 -22
- package/assets/init/.qfai/assistant/skills/qfai-sdd/references/contract-artifact-rules.md +148 -0
- package/assets/init/.qfai/assistant/skills/qfai-sdd/references/rcp_footer.md +10 -4
- package/assets/init/.qfai/assistant/skills/qfai-sdd/references/review-cycle-playbook.md +1 -1
- package/assets/init/.qfai/assistant/skills/qfai-sdd/references/sdd-execution-playbook.md +4 -2
- package/assets/init/.qfai/assistant/skills/qfai-sdd/references/sdd-phase-checklists.md +18 -0
- package/assets/init/.qfai/assistant/skills/qfai-sdd/references/sdd-quality-gate.md +44 -3
- package/assets/init/.qfai/assistant/skills/qfai-sdd/references/sdd-triage.md +60 -7
- package/assets/init/.qfai/assistant/skills/qfai-sdd/references/spec-traceability-rules.md +157 -5
- package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/change-request.md +125 -0
- package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/contracts/db-contract.sample.sql +6 -0
- package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/evidence/sdd-spec.md +92 -0
- package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/_policies/01_Objective.md +27 -0
- package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/_policies/02_Initiative.md +30 -0
- package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/_policies/05_Contracts.md +16 -6
- package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/_policies/06_Glossary.md +19 -0
- package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/_policies/07_Constraints.md +25 -0
- package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/_policies/08_Decisions.md +22 -2
- package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/_policies/11_Slice-Policy.md +37 -10
- package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/spec/02_User-stories.md +20 -0
- package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/spec/03_Acceptance-Criteria.md +19 -0
- package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/spec/04_Business-Rules.md +32 -3
- package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/spec/06_Test-Cases.md +56 -0
- package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/spec/07_Decisions.md +29 -2
- package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/spec/10_Plan.md +41 -0
- package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/spec/16_Traceability-ledger.md +58 -0
- package/assets/init/.qfai/assistant/skills/qfai-sdd/templates/specs/spec/tdd/test-list.md +56 -0
- package/assets/init/.qfai/assistant/skills/qfai-verify/SKILL.md +57 -102
- package/assets/init/.qfai/assistant/skills/qfai-verify/references/articles.md +24 -0
- package/assets/init/.qfai/assistant/skills/qfai-verify/references/context-load.md +22 -0
- package/assets/init/.qfai/assistant/skills/qfai-verify/references/verify-output-contract.md +48 -0
- package/assets/init/.qfai/assistant/skills/qfai-verify/templates/verify-evidence.md +48 -0
- package/assets/init/.qfai/assistant/skills/web-research/SKILL.md +25 -7
- package/assets/init/.qfai/waivers.yml +11 -5
- package/assets/init/root/DESIGN.md +6 -0
- package/assets/init/root/qfai.config.yaml +15 -12
- package/dist/cli/index.cjs +11023 -7139
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.mjs +10963 -7080
- package/dist/cli/index.mjs.map +1 -1
- package/dist/index.cjs +8782 -5257
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +280 -8
- package/dist/index.d.ts +280 -8
- package/dist/index.mjs +11776 -8264
- package/dist/index.mjs.map +1 -1
- package/package.json +18 -19
package/dist/index.d.ts
CHANGED
|
@@ -27,6 +27,12 @@ type Issue = {
|
|
|
27
27
|
suppressed?: boolean;
|
|
28
28
|
suggested_action?: string;
|
|
29
29
|
file?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Every other file this finding implicates, when `file` is only a
|
|
32
|
+
* representative (a duplicate ID is defined in N files but reported once).
|
|
33
|
+
* `--spec` scoping keeps the finding if any of these is in scope.
|
|
34
|
+
*/
|
|
35
|
+
relatedFiles?: string[];
|
|
30
36
|
refs?: string[];
|
|
31
37
|
rule?: string;
|
|
32
38
|
loc?: IssueLocation;
|
|
@@ -169,8 +175,10 @@ type QfaiPrototypingExecutionConfig = {
|
|
|
169
175
|
*
|
|
170
176
|
* Accepted values during the deprecation window:
|
|
171
177
|
* - `"playwright"` (primary, post-1.9.x default).
|
|
172
|
-
* - `"playwright-cli"` (deprecated; sunset
|
|
173
|
-
* the doctor probe emits `D-DEPRECATED-PROBE`
|
|
178
|
+
* - `"playwright-cli"` (deprecated; sunset `SUNSETS.playwrightCli`).
|
|
179
|
+
* Inside the window the doctor probe emits `D-DEPRECATED-PROBE` at
|
|
180
|
+
* `warning`; from the sunset onwards `normalizePrototypingExecution`
|
|
181
|
+
* rejects the value and the probe reports `error`.
|
|
174
182
|
*
|
|
175
183
|
* At sunset only `"playwright"` is accepted.
|
|
176
184
|
*/
|
|
@@ -246,7 +254,7 @@ declare function loadConfig(root: string): Promise<ConfigLoadResult>;
|
|
|
246
254
|
declare function resolvePath(root: string, config: QfaiConfig, key: ConfigPathKey): string;
|
|
247
255
|
|
|
248
256
|
type AtddTestKind = "e2e" | "api" | "integration";
|
|
249
|
-
type AtddUnknownRefKind = "us" | "tc" | "conApi";
|
|
257
|
+
type AtddUnknownRefKind = "us" | "tc" | "conApi" | "conDb";
|
|
250
258
|
type AtddUnknownRef = {
|
|
251
259
|
file: string;
|
|
252
260
|
token: string;
|
|
@@ -267,27 +275,109 @@ type AtddTraceabilityMissing = {
|
|
|
267
275
|
us: string[];
|
|
268
276
|
tc: string[];
|
|
269
277
|
conApi: string[];
|
|
278
|
+
conDb: string[];
|
|
270
279
|
};
|
|
271
280
|
type AtddCodeTraceabilityResult = {
|
|
272
281
|
specsRoot: string;
|
|
273
282
|
contractsApiRoot: string;
|
|
274
283
|
specUsIds: Map<string, Set<string>>;
|
|
275
284
|
specTcIds: Map<string, Set<string>>;
|
|
285
|
+
/**
|
|
286
|
+
* Every declared `CON-API-*`, active and deferred alike. This is the public
|
|
287
|
+
* meaning the field has always had — adding `x-qfai-status: planned` defers
|
|
288
|
+
* the test obligation, it does not un-declare the contract, so an external
|
|
289
|
+
* consumer using this set for "is this ID declared?" must keep seeing it.
|
|
290
|
+
*/
|
|
276
291
|
apiContractIds: Set<string>;
|
|
292
|
+
/** The subset that carries the `QFAI-ATDD-113` obligation. */
|
|
293
|
+
activeApiContractIds: Set<string>;
|
|
294
|
+
/**
|
|
295
|
+
* `CON-API-*` IDs excluded from the `QFAI-ATDD-113` obligation because their
|
|
296
|
+
* contract declares `x-qfai-status: planned`. Reported as `info` so the
|
|
297
|
+
* deferral stays visible instead of silently shrinking the gate.
|
|
298
|
+
*/
|
|
299
|
+
deferredApiContractIds: Set<string>;
|
|
300
|
+
contractsDbRoot: string;
|
|
301
|
+
/** Every declared `CON-DB-*`, active and deferred alike. */
|
|
302
|
+
dbContractIds: Set<string>;
|
|
303
|
+
/** The subset that carries the `QFAI-ATDD-115` obligation. */
|
|
304
|
+
activeDbContractIds: Set<string>;
|
|
305
|
+
/** `CON-DB-*` deferred by `-- x-qfai-status: planned`; reported at `info`. */
|
|
306
|
+
deferredDbContractIds: Set<string>;
|
|
277
307
|
refs: {
|
|
278
308
|
us: AtddSpecRefs;
|
|
279
309
|
tc: AtddSpecRefs;
|
|
280
310
|
api: Map<string, Set<string>>;
|
|
311
|
+
/**
|
|
312
|
+
* `CON-DB-*` references found in integration tests. L3 Integration is the
|
|
313
|
+
* layer whose declared scope is real-infrastructure integration including
|
|
314
|
+
* the database, so it is the one that can actually exercise a DB contract.
|
|
315
|
+
*/
|
|
316
|
+
db: Map<string, Set<string>>;
|
|
281
317
|
};
|
|
282
318
|
unknown: AtddUnknownRef[];
|
|
283
319
|
forbidden: {
|
|
284
320
|
tcInApi: AtddForbiddenRef[];
|
|
285
321
|
tcInE2e: AtddForbiddenRef[];
|
|
322
|
+
/** TC annotated under integration although its declared Level routes elsewhere. */
|
|
323
|
+
tcInIntegration: AtddForbiddenRef[];
|
|
286
324
|
};
|
|
287
325
|
missing: AtddTraceabilityMissing;
|
|
326
|
+
/**
|
|
327
|
+
* Formatted missing TC ref -> the test kind its declared `Level` routes to.
|
|
328
|
+
* Lets the CLI phrase `QFAI-ATDD-112` (message, `suggested_action`, report)
|
|
329
|
+
* per declared layer instead of naming `tests/integration/**` for every TC.
|
|
330
|
+
*/
|
|
331
|
+
missingTcHomes: Map<string, AtddTestKind>;
|
|
332
|
+
/** Test files outside the scanned roots; surfaced instead of dropped. */
|
|
333
|
+
skippedTestFiles: string[];
|
|
288
334
|
scan: AtddTraceabilityScan;
|
|
289
335
|
};
|
|
336
|
+
/** Test directory each `AtddTestKind` owns, for user-facing messages. */
|
|
337
|
+
declare const ATDD_TEST_KIND_DIRS: Record<AtddTestKind, string>;
|
|
338
|
+
/**
|
|
339
|
+
* The same map rendered against the project's configured `paths.testsDir`.
|
|
340
|
+
*
|
|
341
|
+
* The scan already follows `testsDir`, so a project that renamed it to e.g.
|
|
342
|
+
* `spec-tests` would otherwise be told by `QFAI-ATDD-112` to annotate
|
|
343
|
+
* `tests/api/**` — a directory the scan never reads, leaving the finding
|
|
344
|
+
* unclearable. A root-level layout (`testsDir: "."`) is the same trap in the
|
|
345
|
+
* other direction: the scan reads `api/**` at the repository root, so the
|
|
346
|
+
* `tests/` segment must be dropped rather than kept.
|
|
347
|
+
* {@link ATDD_TEST_KIND_DIRS} stays as the default-shaped fallback for callers
|
|
348
|
+
* with no config in hand.
|
|
349
|
+
*/
|
|
350
|
+
declare function atddTestKindDirs(testsDirRelative: string): Record<AtddTestKind, string>;
|
|
290
351
|
declare function evaluateAtddCodeTraceability(root: string, config: QfaiConfig): Promise<AtddCodeTraceabilityResult>;
|
|
352
|
+
declare const PLANNED_CONTRACT_KEY = "x-qfai-status";
|
|
353
|
+
/**
|
|
354
|
+
* True when the contract declares itself not yet implemented.
|
|
355
|
+
*
|
|
356
|
+
* `/qfai-sdd` authors contracts in Phase 0 (Contracts-first) but slices them in
|
|
357
|
+
* Phase 2, so between the second contract and the last slice every declared
|
|
358
|
+
* `CON-API-*` would otherwise be a `QFAI-ATDD-113` error. The marker makes the
|
|
359
|
+
* deferral explicit and reviewable in the contract itself.
|
|
360
|
+
*
|
|
361
|
+
* The marker is only honoured at the **document root**. A text scan that
|
|
362
|
+
* accepted any indentation would let an `x-qfai-status: planned` on a single
|
|
363
|
+
* OpenAPI operation defer the whole file, silently dropping the API-test
|
|
364
|
+
* obligation for every other `CON-API-*` it declares. The document is therefore
|
|
365
|
+
* parsed (YAML is a superset of JSON, so both contract formats go through the
|
|
366
|
+
* same path) and only a top-level key counts. An unparseable document falls
|
|
367
|
+
* back to a column-0 text match, which cannot see a nested key either.
|
|
368
|
+
*/
|
|
369
|
+
declare function isPlannedApiContract(text: string): boolean;
|
|
370
|
+
/**
|
|
371
|
+
* Derives the per-layer file pattern from the project's configured
|
|
372
|
+
* `testFileGlobs`, so a non-JS repository is scanned with its own extensions.
|
|
373
|
+
*
|
|
374
|
+
* Configured globs describe whole paths (`tests/**\/*.py`); the ATDD scan needs
|
|
375
|
+
* a pattern to append under `tests/{e2e,api,integration}/`. The extension set is
|
|
376
|
+
* therefore lifted out of them, unioned with the structural annotation carriers
|
|
377
|
+
* above, and recombined. When no extension can be recovered, the JS/TS default
|
|
378
|
+
* is used.
|
|
379
|
+
*/
|
|
380
|
+
declare function deriveAtddFilePattern(testFileGlobs: readonly string[]): string;
|
|
291
381
|
|
|
292
382
|
type GuardrailType = "non-goal" | "not-now" | "trade-off";
|
|
293
383
|
type DecisionGuardrailEntry = {
|
|
@@ -351,12 +441,77 @@ declare function filterDecisionGuardrailsByKeyword(items: DecisionGuardrail[], k
|
|
|
351
441
|
declare function formatGuardrailsForLlm(items: DecisionGuardrail[], max: number): string;
|
|
352
442
|
declare function checkDecisionGuardrails(entries: DecisionGuardrailEntry[]): GuardrailCheckResult;
|
|
353
443
|
|
|
354
|
-
type IdPrefix = "CAP" | "SPEC" | "US" | "BR" | "SC" | "AC" | "CASE" | "UI" | "API" | "DB" | "THEMA";
|
|
355
|
-
|
|
444
|
+
type IdPrefix = "CAP" | "SPEC" | "US" | "BR" | "SC" | "AC" | "EX" | "TC" | "CASE" | "UI" | "API" | "DB" | "THEMA";
|
|
445
|
+
/**
|
|
446
|
+
* Prefixes with a declared format but no membership in {@link ID_PREFIXES}.
|
|
447
|
+
*
|
|
448
|
+
* `DR` joins `ADR` here rather than in `ID_PREFIXES` because a Decision Record
|
|
449
|
+
* is not a spec-pack item: `extractAllIds` walks the layers a spec decomposes
|
|
450
|
+
* into, and sweeping `DR-*` into that walk would make every citation of a
|
|
451
|
+
* decision look like an undeclared spec item to the traceability rules.
|
|
452
|
+
*
|
|
453
|
+
* What was missing is the *format*. `qfai-implement` makes a non-empty `DR-ID`
|
|
454
|
+
* the hard precondition for the `exception` status and `tddList.ts` enforces it
|
|
455
|
+
* at `error`, but no ID class existed — so any non-empty string satisfied the
|
|
456
|
+
* gate, including a token the operator invented on the spot.
|
|
457
|
+
*/
|
|
458
|
+
type IdFormatPrefix = IdPrefix | "ADR" | "DR";
|
|
356
459
|
declare const ID_PREFIXES: IdPrefix[];
|
|
357
|
-
|
|
460
|
+
/**
|
|
461
|
+
* Every strict-format match for `prefix`.
|
|
462
|
+
*
|
|
463
|
+
* Takes {@link IdFormatPrefix}, not {@link IdPrefix}: `ADR` and `DR` have a
|
|
464
|
+
* declared format but are not spec-pack items, and a caller asking for one
|
|
465
|
+
* should not have to assert its way past the type. `extractAllIds` still walks
|
|
466
|
+
* {@link ID_PREFIXES} only, so the decomposition layers are unchanged.
|
|
467
|
+
*/
|
|
468
|
+
declare function extractIds(text: string, prefix: IdFormatPrefix): string[];
|
|
358
469
|
declare function extractAllIds(text: string): string[];
|
|
359
|
-
|
|
470
|
+
/**
|
|
471
|
+
* The one section whose fenced bodies are primary spec content: the v1421
|
|
472
|
+
* `03_Acceptance-Criteria.md` `## AC Gherkin (required)` block. Masking it
|
|
473
|
+
* would let a mistyped required definition (`# AC-0001-1`) reach
|
|
474
|
+
* `validateLayeredIdFormat` as if it did not exist.
|
|
475
|
+
*/
|
|
476
|
+
declare const AC_GHERKIN_SECTION = "ac gherkin (required)";
|
|
477
|
+
type FenceMaskOptions = {
|
|
478
|
+
/**
|
|
479
|
+
* Normalized H2 heading (see {@link AC_GHERKIN_SECTION}) whose fenced bodies
|
|
480
|
+
* stay in the ID scan when their info string is a Gherkin dialect. Omitted:
|
|
481
|
+
* every fence body is masked.
|
|
482
|
+
*/
|
|
483
|
+
scannedSection?: string;
|
|
484
|
+
};
|
|
485
|
+
/**
|
|
486
|
+
* Blanks the body of illustrative fenced code blocks while preserving the line
|
|
487
|
+
* count, so an ID-shaped token inside a sample or a diagram is not read as a
|
|
488
|
+
* spec ID and reported line numbers still point at the source file.
|
|
489
|
+
*
|
|
490
|
+
* Two properties matter:
|
|
491
|
+
*
|
|
492
|
+
* - A fence closes only on the **same marker character** at **at least the
|
|
493
|
+
* opening length**. A ```` ```` ```` block that quotes a ```` ``` ```` sample
|
|
494
|
+
* inside itself is legal markdown; toggling on any fence line would end the
|
|
495
|
+
* outer block early and re-expose the very sample it was hiding.
|
|
496
|
+
* - A fence keeps its body only when it is tagged with a
|
|
497
|
+
* `SCANNED_FENCE_LANGUAGES` info string **and** sits inside
|
|
498
|
+
* `options.scannedSection`. Keying on the language alone exempted every
|
|
499
|
+
* ```` ```gherkin ```` block in every layered file — including an
|
|
500
|
+
* illustration in a Purpose paragraph — which is the case the mask exists
|
|
501
|
+
* for. Only the required AC Gherkin section is the spec's own definition.
|
|
502
|
+
*/
|
|
503
|
+
declare function maskFencedCodeBlocks(text: string, options?: FenceMaskOptions): string;
|
|
504
|
+
type InvalidIdOccurrence = {
|
|
505
|
+
id: string;
|
|
506
|
+
/** 1-based line number in the original text. */
|
|
507
|
+
line: number;
|
|
508
|
+
};
|
|
509
|
+
/**
|
|
510
|
+
* Finds ID-shaped tokens that do not match their prefix's canonical format,
|
|
511
|
+
* with the line each was first seen on. Fenced code blocks are excluded.
|
|
512
|
+
*/
|
|
513
|
+
declare function extractInvalidIdOccurrences(text: string, prefixes: IdFormatPrefix[], options?: FenceMaskOptions): InvalidIdOccurrence[];
|
|
514
|
+
declare function extractInvalidIds(text: string, prefixes: IdFormatPrefix[], options?: FenceMaskOptions): string[];
|
|
360
515
|
declare function extractSpecNumber(specId: string): string | null;
|
|
361
516
|
declare function extractCapSpecNumber(capId: string): string | null;
|
|
362
517
|
declare function extractUsSpecNumber(usId: string): string | null;
|
|
@@ -450,6 +605,20 @@ type ReportTraceability = {
|
|
|
450
605
|
type ReportTestStrategy = {
|
|
451
606
|
totalScenarios: number;
|
|
452
607
|
limit: number;
|
|
608
|
+
/**
|
|
609
|
+
* Where the layer buckets came from.
|
|
610
|
+
*
|
|
611
|
+
* `scenario-tags` is the Gherkin `@layer-*` path, which only exists for the
|
|
612
|
+
* legacy `scenario.feature` layout. On the v1421 layered layout
|
|
613
|
+
* `examplesPath` is the **Markdown** `05_Examples.md`, so the parse failed,
|
|
614
|
+
* the error was swallowed by `continue`, and every bucket printed 0 — while
|
|
615
|
+
* the toolkit mandates layer routing and gates completion on it.
|
|
616
|
+
* `ledger-layer` is the `Layer` column of `tdd/test-list.md`, which is the
|
|
617
|
+
* artifact the shipped templates actually produce.
|
|
618
|
+
*/
|
|
619
|
+
layerSource: "scenario-tags" | "ledger-layer" | "none";
|
|
620
|
+
/** Scenario files that failed to parse; reported instead of silently zeroed. */
|
|
621
|
+
unparsedScenarioFiles: string[];
|
|
453
622
|
layer: Record<"unit" | "component" | "integration" | "api" | "e2e" | "none" | "unknown", number>;
|
|
454
623
|
size: Record<"s" | "m" | "l" | "none" | "unknown", number>;
|
|
455
624
|
missing: {
|
|
@@ -545,8 +714,12 @@ type ReportTddCoverageSpec = {
|
|
|
545
714
|
specNumber: string;
|
|
546
715
|
unitComponentTotal: number;
|
|
547
716
|
doneCount: number;
|
|
717
|
+
/** Has a passing test, has not cleared its blocking reviewers / checkpoint. */
|
|
718
|
+
inReviewCount: number;
|
|
548
719
|
exceptionCount: number;
|
|
549
720
|
openCount: number;
|
|
721
|
+
/** Open rows that cannot be started, reported apart from "not started yet". */
|
|
722
|
+
blockedCount: number;
|
|
550
723
|
missingTcRefs: string[];
|
|
551
724
|
exceptionRows: Array<{
|
|
552
725
|
tddId: string;
|
|
@@ -699,6 +872,12 @@ declare function formatReportJson(data: ReportData): string;
|
|
|
699
872
|
type ValidationOptions = {
|
|
700
873
|
profile?: ValidationProfile;
|
|
701
874
|
platform?: string;
|
|
875
|
+
/**
|
|
876
|
+
* Restrict the run to the named specs (`--spec`). Repo-level findings are
|
|
877
|
+
* always kept; only findings owned by an out-of-scope `spec-NNNN` directory
|
|
878
|
+
* are dropped, and per-spec report writes are skipped for them.
|
|
879
|
+
*/
|
|
880
|
+
specIds?: readonly string[];
|
|
702
881
|
};
|
|
703
882
|
declare function validateProject(root: string, configResult?: ConfigLoadResult, options?: ValidationOptions): Promise<ValidationResult>;
|
|
704
883
|
|
|
@@ -720,6 +899,61 @@ declare function validateSpecSplitByCapability(root: string, config: QfaiConfig)
|
|
|
720
899
|
declare function validateTraceability(root: string, config: QfaiConfig, options: {
|
|
721
900
|
includeCodeReferences: boolean;
|
|
722
901
|
}): Promise<Issue[]>;
|
|
902
|
+
type TraceabilityGraphNode = {
|
|
903
|
+
id: string;
|
|
904
|
+
layer: string;
|
|
905
|
+
path?: string;
|
|
906
|
+
};
|
|
907
|
+
type TraceabilityGraphEdge = {
|
|
908
|
+
from: string;
|
|
909
|
+
to: string;
|
|
910
|
+
type: string;
|
|
911
|
+
};
|
|
912
|
+
type TraceabilityGraph = {
|
|
913
|
+
nodes: TraceabilityGraphNode[];
|
|
914
|
+
edges: TraceabilityGraphEdge[];
|
|
915
|
+
};
|
|
916
|
+
/**
|
|
917
|
+
* Builds the requirement graph from the parsed spec pack.
|
|
918
|
+
*
|
|
919
|
+
* Exposed so the per-run `traceability.json` artifact can be populated from the specs themselves
|
|
920
|
+
* rather than from the refs of emitted findings. Deriving it from findings inverted the artifact's
|
|
921
|
+
* intent: it was empty precisely when the spec pack was healthy, and populated only with IDs that
|
|
922
|
+
* failed.
|
|
923
|
+
*
|
|
924
|
+
* Every layered style `collectSpecEntries` recognises is walked, because restricting this to the
|
|
925
|
+
* v1416 style `validateTraceability` gates would leave the artifact empty for every spec written
|
|
926
|
+
* in the current v1421 layout. The layer vocabulary differs per style — v1416 links
|
|
927
|
+
* `US -> AC -> BR -> SC -> CASE`, v1417/v1421 link `US -> AC -> BR -> EX -> TC` — so the edge
|
|
928
|
+
* types differ too; the node/edge shape does not.
|
|
929
|
+
*
|
|
930
|
+
* Emits no issues; parse problems are reported by `validateTraceability` and
|
|
931
|
+
* `validateLayerCoverage` on the same inputs.
|
|
932
|
+
*/
|
|
933
|
+
declare function buildLayeredTraceabilityGraph(root: string, config: QfaiConfig): Promise<TraceabilityGraph>;
|
|
934
|
+
/**
|
|
935
|
+
* Make an item ID unique across the pack.
|
|
936
|
+
*
|
|
937
|
+
* Item IDs are file-local (`spec-traceability-rules.md`, "ID and Parent
|
|
938
|
+
* Rules") and the shipped templates start every spec at `US-0001` / `AC-0001`,
|
|
939
|
+
* so two specs using the short form collide. Keying the graph on the raw ID
|
|
940
|
+
* silently dropped the second spec's nodes and overwrote its same-shaped edges,
|
|
941
|
+
* leaving `traceability.json` holding only the first spec's paths.
|
|
942
|
+
*
|
|
943
|
+
* The composite form already carries its spec number, so it is left untouched —
|
|
944
|
+
* qualifying it would rewrite every ID in the packs that actually ship today
|
|
945
|
+
* for no gain.
|
|
946
|
+
*/
|
|
947
|
+
declare function qualifyId(specNumber: string, id: string): string;
|
|
948
|
+
/**
|
|
949
|
+
* The spec number owning `filePath`, or `null` for a repo-level file.
|
|
950
|
+
*
|
|
951
|
+
* Exported next to {@link qualifyId} because every producer of graph IDs has to
|
|
952
|
+
* namespace them the same way. A finding-derived node built from a raw short ID
|
|
953
|
+
* lands beside — not on — the `spec-NNNN/AC-0001` node the edges point at, and
|
|
954
|
+
* two specs' findings then merge onto the same unqualified node.
|
|
955
|
+
*/
|
|
956
|
+
declare function specNumberForPath(filePath: string | undefined): string | null;
|
|
723
957
|
|
|
724
958
|
type SurfaceType = CanonicalPrototypingSurface | "non-ui";
|
|
725
959
|
declare const DISCUSSION_UI_BEARING_SURFACES: Set<SurfaceType>;
|
|
@@ -932,5 +1166,43 @@ type ParseResult = {
|
|
|
932
1166
|
declare function parseDesignMd(text: string): ParseResult;
|
|
933
1167
|
declare function validateDesignMd(d: DesignMd): ValidationIssue[];
|
|
934
1168
|
declare function hashDesignMd(text: string): string;
|
|
1169
|
+
/**
|
|
1170
|
+
* Sentinel carried by every DESIGN.md the package ships as a sample:
|
|
1171
|
+
* - `assets/init/root/DESIGN.md` (seeded into the project root by `qfai init`)
|
|
1172
|
+
* - `assets/init/.qfai/assistant/skills/qfai-prototyping/templates/DESIGN.md.sample`
|
|
1173
|
+
*
|
|
1174
|
+
* The two files are the same fictional brand but are NOT byte-identical
|
|
1175
|
+
* (they differ in front-matter whitespace alignment), so a sha256-equality
|
|
1176
|
+
* guard would have to enumerate — and keep in sync — one digest per shipped
|
|
1177
|
+
* sample. A marker is content-addressed instead of byte-addressed: it
|
|
1178
|
+
* survives whitespace edits, covers both samples with one constant, and
|
|
1179
|
+
* keeps covering any future sample that carries it.
|
|
1180
|
+
*
|
|
1181
|
+
* The marker lives in the markdown body, so `parseDesignMd` (which only
|
|
1182
|
+
* reads front-matter) is unaffected: an unreplaced sample still parses and
|
|
1183
|
+
* validates, and is rejected by identity instead.
|
|
1184
|
+
*/
|
|
1185
|
+
declare const DESIGN_MD_SAMPLE_MARKER = "QFAI-SAMPLE-DESIGN-MD";
|
|
1186
|
+
/**
|
|
1187
|
+
* True when `text` is still (or is derived from) a DESIGN.md the package
|
|
1188
|
+
* ships as a sample. Used to stop `/qfai-sdd` Phase 0 from sha256-freezing
|
|
1189
|
+
* an unauthored brand as the project's brand contract, and to surface the
|
|
1190
|
+
* same condition from `qfai validate` (QFAI-DCON-034).
|
|
1191
|
+
*
|
|
1192
|
+
* Two detectors, because the marker only covers samples seeded by releases
|
|
1193
|
+
* that carry it:
|
|
1194
|
+
* 1. `DESIGN_MD_SAMPLE_MARKER` — current samples, survives any edit that
|
|
1195
|
+
* leaves the comment in place.
|
|
1196
|
+
* 2. Legacy content fingerprint — samples seeded before the marker
|
|
1197
|
+
* existed, which `qfai init` will never overwrite.
|
|
1198
|
+
*
|
|
1199
|
+
* `text` is `unknown` rather than `string` because this is re-exported from
|
|
1200
|
+
* `core/index.ts` and so is reachable from untyped JavaScript, where a caller
|
|
1201
|
+
* can hand over the result of a read that failed or a value that was never a
|
|
1202
|
+
* file body. The guard below is what makes that safe; typing the parameter
|
|
1203
|
+
* `string` would have made it dead code that only looked defensive. Internal
|
|
1204
|
+
* callers pass a string and are unaffected.
|
|
1205
|
+
*/
|
|
1206
|
+
declare function isUnreplacedDesignMdSample(text: unknown): boolean;
|
|
935
1207
|
|
|
936
|
-
export { ARCHETYPES, type Archetype, type AtddCodeTraceabilityResult, type AtddForbiddenRef, type AtddSpecRefs, type AtddTestKind, type AtddTraceabilityMissing, type AtddTraceabilityScan, type AtddUnknownRef, type AtddUnknownRefKind, BROWSER_QA_PHASES, COLOR_KEYS, type ColorKey, type ConfigLoadResult, type ConfigPathKey, type ConfigSearchResult, DISCUSSION_NON_UI_SURFACES, DISCUSSION_UI_BEARING_SURFACES, type DecisionGuardrail, type DecisionGuardrailEntry, type DesignMd, type DesignMdColors, type DesignMdFonts, type DesignMdRadius, type DesignMdShadow, FONT_KEYS, type FailOn, type FontKey, type GuardrailCheckResult, type GuardrailIssue, type GuardrailIssueSeverity, type GuardrailLoadError, type GuardrailLoadResult, type GuardrailType, ID_PREFIXES, type IdFormatPrefix, type IdPrefix, type Issue, type IssueCategory, type IssueLocation, type IssueSeverity, type OrphanContractsPolicy, type OutputFormat, PROTOTYPING_SUPPORTED_SURFACES, type ParseError, type ParseResult, type PrototypingBrowserTool, type PrototypingSurface, type QfaiAtddConfig, type QfaiConfig, type QfaiOutputConfig, type QfaiPaths, type QfaiPrototypingCalibrationConfig, type QfaiPrototypingConfig, type QfaiPrototypingExecutionConfig, type QfaiReviewConfig, type QfaiUiuxAuditConfig, type QfaiUiuxConfig, type QfaiValidationConfig, RADIUS_KEYS, type RadiusKey, type ReportChangeType, type ReportChangeTypeSummary, type ReportChangeTypeWarning, type ReportContractCoverage, type ReportData, type ReportDeltaCoverage, type ReportFullHarnessExecution, type ReportGuardrailItem, type ReportGuardrails, type ReportIds, type ReportPrototypingSummary, type ReportRoundLifecycle, type ReportRuleFinding, type ReportSpecContractRefs, type ReportSpecCoverage, type ReportSummary, type ReportSurfaceClassification, type ReportTddCoverage, type ReportTddCoverageSpec, type ReportTestStrategy, type ReportTraceability, type ReportWaivers, type RunSddPreflightOptions, SHADOW_KEYS, type SddPreflightResult, type SddPreflightSource, type SddPreflightStatus, type ShadowKey, type TraceabilitySeverity, VISUAL_BROWSER_SURFACES, type ValidationCounts, type ValidationIssue, type ValidationOptions, type ValidationProfile, type ValidationResult, type ValidationTraceability, type ValidationWaiverAction, type ValidationWaiverDowngradeTo, type ValidationWaiverEntry, type ValidationWaiverMatch, type ValidationWaiverScope, type ValidationWaiverSeverity, type ValidationWaiverSuppressed, type ValidationWaivers, checkDecisionGuardrails, createReportData, defaultConfig, evaluateAtddCodeTraceability, extractAcSpecNumber, extractAllIds, extractBrSpecNumber, extractCapSpecNumber, extractCaseSpecNumber, extractDecisionGuardrailsFromMarkdown, extractIds, extractInvalidIds, extractScSpecNumber, extractSpecNumber, extractUsSpecNumber, filterDecisionGuardrailsByKeyword, findConfigRoot, formatGuardrailsForLlm, formatReportJson, formatReportMarkdown, getConfigPath, hashDesignMd, isDiscussionUiBearingSurfaceType, isNonUiDiscussionSurface, isSupportedPrototypingSurface, isValidPrototypingSurface, lintSql, loadConfig, loadDecisionGuardrails, normalizeDecisionGuardrails, parseDesignMd, requiresVisualBrowserEvidence, resolvePath, resolveToolVersion, runBrowserQaOrchestrated, runRenderCapture, runSddPreflight, sortDecisionGuardrails, summarizeBrowserQaResult, validateAtddCodeTraceability, validateContracts, validateDefinedIds, validateDesignMd, validateLayeredTraceability, validateOrphanProhibition, validateProject, validateSpecSplitByCapability, validateTraceability };
|
|
1208
|
+
export { AC_GHERKIN_SECTION, ARCHETYPES, ATDD_TEST_KIND_DIRS, type Archetype, type AtddCodeTraceabilityResult, type AtddForbiddenRef, type AtddSpecRefs, type AtddTestKind, type AtddTraceabilityMissing, type AtddTraceabilityScan, type AtddUnknownRef, type AtddUnknownRefKind, BROWSER_QA_PHASES, COLOR_KEYS, type ColorKey, type ConfigLoadResult, type ConfigPathKey, type ConfigSearchResult, DESIGN_MD_SAMPLE_MARKER, DISCUSSION_NON_UI_SURFACES, DISCUSSION_UI_BEARING_SURFACES, type DecisionGuardrail, type DecisionGuardrailEntry, type DesignMd, type DesignMdColors, type DesignMdFonts, type DesignMdRadius, type DesignMdShadow, FONT_KEYS, type FailOn, type FenceMaskOptions, type FontKey, type GuardrailCheckResult, type GuardrailIssue, type GuardrailIssueSeverity, type GuardrailLoadError, type GuardrailLoadResult, type GuardrailType, ID_PREFIXES, type IdFormatPrefix, type IdPrefix, type InvalidIdOccurrence, type Issue, type IssueCategory, type IssueLocation, type IssueSeverity, type OrphanContractsPolicy, type OutputFormat, PLANNED_CONTRACT_KEY, PROTOTYPING_SUPPORTED_SURFACES, type ParseError, type ParseResult, type PrototypingBrowserTool, type PrototypingSurface, type QfaiAtddConfig, type QfaiConfig, type QfaiOutputConfig, type QfaiPaths, type QfaiPrototypingCalibrationConfig, type QfaiPrototypingConfig, type QfaiPrototypingExecutionConfig, type QfaiReviewConfig, type QfaiUiuxAuditConfig, type QfaiUiuxConfig, type QfaiValidationConfig, RADIUS_KEYS, type RadiusKey, type ReportChangeType, type ReportChangeTypeSummary, type ReportChangeTypeWarning, type ReportContractCoverage, type ReportData, type ReportDeltaCoverage, type ReportFullHarnessExecution, type ReportGuardrailItem, type ReportGuardrails, type ReportIds, type ReportPrototypingSummary, type ReportRoundLifecycle, type ReportRuleFinding, type ReportSpecContractRefs, type ReportSpecCoverage, type ReportSummary, type ReportSurfaceClassification, type ReportTddCoverage, type ReportTddCoverageSpec, type ReportTestStrategy, type ReportTraceability, type ReportWaivers, type RunSddPreflightOptions, SHADOW_KEYS, type SddPreflightResult, type SddPreflightSource, type SddPreflightStatus, type ShadowKey, type TraceabilityGraph, type TraceabilityGraphEdge, type TraceabilityGraphNode, type TraceabilitySeverity, VISUAL_BROWSER_SURFACES, type ValidationCounts, type ValidationIssue, type ValidationOptions, type ValidationProfile, type ValidationResult, type ValidationTraceability, type ValidationWaiverAction, type ValidationWaiverDowngradeTo, type ValidationWaiverEntry, type ValidationWaiverMatch, type ValidationWaiverScope, type ValidationWaiverSeverity, type ValidationWaiverSuppressed, type ValidationWaivers, atddTestKindDirs, buildLayeredTraceabilityGraph, checkDecisionGuardrails, createReportData, defaultConfig, deriveAtddFilePattern, evaluateAtddCodeTraceability, extractAcSpecNumber, extractAllIds, extractBrSpecNumber, extractCapSpecNumber, extractCaseSpecNumber, extractDecisionGuardrailsFromMarkdown, extractIds, extractInvalidIdOccurrences, extractInvalidIds, extractScSpecNumber, extractSpecNumber, extractUsSpecNumber, filterDecisionGuardrailsByKeyword, findConfigRoot, formatGuardrailsForLlm, formatReportJson, formatReportMarkdown, getConfigPath, hashDesignMd, isDiscussionUiBearingSurfaceType, isNonUiDiscussionSurface, isPlannedApiContract, isSupportedPrototypingSurface, isUnreplacedDesignMdSample, isValidPrototypingSurface, lintSql, loadConfig, loadDecisionGuardrails, maskFencedCodeBlocks, normalizeDecisionGuardrails, parseDesignMd, qualifyId, requiresVisualBrowserEvidence, resolvePath, resolveToolVersion, runBrowserQaOrchestrated, runRenderCapture, runSddPreflight, sortDecisionGuardrails, specNumberForPath, summarizeBrowserQaResult, validateAtddCodeTraceability, validateContracts, validateDefinedIds, validateDesignMd, validateLayeredTraceability, validateOrphanProhibition, validateProject, validateSpecSplitByCapability, validateTraceability };
|