The roadmap parser regex used (\w+) to capture slice/task IDs, which
only matches [a-zA-Z0-9_]. Fractional IDs like S03.5 (created by
/gsd steer) contain a dot, causing the parser to skip the entire line.
The dispatcher then jumps from S03 to S04, finds S04 blocked by
the unparsed S03.5, and gives up with 'earlier slice is not complete'.
Update the ID capture group to ([\w.]+) in both:
- roadmap-slices.ts (primary roadmap parser)
- files.ts (plan task parser, for consistency)
This allows dots in slice/task IDs while preserving all existing
behavior for standard IDs like S01, S02, T01, etc.
Closes#681
When auto-mode runs in a worktree, .gsd/ metadata (STATE.md, roadmap
checkboxes, slice plans, task summaries) only updates inside the
worktree directory. The project root on main retains stale state.
If auto-mode restarts, startAutoMode() calls deriveState(projectRoot)
which reads the stale .gsd/ from main, sees completed units as
incomplete, and re-dispatches them — causing an infinite loop on
already-finished work.
Add syncStateToProjectRoot() that copies STATE.md and the active
milestone directory from worktree → project root after each unit's
rebuildState + autoCommit. This ensures deriveState(projectRoot) on
restart reads current completion state.
The sync is fully non-fatal (try/catch wrapped). Failure falls back
to existing behavior. Uses cpSync with recursive:true for the
milestone directory tree.
When auto-mode restarts after being stopped, the initial deriveState()
reads from the project root which has stale .gsd/ metadata. Completed
units appear incomplete, causing re-dispatch of finished work.
The auto-worktree (if it exists from the previous run) has the current
state. After the initial deriveState(base), check if an auto-worktree
exists for the active milestone and re-derive from there.
This is safe because:
- Only triggers when worktree isolation is enabled
- Only when not already inside a worktree
- Only when an auto-worktree actually exists for the milestone
- The worktree setup at lines 976+ still runs normally after
Fixes#654
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use separate git commands instead of && chains (fails on Windows).
Configure git user.name/email before commit (not set in CI runners).
Mirrors the pattern from worktree-e2e.test.ts.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Warp terminal does not correctly re-render inverse video (\x1b[7m)
cursor indicators on arrow key movement, making the cursor appear
invisible when navigating with arrow keys.
Auto-detect Warp via TERM_PROGRAM=WarpTerminal and enable the hardware
cursor by default (same as PI_HARDWARE_CURSOR=1). The hardware cursor
is positioned correctly via CURSOR_MARKER and provides reliable visual
feedback in Warp.
Terminals that render inverse video correctly (iTerm2, Terminal.app)
are unaffected — they continue using the fake cursor by default.
During full redraws, the TUI emitted \x1b[3J (clear scrollback) before
\x1b[2J\x1b[H (clear screen + home). In terminals like Ubuntu Terminal
that honor CSI 3J, this destroyed the scrollback buffer and caused the
scrollbar/view position to jump to the top during phase transitions.
Replace with just \x1b[2J\x1b[H which clears the visible screen and
homes the cursor without touching scrollback history. This preserves
view continuity while still performing a clean redraw.
Adds git.isolation: "none" so developers can use GSD's full planning/execution
methodology with all work happening directly on their current branch — no worktree,
no milestone branch, no merge step.
- Preference plumbing: "none" accepted/validated, getIsolationMode() helper
- Core bypass: all worktree/branch gates in auto.ts skip in none mode
- Peripheral: doctor skips worktree checks, system prompt omits worktree context
- Docs: git-strategy, configuration, auto-mode, troubleshooting, system prompt updated
- Tests: 11 new tests, 621/621 pass
Three fixes for git worktree usage:
1. Add resolveGitDir() that follows the gitdir: pointer in worktree
.git files. Without this, any code looking for MERGE_HEAD,
SQUASH_MSG, or rebase state checks the wrong path in worktrees.
2. Guard captureIntegrationBranch() with detectWorktreeName() — in a
worktree the base branch is implicit (worktree/<name>), so writing
it to META.json leaves stale metadata that persists after merge-back.
3. Use resolveGitDir() in doctor.ts for corrupt merge state detection.
Previously hardcoded join(basePath, ".git") which misses worktrees.
Includes 7 regression tests covering all three fixes.
Relates to #654 (stale state from main branch instead of worktree)
Relates to #672 (parallel milestone orchestration)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix type compatibility issues introduced in the JS→TS conversion:
- Restore PageEntry.page to `any` (holds Playwright Page instance)
- Use Record<string, any> for session parameters in
buildFailureHypothesis and summarizeBrowserSession (callers pass
rich objects with extra properties)
- Use Record<string, unknown> for formatTimelineEntries options
- Add explicit type annotations to local variables and callbacks
to satisfy noImplicitAny in tsconfig.extensions.json
Capture the session file path on pause and synthesize a recovery briefing
on resume, so the next agent knows what already happened instead of
restarting the unit from scratch.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Move @types/mime-types from dependencies to devDependencies in pi-tui
(type declarations are only needed at compile time)
- Align chalk version: upgrade root from ^5.5.0 to ^5.6.2 to match
pi-ai and avoid version skew
- Extract duplicated help text from loader.ts and cli.ts into shared
help-text.ts module (single source of truth)
- Convert validate-pack.sh to Node.js for Windows compatibility
- Fix dev.js using unnecessary npx for tsc (it's a devDependency,
use node_modules/.bin/tsc directly)
When auto-mode loop recovery marks tasks as [x] in the plan file and
auto is restarted, the done count can equal total. The display always
showed done+1 (assuming "currently working on next task"), causing
values like "task 5/4". Clamp to total so it never exceeds the max.
Closes#662
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Convert browser-tools/core.js (1058 lines) to native TypeScript with
full type annotations from the existing .d.ts file. Remove the
separate .d.ts declaration file (types are now inline).
- Add c8 test coverage reporting: `npm run test:coverage` generates
text + lcov reports with 50% statement threshold baseline.
- Add coverage/ to .gitignore
All 712 unit tests, 63 browser-tools tests, and 11 integration tests
pass with zero regressions.
1. Windows: `start` command opens CMD instead of browser during GitHub
Copilot login — pass empty title arg so URL is treated as target
2. Launch banner missing Tavily provider in web search status display
3. MCPorter auto-installs via npm when not found (like ripgrep auto-download)
4. Notification prefs showing [object Object] — guard against non-boolean values
Closes#663
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Agent now cancels in-flight async_bash jobs after editing source files
before re-running them, preventing stale results from polluting context.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix loadStoredEnvKeys divergent provider lists: add telegram_bot and
custom-openai to wizard.ts (the canonical copy used by CLI), remove
dead duplicate from onboarding.ts
- Security: add SAFE_COMMAND_PREFIXES allowlist to resolveConfigValue
to prevent arbitrary RCE via settings.json shell commands
- Security: add TOFU (Trust On First Use) model for project-local
extensions — skip untrusted .pi/extensions/ with stderr warning
- Performance: debounce sql.js MemoryStorage persistence (500ms window)
so rapid mutations coalesce into a single db.export()+writeFileSync
- Fix double lstatSync call in tool-bootstrap.ts isRegularFile
- Add 26 new tests covering all changes
findMilestoneIds() had a bare catch that returned [] on any error,
causing showSmartEntry() to think no milestones exist and restart
the new-project discuss flow in a loop. Add error logging when the
directory exists but scanning fails, and a sanity check that warns
the user instead of looping when the directory has entries that
weren't recognized.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- google-search test: mock getApiKeyForProvider to return JSON string
matching real OAuth provider behavior (token+projectId), instead of
using AuthStorage.inMemory which bypasses the OAuth getApiKey transform
- smoke test: split on /[/\\]/ for Windows path separator compatibility
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
On Windows, raw paths like D:\... are interpreted as protocol "d:" by
the ESM loader. Convert via pathToFileURL before dynamic import.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>