@opengsd/gsd-pi 1.2.0-dev.4c756166 → 1.2.0-dev.5457a158
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.
- package/dist/cli-style.d.ts +17 -0
- package/dist/cli-style.js +28 -0
- package/dist/cli.js +1 -1
- package/dist/headless-events.d.ts +4 -2
- package/dist/headless-events.js +7 -29
- package/dist/models-resolver.d.ts +3 -13
- package/dist/models-resolver.js +3 -22
- package/dist/resource-loader.js +2 -14
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/bg-shell/utilities.js +5 -2
- package/dist/resources/extensions/claude-code-cli/models.js +9 -0
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +35 -4
- package/dist/resources/extensions/gsd/auto/orchestrator.js +33 -4
- package/dist/resources/extensions/gsd/auto/phases.js +6 -1
- package/dist/resources/extensions/gsd/auto-post-unit.js +19 -8
- package/dist/resources/extensions/gsd/auto-prompts.js +3 -0
- package/dist/resources/extensions/gsd/auto-start.js +12 -14
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +18 -0
- package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +7 -16
- package/dist/resources/extensions/gsd/auto-worktree-repair.js +10 -2
- package/dist/resources/extensions/gsd/auto-worktree.js +35 -352
- package/dist/resources/extensions/gsd/auto.js +8 -20
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +3 -2
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +9 -6
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +86 -6
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +30 -4
- package/dist/resources/extensions/gsd/branch-patterns.js +2 -0
- package/dist/resources/extensions/gsd/captures.js +5 -15
- package/dist/resources/extensions/gsd/closeout-recovery.js +3 -2
- package/dist/resources/extensions/gsd/commands/catalog.js +6 -62
- package/dist/resources/extensions/gsd/crash-recovery.js +4 -12
- package/dist/resources/extensions/gsd/db/engine.js +755 -0
- package/dist/resources/extensions/gsd/db/queries.js +372 -0
- package/dist/resources/extensions/gsd/db/sql-constants.js +11 -0
- package/dist/resources/extensions/gsd/db/writers/cascades.js +194 -0
- package/dist/resources/extensions/gsd/db/writers/import-restore.js +182 -0
- package/dist/resources/extensions/gsd/db/writers/memory.js +149 -0
- package/dist/resources/extensions/gsd/db/writers/reconcile.js +458 -0
- package/dist/resources/extensions/gsd/db/writers/status.js +70 -0
- package/dist/resources/extensions/gsd/doctor-environment.js +5 -11
- package/dist/resources/extensions/gsd/doctor-format.js +9 -6
- package/dist/resources/extensions/gsd/doctor-git-checks.js +4 -3
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +21 -16
- package/dist/resources/extensions/gsd/error-classifier.js +9 -0
- package/dist/resources/extensions/gsd/git-service.js +1 -0
- package/dist/resources/extensions/gsd/gitignore.js +3 -0
- package/dist/resources/extensions/gsd/gsd-db.js +171 -2048
- package/dist/resources/extensions/gsd/guidance.js +98 -0
- package/dist/resources/extensions/gsd/guided-flow.js +51 -5
- package/dist/resources/extensions/gsd/mcp-tool-name.js +5 -13
- package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +1 -1
- package/dist/resources/extensions/gsd/migrate/safety.js +20 -9
- package/dist/resources/extensions/gsd/migration-auto-check.js +24 -3
- package/dist/resources/extensions/gsd/model-cost-table.js +1 -0
- package/dist/resources/extensions/gsd/model-router.js +3 -0
- package/dist/resources/extensions/gsd/notification-store.js +11 -4
- package/dist/resources/extensions/gsd/parallel-merge.js +14 -11
- package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +11 -7
- package/dist/resources/extensions/gsd/paths.js +37 -24
- package/dist/resources/extensions/gsd/pre-execution-checks.js +91 -3
- package/dist/resources/extensions/gsd/preferences-models.js +12 -46
- package/dist/resources/extensions/gsd/preferences.js +14 -0
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/replan-slice.md +1 -1
- package/dist/resources/extensions/gsd/provider-error-guidance.js +1 -5
- package/dist/resources/extensions/gsd/provider-switch-observer.js +1 -1
- package/dist/resources/extensions/gsd/publication.js +87 -0
- package/dist/resources/extensions/gsd/recovery-classification.js +41 -87
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +37 -4
- package/dist/resources/extensions/gsd/safety/evidence-cross-ref.js +7 -2
- package/dist/resources/extensions/gsd/safety/file-change-validator.js +10 -0
- package/dist/resources/extensions/gsd/state-transition-matrix.js +38 -0
- package/dist/resources/extensions/gsd/state.js +1 -20
- package/dist/resources/extensions/gsd/status-guards.js +56 -8
- package/dist/resources/extensions/gsd/stop-notice.js +57 -0
- package/dist/resources/extensions/gsd/tool-surface-readiness.js +56 -0
- package/dist/resources/extensions/gsd/tools/complete-slice.js +24 -43
- package/dist/resources/extensions/gsd/tools/exec-tool.js +5 -8
- package/dist/resources/extensions/gsd/tools/plan-slice.js +12 -6
- package/dist/resources/extensions/gsd/tools/reopen-milestone.js +11 -29
- package/dist/resources/extensions/gsd/tools/reopen-slice.js +14 -33
- package/dist/resources/extensions/gsd/tools/skip-slice.js +18 -36
- package/dist/resources/extensions/gsd/undo.js +8 -7
- package/dist/resources/extensions/gsd/unit-closeout.js +138 -0
- package/dist/resources/extensions/gsd/unit-context-composer.js +9 -1
- package/dist/resources/extensions/gsd/unit-context-manifest.js +4 -27
- package/dist/resources/extensions/gsd/unit-registry.js +350 -0
- package/dist/resources/extensions/gsd/unit-tool-contracts.js +9 -182
- package/dist/resources/extensions/gsd/workflow-tool-surface.js +1 -1
- package/dist/resources/extensions/gsd/worktree-git-recovery.js +293 -0
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +9 -1
- package/dist/resources/extensions/gsd/worktree-manager.js +45 -28
- package/dist/resources/extensions/gsd/worktree-placement.js +59 -0
- package/dist/resources/extensions/gsd/worktree-reentry.js +12 -8
- package/dist/resources/extensions/gsd/worktree-root.js +28 -6
- package/dist/resources/extensions/gsd/worktree-safety.js +8 -5
- package/dist/resources/extensions/gsd/worktree-session-state.js +12 -11
- package/dist/resources/skills/gsd-browser/SKILL.md +1 -1
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +9 -9
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +9 -9
- package/dist/web/standalone/.next/server/chunks/5124.js +1 -1
- package/dist/web/standalone/.next/server/chunks/{5047.js → 5942.js} +2 -2
- package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/worktree-cli.js +3 -6
- package/dist/worktree-status-banner.js +7 -11
- package/package.json +1 -1
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/dist/workflow.d.ts +4 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -1
- package/packages/contracts/dist/workflow.js.map +1 -1
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/dist/cli.js +6 -3
- package/packages/mcp-server/dist/cli.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +8 -0
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +46 -21
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +3 -3
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +294 -239
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +260 -256
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/capability-patches.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/capability-patches.js +3 -1
- package/packages/pi-coding-agent/dist/core/capability-patches.js.map +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/package.json +2 -2
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- package/src/resources/extensions/bg-shell/utilities.ts +5 -2
- package/src/resources/extensions/claude-code-cli/models.ts +9 -0
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +37 -2
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +28 -0
- package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -1
- package/src/resources/extensions/gsd/auto/orchestrator.ts +39 -5
- package/src/resources/extensions/gsd/auto/phases.ts +10 -1
- package/src/resources/extensions/gsd/auto-post-unit.ts +25 -7
- package/src/resources/extensions/gsd/auto-prompts.ts +3 -0
- package/src/resources/extensions/gsd/auto-start.ts +12 -15
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +19 -0
- package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +10 -17
- package/src/resources/extensions/gsd/auto-worktree-repair.ts +13 -2
- package/src/resources/extensions/gsd/auto-worktree.ts +41 -364
- package/src/resources/extensions/gsd/auto.ts +20 -24
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +3 -5
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +10 -6
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +87 -6
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +29 -3
- package/src/resources/extensions/gsd/branch-patterns.ts +3 -0
- package/src/resources/extensions/gsd/captures.ts +5 -16
- package/src/resources/extensions/gsd/closeout-recovery.ts +2 -1
- package/src/resources/extensions/gsd/commands/catalog.ts +6 -68
- package/src/resources/extensions/gsd/crash-recovery.ts +3 -9
- package/src/resources/extensions/gsd/db/engine.ts +809 -0
- package/src/resources/extensions/gsd/db/queries.ts +453 -0
- package/src/resources/extensions/gsd/db/sql-constants.ts +12 -0
- package/src/resources/extensions/gsd/db/writers/cascades.ts +237 -0
- package/src/resources/extensions/gsd/db/writers/import-restore.ts +310 -0
- package/src/resources/extensions/gsd/db/writers/memory.ts +220 -0
- package/src/resources/extensions/gsd/db/writers/reconcile.ts +500 -0
- package/src/resources/extensions/gsd/db/writers/status.ts +88 -0
- package/src/resources/extensions/gsd/doctor-environment.ts +5 -13
- package/src/resources/extensions/gsd/doctor-format.ts +12 -7
- package/src/resources/extensions/gsd/doctor-git-checks.ts +3 -3
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +22 -17
- package/src/resources/extensions/gsd/error-classifier.ts +11 -0
- package/src/resources/extensions/gsd/git-service.ts +1 -0
- package/src/resources/extensions/gsd/gitignore.ts +3 -0
- package/src/resources/extensions/gsd/gsd-db.ts +173 -2373
- package/src/resources/extensions/gsd/guidance.ts +139 -0
- package/src/resources/extensions/gsd/guided-flow.ts +50 -5
- package/src/resources/extensions/gsd/mcp-tool-name.ts +6 -11
- package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +1 -1
- package/src/resources/extensions/gsd/migrate/safety.ts +18 -7
- package/src/resources/extensions/gsd/migration-auto-check.ts +28 -3
- package/src/resources/extensions/gsd/model-cost-table.ts +1 -0
- package/src/resources/extensions/gsd/model-router.ts +3 -0
- package/src/resources/extensions/gsd/notification-store.ts +26 -3
- package/src/resources/extensions/gsd/parallel-merge.ts +12 -9
- package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +10 -7
- package/src/resources/extensions/gsd/paths.ts +42 -22
- package/src/resources/extensions/gsd/pre-execution-checks.ts +109 -3
- package/src/resources/extensions/gsd/preferences-models.ts +10 -46
- package/src/resources/extensions/gsd/preferences.ts +18 -0
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/replan-slice.md +1 -1
- package/src/resources/extensions/gsd/provider-error-guidance.ts +4 -9
- package/src/resources/extensions/gsd/provider-switch-observer.ts +1 -1
- package/src/resources/extensions/gsd/publication.ts +122 -0
- package/src/resources/extensions/gsd/recovery-classification.ts +47 -88
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +36 -4
- package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +7 -2
- package/src/resources/extensions/gsd/safety/file-change-validator.ts +14 -0
- package/src/resources/extensions/gsd/state-transition-matrix.ts +42 -0
- package/src/resources/extensions/gsd/state.ts +4 -21
- package/src/resources/extensions/gsd/status-guards.ts +59 -8
- package/src/resources/extensions/gsd/stop-notice.ts +75 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +123 -0
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/auto-post-unit-evidence-crossref-4909.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-worktree-repair.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/checkout-branch-stash-guard.test.ts +66 -1
- package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +8 -7
- package/src/resources/extensions/gsd/tests/evidence-xref-gsd-exec.test.ts +157 -0
- package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +33 -1
- package/src/resources/extensions/gsd/tests/guidance.test.ts +125 -0
- package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +51 -4
- package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +54 -1
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +85 -1
- package/src/resources/extensions/gsd/tests/notification-store.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +193 -1
- package/src/resources/extensions/gsd/tests/provider-error-guidance.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/publication.test.ts +120 -0
- package/src/resources/extensions/gsd/tests/recovery-classification-illegal-transition.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +248 -1
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/session-switch-clears-pending-autostart.test.ts +108 -0
- package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +43 -6
- package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/status-guards.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/stop-notice.test.ts +70 -0
- package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/tool-surface-readiness.test.ts +155 -0
- package/src/resources/extensions/gsd/tests/unit-closeout.test.ts +209 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +23 -2
- package/src/resources/extensions/gsd/tests/unit-registry.test.ts +163 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +41 -4
- package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +22 -1
- package/src/resources/extensions/gsd/tests/worktree-placement.test.ts +113 -0
- package/src/resources/extensions/gsd/tests/worktree-reentry.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +12 -6
- package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/write-gate.test.ts +42 -0
- package/src/resources/extensions/gsd/tool-surface-readiness.ts +76 -0
- package/src/resources/extensions/gsd/tools/complete-slice.ts +23 -58
- package/src/resources/extensions/gsd/tools/exec-tool.ts +5 -8
- package/src/resources/extensions/gsd/tools/plan-slice.ts +12 -6
- package/src/resources/extensions/gsd/tools/reopen-milestone.ts +11 -38
- package/src/resources/extensions/gsd/tools/reopen-slice.ts +14 -42
- package/src/resources/extensions/gsd/tools/skip-slice.ts +18 -44
- package/src/resources/extensions/gsd/undo.ts +9 -8
- package/src/resources/extensions/gsd/unit-closeout.ts +201 -0
- package/src/resources/extensions/gsd/unit-context-composer.ts +12 -1
- package/src/resources/extensions/gsd/unit-context-manifest.ts +4 -28
- package/src/resources/extensions/gsd/unit-registry.ts +425 -0
- package/src/resources/extensions/gsd/unit-tool-contracts.ts +27 -192
- package/src/resources/extensions/gsd/workflow-tool-surface.ts +4 -1
- package/src/resources/extensions/gsd/worktree-git-recovery.ts +314 -0
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +10 -1
- package/src/resources/extensions/gsd/worktree-manager.ts +47 -28
- package/src/resources/extensions/gsd/worktree-placement.ts +63 -0
- package/src/resources/extensions/gsd/worktree-reentry.ts +10 -7
- package/src/resources/extensions/gsd/worktree-root.ts +29 -6
- package/src/resources/extensions/gsd/worktree-safety.ts +8 -5
- package/src/resources/extensions/gsd/worktree-session-state.ts +11 -11
- package/src/resources/skills/gsd-browser/SKILL.md +1 -1
- /package/dist/web/standalone/.next/static/{DUFWcMFRH3iXh7d2fbrOF → 2p9Rv9pQflAxCBbGVI2vb}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{DUFWcMFRH3iXh7d2fbrOF → 2p9Rv9pQflAxCBbGVI2vb}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal presentation helpers for CLI-side notices on stderr — warnings,
|
|
3
|
+
* hints, and names. Pairs with the extension-side glyph set in
|
|
4
|
+
* resources/extensions/shared/ui.ts. Adopt incrementally: banner-shaped CLI
|
|
5
|
+
* surfaces (worktree banners today; update checks et al. as they're touched)
|
|
6
|
+
* should render through these instead of ad-hoc chalk.
|
|
7
|
+
*/
|
|
8
|
+
/** Dim "[gsd] " line tag that prefixes CLI banner lines. */
|
|
9
|
+
export declare function gsdTag(): string;
|
|
10
|
+
/** A yellow warning fragment. */
|
|
11
|
+
export declare function warn(text: string): string;
|
|
12
|
+
/** A dim "what to do next" hint fragment. */
|
|
13
|
+
export declare function hint(text: string): string;
|
|
14
|
+
/** A cyan user-supplied name (worktree, branch, file). */
|
|
15
|
+
export declare function name(text: string): string;
|
|
16
|
+
/** One banner line: tagged warning followed by a tagged hint line. */
|
|
17
|
+
export declare function bannerLines(warning: string, hintText: string): string;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal presentation helpers for CLI-side notices on stderr — warnings,
|
|
3
|
+
* hints, and names. Pairs with the extension-side glyph set in
|
|
4
|
+
* resources/extensions/shared/ui.ts. Adopt incrementally: banner-shaped CLI
|
|
5
|
+
* surfaces (worktree banners today; update checks et al. as they're touched)
|
|
6
|
+
* should render through these instead of ad-hoc chalk.
|
|
7
|
+
*/
|
|
8
|
+
import chalk from 'chalk';
|
|
9
|
+
/** Dim "[gsd] " line tag that prefixes CLI banner lines. */
|
|
10
|
+
export function gsdTag() {
|
|
11
|
+
return chalk.dim('[gsd] ');
|
|
12
|
+
}
|
|
13
|
+
/** A yellow warning fragment. */
|
|
14
|
+
export function warn(text) {
|
|
15
|
+
return chalk.yellow(text);
|
|
16
|
+
}
|
|
17
|
+
/** A dim "what to do next" hint fragment. */
|
|
18
|
+
export function hint(text) {
|
|
19
|
+
return chalk.dim(text);
|
|
20
|
+
}
|
|
21
|
+
/** A cyan user-supplied name (worktree, branch, file). */
|
|
22
|
+
export function name(text) {
|
|
23
|
+
return chalk.cyan(text);
|
|
24
|
+
}
|
|
25
|
+
/** One banner line: tagged warning followed by a tagged hint line. */
|
|
26
|
+
export function bannerLines(warning, hintText) {
|
|
27
|
+
return gsdTag() + warning + '\n' + gsdTag() + hint(hintText) + '\n\n';
|
|
28
|
+
}
|
package/dist/cli.js
CHANGED
|
@@ -524,7 +524,7 @@ const authStorage = AuthStorage.create(authFilePath);
|
|
|
524
524
|
markStartup('AuthStorage.create');
|
|
525
525
|
loadStoredEnvKeys(authStorage);
|
|
526
526
|
migratePiCredentials(authStorage);
|
|
527
|
-
// Resolve models.json path
|
|
527
|
+
// Resolve models.json path
|
|
528
528
|
const { resolveModelsJsonPath } = await import('./models-resolver.js');
|
|
529
529
|
const modelsJsonPath = resolveModelsJsonPath();
|
|
530
530
|
const modelRegistry = ModelRegistry.create(authStorage, modelsJsonPath);
|
|
@@ -5,6 +5,10 @@
|
|
|
5
5
|
* and classifies commands as quick (single-turn) vs long-running.
|
|
6
6
|
*
|
|
7
7
|
* Also defines exit code constants and the status→exit-code mapping function.
|
|
8
|
+
*
|
|
9
|
+
* The stop/pause notice vocabulary itself (prefixes + message classifiers)
|
|
10
|
+
* lives in the Stop Notice module — the same module the emitters format with,
|
|
11
|
+
* so wording stays in lockstep with detection.
|
|
8
12
|
*/
|
|
9
13
|
export declare const EXIT_SUCCESS = 0;
|
|
10
14
|
export declare const EXIT_ERROR = 1;
|
|
@@ -42,8 +46,6 @@ export declare function mapStatusToExitCode(status: string): number;
|
|
|
42
46
|
*
|
|
43
47
|
* Blocked detection is separate — checked via isBlockedNotification.
|
|
44
48
|
*/
|
|
45
|
-
export declare const PAUSED_PREFIXES: string[];
|
|
46
|
-
export declare const TERMINAL_PREFIXES: string[];
|
|
47
49
|
export declare const IDLE_TIMEOUT_MS = 15000;
|
|
48
50
|
export declare const NEW_MILESTONE_IDLE_TIMEOUT_MS = 120000;
|
|
49
51
|
export declare function canonicalHeadlessToolName(toolName: string | undefined): string;
|
package/dist/headless-events.js
CHANGED
|
@@ -5,7 +5,12 @@
|
|
|
5
5
|
* and classifies commands as quick (single-turn) vs long-running.
|
|
6
6
|
*
|
|
7
7
|
* Also defines exit code constants and the status→exit-code mapping function.
|
|
8
|
+
*
|
|
9
|
+
* The stop/pause notice vocabulary itself (prefixes + message classifiers)
|
|
10
|
+
* lives in the Stop Notice module — the same module the emitters format with,
|
|
11
|
+
* so wording stays in lockstep with detection.
|
|
8
12
|
*/
|
|
13
|
+
import { isBlockedNoticeMessage, isManualResolutionNotice, isPauseNotice, isTerminalNotice, } from './resources/extensions/gsd/stop-notice.js';
|
|
9
14
|
// ---------------------------------------------------------------------------
|
|
10
15
|
// Exit Code Constants
|
|
11
16
|
// ---------------------------------------------------------------------------
|
|
@@ -65,14 +70,6 @@ export function mapStatusToExitCode(status) {
|
|
|
65
70
|
*
|
|
66
71
|
* Blocked detection is separate — checked via isBlockedNotification.
|
|
67
72
|
*/
|
|
68
|
-
export const PAUSED_PREFIXES = ['auto-mode paused', 'step-mode paused'];
|
|
69
|
-
export const TERMINAL_PREFIXES = [
|
|
70
|
-
'auto-mode stopped',
|
|
71
|
-
'step-mode stopped',
|
|
72
|
-
'auto-mode complete',
|
|
73
|
-
'no active milestone',
|
|
74
|
-
'auto-mode idle',
|
|
75
|
-
];
|
|
76
73
|
export const IDLE_TIMEOUT_MS = 15_000;
|
|
77
74
|
// new-milestone is a long-running creative task where the LLM may pause
|
|
78
75
|
// between tool calls (e.g. after mkdir, before writing files). Use a
|
|
@@ -86,20 +83,6 @@ export function canonicalHeadlessToolName(toolName) {
|
|
|
86
83
|
const toolSeparator = name.indexOf('__', 'mcp__'.length);
|
|
87
84
|
return toolSeparator >= 0 ? name.slice(toolSeparator + 2) : name;
|
|
88
85
|
}
|
|
89
|
-
function isManualResolutionNotification(message) {
|
|
90
|
-
return (message.includes('resolve manually and re-run /gsd auto') ||
|
|
91
|
-
message.includes('resolve conflicts manually and run /gsd auto to resume') ||
|
|
92
|
-
message.includes('resolve and run /gsd auto to resume'));
|
|
93
|
-
}
|
|
94
|
-
function isNonBlockingPauseNotification(message) {
|
|
95
|
-
return message.includes('idempotent advance: unit already active');
|
|
96
|
-
}
|
|
97
|
-
function isPauseNotification(message) {
|
|
98
|
-
return PAUSED_PREFIXES.some((prefix) => message.startsWith(prefix));
|
|
99
|
-
}
|
|
100
|
-
function isPauseNotificationRequiringIntervention(message) {
|
|
101
|
-
return isPauseNotification(message) && !isNonBlockingPauseNotification(message);
|
|
102
|
-
}
|
|
103
86
|
function getCommandBlockContent(event) {
|
|
104
87
|
if (event.type !== 'message_start' && event.type !== 'message_end')
|
|
105
88
|
return null;
|
|
@@ -122,20 +105,15 @@ export function isTerminalNotification(event) {
|
|
|
122
105
|
if (event.type !== 'extension_ui_request' || event.method !== 'notify')
|
|
123
106
|
return false;
|
|
124
107
|
const message = String(event.message ?? '').toLowerCase();
|
|
125
|
-
return (
|
|
126
|
-
isPauseNotification(message) ||
|
|
127
|
-
isManualResolutionNotification(message));
|
|
108
|
+
return isTerminalNotice(message) || isPauseNotice(message) || isManualResolutionNotice(message);
|
|
128
109
|
}
|
|
129
110
|
export function isBlockedNotification(event) {
|
|
130
111
|
if (isBlockingCommandBlock(event))
|
|
131
112
|
return true;
|
|
132
113
|
if (event.type !== 'extension_ui_request' || event.method !== 'notify')
|
|
133
114
|
return false;
|
|
134
|
-
const message = String(event.message ?? '').toLowerCase();
|
|
135
115
|
// Recoverable pauses need operator intervention in headless mode.
|
|
136
|
-
return (message
|
|
137
|
-
isPauseNotificationRequiringIntervention(message) ||
|
|
138
|
-
isManualResolutionNotification(message));
|
|
116
|
+
return isBlockedNoticeMessage(String(event.message ?? '').toLowerCase());
|
|
139
117
|
}
|
|
140
118
|
export function isMilestoneReadyNotification(event) {
|
|
141
119
|
if (event.type !== 'extension_ui_request' || event.method !== 'notify')
|
|
@@ -1,20 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Models.json resolution
|
|
2
|
+
* Models.json resolution for GSD.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* experience, this module provides resolution logic that:
|
|
6
|
-
*
|
|
7
|
-
* 1. Reads ~/.gsd/agent/models.json if it exists
|
|
8
|
-
* 2. Falls back to ~/.pi/agent/models.json if GSD file doesn't exist
|
|
9
|
-
* 3. Merges both files if both exist (GSD takes precedence)
|
|
4
|
+
* Uses ~/.gsd/agent/models.json exclusively.
|
|
10
5
|
*/
|
|
11
6
|
/**
|
|
12
|
-
* Resolve the path to models.json
|
|
13
|
-
*
|
|
14
|
-
* Priority:
|
|
15
|
-
* 1. ~/.gsd/agent/models.json (exists) → return this path
|
|
16
|
-
* 2. ~/.pi/agent/models.json (exists) → return this path (fallback)
|
|
17
|
-
* 3. Neither exists → return GSD path (will be created)
|
|
7
|
+
* Resolve the path to models.json.
|
|
18
8
|
*
|
|
19
9
|
* @returns The path to use for models.json
|
|
20
10
|
*/
|
package/dist/models-resolver.js
CHANGED
|
@@ -1,35 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Models.json resolution
|
|
2
|
+
* Models.json resolution for GSD.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* experience, this module provides resolution logic that:
|
|
6
|
-
*
|
|
7
|
-
* 1. Reads ~/.gsd/agent/models.json if it exists
|
|
8
|
-
* 2. Falls back to ~/.pi/agent/models.json if GSD file doesn't exist
|
|
9
|
-
* 3. Merges both files if both exist (GSD takes precedence)
|
|
4
|
+
* Uses ~/.gsd/agent/models.json exclusively.
|
|
10
5
|
*/
|
|
11
|
-
import { existsSync } from 'node:fs';
|
|
12
|
-
import { homedir } from 'node:os';
|
|
13
6
|
import { join } from 'node:path';
|
|
14
7
|
import { agentDir } from './app-paths.js';
|
|
15
8
|
const GSD_MODELS_PATH = join(agentDir, 'models.json');
|
|
16
|
-
const PI_MODELS_PATH = join(homedir(), '.pi', 'agent', 'models.json');
|
|
17
9
|
/**
|
|
18
|
-
* Resolve the path to models.json
|
|
19
|
-
*
|
|
20
|
-
* Priority:
|
|
21
|
-
* 1. ~/.gsd/agent/models.json (exists) → return this path
|
|
22
|
-
* 2. ~/.pi/agent/models.json (exists) → return this path (fallback)
|
|
23
|
-
* 3. Neither exists → return GSD path (will be created)
|
|
10
|
+
* Resolve the path to models.json.
|
|
24
11
|
*
|
|
25
12
|
* @returns The path to use for models.json
|
|
26
13
|
*/
|
|
27
14
|
export function resolveModelsJsonPath() {
|
|
28
|
-
if (existsSync(GSD_MODELS_PATH)) {
|
|
29
|
-
return GSD_MODELS_PATH;
|
|
30
|
-
}
|
|
31
|
-
if (existsSync(PI_MODELS_PATH)) {
|
|
32
|
-
return PI_MODELS_PATH;
|
|
33
|
-
}
|
|
34
15
|
return GSD_MODELS_PATH;
|
|
35
16
|
}
|
package/dist/resource-loader.js
CHANGED
|
@@ -701,9 +701,8 @@ function collectRelativeFiles(rootDir) {
|
|
|
701
701
|
return files;
|
|
702
702
|
}
|
|
703
703
|
/**
|
|
704
|
-
* Constructs a DefaultResourceLoader that loads extensions from
|
|
705
|
-
* ~/.gsd/agent/extensions/ (GSD's default)
|
|
706
|
-
* This allows users to use extensions from either location.
|
|
704
|
+
* Constructs a DefaultResourceLoader that loads extensions from
|
|
705
|
+
* ~/.gsd/agent/extensions/ (GSD's default) only.
|
|
707
706
|
*/
|
|
708
707
|
// Cache bundled extension keys at module load — avoids re-scanning the extensions
|
|
709
708
|
// directory in buildResourceLoader() (already scanned by loader.ts for env var).
|
|
@@ -718,19 +717,8 @@ export async function buildResourceLoader(agentDir, options = {}) {
|
|
|
718
717
|
const { DefaultResourceLoader } = await loadPiCodingAgentModule();
|
|
719
718
|
const { sortExtensionPaths } = await import('./extension-sort.js');
|
|
720
719
|
const registry = loadRegistry();
|
|
721
|
-
const piAgentDir = join(homedir(), '.pi', 'agent');
|
|
722
|
-
const piExtensionsDir = join(piAgentDir, 'extensions');
|
|
723
720
|
const bundledKeys = getBundledExtensionKeys();
|
|
724
|
-
const piExtensionPaths = discoverExtensionEntryPaths(piExtensionsDir)
|
|
725
|
-
.filter((entryPath) => !bundledKeys.has(getExtensionKey(entryPath, piExtensionsDir)))
|
|
726
|
-
.filter((entryPath) => {
|
|
727
|
-
const manifest = readManifestFromEntryPath(entryPath);
|
|
728
|
-
if (!manifest)
|
|
729
|
-
return true;
|
|
730
|
-
return isExtensionEnabled(registry, manifest.id);
|
|
731
|
-
});
|
|
732
721
|
const additionalExtensionPaths = [
|
|
733
|
-
...piExtensionPaths,
|
|
734
722
|
...(options.additionalExtensionPaths ?? []),
|
|
735
723
|
];
|
|
736
724
|
return new DefaultResourceLoader({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
eb84bf3c0ea71702
|
|
@@ -37,10 +37,13 @@ export const formatUptime = formatDuration;
|
|
|
37
37
|
export function formatTimeAgo(timestamp) {
|
|
38
38
|
return formatDuration(Date.now() - timestamp) + " ago";
|
|
39
39
|
}
|
|
40
|
+
// NOTE: these worktree-layout regexes mirror findWorktreeSegment in
|
|
41
|
+
// src/resources/extensions/gsd/worktree-root.ts (bg-shell does not import the
|
|
42
|
+
// gsd extension). Keep them synchronized when a layout changes.
|
|
40
43
|
function deriveProjectRootFromAutoWorktree(cachedCwd) {
|
|
41
44
|
if (!cachedCwd)
|
|
42
45
|
return undefined;
|
|
43
|
-
const match = cachedCwd.match(/^(.*?)[\\/]\.gsd[\\/]worktrees[\\/][^\\/]+(?:[\\/].*)?$/);
|
|
46
|
+
const match = cachedCwd.match(/^(.*?)[\\/]\.gsd(?:-worktrees|[\\/]worktrees)[\\/][^\\/]+(?:[\\/].*)?$/);
|
|
44
47
|
return match?.[1];
|
|
45
48
|
}
|
|
46
49
|
export function getBgShellLiveCwd(cachedCwd, pathExists = existsSync, getCwd = () => process.cwd(), chdir = (path) => process.chdir(path)) {
|
|
@@ -67,7 +70,7 @@ export function getBgShellLiveCwd(cachedCwd, pathExists = existsSync, getCwd = (
|
|
|
67
70
|
}
|
|
68
71
|
export function resolveBgShellPersistenceCwd(cachedCwd, liveCwd = undefined, pathExists = existsSync) {
|
|
69
72
|
const resolvedLiveCwd = liveCwd ?? getBgShellLiveCwd(cachedCwd, pathExists);
|
|
70
|
-
const cachedIsAutoWorktree = /(?:^|[\\/])\.gsd[\\/]worktrees[\\/]/.test(cachedCwd);
|
|
73
|
+
const cachedIsAutoWorktree = /(?:^|[\\/])\.gsd(?:-worktrees|[\\/]worktrees)[\\/]/.test(cachedCwd);
|
|
71
74
|
if (!cachedIsAutoWorktree)
|
|
72
75
|
return cachedCwd;
|
|
73
76
|
if (cachedCwd === resolvedLiveCwd && pathExists(cachedCwd))
|
|
@@ -37,6 +37,15 @@ export const CLAUDE_CODE_MODELS = [
|
|
|
37
37
|
contextWindow: 1_000_000,
|
|
38
38
|
maxTokens: 128_000,
|
|
39
39
|
},
|
|
40
|
+
{
|
|
41
|
+
id: "claude-fable-5",
|
|
42
|
+
name: "Claude Fable 5 (via Claude Code)",
|
|
43
|
+
reasoning: true,
|
|
44
|
+
input: ["text", "image"],
|
|
45
|
+
cost: ZERO_COST,
|
|
46
|
+
contextWindow: 1_000_000,
|
|
47
|
+
maxTokens: 128_000,
|
|
48
|
+
},
|
|
40
49
|
{
|
|
41
50
|
id: "claude-sonnet-4-6",
|
|
42
51
|
name: "Claude Sonnet 4.6 (via Claude Code)",
|
|
@@ -24,6 +24,7 @@ import { markToolStart, markToolEnd } from "../gsd/auto.js";
|
|
|
24
24
|
import { markInteractiveElicitationStart, markInteractiveElicitationEnd, } from "../gsd/auto-tool-tracking.js";
|
|
25
25
|
import { discoverBrowserMcpServerName, discoverMcpServers, discoverMcpServerNames, discoverUserMcpServerNames, discoverWorkflowMcpServerName, computeMcpDisallowedTools, } from "../gsd/mcp-filter.js";
|
|
26
26
|
import { RUN_UAT_CLAUDE_NATIVE_TOOL_NAMES, RUN_UAT_FORBIDDEN_TOOL_NAMES, RUN_UAT_WORKFLOW_TOOL_NAMES, resolveToolPresentationPlan } from "../gsd/tool-presentation-plan.js";
|
|
27
|
+
import { getToolSurfaceReadinessError } from "../gsd/tool-surface-readiness.js";
|
|
27
28
|
import { showInterviewRound } from "../shared/tui.js";
|
|
28
29
|
export { buildFinalAssistantContent, extractToolResultsFromSdkUserMessage, handleClaudeCodePartialStreamEvent, mergePendingToolCalls, } from "./turn-assembler.js";
|
|
29
30
|
export function serverToolUseToToolCallLike(block) {
|
|
@@ -1242,6 +1243,8 @@ function modelSupportsAdaptiveThinking(modelId) {
|
|
|
1242
1243
|
|| modelId.includes("opus-4.7")
|
|
1243
1244
|
|| modelId.includes("opus-4-8")
|
|
1244
1245
|
|| modelId.includes("opus-4.8")
|
|
1246
|
+
|| modelId.includes("fable-5")
|
|
1247
|
+
|| modelId.includes("fable.5")
|
|
1245
1248
|
|| modelId.includes("sonnet-4-6")
|
|
1246
1249
|
|| modelId.includes("sonnet-4.6")
|
|
1247
1250
|
|| modelId.includes("sonnet-4-7")
|
|
@@ -1263,7 +1266,9 @@ function mapThinkingLevelToAnthropicEffort(level, modelId) {
|
|
|
1263
1266
|
if (modelId.includes("opus-4-7")
|
|
1264
1267
|
|| modelId.includes("opus-4.7")
|
|
1265
1268
|
|| modelId.includes("opus-4-8")
|
|
1266
|
-
|| modelId.includes("opus-4.8")
|
|
1269
|
+
|| modelId.includes("opus-4.8")
|
|
1270
|
+
|| modelId.includes("fable-5")
|
|
1271
|
+
|| modelId.includes("fable.5"))
|
|
1267
1272
|
return "xhigh";
|
|
1268
1273
|
if (modelId.includes("opus-4-6") || modelId.includes("opus-4.6"))
|
|
1269
1274
|
return "max";
|
|
@@ -1564,7 +1569,9 @@ export function buildSdkOptions(modelId, prompt, overrides, extraOptions = {}) {
|
|
|
1564
1569
|
|| modelId.includes("opus-4-7")
|
|
1565
1570
|
|| modelId.includes("opus-4.7")
|
|
1566
1571
|
|| modelId.includes("opus-4-8")
|
|
1567
|
-
|| modelId.includes("opus-4.8")
|
|
1572
|
+
|| modelId.includes("opus-4.8")
|
|
1573
|
+
|| modelId.includes("fable-5")
|
|
1574
|
+
|| modelId.includes("fable.5")) ? ["context-1m-2025-08-07"] : [],
|
|
1568
1575
|
...(thinkingConfig ?? {}),
|
|
1569
1576
|
...(effort ? { effort } : {}),
|
|
1570
1577
|
...sdkExtraOptions,
|
|
@@ -1629,8 +1636,9 @@ async function pumpSdkMessages(model, context, options, stream) {
|
|
|
1629
1636
|
}
|
|
1630
1637
|
: {}),
|
|
1631
1638
|
});
|
|
1639
|
+
const workflowMcpServerName = workflowMcpServerNameFromAllowedTools(sdkOpts.allowedTools);
|
|
1632
1640
|
const prompt = buildPromptFromContext(context, {
|
|
1633
|
-
workflowMcpServerName
|
|
1641
|
+
workflowMcpServerName,
|
|
1634
1642
|
browserMcpServerName: browserMcpServerNameFromAllowedTools(sdkOpts.allowedTools),
|
|
1635
1643
|
});
|
|
1636
1644
|
const queryPrompt = buildSdkQueryPrompt(context, prompt);
|
|
@@ -1668,7 +1676,30 @@ async function pumpSdkMessages(model, context, options, stream) {
|
|
|
1668
1676
|
switch (msg.type) {
|
|
1669
1677
|
// -- Init --
|
|
1670
1678
|
case "system": {
|
|
1671
|
-
//
|
|
1679
|
+
// Tool Surface Readiness gate: the init message is the first (and
|
|
1680
|
+
// only) point where the session reports its live tool surface and
|
|
1681
|
+
// MCP server statuses. If the workflow server failed or has not
|
|
1682
|
+
// registered this Unit's required tools, abort before the first
|
|
1683
|
+
// model turn with a transient, recovery-classifiable error
|
|
1684
|
+
// (tool-unavailable → retry) instead of letting the model hit
|
|
1685
|
+
// "No such tool available" mid-Unit and improvise around it.
|
|
1686
|
+
const init = msg;
|
|
1687
|
+
if (init.subtype === "init") {
|
|
1688
|
+
const readinessError = getToolSurfaceReadinessError({
|
|
1689
|
+
unitType: gsdPhase,
|
|
1690
|
+
workflowServerName: workflowMcpServerName,
|
|
1691
|
+
observation: { tools: init.tools ?? [], mcpServers: init.mcp_servers ?? [] },
|
|
1692
|
+
});
|
|
1693
|
+
if (readinessError) {
|
|
1694
|
+
controller.abort();
|
|
1695
|
+
stream.push({
|
|
1696
|
+
type: "error",
|
|
1697
|
+
reason: "error",
|
|
1698
|
+
error: makeErrorMessage(modelId, readinessError),
|
|
1699
|
+
});
|
|
1700
|
+
return;
|
|
1701
|
+
}
|
|
1702
|
+
}
|
|
1672
1703
|
break;
|
|
1673
1704
|
}
|
|
1674
1705
|
// -- Streaming partial messages --
|
|
@@ -9,8 +9,9 @@
|
|
|
9
9
|
// the real collaborators (state-reconciliation, doctor-proactive,
|
|
10
10
|
// auto-dispatch, recovery-classification, tool-contract, worktree-safety,
|
|
11
11
|
// uok/gate-runner, journal, session-lock, ctx.ui.notify) directly.
|
|
12
|
-
import { debugCount, debugTime } from "../debug-logger.js";
|
|
12
|
+
import { debugCount, debugLog, debugTime } from "../debug-logger.js";
|
|
13
13
|
import { reconcileBeforeDispatch } from "../state-reconciliation.js";
|
|
14
|
+
import { isLegalEdge, IllegalPhaseTransitionError } from "../state-transition-matrix.js";
|
|
14
15
|
import { resolveDispatch } from "../auto-dispatch.js";
|
|
15
16
|
import { classifyFailure } from "../recovery-classification.js";
|
|
16
17
|
import { verifyExpectedArtifact, refreshRecoveryDbForArtifact } from "../auto-recovery.js";
|
|
@@ -24,7 +25,7 @@ import { checkResourcesStale, autoWorktreeBranch, mergeMilestoneToMain } from ".
|
|
|
24
25
|
import { getSessionLockStatus } from "../session-lock.js";
|
|
25
26
|
import { resolveUokFlags } from "../uok/flags.js";
|
|
26
27
|
import { emitJournalEvent as _emitJournalEvent } from "../journal.js";
|
|
27
|
-
import { loadEffectiveGSDPreferences, getIsolationMode } from "../preferences.js";
|
|
28
|
+
import { loadEffectiveGSDPreferences, getIsolationMode, resolveEffectiveUnitIsolationMode } from "../preferences.js";
|
|
28
29
|
import { detectWorktreeName, getMainBranch, resolveProjectRoot, resolveWorktreeProjectRoot, } from "../worktree.js";
|
|
29
30
|
import { getPriorSliceCompletionBlocker } from "../dispatch-guard.js";
|
|
30
31
|
import { GitServiceImpl } from "../git-service.js";
|
|
@@ -244,6 +245,10 @@ export class AutoOrchestrator {
|
|
|
244
245
|
lastAdvanceKey = null;
|
|
245
246
|
lastFinalizedUnitKey = null;
|
|
246
247
|
dispatchKeyWindow = [];
|
|
248
|
+
// ADR-030 Phase Transition Invariant: the prior advance's reconciled Phase,
|
|
249
|
+
// the "from" endpoint of the edge check. In-memory; reset on start/resume/stop
|
|
250
|
+
// so the first advance of a session has no edge to assert.
|
|
251
|
+
lastDerivedPhase = null;
|
|
247
252
|
// #442: the unit key we last attempted graduated stuck-recovery for. Bounds
|
|
248
253
|
// recovery to one attempt per stuck episode per run (reset on start/resume/
|
|
249
254
|
// stop), mirroring the legacy Level-1-then-Level-2 escalation in phases.ts.
|
|
@@ -476,8 +481,7 @@ export class AutoOrchestrator {
|
|
|
476
481
|
}
|
|
477
482
|
// ── WorktreeAdapter (folded) ─────────────────────────────────────────────
|
|
478
483
|
getEffectiveUnitIsolationMode(basePath) {
|
|
479
|
-
|
|
480
|
-
return configuredMode === "worktree" && this.s.isolationDegraded ? "branch" : configuredMode;
|
|
484
|
+
return resolveEffectiveUnitIsolationMode(getIsolationMode(basePath), this.s.isolationDegraded, this.s.strandedRecoveryIsolationMode);
|
|
481
485
|
}
|
|
482
486
|
buildLifecycle() {
|
|
483
487
|
return new WorktreeLifecycle(this.s, {
|
|
@@ -576,6 +580,21 @@ export class AutoOrchestrator {
|
|
|
576
580
|
const recovery = classifyFailure(input);
|
|
577
581
|
return { action: recovery.action, reason: recovery.reason };
|
|
578
582
|
}
|
|
583
|
+
/**
|
|
584
|
+
* ADR-030 Phase Transition Invariant (advisory mode). The matrix is an
|
|
585
|
+
* assertion, not a decision-maker — deriveState already chose the phase; we
|
|
586
|
+
* only observe illegal *derived* edges that survived reconciliation. The
|
|
587
|
+
* matrix is still a sparse hardening spec, so this is telemetry-only (no
|
|
588
|
+
* block) until it is expanded into a validated legal-edge graph. To enforce:
|
|
589
|
+
* `throw violation;` instead of logging — recovery-classification maps
|
|
590
|
+
* IllegalPhaseTransitionError to kind "illegal-transition" (escalate).
|
|
591
|
+
*/
|
|
592
|
+
observePhaseTransition(from, to) {
|
|
593
|
+
if (isLegalEdge(from, to))
|
|
594
|
+
return;
|
|
595
|
+
const violation = new IllegalPhaseTransitionError(from, to);
|
|
596
|
+
debugLog("phase-transition-advisory", { from, to, message: violation.message });
|
|
597
|
+
}
|
|
579
598
|
// ── Lifecycle verbs ──────────────────────────────────────────────────────
|
|
580
599
|
/**
|
|
581
600
|
* #442: graduated stuck recovery, ported from the legacy
|
|
@@ -636,6 +655,7 @@ export class AutoOrchestrator {
|
|
|
636
655
|
this.lastFinalizedUnitKey = null;
|
|
637
656
|
this.dispatchKeyWindow = [];
|
|
638
657
|
this.lastStuckRecoveryKey = null;
|
|
658
|
+
this.lastDerivedPhase = null;
|
|
639
659
|
this.status.phase = "running";
|
|
640
660
|
this.bumpTransition();
|
|
641
661
|
this.journalTransition({ name: "start" });
|
|
@@ -721,6 +741,11 @@ export class AutoOrchestrator {
|
|
|
721
741
|
this.postAdvanceRecord(blocked);
|
|
722
742
|
return blocked;
|
|
723
743
|
}
|
|
744
|
+
const reconciledPhase = reconciliation.stateSnapshot.phase;
|
|
745
|
+
if (this.lastDerivedPhase !== null) {
|
|
746
|
+
this.observePhaseTransition(this.lastDerivedPhase, reconciledPhase);
|
|
747
|
+
}
|
|
748
|
+
this.lastDerivedPhase = reconciledPhase;
|
|
724
749
|
const decision = await this.decideNextUnit({ stateSnapshot: reconciliation.stateSnapshot });
|
|
725
750
|
if (!decision) {
|
|
726
751
|
const settlementBlock = this.evaluateNoRemainingUnitsSettlement(reconciliation.stateSnapshot);
|
|
@@ -981,6 +1006,9 @@ export class AutoOrchestrator {
|
|
|
981
1006
|
// Preserve dispatchKeyWindow across resume so stuck-loop detection
|
|
982
1007
|
// accumulates across pause/resume cycles rather than resetting each time.
|
|
983
1008
|
this.lastStuckRecoveryKey = null;
|
|
1009
|
+
// ADR-030: drop the prior "from" — the first advance after resume has no
|
|
1010
|
+
// edge to assert (avoids a false illegal-edge across the pause boundary).
|
|
1011
|
+
this.lastDerivedPhase = null;
|
|
984
1012
|
this.status.phase = "running";
|
|
985
1013
|
this.bumpTransition();
|
|
986
1014
|
this.journalTransition({ name: "resume" });
|
|
@@ -996,6 +1024,7 @@ export class AutoOrchestrator {
|
|
|
996
1024
|
this.status.activeUnit = undefined;
|
|
997
1025
|
this.lastAdvanceKey = null;
|
|
998
1026
|
this.lastFinalizedUnitKey = null;
|
|
1027
|
+
this.lastDerivedPhase = null;
|
|
999
1028
|
// Preserve dispatchKeyWindow on pause so stuck-loop detection accumulates
|
|
1000
1029
|
// across pause/resume cycles. Only clear on a hard stop.
|
|
1001
1030
|
if (reason !== "pause") {
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import { importExtensionModule } from "@gsd/pi-coding-agent";
|
|
12
12
|
import { USER_DRIVEN_DEEP_UNITS, isAwaitingUserInput, } from "../auto-post-unit.js";
|
|
13
13
|
import { lastAssistantText } from "../user-input-boundary.js";
|
|
14
|
+
import { resolveEffectiveUnitIsolationMode } from "../preferences.js";
|
|
14
15
|
import { MAX_RECOVERY_CHARS, BUDGET_THRESHOLDS, MAX_FINALIZE_TIMEOUTS, } from "./types.js";
|
|
15
16
|
import { detectStuck } from "./detect-stuck.js";
|
|
16
17
|
import { runUnit } from "./run-unit.js";
|
|
@@ -265,7 +266,11 @@ async function validateSourceWriteWorktreeSafety(ic, unitType, unitId, milestone
|
|
|
265
266
|
if (!writesSource)
|
|
266
267
|
return null;
|
|
267
268
|
const projectRoot = s.canonicalProjectRoot ?? resolveWorktreeProjectRoot(s.basePath, s.originalBasePath);
|
|
268
|
-
|
|
269
|
+
// A degraded session already fell back to the milestone branch in the
|
|
270
|
+
// project root — validating against the canonical worktree root there
|
|
271
|
+
// would fail every dispatch with a false invalid-root. The same applies
|
|
272
|
+
// to a stranded-recovery session that adopted the milestone branch.
|
|
273
|
+
const isolationMode = resolveEffectiveUnitIsolationMode(deps.getIsolationMode(projectRoot), s.isolationDegraded, s.strandedRecoveryIsolationMode);
|
|
269
274
|
if (isolationMode !== "worktree")
|
|
270
275
|
return null;
|
|
271
276
|
const safety = createWorktreeSafetyModule();
|
|
@@ -39,7 +39,7 @@ import { debugLog } from "./debug-logger.js";
|
|
|
39
39
|
import { runSafely } from "./auto-utils.js";
|
|
40
40
|
import { isMilestoneCloseoutSettled, runMilestoneCloseoutGitHub, } from "./milestone-closeout.js";
|
|
41
41
|
import { getEvidence, clearEvidenceFromDisk, isExecutionToolName } from "./safety/evidence-collector.js";
|
|
42
|
-
import { validateFileChanges } from "./safety/file-change-validator.js";
|
|
42
|
+
import { validateFileChanges, effectiveFileChangeAllowlist } from "./safety/file-change-validator.js";
|
|
43
43
|
import { crossReferenceEvidence } from "./safety/evidence-cross-ref.js";
|
|
44
44
|
import { validateContent } from "./safety/content-validator.js";
|
|
45
45
|
import { resolveSafetyHarnessConfig } from "./safety/safety-harness.js";
|
|
@@ -55,7 +55,7 @@ import { writeTurnGitTransaction } from "./uok/gitops.js";
|
|
|
55
55
|
import { isClosedStatus } from "./status-guards.js";
|
|
56
56
|
import { detectAbandonMilestone } from "./abandon-detect.js";
|
|
57
57
|
import { getPendingGate } from "./bootstrap/write-gate.js";
|
|
58
|
-
import { isDeterministicPolicyError } from "./auto-tool-tracking.js";
|
|
58
|
+
import { isDeterministicPolicyError, isToolUnavailableError } from "./auto-tool-tracking.js";
|
|
59
59
|
import { formatConnectedStepStack, formatPostUnitStatusCard } from "./auto-status-message.js";
|
|
60
60
|
import { clearProjectResearchInflightMarker, finalizeProjectResearchTimeout, } from "./project-research-policy.js";
|
|
61
61
|
import { validateArtifact } from "./schemas/validate.js";
|
|
@@ -507,9 +507,10 @@ export function _hasExecutionToolCallsInSessionForTest(entries) {
|
|
|
507
507
|
if (e?.type === "toolCall" && isExecutionToolName(e?.name ?? e?.toolName)) {
|
|
508
508
|
return true;
|
|
509
509
|
}
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
510
|
+
// Accept both session-manager entries ({type: "message", message}) and
|
|
511
|
+
// bare agent-end messages ({role, content}) — the auto loop passes the
|
|
512
|
+
// latter via opts.agentEndMessages.
|
|
513
|
+
const msg = e?.type === "message" ? e?.message : e;
|
|
513
514
|
if (!msg || msg.role !== "assistant" || !Array.isArray(msg.content))
|
|
514
515
|
continue;
|
|
515
516
|
for (const block of msg.content) {
|
|
@@ -1289,6 +1290,7 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
1289
1290
|
const safetyConfig = resolveSafetyHarnessConfig(prefs?.safety_harness);
|
|
1290
1291
|
if (safetyConfig.enabled) {
|
|
1291
1292
|
const { milestone: sMid, slice: sSid, task: sTid } = parseUnitId(s.currentUnit.id);
|
|
1293
|
+
const fileChangeAllowlist = effectiveFileChangeAllowlist(safetyConfig.file_change_allowlist, prefs?.git?.manage_gitignore);
|
|
1292
1294
|
// File change validation (execute-task only, after unit execution)
|
|
1293
1295
|
if (safetyConfig.file_change_validation && s.currentUnit.type === "execute-task" && sMid && sSid && sTid) {
|
|
1294
1296
|
try {
|
|
@@ -1303,7 +1305,7 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
1303
1305
|
const plannedFiles = getPlannedKeyFiles(sliceTaskRows.map((taskRow) => ({
|
|
1304
1306
|
files: taskRow.files,
|
|
1305
1307
|
})));
|
|
1306
|
-
const audit = validateFileChanges(s.basePath, expectedOutput, plannedFiles,
|
|
1308
|
+
const audit = validateFileChanges(s.basePath, expectedOutput, plannedFiles, fileChangeAllowlist);
|
|
1307
1309
|
if (audit && audit.violations.length > 0) {
|
|
1308
1310
|
const warnings = audit.violations.filter(v => v.severity === "warning");
|
|
1309
1311
|
for (const v of warnings) {
|
|
@@ -1319,7 +1321,7 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
1319
1321
|
if (taskRow) {
|
|
1320
1322
|
const expectedOutput = taskRow.expected_output ?? [];
|
|
1321
1323
|
const plannedFiles = taskRow.files ?? [];
|
|
1322
|
-
const audit = validateFileChanges(s.basePath, expectedOutput, plannedFiles,
|
|
1324
|
+
const audit = validateFileChanges(s.basePath, expectedOutput, plannedFiles, fileChangeAllowlist);
|
|
1323
1325
|
if (audit && audit.violations.length > 0) {
|
|
1324
1326
|
const warnings = audit.violations.filter(v => v.severity === "warning");
|
|
1325
1327
|
for (const v of warnings) {
|
|
@@ -1699,7 +1701,16 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
1699
1701
|
ctx.ui.notify(`Artifact missing for ${s.currentUnit.type} ${s.currentUnit.id} — DB unavailable, skipping retry.${dbSkipDiag ? ` Expected: ${dbSkipDiag}` : ""}`, "error");
|
|
1700
1702
|
}
|
|
1701
1703
|
else if (!triggerArtifactVerified) {
|
|
1702
|
-
if (s.lastToolInvocationError) {
|
|
1704
|
+
if (s.lastToolInvocationError && isToolUnavailableError(s.lastToolInvocationError)) {
|
|
1705
|
+
// Tool-unavailable is the one transient invocation error: the
|
|
1706
|
+
// workflow MCP server registers its surface asynchronously, so a
|
|
1707
|
+
// Unit's first call can race the registration. Fall through to the
|
|
1708
|
+
// bounded verification retry instead of pausing.
|
|
1709
|
+
debugLog("postUnit", { phase: "tool-unavailable-retry", unitType: s.currentUnit.type, unitId: s.currentUnit.id, error: s.lastToolInvocationError });
|
|
1710
|
+
ctx.ui.notify(`Tool unavailable for ${s.currentUnit.type}: ${s.lastToolInvocationError}. The tool surface may still be registering — retrying.`, "warning");
|
|
1711
|
+
s.lastToolInvocationError = null;
|
|
1712
|
+
}
|
|
1713
|
+
else if (s.lastToolInvocationError) {
|
|
1703
1714
|
const isUserSkip = /queued user message/i.test(s.lastToolInvocationError);
|
|
1704
1715
|
const errMsg = isUserSkip
|
|
1705
1716
|
? `Tool skipped for ${s.currentUnit.type}: ${s.lastToolInvocationError}. Queued user message interrupted the turn — pausing auto-mode.`
|
|
@@ -2146,6 +2146,9 @@ export async function buildPlanSlicePrompt(mid, _midTitle, sid, sTitle, base, le
|
|
|
2146
2146
|
`Either (a) add an earlier task that creates X on disk before the task that needs it, ` +
|
|
2147
2147
|
`or (b) if this task IS the one that creates X, move X from inputs to expected_output. ` +
|
|
2148
2148
|
`Do NOT put X in a task's expected_output if that task only reads or verifies X — only tasks that actually write X to disk should list it in expected_output.\n` +
|
|
2149
|
+
`- **"[file] X: ... GSD planning artifacts are projections preloaded as context / written by workflow tools"**: ` +
|
|
2150
|
+
`Remove X from the task's inputs, files, and expectedOutput entirely. Planning artifacts (anything under .gsd/, .planning/, or .audits/, or names like M001-CONTEXT.md / S01-PLAN.md) are preloaded as context and written by workflow tools — ` +
|
|
2151
|
+
`do NOT add a task that creates X and do NOT move X to expectedOutput.\n` +
|
|
2149
2152
|
`- **"[file] X: Task T_early reads X but it's created by task T_late (sequence violation)"**: ` +
|
|
2150
2153
|
`Either (a) reorder tasks so T_late (the creator) runs before T_early (the reader), ` +
|
|
2151
2154
|
`or (b) if T_late doesn't actually create X (it only reads/tests it), remove X from T_late's expected_output entirely.\n` +
|