Tasks:
- chore(M002/S06): auto-commit after complete-slice
- chore(M002/S06): auto-commit after complete-slice
- chore(M002/S06/T02): auto-commit after execute-task
- chore(M002/S06/T02): auto-commit after execute-task
- chore(M002/S06/T01): auto-commit after execute-task
- chore(M002/S06/T01): auto-commit after execute-task
- chore(M002/S06): auto-commit after plan-slice
- chore: update state for S06 execution
- docs(S06): add slice plan
Branch: gsd/M002/S06
Tasks:
- chore(M002/S02): auto-commit after complete-slice
- chore(M002/S02): auto-commit after complete-slice
- chore(M002/S02/T02): auto-commit after execute-task
- chore(M002/S02/T02): auto-commit after execute-task
- chore(M002/S02/T01): auto-commit after execute-task
- fix: expand tool outputs by default and pull main before slice merge
- chore(M002/S02): auto-commit after plan-slice
- docs(S02): add slice plan
Branch: gsd/M002/S02
interview-ui.ts saveEditorToState() was calling getText() which returns
paste markers like '[paste #1 2033 chars]' for content >1000 chars or
>10 lines. The actual pasted content was stored in the Editor's paste
map but never expanded back.
This silently discards user input in ask_user_questions notes — any
substantive response (voice transcripts, detailed explanations, extended
enrichments) that exceeds the paste threshold gets replaced with a
marker string. The LLM receives '[paste #1 N chars]' instead of the
user's actual words.
Fix: getText() → getExpandedText() — the Editor already has the method
that expands paste markers to their stored content. One-line change.
External packages (pi-rtk, pi-context, pi-agent-browser, etc.) import from
the original @mariozechner/* scope which GSD forked to @gsd/*. Add aliases
in both jiti resolution paths (virtualModules for Bun, getAliases for Node)
so these packages resolve correctly without manual workarounds.
Closes#161
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add .gitignore negation for vendor path
- Restore marked.min.js from pi-mono upstream
- Restore highlight.min.js from pi-mono upstream
Fixes build failure in pi-coding-agent caused by
global vendor/ ignore rule excluding vendored libs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Workspace packages (@gsd/pi-agent-core, @gsd/pi-ai, @gsd/pi-coding-agent,
@gsd/pi-tui) are included in the published tarball via the "files" field but
are not resolvable by Node because npm does not recreate workspace symlinks
when installing from the registry. This causes "ERR_MODULE_NOT_FOUND: Cannot
find package '@gsd/pi-coding-agent'" on fresh installs.
Add workspace packages to both "dependencies" and "bundleDependencies" so npm
packs them into node_modules/ within the tarball and installs them correctly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- /exit now calls stopAuto() before exiting to save activity log and clear locks
- Added new /kill command for immediate exit without cleanup
- Fixes issue #132: /exit terminates too abruptly and leaves terminal state dirty
The ESM resolve hook was rewriting .js imports from vendored Pi
packages (packages/*/dist/) to .ts, breaking test resolution.
Compiled dist/ files need their .js specifiers left intact.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Vendor all 4 Pi packages (tui, ai, agent-core, coding-agent) from
pi-mono v0.57.1 as @gsd/* workspace packages under packages/. This
replaces the compiled npm dependency (@mariozechner/pi-coding-agent)
and patch-package workflow, giving direct source access for
modifications.
- Copy Pi source from pi-mono v0.57.1 into packages/
- Create workspace package.json + tsconfig.json for each package
- Rename ~240 imports from @mariozechner/pi-* to @gsd/pi-*
- Apply existing patches as source edits (setModel persist, VT input)
- Remove @mariozechner/pi-coding-agent dep and patch-package
- Update build pipeline to build packages in dependency order
- Add pi-upstream git remote for future selective syncing
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Doctor's fix:true mode was creating summary stubs and marking slices
done in the roadmap during the post-hook after every task. This
short-circuited the complete-slice dispatch unit — by the time
dispatchNextUnit ran, the slice was already 'done' and the merge
guard merged it to main, so complete-slice (which writes the real
compressed summary) never got a chance to run.
Root cause: doctor conflated two responsibilities — task-level
bookkeeping (marking checkboxes) and completion state transitions
(summary stubs, roadmap marking). The post-hook should only do
the former.
Fix: added fixLevel option to runGSDDoctor. fixLevel:'task' (used
by post-hook) skips completion transition codes. fixLevel:'all'
(default, used by manual gsd doctor and resume) preserves existing
recovery behavior.
Completion transition codes gated by fixLevel:
- all_tasks_done_missing_slice_summary
- all_tasks_done_missing_slice_uat
- all_tasks_done_roadmap_not_checked
Restores main_branch field on GitPreferences (removed in a prior merge conflict
resolution) and adds VALID_BRANCH_NAME validation in getMainBranch(). Implements
runPreMergeCheck with auto-detection from package.json test scripts and support
for custom commands via prefs.pre_merge_check string values.
Fixes 5 pre-existing test failures in git-service.test.ts (158/158 now pass).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The crash loop: stale state → unit redispatched → activity log grows →
retry diagnostic reads full log → prompt grows → replaceAll on huge
string → V8 heap exhaustion. Cap both the read path (10MB JSONL parse
limit) and the injection path (50K char prompt cap) to break the cycle.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Pre-switch auto-commits were including .gsd/ planning artifacts (roadmaps, STATE.md)
on both sides of a branch switch, causing reliable merge conflicts when squash-merging
slices back to main. Now pre-switch auto-commits exclude the entire .gsd/ directory,
while post-task auto-commits continue to include them normally.
Also restores VALID_BRANCH_NAME export removed in a prior merge conflict resolution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Front-load API key collection into GSD's planning phase so auto-mode
runs uninterrupted. Planning prompts forecast secrets into a manifest,
auto-mode collects pending keys before dispatching the first slice.
- getManifestStatus() queries manifest state against env
- collectSecretsFromManifest() orchestrates summary, collection, manifest update
- showSecretsSummary() read-only TUI summary with status indicators
- collectOneSecret() enhanced with guidance display above masked input
- Secrets gate in startAuto() — non-fatal, inherited by guided flow
- 19 new tests (manifest-status, collect-from-manifest, auto-secrets-gate)
- All 10 requirements (R001-R010) validated
Uses the existing SessionManager.continueRecent() from the Pi SDK
to load the most recent session for the current working directory.
Mirrors the --continue flag already available in the base Pi CLI.
mergeSliceToMain now runs git reset --hard if git merge --squash fails,
restoring a clean working tree instead of leaving conflict markers.
The merge guard catch block in auto.ts now:
1. Detects leftover conflicted state (UU/AA/UD in porcelain status)
2. Resets the working tree if conflicts remain
3. Stops auto-mode with a clear error instead of continuing with
corrupted .gsd/ state files that cause an infinite dispatch loop
Also fixes conflict markers in loader.ts, logo.ts, and postinstall.js
that were baked into main from a prior bad merge resolution.
Remove task/project/product classification taxonomy from discuss prompt.
The LLM now sizes work based on judgment, not labels.
Key changes:
- discuss.md: Replace 3-tier classification with judgment-based sizing.
Remove hard minimum question rounds (2 for task, 4 for project).
Questioning depth now matches actual scope.
- plan-milestone.md: Add right-sizing doctrine. Single-slice milestones
now write the S01 plan + task plans inline, eliminating separate
research-slice and plan-slice sessions.
- plan-slice.md: Add right-sizing guidance. Make Proof Level,
Integration Closure, and Observability sections conditional —
omit entirely for simple slices instead of filling with 'none'.
Consolidate self-audit from 10 items to 7 (remove duplicates).
- auto.ts: Skip research-slice for S01 when milestone research exists.
Update peekNext label for plan-milestone.
- complete-slice.md: Add effort-matching guidance. Lighten observability
verification for simple slices.
- execute-task.md: Make observability steps conditional on task plan
content rather than always required.
- templates (plan.md, task-plan.md): Add comments making heavyweight
sections explicitly optional for simple work.
Pipeline reduction for simple 1-slice milestone:
Before: 9-10 sessions (research-M, plan-M, research-S, plan-S,
execute×N, complete-S, reassess, complete-M)
After: 5-6 sessions (research-M, plan-M [+S01 inline],
execute×N, complete-S, complete-M)
Adds support for specifying fallback models in GSD preferences. When a
primary model fails to switch (provider unavailable, rate limited, etc.),
GSD automatically tries the next model in the fallbacks list.
Changes:
- Add GSDPhaseModelConfig interface for per-phase model with fallbacks
- Add resolveModelWithFallbacksForUnit() function
- Update model switching in auto.ts to try fallbacks in order
- Update preferences-reference.md with fallback examples
Example usage:
```yaml
models:
planning:
model: claude-opus-4-6
fallbacks:
- openrouter/z-ai/glm-5
- openrouter/minimax/minimax-m2.5
```
This enables cost-optimized configurations with resilience against
provider outages or credit exhaustion.
Covers VALID_BRANCH_NAME regex validation, configured preference
returns correctly, fallback to auto-detection, and injection rejection.
Closes#108
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>