sequant 2.11.0 → 2.13.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 (75) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.md +47 -3
  4. package/dist/dashboard/server.js +4 -0
  5. package/dist/marketplace/external_plugins/sequant/.claude-plugin/plugin.json +1 -1
  6. package/dist/marketplace/external_plugins/sequant/.mcp.json +1 -1
  7. package/dist/marketplace/external_plugins/sequant/README.md +9 -0
  8. package/dist/marketplace/external_plugins/sequant/hooks/pre-tool.sh +331 -12
  9. package/dist/marketplace/external_plugins/sequant/skills/_shared/references/subagent-types.md +7 -18
  10. package/dist/marketplace/external_plugins/sequant/skills/assess/SKILL.md +5 -1
  11. package/dist/marketplace/external_plugins/sequant/skills/exec/SKILL.md +62 -8
  12. package/dist/marketplace/external_plugins/sequant/skills/fullsolve/SKILL.md +187 -28
  13. package/dist/marketplace/external_plugins/sequant/skills/loop/SKILL.md +127 -23
  14. package/dist/marketplace/external_plugins/sequant/skills/merger/SKILL.md +130 -13
  15. package/dist/marketplace/external_plugins/sequant/skills/qa/SKILL.md +306 -8
  16. package/dist/marketplace/external_plugins/sequant/skills/release/SKILL.md +79 -0
  17. package/dist/marketplace/external_plugins/sequant/skills/spec/SKILL.md +42 -20
  18. package/dist/marketplace/external_plugins/sequant/skills/spec/references/recommended-workflow.md +14 -1
  19. package/dist/marketplace/external_plugins/sequant/skills/test/SKILL.md +1 -1
  20. package/dist/marketplace/external_plugins/sequant/skills/testgen/SKILL.md +23 -6
  21. package/dist/src/commands/doctor.js +20 -18
  22. package/dist/src/commands/ready.js +7 -1
  23. package/dist/src/commands/status.js +4 -0
  24. package/dist/src/lib/ac-linter.js +26 -0
  25. package/dist/src/lib/ac-parser.d.ts +40 -0
  26. package/dist/src/lib/ac-parser.js +202 -16
  27. package/dist/src/lib/markdown-fence.d.ts +24 -0
  28. package/dist/src/lib/markdown-fence.js +51 -0
  29. package/dist/src/lib/mcp-config.d.ts +24 -0
  30. package/dist/src/lib/mcp-config.js +51 -0
  31. package/dist/src/lib/scope/analyzer.d.ts +4 -0
  32. package/dist/src/lib/scope/analyzer.js +7 -1
  33. package/dist/src/lib/settings.d.ts +73 -14
  34. package/dist/src/lib/settings.js +45 -3
  35. package/dist/src/lib/system.d.ts +7 -3
  36. package/dist/src/lib/system.js +7 -3
  37. package/dist/src/lib/test-tautology-detector.js +50 -3
  38. package/dist/src/lib/workflow/batch-executor.d.ts +20 -1
  39. package/dist/src/lib/workflow/batch-executor.js +81 -6
  40. package/dist/src/lib/workflow/config-resolver.d.ts +30 -2
  41. package/dist/src/lib/workflow/config-resolver.js +59 -2
  42. package/dist/src/lib/workflow/drivers/agent-driver.d.ts +14 -0
  43. package/dist/src/lib/workflow/drivers/claude-code.js +36 -4
  44. package/dist/src/lib/workflow/metrics-schema.d.ts +10 -1
  45. package/dist/src/lib/workflow/metrics-schema.js +13 -1
  46. package/dist/src/lib/workflow/metrics-writer.d.ts +3 -1
  47. package/dist/src/lib/workflow/mutation-marker.d.ts +86 -0
  48. package/dist/src/lib/workflow/mutation-marker.js +97 -0
  49. package/dist/src/lib/workflow/phase-executor.d.ts +17 -0
  50. package/dist/src/lib/workflow/phase-executor.js +60 -6
  51. package/dist/src/lib/workflow/qa-gaps-marker.d.ts +38 -0
  52. package/dist/src/lib/workflow/qa-gaps-marker.js +66 -0
  53. package/dist/src/lib/workflow/ready-gate.d.ts +25 -1
  54. package/dist/src/lib/workflow/ready-gate.js +81 -11
  55. package/dist/src/lib/workflow/reconcile.js +4 -2
  56. package/dist/src/lib/workflow/run-log-schema.d.ts +120 -0
  57. package/dist/src/lib/workflow/run-log-schema.js +40 -0
  58. package/dist/src/lib/workflow/run-orchestrator.d.ts +18 -0
  59. package/dist/src/lib/workflow/run-orchestrator.js +38 -2
  60. package/dist/src/lib/workflow/state-cleanup.d.ts +4 -4
  61. package/dist/src/lib/workflow/state-cleanup.js +9 -5
  62. package/dist/src/lib/workflow/state-schema.d.ts +10 -1
  63. package/dist/src/lib/workflow/state-schema.js +13 -1
  64. package/dist/src/lib/workflow/types.d.ts +20 -0
  65. package/dist/src/mcp/tools/run.js +10 -1
  66. package/package.json +13 -12
  67. package/templates/hooks/pre-tool.sh +108 -17
  68. package/templates/memory/constitution.md +112 -45
  69. package/templates/skills/exec/SKILL.md +1 -1
  70. package/templates/skills/fullsolve/SKILL.md +62 -9
  71. package/templates/skills/loop/SKILL.md +71 -12
  72. package/templates/skills/merger/SKILL.md +32 -3
  73. package/templates/skills/qa/SKILL.md +247 -2
  74. package/templates/skills/spec/SKILL.md +11 -5
  75. package/templates/skills/test/SKILL.md +1 -1
@@ -540,6 +540,32 @@ On a *failure* exit instead, the release is done at the halt site — the
540
540
  regression gate (Step 7) or "Error Handling" — never both, so exactly one release
541
541
  runs per invocation.
542
542
 
543
+ <!-- BEGIN: named-set-boundary (#961) -->
544
+ ## Named-Set Boundary (REQUIRED)
545
+
546
+ `/merger <issue-numbers>` is the user's consent to merge **exactly those
547
+ issues** — invoking it is the explicit authorization, the same way `sequant
548
+ merge`/`sequant merge --watch` are explicit and human-triggered (#958's
549
+ Non-Goals). That consent does not extend past the named set: never let
550
+ Dependency Detection or Stacked PR Detection below pull an**other** issue's PR
551
+ into `gh pr merge` just because it happens to unblock or precede a named one.
552
+
553
+ **Rule:** if merge ordering requires a PR whose issue number is **not** in the
554
+ invocation's arg list, halt before merging anything and report it — do not
555
+ widen the merge silently, and do not treat the stacked-PR "Continue anyway?
556
+ (y/N)" confirmation as license to include an unnamed predecessor. Offer the
557
+ widened command for the user to re-run:
558
+
559
+ ```text
560
+ ❌ Out-of-named-set dependency
561
+ #101 depends on #100, but #100 was not in your /merger invocation.
562
+ Halting before any merge.
563
+ To include it: /merger 100 101
564
+ ```
565
+
566
+ This rule governs both sections below.
567
+ <!-- END: named-set-boundary (#961) -->
568
+
543
569
  ## Dependency Detection
544
570
 
545
571
  Parse dependencies from issue body or comments:
@@ -557,7 +583,9 @@ Labels: depends-on/10
557
583
  gh issue view <issue> --json body,labels | jq '.body, .labels[].name'
558
584
  ```
559
585
 
560
- If dependencies found, enforce merge order.
586
+ If dependencies found, enforce merge order **among the named set**. If a
587
+ dependency's issue number falls outside the named set, apply the Named-Set
588
+ Boundary rule above: halt and report instead of merging it.
561
589
 
562
590
  ### Stacked PR Detection (#605)
563
591
 
@@ -578,8 +606,9 @@ gh pr view <PR_NUMBER> --json baseRefName,body | \
578
606
 
579
607
  1. Extract the stack manifest from each PR's body (`Part of stack: #100 → #101 (this) → #102`).
580
608
  2. Treat the order in the manifest as the merge order — earlier entries land first.
581
- 3. If the user requests an out-of-order merge (e.g. `/merger 102 100 101` for the stack above), **warn before proceeding** and recommend the manifest order.
582
- 4. GitHub auto-updates the dependent PR's base when its predecessor merges, so once the order is correct no manual rebasing is needed.
609
+ 3. If **every** predecessor is in the named set but requested out of order (e.g. `/merger 102 100 101` for the stack above), **warn before proceeding** and recommend the manifest order.
610
+ 4. If a predecessor is **not** in the named set at all (e.g. `/merger 102` alone for that stack), the Named-Set Boundary rule applies: halt and report — do not fall through to the "Continue anyway? (y/N)" prompt, since that prompt is for reordering named issues, not for merging an unnamed one.
611
+ 5. GitHub auto-updates the dependent PR's base when its predecessor merges, so once the order is correct no manual rebasing is needed.
583
612
 
584
613
  **Warning template:**
585
614
 
@@ -2402,6 +2402,181 @@ Two classes are explicitly **not** findings. Legitimate imperative *requirements
2402
2402
 
2403
2403
  ---
2404
2404
 
2405
+ ### 6h. Declared-Evidence Execution (REQUIRED for evidence-bearing ACs)
2406
+
2407
+ **Purpose:** For any AC with a declared `Evidence:` clause naming a runnable command, verify that exact command was executed against this diff (or a captured run of it verified) before marking the AC `MET`. Closes the #853 "marked MET by construction" path (#938) — a declared, checkable claim that goes unexecuted is a bug, not a checkbox.
2408
+
2409
+ **When to apply:** Any AC whose stored state includes a non-empty `evidence` field naming a backtick-quoted command (i.e., `verificationMethod` resolved to `unit_test` or `integration_test` via declaration, not inference — see `resolveVerificationMethod` in `ac-parser.ts`). Skip entirely when no AC declares a runnable command (cheap short-circuit).
2410
+
2411
+ **How to perform:**
2412
+
2413
+ ```bash
2414
+ # Retrieve declared evidence per AC from state.
2415
+ npx tsx -e '
2416
+ (async () => {
2417
+ const sm = await import("./src/lib/workflow/state-manager.ts");
2418
+ const mgr = new sm.StateManager(process.cwd());
2419
+ const ac = await mgr.getAcceptanceCriteria(<issue-number>);
2420
+ const declared = (ac?.items ?? []).filter(
2421
+ (i) => i.evidence && /`[^`]+`/.test(i.evidence),
2422
+ );
2423
+ console.log(JSON.stringify(declared.map((i) => ({ id: i.id, evidence: i.evidence })), null, 2));
2424
+ })();
2425
+ '
2426
+ ```
2427
+
2428
+ For each AC returned, **execute the exact backtick-quoted command** — or verify a captured run of it from earlier in this session's tool output — and record its exit code / pass-fail result before marking that AC `MET`. Do not mark a declared-evidence AC `MET` on reasoning alone; that is precisely the #853 gap this section closes.
2429
+
2430
+ **Status outcomes:**
2431
+
2432
+ | Status | Criteria |
2433
+ |--------|----------|
2434
+ | **Complete** | Every declared-evidence AC's command was executed (or a captured prior run verified) this QA pass |
2435
+ | **Incomplete** | One or more declared-evidence ACs have no executed/verified command |
2436
+ | **N/A** | No AC declares evidence with a runnable command |
2437
+
2438
+ **AC marking and verdict gating:**
2439
+
2440
+ - A declared-evidence AC whose command was NOT executed or verified this pass → AC status = `PENDING` (increments `pending_count`, same mechanism as the Manual Test AC Enforcement in step 3a) — it cannot be marked `MET` on reasoning alone.
2441
+ - `declared_evidence_status == "Incomplete"` also floors the verdict directly — see step 4's `Section 6h` branch.
2442
+
2443
+ **Output Format:**
2444
+
2445
+ ```markdown
2446
+ ### Declared-Evidence Execution
2447
+
2448
+ | AC | Evidence | Executed? | Result |
2449
+ |----|----------|-----------|--------|
2450
+ | AC-N | `npm test -- reset-expiry` | Yes | ✅ 4 passed |
2451
+ | AC-M | `npx sequant doctor --help` | No | ⚠️ Not run — AC marked PENDING |
2452
+
2453
+ **Status:** Complete / Incomplete / N/A
2454
+ ```
2455
+
2456
+ ---
2457
+
2458
+ ### 6i. Mutation Verification (REQUIRED for gate-test ACs)
2459
+
2460
+ **Purpose:** CLAUDE.md's testing rule — "Gate tests ship with a recorded mutation result: delete the thing it asserts, confirm exactly that test fails, restore, and record the result" — was honor-system prose until now: nothing parsed or checked the recorded result, so compliance was invisible (#830, and the same "prose only, and therefore unenforceable" defect class #834 fixed for `/qa`'s own §7 gates). This section promotes that record to a parseable `SEQUANT_MUTATION` PR-body marker and gates on it.
2461
+
2462
+ **When to apply:** Any AC whose declared `evidence` text matches the CLAUDE.md gate-test definition — a fixture-exists / section-present / flag-wired assertion (see `isGateTestEvidence` in `ac-parser.ts`). Skip entirely when no AC in the diff is a gate-test AC (cheap short-circuit — mark N/A).
2463
+
2464
+ > **Scope note (v1):** gate-test ACs only, not every AC with a declared runnable-command `Evidence:` clause. The population widens after a backtest measures the real authoring burden (#939 AC-5) — see that issue for the human-decision record if this scope is revisited.
2465
+
2466
+ **How to perform:**
2467
+
2468
+ ```bash
2469
+ # 1. Identify in-scope (gate-test) ACs for this issue.
2470
+ npx tsx -e '
2471
+ (async () => {
2472
+ const sm = await import("./src/lib/workflow/state-manager.ts");
2473
+ const acp = await import("./src/lib/ac-parser.ts");
2474
+ const mgr = new sm.StateManager(process.cwd());
2475
+ const ac = await mgr.getAcceptanceCriteria(<issue-number>);
2476
+ const gateTests = (ac?.items ?? []).filter(
2477
+ (i) => i.evidence && acp.isGateTestEvidence(i.evidence),
2478
+ );
2479
+ console.log(JSON.stringify(gateTests.map((i) => ({ id: i.id, evidence: i.evidence })), null, 2));
2480
+ })();
2481
+ '
2482
+
2483
+ # 2. Parse SEQUANT_MUTATION markers from the PR body — this single call
2484
+ # both parses AND rejects: given the diff's test-file paths, each
2485
+ # returned marker carries a "classification" ("valid" or
2486
+ # "test_not_in_diff"), so a marker naming a test absent from the diff
2487
+ # is surfaced, not silently dropped.
2488
+ npx tsx -e '
2489
+ (async () => {
2490
+ const mm = await import("./src/lib/workflow/mutation-marker.ts");
2491
+ const prBody = process.argv[1];
2492
+ const diffTestFiles = process.argv.slice(2);
2493
+ const markers = mm.parseMutationMarkers(prBody, diffTestFiles);
2494
+ const byAc = new Map(markers.map((m) => [m.ac, m]));
2495
+ for (const [ac, marker] of byAc) {
2496
+ console.log(ac, marker.classification, marker.failedTest);
2497
+ }
2498
+ })();
2499
+ ' -- "$PR_BODY" $(git diff origin/main...HEAD --diff-filter=AM --name-only | grep -E '\.(test|spec)\.')
2500
+ ```
2501
+
2502
+ **Safety rules (carry into any manual mutation performed during this check, per #883 and the commit-before-mutating discipline):**
2503
+ - **Commit before mutating.** `git checkout <file>` to revert a mutation wipes any uncommitted edits in that file, not just the mutation.
2504
+ - **Never mutate a variable a `finally` block passes to `rmSync`.** A mutation that touches cleanup-path state can delete a worktree (#883's motivating incident).
2505
+
2506
+ **Per-AC status outcomes:**
2507
+
2508
+ | Status | Criteria |
2509
+ |--------|----------|
2510
+ | **Verified** | The in-scope AC has a `SEQUANT_MUTATION` marker whose `failedTest` names a test file present in the diff |
2511
+ | **Missing** | The in-scope AC has no `SEQUANT_MUTATION` marker |
2512
+ | **Failed** | The in-scope AC has a marker naming a test file NOT present in the diff — a fabricated marker is worse than a missing one |
2513
+
2514
+ **Aggregate `mutation_verification_status`** (the single §7 step-2 token — worst case across in-scope ACs wins, mirroring §6e's per-AC-table-to-single-status rollup): `Failed` if any in-scope AC is `Failed`; else `Missing` if any in-scope AC is `Missing`; else `Verified` if every in-scope AC is `Verified`; `Not-Applicable` when no AC in the diff is a gate-test AC.
2515
+
2516
+ **AC marking and verdict gating:**
2517
+
2518
+ - Aggregate `Missing` → the mutation-verification gate caps the verdict at `AC_MET_BUT_NOT_A_PLUS` regardless of individual ACs' own MET status — see step 4's `mutation_verification_status == "Missing"` branch.
2519
+ - Aggregate `Failed` → floor the verdict at `AC_NOT_MET` — see step 4's `mutation_verification_status == "Failed"` branch. This is a hard floor, not a soft cap: a marker naming a test absent from the diff is affirmatively false evidence, not merely absent evidence.
2520
+
2521
+ **Output Format:**
2522
+
2523
+ ```markdown
2524
+ ### Mutation Verification
2525
+
2526
+ | AC | Gate Test? | Marker | Status |
2527
+ |----|-----------|--------|--------|
2528
+ | AC-N | Yes | `injection.test.ts > rejects payload` | Verified |
2529
+ | AC-M | Yes | — | Missing |
2530
+ | AC-P | Yes | `nonexistent.test.ts > some test` | Failed — test not in diff |
2531
+ | AC-Q | No | — | N/A |
2532
+
2533
+ **Status:** Verified / Missing / Failed / Not-Applicable
2534
+ ```
2535
+
2536
+ ---
2537
+
2538
+ ### 6j. Structured Gap Findings (REQUIRED)
2539
+
2540
+ **Purpose:** `parseQaSummary`'s gap channel (`src/lib/workflow/phase-executor.ts`) used to scrape only the `**Issues:**` bullet list under Code Review — one specific spot in this template. It missed AC-table `NOT_MET`/`PARTIALLY_MET` rows, §6d Adversarial Re-Read findings, and §5/Risk Assessment gaps entirely, so a QA pass that failed on a §6d "Severe Gap" could hand `/loop` an empty findings list (#937). This section closes that gap: every finding this review surfaces — anywhere in the output, not just Code Review — gets classified into the taxonomy below and emitted as one machine-readable marker.
2541
+
2542
+ **Taxonomy** (finite — six categories, pick the closest fit):
2543
+
2544
+ | Category | Use for |
2545
+ |----------|---------|
2546
+ | `requirement_gap` | An AC (or a table row) is `NOT_MET`/`PARTIALLY_MET` |
2547
+ | `dependency_gap` | Missing/incompatible dependency, unregistered CLI flag, wiring gap (§2h, §3g-class) |
2548
+ | `test_gap` | Missing/tautological/insufficient test coverage (§2b, §2d, §6i Missing/Failed) |
2549
+ | `repository_gap` | Code quality, duplication, anti-pattern, dead code (§2, §2e) |
2550
+ | `risk_gap` | §5 Risk Assessment item, §6d Adversarial Re-Read finding, §6f Trust-Boundary finding |
2551
+ | `execution_gap` | Build/lint/CI failure, script/CLI execution failure (§2a, §Phase 1 CI Status) |
2552
+
2553
+ **Per-finding fields:**
2554
+
2555
+ | Field | Required? | Content |
2556
+ |-------|-----------|---------|
2557
+ | `category` | Yes | One of the six above |
2558
+ | `evidence` | Yes | A concrete observation — file:line, failing check name, or table row — never speculation |
2559
+ | `description` | Yes | One-sentence statement of the gap (same text you'd put in a prose bullet) |
2560
+ | `recommendedAction` | Yes | `fix_now` (blocks `READY_FOR_MERGE`, actionable by a code change), `document` (real but non-blocking — quality/polish, or explicitly deferred), or `pause_for_human` (needs a decision `/loop` cannot make, e.g. `SCOPE_SPLIT_RECOMMENDED`-class ambiguity) |
2561
+ | `affectedAcs` | If applicable | e.g. `["AC-3"]` |
2562
+ | `nonGoal` | If applicable | `true` when the finding overlaps one of the issue's Non-Goals — report-only under `ac` policy, same semantics as `ReadyGapItem.nonGoal` |
2563
+
2564
+ **Fallback rule (no dropped findings):** if a real finding does not fit any of the six categories, **do not force it into the marker** — leave it as prose only (in Code Review's `**Issues:**`, Risk Assessment, or wherever it naturally belongs). The marker narrows the *structured* channel; every consumer that reads it also unions it with the prose scrape, so an unclassifiable finding is never silently lost — it just doesn't get machine-readable category/action metadata.
2565
+
2566
+ **How to build the marker:** after finishing every other section, walk back through this review's own output — the AC Coverage table's non-MET rows, §5 Risk Assessment, §6d Adversarial Re-Read (Standard only), §6f Trust-Boundary, and Code Review's `**Issues:**` — and classify each real finding. Append exactly one marker as the LAST line of the comment (after `### Next Steps`), single-line flat-ish JSON (no line breaks inside the `{...}`, and no literal `-->` inside any string value — both would break the parser's `[\s\S]*?-->` match):
2567
+
2568
+ ```markdown
2569
+ <!-- SEQUANT_QA_GAPS: {"findings":[{"category":"requirement_gap","evidence":"AC-3 table row: NOT_MET — no rate limit found in src/retry.ts","description":"AC-3 (rate limiting) is not implemented","recommendedAction":"fix_now","affectedAcs":["AC-3"]}]} -->
2570
+ ```
2571
+
2572
+ When there are no findings to report (clean pass), still emit the marker with an empty array — this positively confirms the structured channel ran, rather than leaving `/loop` to distinguish "clean" from "QA output predates this marker":
2573
+
2574
+ ```markdown
2575
+ <!-- SEQUANT_QA_GAPS: {"findings":[]} -->
2576
+ ```
2577
+
2578
+ ---
2579
+
2405
2580
 
2406
2581
  ### 7. A+ Status Verdict
2407
2582
 
@@ -2433,6 +2608,8 @@ Provide an overall verdict:
2433
2608
  - adversarial_reread_status = status from Section 6d (Clean/Gaps Found/Severe Gap) — REQUIRED for Standard QA, omitted for Simple Fix
2434
2609
  - behavior_rule_survival_status = status from Section 6e (Clean/Survivors Found/N/A) — REQUIRED when any AC triggers the behavior-rule heuristic, omitted otherwise
2435
2610
  - trust_boundary_status = status from Section 6f (Clean/Injection Acted On) — REQUIRED in **both** Standard QA and Simple Fix mode (unlike 6d, it is never omitted: an injected command is a small diff by definition)
2611
+ - declared_evidence_status = status from Section 6h (Complete/Incomplete/N/A) — REQUIRED when any AC declares evidence naming a runnable command, `N/A` otherwise
2612
+ - mutation_verification_status = status from Section 6i (Verified/Missing/Failed/Not-Applicable) — REQUIRED when any AC is a gate-test AC per `isGateTestEvidence`, `Not-Applicable` otherwise
2436
2613
  - cli_registration_status = status from Section 2h (Passed/Failed/N/A) — REQUIRED when option interfaces are modified, `N/A` otherwise; omitted in Simple Fix mode along with the rest of §2h
2437
2614
  - script_verification_status = status from Section 11 (Verified/Overridden/Not Verified/Not Required) — REQUIRED when `scripts/` or `templates/scripts/` files are modified, `Not Required` otherwise
2438
2615
  - changelog_required = true IFF Section 10a's `CHANGELOG.md` exists AND Section 10a's `user_facing` count is >0 (single source of truth — see §10a for the conventional-commit detection regex, which accepts unscoped, scoped, and breaking variants of `feat`/`fix`/`perf`/`refactor`/`docs`); false otherwise
@@ -2467,12 +2644,18 @@ Provide an overall verdict:
2467
2644
  → AC_NOT_MET (the diff acted on an agent-directed instruction embedded in untrusted external text — see Section 6f and _shared/references/trust-model.md; name the instruction verbatim with its path:line)
2468
2645
  - ELSE IF cli_registration_status == "Failed":
2469
2646
  → AC_NOT_MET (an option-interface field has runtime `mergedOptions.X` usage but no `.option()` registration in `bin/cli.ts`, so users cannot reach the feature from the command line — invisible to TypeScript, build, and unit tests; see Section 2h and #305. Name each unregistered field.)
2647
+ - ELSE IF mutation_verification_status == "Failed":
2648
+ → AC_NOT_MET (a `SEQUANT_MUTATION` marker names a test file absent from this diff — a fabricated mutation-verification record; see Section 6i and #939. A fabricated marker is worse than a missing one.)
2470
2649
  - ELSE IF adversarial_reread_status == "Severe Gap":
2471
2650
  → AC_NOT_MET (verbatim motivating-example fixture not run / evidence claim is bug reproduction not validation / AC marked MET without runtime or corpus check the AC text required)
2472
2651
  - ELSE IF skill_verification == "Failed":
2473
2652
  → AC_MET_BUT_NOT_A_PLUS (skill commands have issues - cannot be READY_FOR_MERGE)
2474
2653
  - ELSE IF execution_evidence == "Incomplete":
2475
2654
  → AC_MET_BUT_NOT_A_PLUS (scripts not verified - cannot be READY_FOR_MERGE)
2655
+ - ELSE IF declared_evidence_status == "Incomplete":
2656
+ → AC_MET_BUT_NOT_A_PLUS (a declared `Evidence:` command was not executed/verified for one or more ACs - see Section 6h; the #853 "marked MET by construction" path)
2657
+ - ELSE IF mutation_verification_status == "Missing":
2658
+ → AC_MET_BUT_NOT_A_PLUS (a gate-test AC has no recorded `SEQUANT_MUTATION` marker - see Section 6i; the honor-system-prose gap #939 closes)
2476
2659
  - ELSE IF script_verification_status == "Not Verified":
2477
2660
  → AC_MET_BUT_NOT_A_PLUS (`scripts/` changed with no `/verify` evidence and no approved §11a override — code review and unit tests miss integration failures; see Section 11)
2478
2661
  - ELSE IF changelog_required AND changelog_missing:
@@ -2713,7 +2896,10 @@ Produce a Markdown snippet for the PR/issue:
2713
2896
  ### 9. Update GitHub Issue
2714
2897
 
2715
2898
  **If orchestrated (SEQUANT_ORCHESTRATOR is set):**
2716
- - Skip posting GitHub comment (orchestrator handles aggregated summary)
2899
+ - Skip posting this skill's own GitHub comment under `sequant run`,
2900
+ `batch-executor.ts` posts a compact verdict comment (AC coverage + a
2901
+ `SEQUANT_QA_VERDICT` marker) itself right after this phase completes with a
2902
+ parseable verdict (#964); don't post a second, redundant one here
2717
2903
  - Include verdict and AC coverage in output for orchestrator to capture
2718
2904
  - Let orchestrator update labels based on final workflow status
2719
2905
 
@@ -2932,7 +3118,7 @@ When the size gate determined `SMALL_DIFF=true`, use the **simplified output tem
2932
3118
  - Skill Change Review
2933
3119
  - Adversarial Re-Read
2934
3120
 
2935
- **Not omitted:** the Trust-Boundary Check (§6f), the Behavior-Rule Survival Check (§6e), and the CHANGELOG Quality Gate (§10a) are all required in simple fix mode too — each is cheap, and each guards a defect class that a small diff is a *likely* carrier of rather than an unlikely one. Every `(REQUIRED` section must appear in either the required list below or the omitted list above; `scripts/lint-skill-gates.ts` (I3) fails the build on silence, because silence is how #819 F2 shipped a security check that Simple Fix mode switched off.
3121
+ **Not omitted:** the Trust-Boundary Check (§6f), the Behavior-Rule Survival Check (§6e), the Declared-Evidence Execution check (§6h), the Mutation Verification check (§6i), and the CHANGELOG Quality Gate (§10a) are all required in simple fix mode too — each is cheap (a short-circuit to N/A when no AC qualifies), and each guards a defect class that a small diff is a *likely* carrier of rather than an unlikely one — a gate test (fixture/section/flag assertion) is very often itself a small, localized diff. Every `(REQUIRED` section must appear in either the required list below or the omitted list above; `scripts/lint-skill-gates.ts` (I3) fails the build on silence, because silence is how #819 F2 shipped a security check that Simple Fix mode switched off.
2936
3122
 
2937
3123
  **Required sections for simple fix mode:**
2938
3124
 
@@ -2944,12 +3130,15 @@ When the size gate determined `SMALL_DIFF=true`, use the **simplified output tem
2944
3130
  - [ ] **Anti-Pattern Detection** - Code patterns check (lightweight)
2945
3131
  - [ ] **Trust-Boundary Check** - Required in simple fix mode too (see Section 6f); "Finding:" and "Status:" lines populated
2946
3132
  - [ ] **Behavior-Rule Survival Check** - Required in simple fix mode too (see Section 6e): a #533-class stale-rule survival is very plausibly a sub-threshold diff. Cheap short-circuit — mark "N/A" when no AC triggers the behavior-rule heuristic
3133
+ - [ ] **Declared-Evidence Execution** - Required in simple fix mode too (see Section 6h): a declared-evidence AC marked MET without running its command is exactly the #853 gap, regardless of diff size. Cheap short-circuit — mark "N/A" when no AC declares evidence naming a runnable command
3134
+ - [ ] **Mutation Verification** - Required in simple fix mode too (see Section 6i): a gate-test AC merged without a recorded mutation result is exactly the #830 gap, regardless of diff size. Cheap short-circuit — mark "N/A" when no AC is a gate-test AC
2947
3135
  - [ ] **CHANGELOG Verification** - Required in simple fix mode too (see Section 10a): a one-line user-facing fix still needs an `[Unreleased]` entry (or marked N/A)
2948
3136
  - [ ] **Risk Assessment** - Likely failure mode and coverage gaps stated
2949
3137
  - [ ] **Verdict** - One of: READY_FOR_MERGE, AC_MET_BUT_NOT_A_PLUS, NEEDS_VERIFICATION, AC_NOT_MET
2950
3138
  - [ ] **Documentation Check** - README/docs updated if feature adds new functionality
2951
3139
  - [ ] **Next Steps** - Clear, actionable recommendations
2952
3140
  - [ ] Adversarial re-read of core logic — list anything the structured pipeline didn't surface
3141
+ - [ ] **Structured Gap Findings** - `SEQUANT_QA_GAPS` marker present as the last line, findings classified per Section 6j (or `{"findings":[]}` on a clean pass)
2953
3142
 
2954
3143
  ### Standard QA (Implementation Exists, `SMALL_DIFF=false`)
2955
3144
 
@@ -2973,6 +3162,8 @@ When the size gate determined `SMALL_DIFF=true`, use the **simplified output tem
2973
3162
  - [ ] **Detection Pattern Verification** - Included if skill markdown adds new `grep`/`awk`/`jq`/`sed`/regex (or marked N/A)
2974
3163
  - [ ] **CLI Registration Verification** - Included if option interfaces modified (or marked N/A — see Section 2h); `Failed` floors the verdict at `AC_NOT_MET` via §7
2975
3164
  - [ ] **Behavior-Rule Survival Check** - Included if any AC triggers the behavior-rule heuristic (or marked N/A — see Section 6e); `Survivors Found` floors the verdict at `AC_NOT_MET` via §7
3165
+ - [ ] **Declared-Evidence Execution** - Included if any AC declares evidence naming a runnable command (or marked N/A — see Section 6h); `Incomplete` floors the verdict at `AC_MET_BUT_NOT_A_PLUS` via §7, and an unexecuted AC is marked PENDING rather than MET
3166
+ - [ ] **Mutation Verification** - Included if any AC is a gate-test AC per `isGateTestEvidence` (or marked Not-Applicable — see Section 6i); `Missing` floors the verdict at `AC_MET_BUT_NOT_A_PLUS` via §7, `Failed` floors it at `AC_NOT_MET`
2976
3167
  - [ ] **Skill Change Review** - Skill-specific verification prompts included if skills changed
2977
3168
  - [ ] **Smoke Test** - Included if workflow-affecting changes (skills, scripts, CLI), or marked "Not Required"
2978
3169
  - [ ] **Manual Test AC Enforcement** - Included if spec plan has Manual Test ACs (or marked N/A if no manual-test ACs detected)
@@ -2981,6 +3172,7 @@ When the size gate determined `SMALL_DIFF=true`, use the **simplified output tem
2981
3172
  - [ ] **Adversarial Re-Read** - Required structured section: all 5 sub-prompts answered with concrete content; "Findings:" and "Status:" lines populated; bare "No gaps" without specific reasoning fails verification (see Section 6d)
2982
3173
  - [ ] **Documentation Check** - README/docs updated if feature adds new functionality
2983
3174
  - [ ] **Next Steps** - Clear, actionable recommendations
3175
+ - [ ] **Structured Gap Findings** - `SEQUANT_QA_GAPS` marker present as the last line, findings classified per Section 6j (or `{"findings":[]}` on a clean pass)
2984
3176
 
2985
3177
  ### Early Exit (No Implementation)
2986
3178
 
@@ -3083,6 +3275,26 @@ When the size gate triggers simple fix mode, use this shorter template:
3083
3275
 
3084
3276
  ---
3085
3277
 
3278
+ ### Declared-Evidence Execution
3279
+
3280
+ | AC | Evidence | Executed? | Result |
3281
+ |----|----------|-----------|--------|
3282
+ | AC-N | `<command>` or — | Yes/No/— | [pass-fail result, or "Not run — AC marked PENDING"] |
3283
+
3284
+ **Status:** Complete / Incomplete / N/A
3285
+
3286
+ ---
3287
+
3288
+ ### Mutation Verification
3289
+
3290
+ | AC | Gate Test? | Marker | Status |
3291
+ |----|-----------|--------|--------|
3292
+ | AC-N | Yes/No | `<file.test.ts > test name>` or — | Verified / Missing / Failed / N/A |
3293
+
3294
+ **Status:** Verified / Missing / Failed / Not-Applicable
3295
+
3296
+ ---
3297
+
3086
3298
  ### CHANGELOG Verification
3087
3299
 
3088
3300
  **Result:** [CHANGELOG requirements met / Missing entry for user-facing changes / N/A (non-user-facing changes only)]
@@ -3110,6 +3322,10 @@ When the size gate triggers simple fix mode, use this shorter template:
3110
3322
  ### Next Steps
3111
3323
 
3112
3324
  1. [Action item]
3325
+
3326
+ ### Structured Gap Findings
3327
+
3328
+ <!-- SEQUANT_QA_GAPS: {"findings":[...]} -->
3113
3329
  ```
3114
3330
 
3115
3331
  ---
@@ -3453,6 +3669,31 @@ You MUST include these sections:
3453
3669
 
3454
3670
  ---
3455
3671
 
3672
+ ### Declared-Evidence Execution
3673
+
3674
+ | AC | Evidence | Executed? | Result |
3675
+ |----|----------|-----------|--------|
3676
+ | AC-N | `npm test -- reset-expiry` | Yes | ✅ 4 passed |
3677
+ | AC-M | `npx sequant doctor --help` | No | ⚠️ Not run — AC marked PENDING |
3678
+ | AC-P | — | — | N/A (no declared evidence) |
3679
+
3680
+ **Status:** Complete / Incomplete / N/A
3681
+
3682
+ ---
3683
+
3684
+ ### Mutation Verification
3685
+
3686
+ | AC | Gate Test? | Marker | Status |
3687
+ |----|-----------|--------|--------|
3688
+ | AC-N | Yes | `injection.test.ts > rejects payload` | Verified |
3689
+ | AC-M | Yes | — | Missing |
3690
+ | AC-P | Yes | `nonexistent.test.ts > some test` | Failed — test not in diff |
3691
+ | AC-Q | No | — | N/A |
3692
+
3693
+ **Status:** Verified / Missing / Failed / Not-Applicable
3694
+
3695
+ ---
3696
+
3456
3697
  ### CHANGELOG Verification
3457
3698
 
3458
3699
  | Check | Status |
@@ -3489,4 +3730,8 @@ You MUST include these sections:
3489
3730
 
3490
3731
  1. [Action item 1]
3491
3732
  2. [Action item 2]
3733
+
3734
+ ### Structured Gap Findings
3735
+
3736
+ <!-- SEQUANT_QA_GAPS: {"findings":[...]} -->
3492
3737
  ```
@@ -107,6 +107,8 @@ Mark tier in HTML comment for downstream parsing: `<!-- SEQUANT_SPEC_TIER: [tier
107
107
  | Open-ended | "etc.", "and more" | Scope undefined |
108
108
  | Title/body tension | doc-noun title ("note", "comment", "snippet") + runtime-imperative body ("execute", "trigger", "capture", incl. inflections like `triggered`/`captured`, `run /<cmd>`); separators `.`/`\n`/`:`/`—` | Two different verification bars |
109
109
 
110
+ > For the house AC format rules (single-line constraint, `Evidence:`/`Risk:`/`Human decision` fields, Non-Goals section), see the constitution's §2 AC Authoring Standard (`.claude/memory/constitution.md`).
111
+
110
112
  3. **Scope Assessment** (unless `--skip-scope-check`): Use `performScopeAssessment` from `./src/lib/scope/index.ts` with settings from `getSettings()`. Verdicts: SCOPE_OK (green), SCOPE_WARNING (yellow, auto-enables quality loop), SCOPE_SPLIT_RECOMMENDED (red). Store results in state.
111
113
 
112
114
  ### If guard fails (consumer projects):
@@ -374,15 +376,19 @@ actually posted via `gh issue comment`, not just shown in this response.
374
376
  | Docs-only (`docs` label) | No | Skip testgen — no unit tests needed |
375
377
  | All ACs have "Manual Test" or "Browser Test" | No | Skip testgen — no code stubs to generate |
376
378
 
377
- **Detection logic:**
378
- 1. Count ACs with "Unit Test" → If >0, recommend testgen
379
- 2. Count ACs with "Integration Test" If >0, recommend testgen
380
- 3. Check labels: `bug`/`fix` only → Skip testgen. `docs` → Skip testgen.
379
+ **Detection logic — declared evidence counts before inferred (#938):**
380
+
381
+ `extractAcceptanceCriteria` resolves each AC's `verificationMethod` from a declared `Evidence:` clause when the AC line has one (`AC.evidence` is set), falling back to keyword inference only when it doesn't. Ground the recommendation in the stronger signal first:
382
+
383
+ 1. Count ACs with **declared** evidence (`AC.evidence` set) resolving to "Unit Test" or "Integration Test" → these are the reasoning's primary citation; if >0, recommend testgen and name them.
384
+ 2. Count remaining ACs — no declared evidence, method came from **inference** — that are "Unit Test" → if >0, recommend testgen.
385
+ 3. Count remaining inferred "Integration Test" ACs → if >0, recommend testgen.
386
+ 4. Check labels: `bug`/`fix` only → Skip testgen. `docs` → Skip testgen.
381
387
 
382
388
  **Example when testgen recommended:**
383
389
  ```markdown
384
390
  **Phases:** spec → testgen → exec → qa
385
- **Reasoning:** ACs include Unit Test verification methods; testgen will create stubs before implementation
391
+ **Reasoning:** AC-1 declares evidence (`npm test -- reset-expiry`, unit_test); testgen will create stubs before implementation
386
392
  ```
387
393
 
388
394
  ### Browser Testing Label Suggestion
@@ -582,7 +582,7 @@ Create structured test results:
582
582
  ### 3.2 GitHub Comment
583
583
 
584
584
  **If orchestrated (SEQUANT_ORCHESTRATOR is set):**
585
- - Skip posting GitHub comment (orchestrator handles summary)
585
+ - Skip posting this skill's own GitHub comment no per-phase comment is posted under `sequant run`; test results surface through the run summary and the PR body (#964)
586
586
  - Include test summary in output for orchestrator to capture
587
587
  - Let orchestrator aggregate results across phases
588
588