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
@@ -29,6 +29,7 @@ allowed-tools:
29
29
  # Worktree management
30
30
  - Bash(./scripts/new-feature.sh:*)
31
31
  - Bash(./scripts/cleanup-worktree.sh:*)
32
+ - Bash(npx sequant worktree:*)
32
33
  # GitHub CLI
33
34
  - Bash(gh issue view:*)
34
35
  - Bash(gh issue comment:*)
@@ -136,7 +137,7 @@ When running as part of an orchestrated workflow (e.g., `sequant run` or `/fulls
136
137
 
137
138
  1. **Skip pre-flight git checks** - The orchestrator has already verified git state
138
139
  2. **Skip worktree creation** - Orchestrator creates worktrees before invoking skills
139
- 3. **Use provided worktree path** - Work in `SEQUANT_WORKTREE` instead of creating a new one
140
+ 3. **Verify, then use, the provided path** - `SEQUANT_WORKTREE` is authoritative *when valid*, but it is never trusted unchecked: run the existence guard in "Feature Worktree Workflow" below and halt if it fails (#899)
140
141
  4. **Reduce GitHub comment frequency** - Defer progress updates to the orchestrator
141
142
  5. **Trust issue context** - The orchestrator has already fetched and validated issue data
142
143
 
@@ -472,15 +473,68 @@ echo "Current branch: $CURRENT_BRANCH"
472
473
  **Why this matters:** Work done directly on main can be lost during sync operations (git reset, git pull --rebase, etc.). Worktrees provide isolation and safe recovery through branches.
473
474
 
474
475
  **If orchestrated (SEQUANT_WORKTREE is set):**
475
- - Use the provided worktree path directly: `cd $SEQUANT_WORKTREE`
476
- - Skip steps 1-2 below (worktree already created by orchestrator)
477
- - Continue with step 3 (Work in the worktree)
476
+
477
+ <!-- BEGIN: worktree-existence-guard (#899) -->
478
+
479
+ **Verify the path before you use it. Never `cd` into it unchecked.** An
480
+ orchestrator can hand over a path that was never created, or one that resolves
481
+ into a *different repository's* worktree — `../worktrees/` is one flat
482
+ namespace shared by every repo under the same parent, and issue numbers are
483
+ per-repo. A bare `cd` fails silently and leaves you implementing in the main
484
+ checkout, on whatever branch it happens to be on.
485
+
486
+ ```bash
487
+ npx sequant worktree verify "$SEQUANT_WORKTREE" --issue <issue-number> || {
488
+ echo "❌ HALT: SEQUANT_WORKTREE is not a usable worktree of this repository."
489
+ exit 1
490
+ }
491
+ cd "$SEQUANT_WORKTREE"
492
+ ```
493
+
494
+ `verify` exits non-zero with one of these named errors. **Every one of them is
495
+ a halt** — report it and stop; do not fall back to creating a worktree, and do
496
+ not continue in the current directory:
497
+
498
+ | Error | Meaning |
499
+ |-------|---------|
500
+ | `SEQUANT_WORKTREE_NOT_FOUND` | Path is empty, an unexpanded glob, or not an existing directory |
501
+ | `SEQUANT_WORKTREE_FOREIGN` | Real directory, but not a worktree of *this* repository (another project's, or stale) |
502
+ | `SEQUANT_WORKTREE_ISSUE_MISMATCH` | A worktree of this repo, but its branch belongs to a different issue |
503
+
504
+ Once verify passes, skip steps 1-2 below and continue with step 3 (Work in the
505
+ worktree).
506
+
507
+ <!-- END: worktree-existence-guard (#899) -->
478
508
 
479
509
  **If standalone:**
480
510
 
481
- 1. **Check if worktree already exists:**
482
- - Check if you're already in a worktree: `git worktree list` or check if `../worktrees/` contains a directory for this issue
483
- - If worktree exists, navigate to it and continue work there
511
+ <!-- BEGIN: worktree-standalone-lookup (#899) -->
512
+
513
+ 1. **Check if a worktree already exists for this issue:**
514
+
515
+ Resolve through git, not the filesystem. `sequant worktree resolve` reads
516
+ `git worktree list` in the current repository — which reports only *this*
517
+ repo's worktrees — and selects on the **branch** git reports, not on the
518
+ directory name. That matters twice over: a directory slug is shared across
519
+ repositories, and it can drift from its own branch after a rename
520
+ (`578-seo-expand-city-coverage` holding branch `feature/578-city-expansion-clean`),
521
+ so a name match proves nothing about which branch you would land on.
522
+
523
+ ```bash
524
+ if WORKTREE="$(npx sequant worktree resolve <issue-number>)"; then
525
+ echo "Existing worktree: $WORKTREE"
526
+ cd "$WORKTREE"
527
+ # Continue work there — skip step 2.
528
+ else
529
+ echo "No worktree for #<issue-number> in this repository — create one (step 2)."
530
+ fi
531
+ ```
532
+
533
+ **Do not glob `../worktrees/feature/<issue-number>-*` to find it.** That
534
+ directory is shared by every sibling repository, so the match may belong to
535
+ another project entirely.
536
+
537
+ <!-- END: worktree-standalone-lookup (#899) -->
484
538
 
485
539
  2. **Create worktree if needed (with parallel context gathering):**
486
540
 
@@ -1901,7 +1955,7 @@ The goal is to satisfy AC with the smallest, safest change possible.
1901
1955
  ### 6. Progress Summary and Draft Issue Update
1902
1956
 
1903
1957
  **If orchestrated (SEQUANT_ORCHESTRATOR is set):**
1904
- - Skip posting progress comments to GitHub (orchestrator handles summary)
1958
+ - Skip posting progress comments to GitHub no per-phase comment is posted under `sequant run`; progress surfaces through the run summary and the PR body (#964)
1905
1959
  - Still provide AC coverage summary in output for orchestrator to capture
1906
1960
  - Let orchestrator handle final GitHub update
1907
1961
 
@@ -23,7 +23,6 @@ allowed-tools:
23
23
  - Bash(gh issue edit:*)
24
24
  - Bash(gh pr create:*)
25
25
  - Bash(gh pr list:*)
26
- - Bash(gh pr merge:*)
27
26
  - Bash(npm test:*)
28
27
  - Bash(npm run build:*)
29
28
  - Bash(git diff:*)
@@ -52,22 +51,28 @@ When invoked as `/fullsolve <issue-number>`, execute the complete issue resoluti
52
51
 
53
52
  ## CRITICAL: Auto-Progression Between Phases
54
53
 
55
- **DO NOT wait for user confirmation between phases.** This is an autonomous workflow.
54
+ **DO NOT wait for user confirmation between phases.** This is an autonomous workflow — through PR creation.
56
55
 
57
56
  After each phase completes successfully, **immediately proceed** to the next phase:
58
57
  1. `/spec` completes → **immediately** invoke `/exec`
59
58
  2. `/exec` completes → **immediately** invoke `/test` (if UI) or `/qa`
60
59
  3. `/test` completes → **immediately** invoke `/qa`
61
- 4. `/qa` completes → **immediately** create PR
60
+ 4. `/qa` completes → **immediately** create the PR and post the final summary
62
61
 
63
- **The user invoked `/fullsolve` expecting end-to-end automation.** Only stop for:
62
+ <!-- BEGIN: merge-gate (#958) -->
63
+ **The workflow's terminal state is PR created + final summary posted — not merged.** Merging (§5.3), post-merge verification (§5.4), and the auto-merge-path lock release (§5.5) run **only** when `--auto-merge` is passed, `run.autoMerge` is `true` in `.sequant/settings.json`, or the user has explicitly instructed a merge in this conversation (invoking `/fullsolve` alone does not count). Without one of those, `/fullsolve` stops after the final summary — the PR is left open for human review. See "Merge Gate" below for how this is resolved, and §5.3 for the gate itself.
64
+
65
+ **The user invoked `/fullsolve` expecting end-to-end automation up to a mergeable PR.** Only stop for:
64
66
  - Unrecoverable errors (after retry attempts exhausted)
65
- - Final summary after PR creation
67
+ - Final summary after PR creation — **this is the workflow's terminal state**, not a pause
66
68
  - Explicit user interruption
69
+ <!-- END: merge-gate (#958) -->
67
70
 
68
71
  ```
69
72
  WRONG: "Spec complete. Ready for exec phase." [waits]
70
73
  RIGHT: "Spec complete. Proceeding to exec..." [invokes /exec immediately]
74
+ WRONG (no --auto-merge): [creates PR, immediately runs `gh pr merge`]
75
+ RIGHT (no --auto-merge): [creates PR, posts final summary, stops]
71
76
  ```
72
77
 
73
78
  ## Workflow Overview
@@ -77,12 +82,17 @@ RIGHT: "Spec complete. Proceeding to exec..." [invokes /exec immediately]
77
82
  ├─────────────────────────────────────────────────────────────┤
78
83
  │ │
79
84
  │ ┌─────────┐ │
80
- │ │ SPEC │ Plan implementation, extract AC
85
+ │ │ SPEC │ Plan implementation, extract AC (main repo)
86
+ │ └────┬────┘ │
87
+ │ │ │
88
+ │ ▼ │
89
+ │ ┌─────────┐ │
90
+ │ │WORKTREE │ Create it here; export the resolved path │
81
91
  │ └────┬────┘ │
82
92
  │ │ │
83
93
  │ ▼ │
84
94
  │ ┌─────────┐ │
85
- │ │ EXEC │ Implement in feature worktree
95
+ │ │ EXEC │ Verify the path, then implement inside it
86
96
  │ └────┬────┘ │
87
97
  │ │ │
88
98
  │ ▼ │
@@ -120,6 +130,7 @@ RIGHT: "Spec complete. Proceeding to exec..." [invokes /exec immediately]
120
130
  /fullsolve 218 --max-iterations 5 # Override max fix iterations
121
131
  /fullsolve 218 --parallel # Force parallel agent execution (faster, higher token usage)
122
132
  /fullsolve 218 --sequential # Force sequential agent execution (slower, lower token usage)
133
+ /fullsolve 218 --auto-merge # Merge the PR automatically once QA passes (default: off)
123
134
  ```
124
135
 
125
136
  ## Agent Execution Mode
@@ -146,6 +157,30 @@ When spawning sub-agents for quality checks, determine the execution mode:
146
157
 
147
158
  **Pass execution mode to child skills:** When invoking `/qa` or other skills that spawn agents, pass the `--parallel` or `--sequential` flag to maintain consistency.
148
159
 
160
+ ## Merge Gate (#958)
161
+
162
+ Determine whether Phase 5.3–5.5's merge workflow runs at all. This mirrors the Agent Execution Mode resolution above — flag first, then settings, defaulting closed.
163
+
164
+ 1. **Check for CLI flag override:**
165
+ - `--auto-merge` → run the merge workflow (§5.3) after the final summary
166
+ - No flag → do not merge automatically; fall through to step 2
167
+
168
+ 2. **If no flag, read project settings:**
169
+ Use the Read tool to check project settings:
170
+ ```
171
+ Read(file_path=".sequant/settings.json")
172
+ # Parse JSON and extract run.autoMerge (default: false)
173
+ ```
174
+
175
+ 3. **Default:** off. `/fullsolve` ends at PR creation + final summary — this
176
+ preserves the human merge gate recorded in #817–#819 (`sequant ready`
177
+ drives an issue to merge-*readiness*; a human runs `sequant merge` to
178
+ actually merge it).
179
+
180
+ **Explicit user instruction overrides the gate independent of the flag or setting.** If the user has told you in this conversation to merge once ready (not merely "run `/fullsolve`"), treat that as satisfying the gate for this run.
181
+
182
+ **If the gate does not fire:** skip §5.3 and §5.4 entirely. Release the concurrency locks immediately after §5.2 (see §5.5) and stop — do not attempt `gh pr merge` under any circumstance without one of the three conditions above.
183
+
149
184
  ## Orchestration Context
150
185
 
151
186
  This skill acts as an **orchestrator** and sets environment variables for child skills to optimize their behavior:
@@ -166,7 +201,7 @@ This skill acts as an **orchestrator** and sets environment variables for child
166
201
 
167
202
  **Child skills detect orchestration via `SEQUANT_ORCHESTRATOR` and adjust behavior:**
168
203
  - `/spec`: Runs normally (first phase, no prior context)
169
- - `/exec`: Skips worktree creation, uses provided path
204
+ - `/exec`: Skips worktree creation, but still verifies the provided path before using it
170
205
  - `/test`: Skips issue fetch, trusts orchestrator context
171
206
  - `/qa`: Skips pre-flight sync, defers GitHub updates
172
207
  - `/loop`: Uses provided worktree, defers GitHub updates
@@ -250,9 +285,30 @@ Before creating any files, check if they already exist:
250
285
 
251
286
  **If work already exists:** Skip to the appropriate phase (e.g., if implementation is done, go to Phase 3 or 4).
252
287
 
253
- ### 0.3 Acquire Concurrency Lock (#625)
288
+ ### 0.3 Acquire Concurrency Locks (#625, #901)
289
+
290
+ **Before invoking `/spec`**, claim the per-issue concurrency lock.
291
+
292
+ **Phase 0 always runs — including on a resumed run.** Smart Resumption (above) chooses only *which phase comes next after Phase 0*; it never skips Phase 0 itself. A resumed session that skipped the acquire below would hold neither lock while doing exactly the work the locks exist to protect, and would then run the release contract against a lock it never took.
254
293
 
255
- **Before invoking `/spec`**, claim the per-issue concurrency lock. This prevents a second session (another `/fullsolve`, an `npx sequant run`, or another `/fullsolve` in a different window) from racing on the same issue and producing zero-diff exec failures.
294
+ **Declare the issue for the guard.** `pre-tool.sh` decides whether *you* are the checkout's holder by `sessionId` when both sides have one, then by `SEQUANT_ISSUE`, and finally by the session→issue binding it records for itself.
295
+
296
+ ```bash
297
+ export SEQUANT_ISSUE=<issue-number>
298
+ ```
299
+
300
+ **You do not need that export to be recognized as the holder (#906).** `PreToolUse` runs *outside and before* your command's shell, so nothing a skill bash block exports is visible to it — not even an export prepended to the same block as the guarded command. Instead the hook watches for `locks checkout acquire --issue=<N>` and records the binding itself, keyed on the session id, which is the one identity that survives the shell boundary killing the acquiring PID. The `export` above still helps a parent process that launched you with it; it is not what unblocks you.
301
+
302
+ Consequences worth knowing:
303
+
304
+ - After the acquire in this phase, branch-mutating git **in the main checkout is allowed for you** and still refused for every other session.
305
+ - `git -C "$SEQUANT_WORKTREE" …` is exempt regardless, and is what every phase after 1.5 should be using anyway.
306
+ - Path-restore (`git checkout -- <path>`) is exempt whether or not the path is quoted.
307
+ - If the hook never observed your acquire (it was disabled, or the lock was taken by another tool), you are treated as a non-holder — release and re-acquire so the binding is recorded.
308
+
309
+ **What this lock covers — and what it does not (#901).** The per-issue lock is keyed on the *issue number*. It prevents a second session from working on **the same issue** — another `/fullsolve <same-issue>`, an `npx sequant run <same-issue>`, or the same issue in a different window — and producing zero-diff exec failures.
310
+
311
+ It is **not** a general concurrency guarantee. Two sessions working *different* issues take different lock files and never contend, even when they share one working tree. `git checkout`, `switch`, `reset`, `rebase`, `merge` and `cherry-pick` are global to a checkout, so the per-issue lock says nothing about them. That contention is covered by the separate **checkout lock** below.
256
312
 
257
313
  ```bash
258
314
  # Acquire lock for this issue. --skip-pid-check is required: the shell that
@@ -267,11 +323,26 @@ if ! npx sequant locks acquire <issue-number> \
267
323
  fi
268
324
  ```
269
325
 
270
- **Release contract:** Phase 5.5 releases the lock on the happy path. On ANY halt/abort branch (spec failure, exec exhausted, qa loop exhausted with AC_NOT_MET, unrecoverable error, stagnation halt), you MUST run `npx sequant locks release <issue-number> || true` **before** printing the halt message. The explicit release calls below cover the known branches; if you add a new abort path, add a release call there too.
326
+ **Checkout lock (#901).** Claim the working tree as well, so a session on a *different* issue cannot run branch-mutating git in the same checkout. `pre-tool.sh` enforces this: a foreign session's `git checkout`/`switch`/`reset`/`rebase`/`merge`/`cherry-pick` in the main checkout is refused with a message naming the holder and its issue.
327
+
328
+ ```bash
329
+ # Claim the shared working tree. Skip when you will work entirely inside a
330
+ # feature worktree (`git -C <worktree> ...` is never blocked).
331
+ npx sequant locks checkout acquire \
332
+ --issue=<issue-number> \
333
+ --command="/fullsolve <issue-number>" \
334
+ --skip-pid-check || true
335
+ ```
336
+
337
+ Release it alongside the per-issue lock: `npx sequant locks checkout release --issue=<issue-number> || true`. **`--issue` is mandatory** (#906) — it is what proves you are the holder. `--skip-pid-check` means the acquiring shell's PID is already dead, so PID identity is unavailable and a release without `--issue` is refused, not merely ineffective. Stale recovery is therefore age-based only for this lock: the 6h `SEQUANT_SKILL_LOCK_TTL_MS` and the 24h `SEQUANT_MAX_LOCK_AGE_MS` ceiling, *not* same-host dead-PID recovery, which `--skip-pid-check` disables by definition. An abandoned holder still cannot wedge the checkout permanently.
338
+
339
+ **Release contract (#958):** the happy path releases both locks **right after §5.2's final summary** — that is the workflow's default terminal state, since §5.3–5.4 do not run without the Merge Gate firing. Only when the Merge Gate *does* fire does release move to §5.5, after merge (§5.3) and post-merge verification (§5.4) complete. On ANY branch that **exits the workflow without reaching Phase 5** — spec failure, exec iterations exhausted, unrecoverable error — you MUST run `npx sequant locks release <issue-number> || true` and `npx sequant locks checkout release --issue=<issue-number> || true` **before** printing the halt message. The explicit release calls below cover the known branches; if you add a new early-exit path, add a release call there too.
340
+
341
+ **Do NOT release at a branch that continues to Phase 5.** QA-loop exhaustion and the stagnation halt both fall through to PR creation, which still runs git in this tree — releasing there would leave Phase 5 unprotected.
271
342
 
272
343
  **Backstop:** If a release is somehow missed, stale recovery clears the lock after 6h on the same host (`SEQUANT_SKILL_LOCK_TTL_MS` overrides). The user can also force-clear via `npx sequant locks clear <issue-number>`.
273
344
 
274
- **Orchestrator/MCP mode:** When `SEQUANT_ORCHESTRATOR` is set, `locks acquire` and `locks release` are no-ops (exit 0, no file touched). Safe to call unconditionally.
345
+ **Orchestrator/MCP mode:** When `SEQUANT_ORCHESTRATOR` is set, `locks acquire`, `locks release` and every `locks checkout` action are no-ops (exit 0, no file touched), and the `pre-tool.sh` checkout guard stands down. Safe to call unconditionally.
275
346
 
276
347
  ## Phase 1: Planning (SPEC)
277
348
 
@@ -290,20 +361,20 @@ The `/spec` skill will:
290
361
  - Extract acceptance criteria (AC-1, AC-2, etc.)
291
362
  - Create implementation plan (3-7 steps)
292
363
  - Post plan comment to the issue
293
- - Create feature worktree
364
+
365
+ `/spec` plans in the main repository and does **not** create a worktree — that
366
+ is this skill's job, in Phase 1.5 below.
294
367
 
295
368
  ### 1.2 Capture Spec Output
296
369
 
297
370
  After `/spec` completes, extract and store:
298
371
  - **AC Checklist:** List of acceptance criteria for tracking
299
- - **Worktree Path:** Location for subsequent phases
300
372
  - **Recommended Phases:** Whether `/test` is needed (UI features)
301
373
 
302
374
  ```markdown
303
375
  ## Spec Output Captured
304
376
 
305
377
  **Issue:** #<N>
306
- **Worktree:** ../worktrees/feature/<issue-number>-*/
307
378
  **AC Count:** <N> items
308
379
  **Needs Testing:** Yes/No (based on labels)
309
380
  ```
@@ -319,6 +390,7 @@ If `/spec` fails:
319
390
  ```bash
320
391
  # Release before halting — see Phase 0.3 release contract.
321
392
  npx sequant locks release <issue-number> || true
393
+ npx sequant locks checkout release --issue=<issue-number> || true
322
394
  ```
323
395
 
324
396
  ```markdown
@@ -333,7 +405,55 @@ Workflow halted. Fix the issue and re-run `/fullsolve <issue-number>`.
333
405
  **State after Phase 1:**
334
406
  - AC checklist defined
335
407
  - Implementation plan created (and posted to GitHub)
336
- - Feature worktree ready
408
+ - Still in the main repository — no worktree exists yet
409
+
410
+ **→ IMMEDIATELY proceed to Phase 1.5 (do not wait for user input)**
411
+
412
+ ## Phase 1.5: Create the Feature Worktree
413
+
414
+ <!-- BEGIN: worktree-creation (#899) -->
415
+
416
+ **This skill creates the worktree. Nothing upstream does it.** Every phase from
417
+ here on runs inside it, and `SEQUANT_WORKTREE` is what tells the child skills
418
+ where "here" is — so it must hold a **resolved absolute path**, never a glob.
419
+
420
+ ```bash
421
+ # 1. Create it. Idempotent: exits 0 with "Worktree already exists" on re-entry
422
+ # (resumed session, retried phase), so this is safe to run unconditionally.
423
+ ./scripts/new-feature.sh <issue-number>
424
+
425
+ # 2. Resolve the real path. `sequant worktree resolve` reads
426
+ # `git worktree list` in THIS repository and selects on the branch, so it
427
+ # can never return a sibling project's worktree — `../worktrees/` is one
428
+ # flat namespace shared by every repo under the same parent.
429
+ SEQUANT_WORKTREE="$(npx sequant worktree resolve <issue-number>)" || {
430
+ echo "❌ Could not resolve a worktree for #<issue-number> after creating one."
431
+ npx sequant locks release <issue-number> || true
432
+ npx sequant locks checkout release --issue=<issue-number> || true
433
+ exit 1
434
+ }
435
+ export SEQUANT_WORKTREE
436
+ echo "Worktree: $SEQUANT_WORKTREE"
437
+ ```
438
+
439
+ **Never substitute a glob for this step.** `../worktrees/feature/<issue>-*/`
440
+ is not a path: unquoted it may not expand at all, and where it does expand it
441
+ matches on the directory slug, which is shared across repositories and can
442
+ drift from its own branch after a rename.
443
+
444
+ **If `new-feature.sh` fails** (dirty tree, branch conflict), release the lock
445
+ and halt — do not proceed into Phase 2 in the main checkout:
446
+
447
+ ```bash
448
+ npx sequant locks release <issue-number> || true
449
+ npx sequant locks checkout release --issue=<issue-number> || true
450
+ ```
451
+
452
+ <!-- END: worktree-creation (#899) -->
453
+
454
+ **State after Phase 1.5:**
455
+ - Feature worktree created and verified to belong to this repository
456
+ - `SEQUANT_WORKTREE` exported as a resolved absolute path
337
457
 
338
458
  **→ IMMEDIATELY proceed to Phase 2 (do not wait for user input)**
339
459
 
@@ -363,12 +483,13 @@ Set environment variables before invoking `/exec` so it can optimize its behavio
363
483
  export SEQUANT_ORCHESTRATOR=fullsolve
364
484
  export SEQUANT_PHASE=exec
365
485
  export SEQUANT_ISSUE=<issue-number>
366
- export SEQUANT_WORKTREE=../worktrees/feature/<issue-number>-*/
486
+ # Absolute path resolved in Phase 1.5 — never a glob.
487
+ export SEQUANT_WORKTREE="$SEQUANT_WORKTREE"
367
488
  ```
368
489
 
369
490
  When `/exec` detects `SEQUANT_ORCHESTRATOR`, it:
370
- - Skips worktree creation (already done by `/spec`)
371
- - Uses the provided worktree path
491
+ - Skips worktree creation (already done in Phase 1.5)
492
+ - Verifies the provided path with `npx sequant worktree verify` before using it
372
493
  - Defers GitHub comment updates to orchestrator
373
494
 
374
495
  ### 2.3 Handle Exec Failures
@@ -393,6 +514,7 @@ while exec_iteration < MAX_EXEC_ITERATIONS:
393
514
  ```bash
394
515
  # Release before halting — see Phase 0.3 release contract.
395
516
  npx sequant locks release <issue-number> || true
517
+ npx sequant locks checkout release --issue=<issue-number> || true
396
518
  ```
397
519
 
398
520
  ```markdown
@@ -465,7 +587,8 @@ The `/test` skill will:
465
587
  export SEQUANT_ORCHESTRATOR=fullsolve
466
588
  export SEQUANT_PHASE=test
467
589
  export SEQUANT_ISSUE=<issue-number>
468
- export SEQUANT_WORKTREE=../worktrees/feature/<issue-number>-*/
590
+ # Absolute path resolved in Phase 1.5 — never a glob.
591
+ export SEQUANT_WORKTREE="$SEQUANT_WORKTREE"
469
592
  ```
470
593
 
471
594
  When `/test` detects `SEQUANT_ORCHESTRATOR`, it:
@@ -534,7 +657,8 @@ The `/qa` skill will:
534
657
  export SEQUANT_ORCHESTRATOR=fullsolve
535
658
  export SEQUANT_PHASE=qa
536
659
  export SEQUANT_ISSUE=<issue-number>
537
- export SEQUANT_WORKTREE=../worktrees/feature/<issue-number>-*/
660
+ # Absolute path resolved in Phase 1.5 — never a glob.
661
+ export SEQUANT_WORKTREE="$SEQUANT_WORKTREE"
538
662
  ```
539
663
 
540
664
  When `/qa` detects `SEQUANT_ORCHESTRATOR`, it:
@@ -632,6 +756,11 @@ echo "Current branch: $CURRENT_BRANCH"
632
756
 
633
757
  # HARD GATE: Must be on a feature branch, not main/master
634
758
  if [[ "$CURRENT_BRANCH" == "main" || "$CURRENT_BRANCH" == "master" ]]; then
759
+ # Release before halting — see Phase 0.3 release contract. This gate fires
760
+ # later than any other exit path, so a leak here wedges the tree for the
761
+ # longest (#906).
762
+ npx sequant locks release <issue-number> || true
763
+ npx sequant locks checkout release --issue=<issue-number> || true
635
764
  echo "❌ ERROR: On $CURRENT_BRANCH — commits must NOT land on main."
636
765
  echo " Fix: git checkout feature/<issue-number>-* or create a new branch."
637
766
  exit 1
@@ -664,9 +793,17 @@ Post completion comment to issue with:
664
793
  - PR link
665
794
  - Quality metrics
666
795
 
667
- ### 5.3 Merge Workflow (Correct Order)
796
+ ### 5.3 Merge Workflow (Opt-In Only) (#958)
668
797
 
669
- **IMPORTANT:** Merge the PR first, then clean up the worktree.
798
+ **STOP do not run this section unless the Merge Gate above fired.** That
799
+ means one of: `--auto-merge` was passed on this `/fullsolve` invocation,
800
+ `run.autoMerge` is `true` in `.sequant/settings.json`, or the user
801
+ explicitly instructed a merge in this conversation. If none of those hold,
802
+ **do not run `gh pr merge`.** Stop after §5.2's final summary instead — the
803
+ PR stays open, awaiting human review. That is the default terminal state,
804
+ not a fallback.
805
+
806
+ **IMPORTANT (once the gate above has fired):** Merge the PR first, then clean up the worktree.
670
807
 
671
808
  ```bash
672
809
  # 1. Merge PR (without --delete-branch; cleanup happens after success)
@@ -684,6 +821,8 @@ gh pr merge <N> --squash
684
821
 
685
822
  ### 5.4 Post-Merge Verification
686
823
 
824
+ **Skip this section if §5.3 did not run.** Nothing to verify post-merge when there was no merge.
825
+
687
826
  **Recommended:** After merge, verify the build and CLI still work:
688
827
 
689
828
  ```bash
@@ -699,16 +838,26 @@ npx sequant doctor
699
838
 
700
839
  If any command fails, fix immediately on main before continuing. This catches issues like ESM compatibility bugs that unit tests may miss.
701
840
 
702
- ### 5.5 Release Concurrency Lock (#625)
841
+ ### 5.5 Release Concurrency Locks (#625, #901)
703
842
 
704
- After the PR is created (or earlier if the workflow exits gracefully), release the lock so other sessions can claim it:
843
+ **Default path (Merge Gate did not fire):** release runs immediately after
844
+ §5.2's final summary — that is the happy path, since §5.3–5.4 never execute.
845
+ Run the release calls below there, not here.
846
+
847
+ **Auto-merge path (Merge Gate fired):** release runs here, after §5.3
848
+ (merge) and §5.4 (post-merge verification) complete.
849
+
850
+ Either way, release both locks so other sessions can claim them:
705
851
 
706
852
  ```bash
707
853
  npx sequant locks release <issue-number> || true
854
+ npx sequant locks checkout release --issue=<issue-number> || true
708
855
  ```
709
856
 
710
857
  `|| true` is intentional — release is idempotent; the lock may already have been cleared (orchestrator mode, age-based recovery, or manual `locks clear`). The exit code is informational only.
711
858
 
859
+ **But read it if you are debugging (#906).** A non-zero exit from `locks checkout release` no longer means only "nothing was held". It now also means **"held, but not by you"** — a refusal, printed with the holder's issue and the `clear --force` recovery command. If you see that after your own run, the usual cause is a missing or wrong `--issue`, not a stale lock.
860
+
712
861
  ## Iteration Tracking
713
862
 
714
863
  Track iterations to prevent infinite loops:
@@ -807,13 +956,16 @@ Ready for human review and merge.
807
956
 
808
957
  ## Error Recovery
809
958
 
810
- **Concurrency lock cleanup (#625, applies to every abort path below):**
959
+ **Concurrency lock cleanup (#625, #901, applies to every abort path below):**
811
960
 
812
961
  ```bash
813
962
  npx sequant locks release <issue-number> || true
963
+ npx sequant locks checkout release --issue=<issue-number> || true
814
964
  ```
815
965
 
816
- Run this BEFORE printing the halt/exit message in any of the branches below. The release call is idempotent (no-op when nothing is held, no-op in orchestrator mode), so calling it unconditionally on every error path is safe.
966
+ Run this BEFORE printing the halt/exit message in any branch below that **exits the workflow**. The release call is idempotent (no-op when nothing is held, no-op in orchestrator mode), so calling it unconditionally on a genuine exit path is safe.
967
+
968
+ Do **not** run it on the two branches below that continue to Phase 5 — "test loop exhausted" and "QA loop exhausted" both go on to create a PR, and releasing there hands the tree away while this session is still using it.
817
969
 
818
970
  **If spec fails:**
819
971
  - Check issue exists and is readable
@@ -844,6 +996,7 @@ Run this BEFORE printing the halt/exit message in any of the branches below. The
844
996
  | MAX_QA_ITERATIONS | 2 | Max fix loops for QA phase |
845
997
  | SKIP_TEST | false | Skip testing phase |
846
998
  | AUTO_PR | true | Create PR automatically |
999
+ | AUTO_MERGE | false | Merge the PR automatically once QA passes (#958) |
847
1000
 
848
1001
  ## Smart Tests Integration
849
1002
 
@@ -888,6 +1041,11 @@ npx tsx scripts/dev/analyze-hook-logs.ts --tests
888
1041
  /fullsolve 218 --max-iterations 5
889
1042
  ```
890
1043
 
1044
+ **End-to-end including merge:**
1045
+ ```
1046
+ /fullsolve 218 --auto-merge
1047
+ ```
1048
+
891
1049
  ## Batch Processing
892
1050
 
893
1051
  For multiple issues, run `/fullsolve` on each sequentially:
@@ -930,7 +1088,8 @@ As an orchestrator, `/fullsolve` must:
930
1088
  export SEQUANT_ORCHESTRATOR=fullsolve
931
1089
  export SEQUANT_PHASE=<current-phase>
932
1090
  export SEQUANT_ISSUE=<issue-number>
933
- export SEQUANT_WORKTREE=<worktree-path>
1091
+ # Resolved in Phase 1.5 via `sequant worktree resolve` — absolute, never a glob.
1092
+ export SEQUANT_WORKTREE="$SEQUANT_WORKTREE"
934
1093
  ```
935
1094
 
936
1095
  2. **State tracking** is handled automatically by the orchestrator runtime when `SEQUANT_ORCHESTRATOR` is set. Child skills defer state management to the orchestrator to avoid duplicate updates.