* fix(#683): auto-degrade phase execution to sequential on worktree base mismatch Claude Code forks worktree-isolated executors off the repository default branch (origin/HEAD), not the orchestrator's HEAD. Running /gsd-execute-phase on a branch diverged from the default (unmerged milestone/feature branch) left every executor without the phase's plan files and tripped the worktree-branch-check guard with `exit 42` — 100% reproducible, all OSes. - New module src/worktree-base-ref.cts: HEAD-vs-fork-base drift detection (origin/HEAD with symbolic-ref fallback) and no-clobber worktree.baseRef management, exposed as `worktree base-check` / `worktree set-baseref`. - execute-phase.md: pre-dispatch, for Claude Code with worktrees enabled, auto-degrades the run to sequential on the main tree when a base mismatch is detected, recommending worktree.baseRef:"head". The exit-42 guard stays as a backstop. - Installer: fresh local Claude installs set worktree.baseRef:"head" in .claude/settings.local.json (no-clobber, respecting an explicit shared settings.json value); upgrades print an opt-in notice pointing at `gsd-tools worktree set-baseref`. - Docs: how-to guide, CLI/config reference, planning-config cross-ref. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#683): auto-apply worktree.baseRef on upgrade; gate fresh+upgrade on use_worktrees Per maintainer direction: on a local Claude Code UPGRADE, set worktree.baseRef:"head" automatically (no opt-in notice) when the project's workflow.use_worktrees is enabled, instead of merely printing a remediation notice. For consistency the FRESH path is now gated the same way: both paths compute worktrees-enabled once (bounded walk-up read of .planning/config.json, default enabled unless workflow.use_worktrees === false) and apply the no-clobber baseRef only when enabled — never overwriting an explicit value in settings.local.json or a shared settings.json. gsd-tools worktree set-baseref remains for manual use. Docs + changeset updated; tests hardened (file-exists assertions, fresh+disabled case, upgrade idempotency). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#683): measure workflow byte-budget on LF, fixing Windows-only CI failure The workflow-size-budget test failed only on Windows: git checks out the .md files as CRLF (no eol=lf in .gitattributes) and byteCount used fs.statSync().size (raw on-disk bytes), counting an extra \r per line. That inflated execute-phase.md — the XL high-water-mark file pinned near its ceiling by the tighten-only ratchet — from 88492 LF bytes to ~90245 on Windows, over the 90000 XL ceiling, while passing on the LF-checkout Mac/Linux runners. The ceilings are explicitly "calibrated against raw `wc -c`" on an LF checkout, so the measurement should be LF-based on every platform. byteCount now reads the file and counts Buffer.byteLength after stripping CR, making the budget platform-independent (a no-op on LF checkouts; verified statSync === normalized for all 88 workflow files). No ceilings changed. Added a regression test asserting CRLF and LF content of the same file count identically. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#683): make worktree-base-ref test path mocks Windows-safe (path.join) tests/worktree-base-ref.test.cjs keyed its injected readFile/writeFile mocks (and a few expected `file` values) with forward-slash template literals like `${claudeDir}/settings.local.json`. The module composes those paths with path.join(), which emits backslashes on Windows, so the mock keys never matched the module's lookup → readFile returned null → resolveEffectiveBaseRef / cmdWorktreeBaseCheck / cmdWorktreeSetBaseRef (and the JSONC variants) failed on the Windows full-test runner only (they passed on Mac/Linux, and the install tests passed because they use the real filesystem). The module is correct; only the test fixtures hardcoded '/'. All mock keys and path assertions now use path.join(base, ...) mirroring the module, so they match on every platform (no-op on POSIX). 19 path references across 16 lines. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -421,6 +421,34 @@ node gsd-tools.cjs websearch <query> [--limit N] [--freshness day|week|month]
|
||||
|
||||
---
|
||||
|
||||
## Worktree Commands
|
||||
|
||||
Diagnose and configure the worktree fork base used by Claude Code's `isolation="worktree"` executor dispatch. These commands address the branch-divergence condition described in [Fix the worktree base-mismatch (exit 42) error](how-to/fix-worktree-base-mismatch.md).
|
||||
|
||||
```bash
|
||||
# Check whether the current HEAD has diverged from the worktree fork base.
|
||||
# Returns JSON: { shouldDegrade, reason, message, headSha, forkRef, forkSha }
|
||||
node gsd-tools.cjs worktree base-check
|
||||
|
||||
# Write worktree.baseRef:"head" into .claude/settings.local.json (no-clobber).
|
||||
# Returns JSON: { changed, skipped, previous, baseRef, file }
|
||||
node gsd-tools.cjs worktree set-baseref
|
||||
```
|
||||
|
||||
**`worktree base-check`** reads `worktree.baseRef` from `.claude/settings.local.json` (then `.claude/settings.json`) and compares the current `HEAD` SHA against `origin/HEAD`. The `shouldDegrade` field is `true` when the execute-phase orchestrator will fall back to sequential execution. Possible `reason` values:
|
||||
|
||||
| `reason` | `shouldDegrade` | Meaning |
|
||||
|---|---|---|
|
||||
| `baseref-head` | `false` | `worktree.baseRef:"head"` is set; no mismatch possible |
|
||||
| `head-matches-fork` | `false` | HEAD and `origin/HEAD` are the same commit |
|
||||
| `head-diverged-from-fork` | `true` | Branch is ahead of or diverged from `origin/HEAD` |
|
||||
| `fork-ref-unknown` | `true` | `origin/HEAD` could not be resolved |
|
||||
| `no-head` | `false` | Not in a git repo (no `HEAD`) |
|
||||
|
||||
**`worktree set-baseref`** applies a no-clobber write of `worktree.baseRef:"head"` to `.claude/settings.local.json`. If the file already contains an explicit `baseRef` value other than `"head"`, the existing value is preserved and `skipped:"explicit-other"` is returned. Malformed JSON causes an error rather than a silent overwrite. Both fresh installs and upgrades of GSD Core run this automatically when `workflow.use_worktrees` is enabled (the default); the command is also available for manual use — for example, to apply the setting when worktrees were toggled on after installation, or to re-apply it after a settings change.
|
||||
|
||||
---
|
||||
|
||||
## Graphify
|
||||
|
||||
Build, query, and inspect the project knowledge graph in `.planning/graphs/`. Requires `graphify.enabled: true` in `config.json` (see [Configuration Reference](CONFIGURATION.md#graphify-settings)).
|
||||
@@ -471,6 +499,7 @@ User-facing entry point: `/gsd-graphify` (see [Command Reference](COMMANDS.md#gs
|
||||
| Audit | `lib/audit.cjs` | Phase/milestone audit queue handlers; `audit-open` helper |
|
||||
| GSD2 Import | `lib/gsd2-import.cjs` | Reverse-migration importer from GSD-2 projects (backs `/gsd-import --from-gsd2`) |
|
||||
| Intel | `lib/intel.cjs` | Queryable codebase intelligence index (backs `/gsd-map-codebase --query`) |
|
||||
| Worktree Base Ref | `lib/worktree-base-ref.cjs` | Worktree fork-base detection and `worktree base-check` / `set-baseref` commands (#683) |
|
||||
|
||||
---
|
||||
|
||||
@@ -498,4 +527,5 @@ API keys configured via `/gsd-settings` (`brave_search`, `firecrawl`, `exa_searc
|
||||
- [Commands](COMMANDS.md)
|
||||
- [Configuration](CONFIGURATION.md)
|
||||
- [Architecture](ARCHITECTURE.md)
|
||||
- [Fix the worktree base-mismatch (exit 42) error](how-to/fix-worktree-base-mismatch.md)
|
||||
- [docs index](README.md)
|
||||
|
||||
@@ -245,7 +245,7 @@ All workflow toggles follow the **absent = enabled** pattern. If a key is missin
|
||||
| `workflow.max_discuss_passes` | number | `3` | Maximum number of question rounds in discuss-phase before the workflow stops asking. Useful in headless/auto mode to prevent infinite discussion loops. |
|
||||
| `workflow.skip_discuss` | boolean | `false` | When `true`, `/gsd-autonomous` bypasses the discuss-phase entirely, writing minimal CONTEXT.md from the ROADMAP phase goal. Useful for projects where developer preferences are fully captured in PROJECT.md/REQUIREMENTS.md. Added in v1.28 |
|
||||
| `workflow.text_mode` | boolean | `false` | Replaces AskUserQuestion TUI menus with plain-text numbered lists. Required for Claude Code remote sessions (`/rc` mode) where TUI menus don't render. Can also be set per-session with `--text` flag on discuss-phase. Added in v1.28 |
|
||||
| `workflow.use_worktrees` | boolean | `true` | When `false`, disables git worktree isolation for parallel execution. Users who prefer sequential execution or whose environment does not support worktrees can disable this. Added in v1.31 |
|
||||
| `workflow.use_worktrees` | boolean | `true` | When `false`, disables git worktree isolation for parallel execution. Users who prefer sequential execution or whose environment does not support worktrees can disable this. Added in v1.31. **Branch-divergence note:** when your branch is ahead of `origin/HEAD`, GSD auto-degrades to sequential and prints a warning. Set `worktree.baseRef:"head"` in `.claude/settings.local.json` (run `node gsd-tools.cjs worktree set-baseref`) to restore parallel execution. See [Fix the worktree base-mismatch (exit 42) error](how-to/fix-worktree-base-mismatch.md). |
|
||||
| `workflow.worktree_skip_hooks` | boolean | `false` | When `true`, executor agents in worktree mode pass `--no-verify` (skipping pre-commit hooks) and post-wave hook validation runs against the merged result instead. Opt-in escape hatch for projects whose hooks cannot run in agent worktrees. Default `false` runs hooks on every commit (#2924). |
|
||||
| `workflow.code_review` | boolean | `true` | Enable `/gsd-code-review` and `/gsd-code-review --fix` commands. When `false`, the commands exit with a configuration gate message. Added in v1.34 |
|
||||
| `workflow.code_review_depth` | string | `standard` | Default review depth for `/gsd-code-review`: `quick` (pattern-matching only), `standard` (per-file analysis), or `deep` (cross-file with import graphs). Can be overridden per-run with `--depth=`. Added in v1.34 |
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"generated": "2026-06-06",
|
||||
"generated": "2026-06-07",
|
||||
"families": {
|
||||
"agents": [
|
||||
"gsd-advisor-researcher",
|
||||
@@ -350,6 +350,7 @@
|
||||
"workstream-inventory.cjs",
|
||||
"workstream-name-policy.cjs",
|
||||
"workstream.cjs",
|
||||
"worktree-base-ref.cjs",
|
||||
"worktree-safety.cjs"
|
||||
],
|
||||
"hooks": [
|
||||
|
||||
@@ -370,7 +370,7 @@ The `gsd-planner` agent is decomposed into a core agent plus reference modules t
|
||||
|
||||
---
|
||||
|
||||
## CLI Modules (86 shipped)
|
||||
## CLI Modules (87 shipped)
|
||||
|
||||
Full listing: `gsd-core/bin/lib/*.cjs`.
|
||||
|
||||
@@ -461,6 +461,7 @@ Full listing: `gsd-core/bin/lib/*.cjs`.
|
||||
| `workstream-inventory.cjs` | Shared workstream inventory projection: state fields, phase/plan/summary counts, roadmap phase count, and active marker — thin orchestrator that delegates pure projection to `workstream-inventory-builder.cjs` |
|
||||
| `workstream-name-policy.cjs` | Canonical workstream name validation (`isValidActiveWorkstreamName`, `hasInvalidPathSegment`, `validateWorkstreamName`) and slug normalization (`toWorkstreamSlug`) |
|
||||
| `workstream.cjs` | Workstream CRUD, migration, session-scoped active pointer |
|
||||
| `worktree-base-ref.cjs` | Worktree base-ref drift detection and degrade decision (`evaluateWorktreeBaseDegrade`) plus no-clobber `worktree.baseRef` settings management for the `base-check`/`set-baseref` subcommands (#683) |
|
||||
| `worktree-safety.cjs` | Worktree-root resolution and non-destructive prune policy decisions; owns W017 health-check logic |
|
||||
|
||||
[`docs/CLI-TOOLS.md`](CLI-TOOLS.md) may describe a subset of these modules; when it disagrees with the filesystem, this table and the directory listing are authoritative.
|
||||
|
||||
@@ -33,6 +33,7 @@ Language versions: [English](README.md) · [Português (pt-BR)](pt-BR/README.md)
|
||||
- [Migrate from GSD 2](how-to/migrate-from-gsd-2.md) — upgrade an existing GSD 2 project to GSD Core
|
||||
- [Update GSD](how-to/update-gsd.md) — re-run the installer to pick up the latest release
|
||||
- [Clean up get-shit-done-cc](cleanup-get-shit-done-cc.md) — remove leftover old-package artifacts that cause a spurious `⬆ /gsd:update` indicator after migrating to `@opengsd/gsd-core`
|
||||
- [Fix the worktree base-mismatch (exit 42) error](how-to/fix-worktree-base-mismatch.md) — resolve the branch-divergence condition that halts parallel phase execution
|
||||
- [Recover and troubleshoot](how-to/recover-and-troubleshoot.md) — fix common problems, rebuild context, and uninstall
|
||||
|
||||
---
|
||||
|
||||
143
docs/how-to/fix-worktree-base-mismatch.md
Normal file
143
docs/how-to/fix-worktree-base-mismatch.md
Normal file
@@ -0,0 +1,143 @@
|
||||
# How to fix the worktree base-mismatch (exit 42) error
|
||||
|
||||
**Goal:** Understand why `/gsd-execute-phase` halts with `FATAL: worktree base mismatch` / exit 42 when your branch is ahead of the default branch, and choose the right fix to restore normal — or parallel — execution.
|
||||
|
||||
**Prerequisites:** GSD Core is installed and you have an active project. You have run `/gsd-execute-phase` and either seen the exit-42 error or the one-line `⚠ Worktree base mismatch` warning.
|
||||
|
||||
---
|
||||
|
||||
## What you will see
|
||||
|
||||
When you run `/gsd-execute-phase` on a branch that is ahead of the repository's default branch (for example, an unmerged milestone branch, a long-lived feature branch, or a branch with commits not yet in `origin/HEAD`), you may see one of two messages:
|
||||
|
||||
**Automatic-degrade warning (phase still completes):**
|
||||
|
||||
```
|
||||
⚠ Worktree base mismatch: HEAD (abc12345) differs from origin/HEAD (def67890).
|
||||
Running this phase sequentially on the main working tree.
|
||||
To keep parallel worktrees, set worktree.baseRef:"head" in
|
||||
.claude/settings.local.json (or run: gsd-tools worktree set-baseref). See #683.
|
||||
```
|
||||
|
||||
The phase runs to completion sequentially; nothing is blocked. This is the runtime mitigation.
|
||||
|
||||
**Exit-42 halt (older installs or misconfigured environments):**
|
||||
|
||||
```
|
||||
FATAL: worktree base mismatch
|
||||
```
|
||||
|
||||
All worktree-isolated executors halt immediately. Zero progress is made.
|
||||
|
||||
---
|
||||
|
||||
## Why this happens
|
||||
|
||||
Claude Code's `isolation="worktree"` forks executor worktrees from the repository's default branch (`origin/HEAD`), not from your current `HEAD`. When your branch contains commits that `origin/HEAD` does not have — plan files, new source files, anything added since the branch diverged — those files are absent inside each worktree. GSD's `worktree-branch-check` safety guard correctly refuses to act on a worktree that does not match the orchestrator's state, and exits with code 42.
|
||||
|
||||
This is the guard working as designed: it prevents silent data loss or phantom edits in the wrong tree. The error is a branch-state condition, not an OS-specific or hardware issue.
|
||||
|
||||
---
|
||||
|
||||
## Option 1 — Do nothing (you are already unblocked)
|
||||
|
||||
If you saw the `⚠ Worktree base mismatch` warning rather than an exit-42 halt, GSD has already automatically degraded to sequential execution on the main working tree for this run. The phase will complete. No action is required.
|
||||
|
||||
Use this option when:
|
||||
|
||||
- You are on a diverged branch temporarily
|
||||
- You do not care about parallel execution for this phase
|
||||
- You want to merge back to the default branch soon
|
||||
|
||||
---
|
||||
|
||||
## Option 2 — Permanent fix: set `worktree.baseRef: "head"` (recommended)
|
||||
|
||||
This option restores parallel worktree execution on diverged branches. It tells Claude Code to fork executor worktrees from your current `HEAD` instead of `origin/HEAD`, so the plan files and branch-only commits are present in every worktree.
|
||||
|
||||
Run the convenience command from your project root:
|
||||
|
||||
```bash
|
||||
node "$HOME/.claude/gsd-core/bin/gsd-tools.cjs" worktree set-baseref
|
||||
```
|
||||
|
||||
This writes `worktree.baseRef: "head"` into `.claude/settings.local.json` in your project root. It is no-clobber: if you already have an explicit `baseRef` set to something else, it leaves your value in place and tells you.
|
||||
|
||||
To verify the result:
|
||||
|
||||
```bash
|
||||
node "$HOME/.claude/gsd-core/bin/gsd-tools.cjs" worktree base-check
|
||||
```
|
||||
|
||||
The output is JSON. When `shouldDegrade` is `false` and `reason` is `"baseref-head"`, parallel worktrees will work on any branch.
|
||||
|
||||
Alternatively, set the value by hand in `.claude/settings.local.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"worktree": {
|
||||
"baseRef": "head"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Note:** Fresh installs and upgrades of GSD Core both set `worktree.baseRef:"head"` automatically in `.claude/settings.local.json` (no-clobber) when `workflow.use_worktrees` is enabled (the default). You can also apply or re-apply it manually at any time with `gsd-tools worktree set-baseref` — for example, if you toggled worktrees on after the initial install.
|
||||
|
||||
Use this option when:
|
||||
|
||||
- You regularly work on long-lived or milestone branches
|
||||
- You want parallel phase execution (faster, lower context-window pressure)
|
||||
- You are a solo developer or team working on a feature branch for an extended period
|
||||
|
||||
---
|
||||
|
||||
## Option 3 — Fallback: disable worktrees entirely
|
||||
|
||||
If worktrees are causing persistent problems beyond the base-mismatch (for example, your environment does not support them), disable them permanently for this project:
|
||||
|
||||
Add or edit `.planning/config.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"workflow": {
|
||||
"use_worktrees": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
All executor agents will then run sequentially on the main working tree for every phase. This is equivalent to what the automatic degrade does, but permanent.
|
||||
|
||||
Use this option when:
|
||||
|
||||
- Worktrees are consistently problematic in your environment
|
||||
- You prefer sequential execution for auditability or tooling reasons
|
||||
- You are on a platform or CI setup that does not support git worktrees
|
||||
|
||||
See also: [`workflow.use_worktrees`](../CONFIGURATION.md#workflow-toggles) in the configuration reference.
|
||||
|
||||
---
|
||||
|
||||
## The exit-42 backstop
|
||||
|
||||
The `worktree-branch-check` guard (exit 42) remains active in all execution modes as a safety backstop. It fires only when an executor worktree's branch does not match the expected orchestrator state — a condition that should not arise once you have applied one of the options above. If you continue to see exit 42 after setting `worktree.baseRef: "head"`, run `/gsd-forensics` to investigate.
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
| Situation | Recommended action |
|
||||
|-----------|-------------------|
|
||||
| Saw the warning, phase completed | Nothing — degrade handled it automatically |
|
||||
| Regularly on diverged branches, want parallel execution | `worktree set-baseref` (Option 2) |
|
||||
| Worktrees consistently problematic | Set `workflow.use_worktrees: false` (Option 3) |
|
||||
| Still seeing exit 42 after fixes | Run `/gsd-forensics "exit 42 after fix"` |
|
||||
|
||||
---
|
||||
|
||||
## Related
|
||||
|
||||
- [Recover and troubleshoot](recover-and-troubleshoot.md)
|
||||
- [Debug a failed execution](debug-a-failed-execution.md)
|
||||
- [Configuration reference — workflow toggles](../CONFIGURATION.md#workflow-toggles)
|
||||
- [CLI Tools reference — worktree commands](../CLI-TOOLS.md#worktree-commands)
|
||||
- [docs index](../README.md)
|
||||
@@ -153,6 +153,18 @@ Check whether the plan is too ambitious. Plans should have two or three tasks at
|
||||
|
||||
For systematic diagnosis of what went wrong, see [Debug a failed execution](debug-a-failed-execution.md).
|
||||
|
||||
### If you see "FATAL: worktree base mismatch" or the exit-42 warning
|
||||
|
||||
This happens when your current branch is ahead of the repository's default branch (for example, an unmerged milestone or feature branch). Claude Code forks executor worktrees from `origin/HEAD`, not your `HEAD`, so plan files that exist only on your branch are absent inside the worktree.
|
||||
|
||||
Since the fix landed, GSD automatically degrades to sequential execution on the main working tree and prints a one-line warning — the phase will complete without any action from you. To restore parallel execution permanently, run:
|
||||
|
||||
```bash
|
||||
node "$HOME/.claude/gsd-core/bin/gsd-tools.cjs" worktree set-baseref
|
||||
```
|
||||
|
||||
For a full explanation and all available options, see [Fix the worktree base-mismatch (exit 42) error](fix-worktree-base-mismatch.md).
|
||||
|
||||
### If parallel execution causes build lock errors or pre-commit hook failures
|
||||
|
||||
This is caused by multiple agents triggering build tools simultaneously. GSD handles this automatically since v1.26. If you are on an older version, or still seeing contention, disable parallel execution:
|
||||
@@ -312,12 +324,14 @@ Also audit which MCP servers are enabled. Every enabled MCP server injects its t
|
||||
| Update broke local changes | `/gsd-update --reapply` |
|
||||
| Want session summary | `/gsd-pause-work --report` |
|
||||
| Parallel execution build errors | Update GSD or set `parallelization.enabled: false` |
|
||||
| Worktree base mismatch / exit 42 | Auto-degraded to sequential (no action needed); run `worktree set-baseref` to restore parallelism |
|
||||
|
||||
---
|
||||
|
||||
## Related
|
||||
|
||||
- [Debug a failed execution](debug-a-failed-execution.md)
|
||||
- [Fix the worktree base-mismatch (exit 42) error](fix-worktree-base-mismatch.md)
|
||||
- [Install on your runtime](install-on-your-runtime.md)
|
||||
- [Commands](../COMMANDS.md)
|
||||
- [docs index](../README.md)
|
||||
|
||||
Reference in New Issue
Block a user