gsd-pi 2.78.0 → 2.78.1-dev.9d08d820b
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/README.md +59 -23
- package/dist/bundled-resource-path.d.ts +7 -0
- package/dist/bundled-resource-path.js +34 -2
- package/dist/claude-cli-check.js +104 -33
- package/dist/cli-policy.d.ts +13 -0
- package/dist/cli-policy.js +17 -0
- package/dist/cli.js +95 -55
- package/dist/headless-query.d.ts +22 -0
- package/dist/headless-query.js +43 -8
- package/dist/headless.d.ts +10 -0
- package/dist/headless.js +16 -1
- package/dist/loader.js +9 -13
- package/dist/onboarding.d.ts +10 -0
- package/dist/onboarding.js +2 -2
- package/dist/provider-migrations.d.ts +2 -2
- package/dist/provider-migrations.js +5 -2
- package/dist/resource-loader.d.ts +5 -2
- package/dist/resource-loader.js +30 -13
- package/dist/resources/.managed-resources-content-hash +1 -0
- package/dist/resources/extensions/claude-code-cli/readiness.js +128 -32
- package/dist/resources/extensions/gsd/auto/loop.js +23 -0
- package/dist/resources/extensions/gsd/auto/phases.js +5 -13
- package/dist/resources/extensions/gsd/auto/run-unit.js +3 -1
- package/dist/resources/extensions/gsd/auto/session.js +5 -6
- package/dist/resources/extensions/gsd/auto-dashboard.js +3 -2
- package/dist/resources/extensions/gsd/auto-dispatch.js +18 -6
- package/dist/resources/extensions/gsd/auto-prompts.js +63 -2
- package/dist/resources/extensions/gsd/auto-recovery.js +43 -4
- package/dist/resources/extensions/gsd/auto-runtime-state.js +31 -0
- package/dist/resources/extensions/gsd/auto-start.js +1 -1
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +2 -2
- package/dist/resources/extensions/gsd/auto-worktree.js +60 -13
- package/dist/resources/extensions/gsd/auto.js +14 -5
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +14 -2
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +7 -5
- package/dist/resources/extensions/gsd/bootstrap/query-tools.js +2 -2
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +5 -4
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +100 -31
- package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +11 -6
- package/dist/resources/extensions/gsd/bootstrap/subagent-input.js +22 -0
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +34 -8
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +121 -3
- package/dist/resources/extensions/gsd/commands/catalog.js +69 -5
- package/dist/resources/extensions/gsd/commands/handlers/core.js +22 -1
- package/dist/resources/extensions/gsd/commands-config.js +3 -2
- package/dist/resources/extensions/gsd/commands-extensions.js +46 -3
- package/dist/resources/extensions/gsd/commands-handlers.js +3 -2
- package/dist/resources/extensions/gsd/commands-mcp-status.js +3 -1
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +10 -1
- package/dist/resources/extensions/gsd/dashboard-overlay.js +1 -1
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +10 -0
- package/dist/resources/extensions/gsd/doctor-providers.js +2 -1
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +39 -1
- package/dist/resources/extensions/gsd/error-classifier.js +1 -1
- package/dist/resources/extensions/gsd/forensics.js +10 -8
- package/dist/resources/extensions/gsd/git-service.js +12 -5
- package/dist/resources/extensions/gsd/gsd-db.js +11 -2
- package/dist/resources/extensions/gsd/guided-flow.js +25 -24
- package/dist/resources/extensions/gsd/home-dir.js +16 -0
- package/dist/resources/extensions/gsd/key-manager.js +2 -1
- package/dist/resources/extensions/gsd/memory-store.js +66 -31
- package/dist/resources/extensions/gsd/migrate/command.js +3 -2
- package/dist/resources/extensions/gsd/milestone-id-reservation.js +36 -0
- package/dist/resources/extensions/gsd/model-router.js +114 -9
- package/dist/resources/extensions/gsd/native-git-bridge.js +7 -1
- package/dist/resources/extensions/gsd/preferences-models.js +91 -15
- package/dist/resources/extensions/gsd/preferences-types.js +2 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +32 -0
- package/dist/resources/extensions/gsd/preferences.js +5 -3
- package/dist/resources/extensions/gsd/prompt-loader.js +23 -12
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +10 -0
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +10 -0
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +10 -0
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +10 -0
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +9 -3
- package/dist/resources/extensions/gsd/state.js +42 -0
- package/dist/resources/extensions/gsd/templates/PREFERENCES.md +1 -0
- package/dist/resources/extensions/gsd/tools/memory-tools.js +18 -1
- package/dist/resources/extensions/gsd/unit-context-manifest.js +29 -4
- package/dist/resources/extensions/gsd/visualizer-overlay.js +1 -1
- package/dist/resources/extensions/gsd/watch/header-renderer.js +3 -1
- package/dist/resources/extensions/gsd/worktree-command.js +26 -46
- package/dist/resources/extensions/gsd/worktree-manager.js +20 -1
- package/dist/resources/extensions/gsd/worktree-resolver.js +4 -13
- package/dist/resources/extensions/gsd/worktree-root.js +124 -0
- package/dist/resources/extensions/gsd/worktree-session-state.js +33 -0
- package/dist/resources/extensions/gsd/worktree.js +4 -115
- package/dist/resources/extensions/mcp-client/index.js +6 -3
- package/dist/resources/extensions/ollama/index.js +15 -2
- package/dist/resources/extensions/ollama/model-capabilities.js +31 -0
- package/dist/resources/extensions/ollama/ollama-client.js +40 -4
- package/dist/resources/extensions/slash-commands/create-extension.js +36 -22
- package/dist/resources/extensions/subagent/index.js +324 -178
- package/dist/resources/skills/create-gsd-extension/SKILL.md +9 -5
- package/dist/resources/skills/create-gsd-extension/references/custom-commands.md +1 -1
- package/dist/resources/skills/create-gsd-extension/references/custom-rendering.md +5 -5
- package/dist/resources/skills/create-gsd-extension/references/custom-tools.md +4 -4
- package/dist/resources/skills/create-gsd-extension/references/custom-ui.md +6 -6
- package/dist/resources/skills/create-gsd-extension/references/events-reference.md +3 -3
- package/dist/resources/skills/create-gsd-extension/references/packaging-distribution.md +1 -1
- package/dist/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +3 -3
- package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +32 -12
- package/dist/rtk-shared.d.ts +3 -0
- package/dist/rtk-shared.js +17 -0
- package/dist/rtk.d.ts +2 -5
- package/dist/rtk.js +3 -20
- package/dist/runtime-checks.d.ts +27 -0
- package/dist/runtime-checks.js +38 -0
- 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 +11 -11
- package/dist/web/standalone/.next/build-manifest.json +4 -4
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +44 -4
- package/dist/web/standalone/.next/required-server-files.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- 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/page.js +2 -2
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- 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 +3 -3
- 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 +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +4 -2
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
- 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 +3 -3
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +11 -11
- package/dist/web/standalone/.next/server/chunks/63.js +3 -3
- package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware.js +2 -2
- package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
- package/dist/web/standalone/.next/server/next-font-manifest.json +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/web/standalone/.next/server/webpack-runtime.js +1 -1
- package/dist/web/standalone/.next/static/chunks/2556.0527fea66e123b7f.js +1 -0
- package/dist/web/standalone/.next/static/chunks/2824.08296bc2f9654698.js +1 -0
- package/dist/web/standalone/.next/static/chunks/3026.3af53b279375f082.js +1 -0
- package/dist/web/standalone/.next/static/chunks/315.6f68ae79b67d25cf.js +1 -0
- package/dist/web/standalone/.next/static/chunks/3497.4bfc60a3b3dea717.js +1 -0
- package/dist/web/standalone/.next/static/chunks/5516.4a07c872b5c3a663.js +1 -0
- package/dist/web/standalone/.next/static/chunks/8336.31b019697882acfb.js +10 -0
- package/dist/web/standalone/.next/static/chunks/8845.c9702695e8c5a9c5.js +2 -0
- package/dist/web/standalone/.next/static/chunks/9058.01ef3a463bda88f1.js +20 -0
- package/dist/web/standalone/.next/static/chunks/9441.1081da1125d1764f.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/page-9bf2e0c50fb2ca05.js +1 -0
- package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
- package/dist/web/standalone/.next/static/chunks/webpack-f9f0dc45e4f3ac10.js +1 -0
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
- package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
- package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
- package/dist/web/standalone/package.json +2 -1
- package/dist/web/standalone/server.js +1 -1
- package/dist/worktree-cli.d.ts +1 -0
- package/dist/worktree-cli.js +9 -3
- package/dist/worktree-status-banner.d.ts +1 -0
- package/dist/worktree-status-banner.js +132 -0
- package/package.json +1 -3
- package/packages/daemon/package.json +2 -2
- package/packages/mcp-server/dist/alias-telemetry.d.ts +8 -0
- package/packages/mcp-server/dist/alias-telemetry.d.ts.map +1 -0
- package/packages/mcp-server/dist/alias-telemetry.js +30 -0
- package/packages/mcp-server/dist/alias-telemetry.js.map +1 -0
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +74 -46
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +2 -2
- package/packages/mcp-server/src/alias-telemetry.test.ts +78 -0
- package/packages/mcp-server/src/alias-telemetry.ts +30 -0
- package/packages/mcp-server/src/workflow-tools.test.ts +78 -0
- package/packages/mcp-server/src/workflow-tools.ts +93 -58
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/native/package.json +1 -1
- package/packages/native/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.js +231 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.js.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.js +48 -19
- package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
- package/packages/pi-ai/dist/types.d.ts +13 -0
- package/packages/pi-ai/dist/types.d.ts.map +1 -1
- package/packages/pi-ai/dist/types.js.map +1 -1
- package/packages/pi-ai/dist/utils/repair-tool-json.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/repair-tool-json.js +24 -3
- package/packages/pi-ai/dist/utils/repair-tool-json.js.map +1 -1
- package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js +26 -0
- package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-ai/src/providers/anthropic-shared.cache-breakpoint.test.ts +289 -0
- package/packages/pi-ai/src/providers/anthropic-shared.ts +52 -20
- package/packages/pi-ai/src/types.ts +13 -0
- package/packages/pi-ai/src/utils/repair-tool-json.ts +24 -3
- package/packages/pi-ai/src/utils/tests/repair-tool-json.test.ts +32 -0
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +6 -0
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/messages.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/messages.js +4 -0
- package/packages/pi-coding-agent/dist/core/messages.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +19 -2
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts +10 -0
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +18 -0
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +13 -0
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +20 -16
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/token-telemetry.d.ts +37 -0
- package/packages/pi-coding-agent/dist/core/token-telemetry.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/token-telemetry.js +49 -0
- package/packages/pi-coding-agent/dist/core/token-telemetry.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +133 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +14 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.js +78 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/tests/token-telemetry.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/tests/token-telemetry.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/tests/token-telemetry.test.js +181 -0
- package/packages/pi-coding-agent/dist/tests/token-telemetry.test.js.map +1 -0
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/agent-session.ts +7 -0
- package/packages/pi-coding-agent/src/core/messages.ts +4 -0
- package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +32 -2
- package/packages/pi-coding-agent/src/core/model-registry.ts +21 -0
- package/packages/pi-coding-agent/src/core/system-prompt.ts +33 -15
- package/packages/pi-coding-agent/src/core/token-telemetry.ts +77 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +212 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +17 -1
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +1 -1
- package/packages/pi-coding-agent/src/tests/system-prompt-cache-stability.test.ts +102 -0
- package/packages/pi-coding-agent/src/tests/token-telemetry.test.ts +200 -0
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/__tests__/autocomplete.test.js +17 -3
- package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts +2 -0
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js +161 -0
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js.map +1 -0
- package/packages/pi-tui/package.json +1 -1
- package/packages/pi-tui/src/__tests__/autocomplete.test.ts +20 -3
- package/packages/pi-tui/src/components/__tests__/leak-fixes-runtime.test.ts +219 -0
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/packages/rpc-client/package.json +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/claude-code-cli/readiness.ts +130 -30
- package/src/resources/extensions/gsd/auto/loop.ts +24 -2
- package/src/resources/extensions/gsd/auto/phases.ts +6 -14
- package/src/resources/extensions/gsd/auto/run-unit.ts +3 -1
- package/src/resources/extensions/gsd/auto/session.ts +5 -6
- package/src/resources/extensions/gsd/auto/types.ts +1 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +3 -2
- package/src/resources/extensions/gsd/auto-dispatch.ts +18 -6
- package/src/resources/extensions/gsd/auto-prompts.ts +60 -2
- package/src/resources/extensions/gsd/auto-recovery.ts +46 -8
- package/src/resources/extensions/gsd/auto-runtime-state.ts +51 -0
- package/src/resources/extensions/gsd/auto-start.ts +1 -1
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +2 -4
- package/src/resources/extensions/gsd/auto-worktree.ts +82 -12
- package/src/resources/extensions/gsd/auto.ts +14 -4
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +15 -13
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +8 -7
- package/src/resources/extensions/gsd/bootstrap/query-tools.ts +2 -2
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +10 -9
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +108 -31
- package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +12 -6
- package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +20 -0
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +39 -8
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +141 -11
- package/src/resources/extensions/gsd/commands/catalog.ts +75 -5
- package/src/resources/extensions/gsd/commands/handlers/core.ts +22 -1
- package/src/resources/extensions/gsd/commands-config.ts +3 -2
- package/src/resources/extensions/gsd/commands-extensions.ts +43 -3
- package/src/resources/extensions/gsd/commands-handlers.ts +3 -2
- package/src/resources/extensions/gsd/commands-mcp-status.ts +3 -1
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +15 -1
- package/src/resources/extensions/gsd/dashboard-overlay.ts +1 -1
- package/src/resources/extensions/gsd/docs/preferences-reference.md +10 -0
- package/src/resources/extensions/gsd/doctor-providers.ts +2 -1
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +39 -1
- package/src/resources/extensions/gsd/doctor-types.ts +3 -1
- package/src/resources/extensions/gsd/error-classifier.ts +1 -1
- package/src/resources/extensions/gsd/forensics.ts +12 -7
- package/src/resources/extensions/gsd/git-service.ts +13 -5
- package/src/resources/extensions/gsd/gsd-db.ts +12 -2
- package/src/resources/extensions/gsd/guided-flow.ts +27 -26
- package/src/resources/extensions/gsd/home-dir.ts +19 -0
- package/src/resources/extensions/gsd/journal.ts +4 -1
- package/src/resources/extensions/gsd/key-manager.ts +2 -1
- package/src/resources/extensions/gsd/memory-store.ts +81 -28
- package/src/resources/extensions/gsd/migrate/command.ts +3 -2
- package/src/resources/extensions/gsd/milestone-id-reservation.ts +47 -0
- package/src/resources/extensions/gsd/model-router.ts +172 -9
- package/src/resources/extensions/gsd/native-git-bridge.ts +7 -1
- package/src/resources/extensions/gsd/preferences-models.ts +101 -15
- package/src/resources/extensions/gsd/preferences-types.ts +6 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +35 -0
- package/src/resources/extensions/gsd/preferences.ts +16 -2
- package/src/resources/extensions/gsd/prompt-loader.ts +26 -12
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +10 -0
- package/src/resources/extensions/gsd/prompts/complete-slice.md +10 -0
- package/src/resources/extensions/gsd/prompts/plan-slice.md +10 -0
- package/src/resources/extensions/gsd/prompts/refine-slice.md +10 -0
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +9 -3
- package/src/resources/extensions/gsd/state.ts +42 -0
- package/src/resources/extensions/gsd/templates/PREFERENCES.md +1 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +178 -1
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +58 -0
- package/src/resources/extensions/gsd/tests/auto-session-encapsulation.test.ts +24 -5
- package/src/resources/extensions/gsd/tests/auto-supervisor.test.mjs +21 -4
- package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/budget-prediction.test.ts +138 -211
- package/src/resources/extensions/gsd/tests/commands-extensions-version-compare.test.ts +58 -0
- package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +142 -59
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +7 -4
- package/src/resources/extensions/gsd/tests/completed-at-reconcile.test.ts +89 -32
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +41 -23
- package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +3 -43
- package/src/resources/extensions/gsd/tests/debug-logger.test.ts +5 -3
- package/src/resources/extensions/gsd/tests/deferred-milestone-dir-4996.test.ts +116 -0
- package/src/resources/extensions/gsd/tests/discuss-empty-db-fallback.test.ts +22 -87
- package/src/resources/extensions/gsd/tests/discuss-queued-milestones.test.ts +7 -118
- package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +18 -60
- package/src/resources/extensions/gsd/tests/doctor-orphan-milestone-4996.test.ts +100 -0
- package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +14 -76
- package/src/resources/extensions/gsd/tests/ensure-preconditions-guard-4996.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/false-degraded-mode-warning.test.ts +22 -83
- package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +1 -63
- package/src/resources/extensions/gsd/tests/find-missing-summaries-closed-runtime.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/forensics-stuck-loops.test.ts +26 -1
- package/src/resources/extensions/gsd/tests/gitignore-bg-shell-runtime.test.ts +63 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/gsd-no-project-error-runtime.test.ts +81 -0
- package/src/resources/extensions/gsd/tests/headless-answers.test.ts +14 -4
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +22 -12
- package/src/resources/extensions/gsd/tests/help-menu-coverage.test.ts +57 -0
- package/src/resources/extensions/gsd/tests/home-dir.test.ts +52 -0
- package/src/resources/extensions/gsd/tests/import-done-milestones-runtime.test.ts +145 -0
- package/src/resources/extensions/gsd/tests/init-prefs-routing.test.ts +64 -1
- package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +72 -1
- package/src/resources/extensions/gsd/tests/integration/token-savings.test.ts +0 -23
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +128 -0
- package/src/resources/extensions/gsd/tests/memory-tools.test.ts +33 -1
- package/src/resources/extensions/gsd/tests/merge-self-branch-guard.test.ts +124 -0
- package/src/resources/extensions/gsd/tests/milestone-id-gap-reuse-4996.test.ts +152 -0
- package/src/resources/extensions/gsd/tests/milestone-report-path.test.ts +18 -1
- package/src/resources/extensions/gsd/tests/model-router.test.ts +169 -8
- package/src/resources/extensions/gsd/tests/native-git-infra-errors.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +32 -43
- package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +4 -10
- package/src/resources/extensions/gsd/tests/preferences.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +6 -6
- package/src/resources/extensions/gsd/tests/register-hooks-compaction-checkpoint.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +168 -19
- package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +23 -1
- package/src/resources/extensions/gsd/tests/steer-worktree-path.test.ts +17 -1
- package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +101 -0
- package/src/resources/extensions/gsd/tests/token-profile.test.ts +51 -4
- package/src/resources/extensions/gsd/tests/turn-epoch.test.ts +7 -16
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +38 -3
- package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +5 -7
- package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +15 -1
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +6 -6
- package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +34 -33
- package/src/resources/extensions/gsd/tests/worktree.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +131 -1
- package/src/resources/extensions/gsd/tools/memory-tools.ts +17 -1
- package/src/resources/extensions/gsd/unit-context-manifest.ts +44 -12
- package/src/resources/extensions/gsd/visualizer-overlay.ts +1 -1
- package/src/resources/extensions/gsd/watch/header-renderer.ts +3 -1
- package/src/resources/extensions/gsd/workflow-logger.ts +1 -0
- package/src/resources/extensions/gsd/worktree-command.ts +31 -44
- package/src/resources/extensions/gsd/worktree-manager.ts +40 -1
- package/src/resources/extensions/gsd/worktree-resolver.ts +4 -14
- package/src/resources/extensions/gsd/worktree-root.ts +144 -0
- package/src/resources/extensions/gsd/worktree-session-state.ts +35 -0
- package/src/resources/extensions/gsd/worktree.ts +8 -119
- package/src/resources/extensions/mcp-client/index.ts +6 -3
- package/src/resources/extensions/mcp-client/tests/global-config.test.ts +91 -0
- package/src/resources/extensions/ollama/index.ts +16 -2
- package/src/resources/extensions/ollama/model-capabilities.ts +34 -0
- package/src/resources/extensions/ollama/ollama-client.ts +41 -4
- package/src/resources/extensions/ollama/tests/model-capabilities.test.ts +96 -0
- package/src/resources/extensions/ollama/tests/ollama-client-timeout-env.test.ts +147 -0
- package/src/resources/extensions/slash-commands/create-extension.ts +38 -24
- package/src/resources/extensions/subagent/index.ts +165 -7
- package/src/resources/skills/create-gsd-extension/SKILL.md +9 -5
- package/src/resources/skills/create-gsd-extension/references/custom-commands.md +1 -1
- package/src/resources/skills/create-gsd-extension/references/custom-rendering.md +5 -5
- package/src/resources/skills/create-gsd-extension/references/custom-tools.md +4 -4
- package/src/resources/skills/create-gsd-extension/references/custom-ui.md +6 -6
- package/src/resources/skills/create-gsd-extension/references/events-reference.md +3 -3
- package/src/resources/skills/create-gsd-extension/references/packaging-distribution.md +1 -1
- package/src/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +3 -3
- package/src/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +2 -2
- package/src/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +3 -3
- package/src/resources/skills/create-gsd-extension/templates/templates.test.ts +58 -0
- package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +32 -12
- package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +0 -601
- package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +0 -651
- package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +0 -91
- package/dist/resources/extensions/gsd/tests/auto-supervisor.test.mjs +0 -53
- package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +0 -112
- package/dist/resources/extensions/gsd/tests/resolve-ts-hooks.mjs +0 -23
- package/dist/resources/extensions/gsd/tests/resolve-ts.mjs +0 -5
- package/dist/resources/skills/github-workflows/references/gh/tests/__init__.py +0 -0
- package/dist/resources/skills/github-workflows/references/gh/tests/test_github_project_setup.py +0 -608
- package/dist/web/standalone/.next/static/chunks/2826.e9f5195e91f9cad2.js +0 -11
- package/dist/web/standalone/.next/static/chunks/3621.fc7480022c972438.js +0 -20
- package/dist/web/standalone/.next/static/chunks/app/page-151349214571e2b6.js +0 -1
- package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
- package/dist/web/standalone/.next/static/chunks/webpack-2e68521d7c82f7c2.js +0 -1
- package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +0 -22
- package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +0 -47
- package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +0 -75
- /package/dist/web/standalone/.next/static/{C1zT2kEfoLhDdbWPWKrXd → -Ukk6_YxRd4GY4iUOnRUE}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{C1zT2kEfoLhDdbWPWKrXd → -Ukk6_YxRd4GY4iUOnRUE}/_ssgManifest.js +0 -0
|
@@ -1,22 +1,14 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
2
|
import { isToolCallEventType } from "@gsd/pi-coding-agent";
|
|
3
3
|
import { updateSnapshot } from "../ecosystem/gsd-extension-api.js";
|
|
4
|
-
import { getEcosystemReadyPromise } from "../ecosystem/loader.js";
|
|
5
4
|
import { buildMilestoneFileName, resolveMilestonePath, resolveSliceFile, resolveSlicePath } from "../paths.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { clearDiscussionFlowState, isDepthConfirmationAnswer, isQueuePhaseActive, markDepthVerified, resetWriteGateState, shouldBlockContextWrite, shouldBlockQueueExecution, isGateQuestionId, setPendingGate, clearPendingGate, getPendingGate, shouldBlockPendingGate, shouldBlockPendingGateBash, extractDepthVerificationMilestoneId } from "./write-gate.js";
|
|
5
|
+
import { clearDiscussionFlowState, isDepthConfirmationAnswer, isQueuePhaseActive, markDepthVerified, resetWriteGateState, shouldBlockContextWrite, shouldBlockPlanningUnit, shouldBlockQueueExecution, isGateQuestionId, setPendingGate, clearPendingGate, getPendingGate, shouldBlockPendingGate, shouldBlockPendingGateBash, extractDepthVerificationMilestoneId } from "./write-gate.js";
|
|
6
|
+
import { resolveManifest } from "../unit-context-manifest.js";
|
|
9
7
|
import { isBlockedStateFile, isBashWriteToStateFile, BLOCKED_WRITE_ERROR } from "../write-intercept.js";
|
|
10
|
-
import { cleanupQuickBranch } from "../quick.js";
|
|
11
|
-
import { getDiscussionMilestoneId } from "../guided-flow.js";
|
|
12
|
-
import { loadToolApiKeys } from "../commands-config.js";
|
|
13
8
|
import { loadFile, saveFile, formatContinue } from "../files.js";
|
|
14
|
-
import {
|
|
15
|
-
import { getAutoDashboardData, isAutoActive, isAutoPaused, markToolEnd, markToolStart, recordToolInvocationError } from "../auto.js";
|
|
16
|
-
import { isParallelActive, shutdownParallel } from "../parallel-orchestrator.js";
|
|
9
|
+
import { getAutoRuntimeSnapshot, isAutoActive, isAutoPaused, markToolEnd, markToolStart, recordToolInvocationError } from "../auto-runtime-state.js";
|
|
17
10
|
import { checkToolCallLoop, resetToolCallLoopGuard } from "./tool-call-loop-guard.js";
|
|
18
11
|
import { saveActivityLog } from "../activity-log.js";
|
|
19
|
-
import { resetAskUserQuestionsCache } from "../../ask-user-questions.js";
|
|
20
12
|
import { recordToolCall as safetyRecordToolCall, recordToolResult as safetyRecordToolResult, saveEvidenceToDisk } from "../safety/evidence-collector.js";
|
|
21
13
|
import { parseUnitId } from "../unit-id.js";
|
|
22
14
|
import { classifyCommand } from "../safety/destructive-guard.js";
|
|
@@ -24,26 +16,53 @@ import { logWarning as safetyLogWarning } from "../workflow-logger.js";
|
|
|
24
16
|
import { installNotifyInterceptor } from "./notify-interceptor.js";
|
|
25
17
|
import { initNotificationStore } from "../notification-store.js";
|
|
26
18
|
import { initNotificationWidget } from "../notification-widget.js";
|
|
27
|
-
import {
|
|
19
|
+
import { extractSubagentAgentClasses } from "./subagent-input.js";
|
|
28
20
|
// Skip the welcome screen on the very first session_start — cli.ts already
|
|
29
21
|
// printed it before the TUI launched. Only re-print on /clear (subsequent sessions).
|
|
30
22
|
let isFirstSession = true;
|
|
23
|
+
async function deriveGsdState(basePath) {
|
|
24
|
+
const { deriveState } = await import("../state.js");
|
|
25
|
+
return deriveState(basePath);
|
|
26
|
+
}
|
|
27
|
+
async function getDiscussionMilestoneIdFor(basePath) {
|
|
28
|
+
const { getDiscussionMilestoneId } = await import("../guided-flow.js");
|
|
29
|
+
return getDiscussionMilestoneId(basePath);
|
|
30
|
+
}
|
|
31
|
+
async function loadToolApiKeysForSession() {
|
|
32
|
+
const { loadToolApiKeys } = await import("../commands-config.js");
|
|
33
|
+
loadToolApiKeys();
|
|
34
|
+
}
|
|
35
|
+
async function resetAskUserQuestionsTurnCache() {
|
|
36
|
+
const { resetAskUserQuestionsCache } = await import("../../ask-user-questions.js");
|
|
37
|
+
resetAskUserQuestionsCache();
|
|
38
|
+
}
|
|
31
39
|
async function syncServiceTierStatus(ctx) {
|
|
32
40
|
const { getEffectiveServiceTier, formatServiceTierFooterStatus } = await import("../service-tier.js");
|
|
33
41
|
ctx.ui.setStatus("gsd-fast", formatServiceTierFooterStatus(getEffectiveServiceTier(), ctx.model?.id));
|
|
34
42
|
}
|
|
43
|
+
async function applyDisabledModelProviderPolicy(ctx) {
|
|
44
|
+
try {
|
|
45
|
+
const { resolveDisabledModelProvidersFromPreferences } = await import("../preferences.js");
|
|
46
|
+
ctx.modelRegistry.setDisabledModelProviders(resolveDisabledModelProvidersFromPreferences());
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
// Non-fatal: keep default provider visibility if preferences cannot be loaded.
|
|
50
|
+
}
|
|
51
|
+
}
|
|
35
52
|
export function registerHooks(pi, ecosystemHandlers) {
|
|
36
53
|
pi.on("session_start", async (_event, ctx) => {
|
|
37
54
|
initNotificationStore(process.cwd());
|
|
38
55
|
installNotifyInterceptor(ctx);
|
|
39
56
|
initNotificationWidget(ctx);
|
|
40
57
|
if (!isAutoActive()) {
|
|
58
|
+
const { initHealthWidget } = await import("../health-widget.js");
|
|
41
59
|
initHealthWidget(ctx);
|
|
42
60
|
}
|
|
43
61
|
resetWriteGateState();
|
|
44
62
|
resetToolCallLoopGuard();
|
|
45
|
-
|
|
63
|
+
await resetAskUserQuestionsTurnCache();
|
|
46
64
|
await syncServiceTierStatus(ctx);
|
|
65
|
+
await applyDisabledModelProviderPolicy(ctx);
|
|
47
66
|
// Skip MCP auto-prep when running inside an auto-worktree (see session_switch below).
|
|
48
67
|
const { isInAutoWorktree } = await import("../auto-worktree.js");
|
|
49
68
|
if (!isInAutoWorktree(process.cwd())) {
|
|
@@ -79,7 +98,7 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
79
98
|
}
|
|
80
99
|
catch { /* non-fatal */ }
|
|
81
100
|
}
|
|
82
|
-
|
|
101
|
+
await loadToolApiKeysForSession();
|
|
83
102
|
if (isAutoActive()) {
|
|
84
103
|
ctx.ui.setWidget("gsd-health", undefined);
|
|
85
104
|
}
|
|
@@ -89,9 +108,10 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
89
108
|
installNotifyInterceptor(ctx);
|
|
90
109
|
resetWriteGateState();
|
|
91
110
|
resetToolCallLoopGuard();
|
|
92
|
-
|
|
111
|
+
await resetAskUserQuestionsTurnCache();
|
|
93
112
|
clearDiscussionFlowState();
|
|
94
113
|
await syncServiceTierStatus(ctx);
|
|
114
|
+
await applyDisabledModelProviderPolicy(ctx);
|
|
95
115
|
// Skip MCP auto-prep when running inside an auto-worktree. The worktree
|
|
96
116
|
// already has .mcp.json from createAutoWorktree, and re-running the writer
|
|
97
117
|
// post-chdir rewrites the file mid-run (non-idempotent due to cwd-relative
|
|
@@ -101,20 +121,26 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
101
121
|
const { prepareWorkflowMcpForProject } = await import("../workflow-mcp-auto-prep.js");
|
|
102
122
|
prepareWorkflowMcpForProject(ctx, process.cwd());
|
|
103
123
|
}
|
|
104
|
-
|
|
105
|
-
if (isAutoActive()) {
|
|
124
|
+
await loadToolApiKeysForSession();
|
|
125
|
+
if (!isAutoActive()) {
|
|
126
|
+
const { initHealthWidget } = await import("../health-widget.js");
|
|
127
|
+
initHealthWidget(ctx);
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
106
130
|
ctx.ui.setWidget("gsd-health", undefined);
|
|
107
131
|
}
|
|
108
132
|
});
|
|
109
133
|
pi.on("before_agent_start", async (event, ctx) => {
|
|
110
134
|
// Wait for ecosystem loader to finish (no-op after first turn).
|
|
135
|
+
const { getEcosystemReadyPromise } = await import("../ecosystem/loader.js");
|
|
111
136
|
await getEcosystemReadyPromise();
|
|
112
137
|
// GSD's own context injection (existing behavior — unchanged).
|
|
138
|
+
const { buildBeforeAgentStartResult } = await import("./system-context.js");
|
|
113
139
|
const gsdResult = await buildBeforeAgentStartResult(event, ctx);
|
|
114
140
|
// Refresh the snapshot used by ecosystem getPhase()/getActiveUnit().
|
|
115
141
|
// deriveState has its own ~100ms cache so this is cheap on repeat calls.
|
|
116
142
|
try {
|
|
117
|
-
const state = await
|
|
143
|
+
const state = await deriveGsdState(process.cwd());
|
|
118
144
|
updateSnapshot(state);
|
|
119
145
|
}
|
|
120
146
|
catch {
|
|
@@ -148,7 +174,8 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
148
174
|
});
|
|
149
175
|
pi.on("agent_end", async (event, ctx) => {
|
|
150
176
|
resetToolCallLoopGuard();
|
|
151
|
-
|
|
177
|
+
await resetAskUserQuestionsTurnCache();
|
|
178
|
+
const { handleAgentEnd } = await import("./agent-end-recovery.js");
|
|
152
179
|
await handleAgentEnd(pi, event, ctx);
|
|
153
180
|
});
|
|
154
181
|
// Squash-merge quick-task branch back to the original branch after the
|
|
@@ -156,6 +183,7 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
156
183
|
// quick-return state is pending, so this is safe to call on every turn.
|
|
157
184
|
pi.on("turn_end", async () => {
|
|
158
185
|
try {
|
|
186
|
+
const { cleanupQuickBranch } = await import("../quick.js");
|
|
159
187
|
cleanupQuickBranch();
|
|
160
188
|
}
|
|
161
189
|
catch {
|
|
@@ -172,8 +200,8 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
172
200
|
const basePath = process.cwd();
|
|
173
201
|
const { ensureDbOpen } = await import("./dynamic-tools.js");
|
|
174
202
|
await ensureDbOpen();
|
|
175
|
-
const state = await
|
|
176
|
-
if (!state.activeMilestone || !state.activeSlice
|
|
203
|
+
const state = await deriveGsdState(basePath);
|
|
204
|
+
if (!state.activeMilestone || !state.activeSlice)
|
|
177
205
|
return;
|
|
178
206
|
// Write checkpoint for ALL phases, not just "executing" — discuss, research,
|
|
179
207
|
// and planning also carry in-memory state (user answers, gate verification)
|
|
@@ -189,21 +217,30 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
189
217
|
if (await loadFile(legacyContinue))
|
|
190
218
|
return;
|
|
191
219
|
const continuePath = join(sliceDir, `${state.activeSlice.id}-CONTINUE.md`);
|
|
220
|
+
const taskId = state.activeTask?.id ?? "none";
|
|
221
|
+
const taskTitle = state.activeTask?.title ?? "";
|
|
222
|
+
const phaseLabel = state.phase.replace(/-/g, " ");
|
|
192
223
|
await saveFile(continuePath, formatContinue({
|
|
193
224
|
frontmatter: {
|
|
194
225
|
milestone: state.activeMilestone.id,
|
|
195
226
|
slice: state.activeSlice.id,
|
|
196
|
-
task:
|
|
227
|
+
task: taskId,
|
|
197
228
|
step: 0,
|
|
198
229
|
totalSteps: 0,
|
|
199
230
|
status: "compacted",
|
|
200
231
|
savedAt: new Date().toISOString(),
|
|
201
232
|
},
|
|
202
|
-
completedWork:
|
|
203
|
-
|
|
233
|
+
completedWork: state.activeTask
|
|
234
|
+
? `Task ${taskId} (${taskTitle}) was in progress when compaction occurred.`
|
|
235
|
+
: `Slice ${state.activeSlice.id} was in ${phaseLabel} phase when compaction occurred.`,
|
|
236
|
+
remainingWork: state.activeTask
|
|
237
|
+
? "Check the task plan for remaining steps."
|
|
238
|
+
: "Continue this slice from the latest planning/research/discussion artifacts.",
|
|
204
239
|
decisions: "Check task summary files for prior decisions.",
|
|
205
240
|
context: "Session was auto-compacted by Pi. Resume with /gsd.",
|
|
206
|
-
nextAction:
|
|
241
|
+
nextAction: state.activeTask
|
|
242
|
+
? `Resume task ${taskId}: ${taskTitle}.`
|
|
243
|
+
: `Resume ${phaseLabel} work for slice ${state.activeSlice.id}.`,
|
|
207
244
|
}));
|
|
208
245
|
});
|
|
209
246
|
// Context-mode snapshot: write .gsd/last-snapshot.md before compaction so
|
|
@@ -225,7 +262,7 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
225
262
|
const basePath = process.cwd();
|
|
226
263
|
let activeContext = null;
|
|
227
264
|
try {
|
|
228
|
-
const state = await
|
|
265
|
+
const state = await deriveGsdState(basePath);
|
|
229
266
|
if (state.activeMilestone && state.activeSlice && state.activeTask) {
|
|
230
267
|
activeContext =
|
|
231
268
|
`Active: ${state.activeMilestone.id} / ${state.activeSlice.id} / ${state.activeTask.id}` +
|
|
@@ -242,6 +279,7 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
242
279
|
}
|
|
243
280
|
});
|
|
244
281
|
pi.on("session_shutdown", async (_event, ctx) => {
|
|
282
|
+
const { isParallelActive, shutdownParallel } = await import("../parallel-orchestrator.js");
|
|
245
283
|
if (isParallelActive()) {
|
|
246
284
|
try {
|
|
247
285
|
await shutdownParallel(process.cwd());
|
|
@@ -252,7 +290,7 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
252
290
|
}
|
|
253
291
|
if (!isAutoActive() && !isAutoPaused())
|
|
254
292
|
return;
|
|
255
|
-
const dash =
|
|
293
|
+
const dash = getAutoRuntimeSnapshot();
|
|
256
294
|
if (dash.currentUnit) {
|
|
257
295
|
saveActivityLog(ctx, dash.basePath, dash.currentUnit.type, dash.currentUnit.id);
|
|
258
296
|
}
|
|
@@ -278,7 +316,7 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
278
316
|
// If ask_user_questions was called with a gate ID but hasn't been confirmed,
|
|
279
317
|
// block all non-read-only tool calls to prevent the model from skipping gates.
|
|
280
318
|
if (getPendingGate()) {
|
|
281
|
-
const milestoneId =
|
|
319
|
+
const milestoneId = await getDiscussionMilestoneIdFor(discussionBasePath);
|
|
282
320
|
if (isToolCallEventType("bash", event)) {
|
|
283
321
|
const bashGuard = shouldBlockPendingGateBash(event.input.command, milestoneId, isQueuePhaseActive());
|
|
284
322
|
if (bashGuard.block)
|
|
@@ -309,6 +347,37 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
309
347
|
if (queueGuard.block)
|
|
310
348
|
return queueGuard;
|
|
311
349
|
}
|
|
350
|
+
// ── Planning-unit tools-policy enforcement (#4934): runtime half ─────
|
|
351
|
+
// The active auto-mode unit's manifest declares a ToolsPolicy. For
|
|
352
|
+
// planning/docs/read-only modes, deny writes outside .gsd/ (or the
|
|
353
|
+
// manifest's allowedPathGlobs), bash that isn't read-only, and
|
|
354
|
+
// subagent dispatch. Closes the b23 bug class where a discuss-milestone
|
|
355
|
+
// turn used the host Edit tool to modify user source files.
|
|
356
|
+
const dash = getAutoRuntimeSnapshot();
|
|
357
|
+
const activeUnitType = dash.currentUnit?.type;
|
|
358
|
+
if (activeUnitType) {
|
|
359
|
+
const manifest = resolveManifest(activeUnitType);
|
|
360
|
+
if (manifest) {
|
|
361
|
+
let planningInput = "";
|
|
362
|
+
let agentClasses;
|
|
363
|
+
if (isToolCallEventType("write", event)) {
|
|
364
|
+
planningInput = event.input.path;
|
|
365
|
+
}
|
|
366
|
+
else if (isToolCallEventType("edit", event)) {
|
|
367
|
+
planningInput = event.input.path;
|
|
368
|
+
}
|
|
369
|
+
else if (isToolCallEventType("bash", event)) {
|
|
370
|
+
planningInput = event.input.command;
|
|
371
|
+
}
|
|
372
|
+
else if (event.toolName === "subagent" || event.toolName === "task") {
|
|
373
|
+
// Subagent inputs use { agent }, { tasks: [{ agent }] }, or { chain: [{ agent }] }.
|
|
374
|
+
agentClasses = extractSubagentAgentClasses(event.input);
|
|
375
|
+
}
|
|
376
|
+
const planningGuard = shouldBlockPlanningUnit(event.toolName, planningInput, dash.basePath || discussionBasePath, activeUnitType, manifest.tools, agentClasses);
|
|
377
|
+
if (planningGuard.block)
|
|
378
|
+
return planningGuard;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
312
381
|
// ── Single-writer engine: block direct writes to STATE.md ──────────
|
|
313
382
|
// Covers write, edit, and bash tools to prevent bypass vectors.
|
|
314
383
|
if (isToolCallEventType("write", event)) {
|
|
@@ -328,7 +397,7 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
328
397
|
}
|
|
329
398
|
if (!isToolCallEventType("write", event))
|
|
330
399
|
return;
|
|
331
|
-
const result = shouldBlockContextWrite(event.toolName, event.input.path,
|
|
400
|
+
const result = shouldBlockContextWrite(event.toolName, event.input.path, await getDiscussionMilestoneIdFor(discussionBasePath), isQueuePhaseActive());
|
|
332
401
|
if (result.block)
|
|
333
402
|
return result;
|
|
334
403
|
});
|
|
@@ -368,7 +437,7 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
368
437
|
}
|
|
369
438
|
if (event.toolName !== "ask_user_questions")
|
|
370
439
|
return;
|
|
371
|
-
const milestoneId =
|
|
440
|
+
const milestoneId = await getDiscussionMilestoneIdFor(process.cwd());
|
|
372
441
|
const queueActive = isQueuePhaseActive();
|
|
373
442
|
const details = event.details;
|
|
374
443
|
// ── Discussion gate enforcement: handle gate question responses ──
|
|
@@ -464,7 +533,7 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
464
533
|
safetyRecordToolResult(event.toolCallId, event.toolName, event.result, event.isError);
|
|
465
534
|
// Persist evidence to disk after each tool result so it survives a session
|
|
466
535
|
// restart mid-unit (Bug #4385 — non-persisted evidence false positives).
|
|
467
|
-
const dash =
|
|
536
|
+
const dash = getAutoRuntimeSnapshot();
|
|
468
537
|
if (dash.basePath && dash.currentUnit?.type === "execute-task") {
|
|
469
538
|
const { milestone: pMid, slice: pSid, task: pTid } = parseUnitId(dash.currentUnit.id);
|
|
470
539
|
if (pMid && pSid && pTid) {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { Key } from "@gsd/pi-tui";
|
|
4
|
-
import { GSDDashboardOverlay } from "../dashboard-overlay.js";
|
|
5
|
-
import { GSDNotificationOverlay } from "../notification-overlay.js";
|
|
6
|
-
import { ParallelMonitorOverlay } from "../parallel-monitor-overlay.js";
|
|
7
4
|
import { GSD_SHORTCUTS } from "../shortcut-defs.js";
|
|
8
|
-
import { projectRoot } from "../commands/context.js";
|
|
9
5
|
import { shortcutDesc } from "../../shared/mod.js";
|
|
6
|
+
async function getProjectRoot() {
|
|
7
|
+
const { projectRoot } = await import("../commands/context.js");
|
|
8
|
+
return projectRoot();
|
|
9
|
+
}
|
|
10
10
|
export function registerShortcuts(pi) {
|
|
11
11
|
const overlayOptions = {
|
|
12
12
|
width: "90%",
|
|
@@ -15,7 +15,10 @@ export function registerShortcuts(pi) {
|
|
|
15
15
|
anchor: "center",
|
|
16
16
|
};
|
|
17
17
|
const openDashboardOverlay = async (ctx) => {
|
|
18
|
-
const basePath =
|
|
18
|
+
const [{ GSDDashboardOverlay }, basePath] = await Promise.all([
|
|
19
|
+
import("../dashboard-overlay.js"),
|
|
20
|
+
getProjectRoot(),
|
|
21
|
+
]);
|
|
19
22
|
if (!existsSync(join(basePath, ".gsd"))) {
|
|
20
23
|
ctx.ui.notify("No .gsd/ directory found. Run /gsd to start.", "info");
|
|
21
24
|
return;
|
|
@@ -26,6 +29,7 @@ export function registerShortcuts(pi) {
|
|
|
26
29
|
});
|
|
27
30
|
};
|
|
28
31
|
const openNotificationsOverlay = async (ctx) => {
|
|
32
|
+
const { GSDNotificationOverlay } = await import("../notification-overlay.js");
|
|
29
33
|
await ctx.ui.custom((tui, theme, _kb, done) => new GSDNotificationOverlay(tui, theme, () => done(true)), {
|
|
30
34
|
overlay: true,
|
|
31
35
|
overlayOptions: {
|
|
@@ -38,12 +42,13 @@ export function registerShortcuts(pi) {
|
|
|
38
42
|
});
|
|
39
43
|
};
|
|
40
44
|
const openParallelOverlay = async (ctx) => {
|
|
41
|
-
const basePath =
|
|
45
|
+
const basePath = await getProjectRoot();
|
|
42
46
|
const parallelDir = join(basePath, ".gsd", "parallel");
|
|
43
47
|
if (!existsSync(parallelDir)) {
|
|
44
48
|
ctx.ui.notify("No parallel workers found. Run /gsd parallel start first.", "info");
|
|
45
49
|
return;
|
|
46
50
|
}
|
|
51
|
+
const { ParallelMonitorOverlay } = await import("../parallel-monitor-overlay.js");
|
|
47
52
|
await ctx.ui.custom((tui, theme, _kb, done) => new ParallelMonitorOverlay(tui, theme, () => done(true), basePath), {
|
|
48
53
|
overlay: true,
|
|
49
54
|
overlayOptions,
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export function extractSubagentAgentClasses(input) {
|
|
2
|
+
if (!input || typeof input !== "object")
|
|
3
|
+
return [];
|
|
4
|
+
const record = input;
|
|
5
|
+
const agentClasses = [];
|
|
6
|
+
const addAgentClass = (value) => {
|
|
7
|
+
if (typeof value === "string" && value.trim().length > 0)
|
|
8
|
+
agentClasses.push(value.trim());
|
|
9
|
+
};
|
|
10
|
+
const addFromItems = (value) => {
|
|
11
|
+
if (!Array.isArray(value))
|
|
12
|
+
return;
|
|
13
|
+
for (const item of value) {
|
|
14
|
+
if (item && typeof item === "object")
|
|
15
|
+
addAgentClass(item.agent);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
addAgentClass(record.agent);
|
|
19
|
+
addFromItems(record.tasks);
|
|
20
|
+
addFromItems(record.chain);
|
|
21
|
+
return agentClasses;
|
|
22
|
+
}
|
|
@@ -12,7 +12,7 @@ import { resolveGsdRootFile, resolveSliceFile, resolveSlicePath, resolveTaskFile
|
|
|
12
12
|
import { ensureCodebaseMapFresh, readCodebaseMap } from "../codebase-generator.js";
|
|
13
13
|
import { hasSkillSnapshot, detectNewSkills, formatSkillsXml } from "../skill-discovery.js";
|
|
14
14
|
import { getActiveAutoWorktreeContext } from "../auto-worktree.js";
|
|
15
|
-
import { getActiveWorktreeName, getWorktreeOriginalCwd } from "../worktree-
|
|
15
|
+
import { getActiveWorktreeName, getWorktreeOriginalCwd } from "../worktree-session-state.js";
|
|
16
16
|
import { deriveState } from "../state.js";
|
|
17
17
|
import { formatOverridesSection, formatShortcut, loadActiveOverrides, loadFile, parseContinue, parseSummary } from "../files.js";
|
|
18
18
|
import { toPosixPath } from "../../shared/mod.js";
|
|
@@ -177,24 +177,50 @@ export async function buildBeforeAgentStartResult(event, ctx) {
|
|
|
177
177
|
const subagentModelBlock = subagentModelConfig
|
|
178
178
|
? `\n\n## Subagent Model\n\nWhen spawning subagents via the \`subagent\` tool, always pass \`model: "${subagentModelConfig.primary}"\` in the tool call parameters. Never omit this — always specify it explicitly.`
|
|
179
179
|
: "";
|
|
180
|
-
|
|
180
|
+
// memoryBlock is FTS-queried against the user prompt and changes per call.
|
|
181
|
+
// Removing it from `fullSystem` keeps the system-prompt cache breakpoint
|
|
182
|
+
// stable across calls — the only scoped goal of this fix. The pi-ai
|
|
183
|
+
// Anthropic adapter additionally cache-marks the last user turn, so the
|
|
184
|
+
// memoryBlock injected via the context message may itself be cached up to
|
|
185
|
+
// that boundary; that's orthogonal and unchanged from prior behavior. The
|
|
186
|
+
// load-bearing win here is preserving the system+tools cache hit. (#5019)
|
|
187
|
+
const fullSystem = `${event.systemPrompt}\n\n[SYSTEM CONTEXT — GSD]\n\n${systemContent}${preferenceBlock}${knowledgeBlock}${codebaseBlock}${newSkillsBlock}${worktreeBlock}${subagentModelBlock}`;
|
|
181
188
|
stopContextTimer({
|
|
182
189
|
systemPromptSize: fullSystem.length,
|
|
183
190
|
injectionSize: injection?.length ?? forensicsInjection?.length ?? 0,
|
|
184
191
|
hasPreferences: preferenceBlock.length > 0,
|
|
185
192
|
hasNewSkills: newSkillsBlock.length > 0,
|
|
186
193
|
});
|
|
187
|
-
|
|
188
|
-
const contextMessage = injection
|
|
189
|
-
? { customType: "gsd-guided-context", content: injection, display: false }
|
|
190
|
-
: forensicsInjection
|
|
191
|
-
? { customType: "gsd-forensics", content: forensicsInjection, display: false }
|
|
192
|
-
: null;
|
|
194
|
+
const contextMessage = buildContextMessage({ memoryBlock, injection, forensicsInjection });
|
|
193
195
|
return {
|
|
194
196
|
systemPrompt: fullSystem,
|
|
195
197
|
...(contextMessage ? { message: contextMessage } : {}),
|
|
196
198
|
};
|
|
197
199
|
}
|
|
200
|
+
/**
|
|
201
|
+
* Route the per-call dynamic blocks (memory, guided-execute, forensics) into a
|
|
202
|
+
* single user-message context payload so they ride the volatile suffix instead
|
|
203
|
+
* of the cached system prefix. Priority when both memory and an injection are
|
|
204
|
+
* present: guided > forensics > memory-only. (#5019)
|
|
205
|
+
*
|
|
206
|
+
* Exported for direct unit testing — the surrounding bootstrap has too many
|
|
207
|
+
* filesystem and DB dependencies to exercise this routing logic in-place.
|
|
208
|
+
*/
|
|
209
|
+
export function buildContextMessage(opts) {
|
|
210
|
+
const memoryContent = opts.memoryBlock.trim();
|
|
211
|
+
if (opts.injection) {
|
|
212
|
+
const content = memoryContent ? `${memoryContent}\n\n${opts.injection}` : opts.injection;
|
|
213
|
+
return { customType: "gsd-guided-context", content, display: false };
|
|
214
|
+
}
|
|
215
|
+
if (opts.forensicsInjection) {
|
|
216
|
+
const content = memoryContent ? `${memoryContent}\n\n${opts.forensicsInjection}` : opts.forensicsInjection;
|
|
217
|
+
return { customType: "gsd-forensics", content, display: false };
|
|
218
|
+
}
|
|
219
|
+
if (memoryContent) {
|
|
220
|
+
return { customType: "gsd-memory", content: memoryContent, display: false };
|
|
221
|
+
}
|
|
222
|
+
return null;
|
|
223
|
+
}
|
|
198
224
|
/**
|
|
199
225
|
* ADR-013 step 4 — auto-injection parity for the memories table.
|
|
200
226
|
*
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { copyFileSync, existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
3
3
|
import { minimatch } from "minimatch";
|
|
4
|
+
import { logWarning } from "../workflow-logger.js";
|
|
4
5
|
/**
|
|
5
6
|
* Regex matching milestone CONTEXT.md file names in both legacy M001
|
|
6
7
|
* and unique M001-abc123 formats. Exported so regex-hardening tests
|
|
@@ -441,8 +442,67 @@ export function shouldBlockQueueExecutionInSnapshot(snapshot, toolName, input, q
|
|
|
441
442
|
};
|
|
442
443
|
}
|
|
443
444
|
// ─── Planning-unit tools-policy enforcement (#4934) ───────────────────────
|
|
445
|
+
//
|
|
446
|
+
// Runtime half of the declarative ToolsPolicy on UnitContextManifest. The
|
|
447
|
+
// manifest assigns each unit type a tools mode; this predicate is what
|
|
448
|
+
// actually rejects a tool call that violates it.
|
|
449
|
+
//
|
|
450
|
+
// Forensics: a discuss-milestone LLM turn used the host Edit tool to modify
|
|
451
|
+
// index.html in test app b23 (~/Github/test-apps/b23). With this predicate
|
|
452
|
+
// wired into the tool_call hook, the same call returns block=true with a
|
|
453
|
+
// HARD BLOCK reason that the model cannot rationalize past.
|
|
454
|
+
//
|
|
455
|
+
// Activation: the hook supplies the policy resolved from the active unit's
|
|
456
|
+
// manifest. When no unit is active (interactive sessions, unknown unit
|
|
457
|
+
// types), the hook passes null and this predicate is a no-op — falling
|
|
458
|
+
// through to the existing pendingGate / queue-execution / context-write
|
|
459
|
+
// guards.
|
|
444
460
|
const PLANNING_WRITE_TOOLS = new Set(["write", "edit", "multi_edit", "notebook_edit"]);
|
|
445
461
|
const PLANNING_SUBAGENT_TOOLS = new Set(["subagent", "task"]);
|
|
462
|
+
/**
|
|
463
|
+
* Canonical registry for agents that planning-dispatch may consider. Unit
|
|
464
|
+
* manifests still declare per-unit subsets via ToolsPolicy.allowedSubagents.
|
|
465
|
+
*/
|
|
466
|
+
const PLANNING_DISPATCH_AGENT_REGISTRY = {
|
|
467
|
+
scout: { readOnlySpecialist: true },
|
|
468
|
+
planner: { readOnlySpecialist: true },
|
|
469
|
+
reviewer: { readOnlySpecialist: true },
|
|
470
|
+
security: { readOnlySpecialist: true },
|
|
471
|
+
tester: { readOnlySpecialist: true },
|
|
472
|
+
};
|
|
473
|
+
export const ALLOWED_PLANNING_DISPATCH_AGENTS = new Set(Object.entries(PLANNING_DISPATCH_AGENT_REGISTRY)
|
|
474
|
+
.filter(([, metadata]) => metadata.readOnlySpecialist)
|
|
475
|
+
.map(([agentId]) => agentId));
|
|
476
|
+
let warnedMissingPlanningDispatchAgentClasses = false;
|
|
477
|
+
function isReadOnlySpecialist(agentId) {
|
|
478
|
+
const metadata = PLANNING_DISPATCH_AGENT_REGISTRY[agentId];
|
|
479
|
+
return metadata?.readOnlySpecialist === true;
|
|
480
|
+
}
|
|
481
|
+
function allowedPlanningDispatchAgentsList() {
|
|
482
|
+
return [...ALLOWED_PLANNING_DISPATCH_AGENTS].join(", ");
|
|
483
|
+
}
|
|
484
|
+
function warnMissingPlanningDispatchAgentClasses(unitType, mode, toolName) {
|
|
485
|
+
if (warnedMissingPlanningDispatchAgentClasses)
|
|
486
|
+
return;
|
|
487
|
+
warnedMissingPlanningDispatchAgentClasses = true;
|
|
488
|
+
// TODO(#5060): Remove this migration shim once all subagent/task callers are verified to forward agent identities.
|
|
489
|
+
const message = `[write-gate] planning-dispatch: shouldBlockPlanningUnit called for tool "${toolName}" ` +
|
|
490
|
+
`on unit "${unitType}" without agentClasses - stale caller; blocking dispatch.`;
|
|
491
|
+
console.warn(message);
|
|
492
|
+
logWarning("intercept", message, {
|
|
493
|
+
unitType,
|
|
494
|
+
mode,
|
|
495
|
+
toolName,
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* Read-only / planning-safe tools that any non-"all" mode allows. Mirrors
|
|
500
|
+
* QUEUE_SAFE_TOOLS / GATE_SAFE_TOOLS but is the inclusive default for
|
|
501
|
+
* planning units (which need their full discussion + research surface).
|
|
502
|
+
*
|
|
503
|
+
* gsd_* MCP tools are passed through unconditionally — they have their own
|
|
504
|
+
* domain validation (e.g. depth-verification gate, single-writer DB).
|
|
505
|
+
*/
|
|
446
506
|
const PLANNING_SAFE_TOOLS = new Set([
|
|
447
507
|
"read", "grep", "find", "ls", "glob",
|
|
448
508
|
"ask_user_questions",
|
|
@@ -458,6 +518,7 @@ function matchesAllowedGlob(absPath, basePath, globs) {
|
|
|
458
518
|
const rel = relative(basePath, absPath);
|
|
459
519
|
if (rel.startsWith("..") || isAbsolute(rel))
|
|
460
520
|
return false;
|
|
521
|
+
// Normalize Windows separators for minimatch.
|
|
461
522
|
const posix = rel.split(sep).join("/");
|
|
462
523
|
return globs.some(g => minimatch(posix, g, { dot: false, nocase: false }));
|
|
463
524
|
}
|
|
@@ -477,17 +538,32 @@ function blockReason(unitType, mode, what) {
|
|
|
477
538
|
* - "read-only" → blocks all writes, bash, and subagent dispatch.
|
|
478
539
|
* - "planning" → blocks writes to paths outside <basePath>/.gsd/,
|
|
479
540
|
* bash that isn't read-only, and subagent dispatch.
|
|
541
|
+
* - "planning-dispatch"
|
|
542
|
+
* → like "planning", but permits subagent dispatch only
|
|
543
|
+
* when every forwarded agent class is globally allowed
|
|
544
|
+
* and listed in the policy's allowedSubagents.
|
|
480
545
|
* - "docs" → like "planning" but also allows writes to paths
|
|
481
546
|
* matching `allowedPathGlobs` relative to basePath.
|
|
482
547
|
*
|
|
483
|
-
* `
|
|
548
|
+
* `pathOrCommand` is the file path for write/edit-shaped tools and the
|
|
549
|
+
* shell command for bash. Other tools ignore this argument.
|
|
550
|
+
*
|
|
551
|
+
* `policy` of null means "no manifest resolved" — pass-through. Callers
|
|
552
|
+
* that have no active unit (interactive sessions) pass null and this
|
|
553
|
+
* predicate is a no-op.
|
|
554
|
+
*
|
|
555
|
+
* `agentClasses` is supplied by the tool hook for subagent-shaped calls. If
|
|
556
|
+
* absent, planning-dispatch fails closed so stale callers cannot silently
|
|
557
|
+
* bypass the agent allowlists. An explicitly supplied-but-empty list is
|
|
558
|
+
* allowed through so the downstream tool call can reject the malformed input.
|
|
484
559
|
*/
|
|
485
|
-
export function shouldBlockPlanningUnit(toolName, pathOrCommand, basePath, unitType, policy) {
|
|
560
|
+
export function shouldBlockPlanningUnit(toolName, pathOrCommand, basePath, unitType, policy, agentClasses) {
|
|
486
561
|
if (!policy)
|
|
487
562
|
return { block: false };
|
|
488
563
|
if (policy.mode === "all")
|
|
489
564
|
return { block: false };
|
|
490
565
|
const tool = toolName;
|
|
566
|
+
// Read-only mode: only Read-class tools are permitted.
|
|
491
567
|
if (policy.mode === "read-only") {
|
|
492
568
|
if (PLANNING_SAFE_TOOLS.has(tool))
|
|
493
569
|
return { block: false };
|
|
@@ -496,14 +572,51 @@ export function shouldBlockPlanningUnit(toolName, pathOrCommand, basePath, unitT
|
|
|
496
572
|
if (PLANNING_WRITE_TOOLS.has(tool) || tool === "bash" || PLANNING_SUBAGENT_TOOLS.has(tool)) {
|
|
497
573
|
return { block: true, reason: blockReason(unitType, policy.mode, `${tool} is not permitted (read-only)`) };
|
|
498
574
|
}
|
|
575
|
+
// Unknown tool in read-only mode — block by default.
|
|
499
576
|
return { block: true, reason: blockReason(unitType, policy.mode, `tool "${tool}" is not on the read-only allowlist`) };
|
|
500
577
|
}
|
|
501
|
-
// planning / docs modes
|
|
578
|
+
// planning / planning-dispatch / docs modes share the same surface for safe tools, bash, and subagent.
|
|
502
579
|
if (PLANNING_SAFE_TOOLS.has(tool))
|
|
503
580
|
return { block: false };
|
|
504
581
|
if (tool.startsWith("gsd_"))
|
|
505
582
|
return { block: false };
|
|
506
583
|
if (PLANNING_SUBAGENT_TOOLS.has(tool)) {
|
|
584
|
+
if (policy.mode === "planning-dispatch") {
|
|
585
|
+
const requested = (agentClasses ?? []).map(a => a.trim()).filter(Boolean);
|
|
586
|
+
const allowedSubagents = Array.isArray(policy.allowedSubagents) ? policy.allowedSubagents : [];
|
|
587
|
+
const allowed = new Set(allowedSubagents);
|
|
588
|
+
// When agentClasses is undefined, the caller has not been updated to extract
|
|
589
|
+
// agent identities yet. Block and warn so stale callers surface in telemetry
|
|
590
|
+
// instead of silently bypassing the gate.
|
|
591
|
+
if (agentClasses === undefined) {
|
|
592
|
+
warnMissingPlanningDispatchAgentClasses(unitType, policy.mode, tool);
|
|
593
|
+
return {
|
|
594
|
+
block: true,
|
|
595
|
+
reason: blockReason(unitType, policy.mode, `subagent dispatch blocked: stale caller did not supply agent identities for "${tool}"; update extractSubagentAgentClasses to handle this input shape`),
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
// agentClasses was explicitly provided but resolved to an empty list (for
|
|
599
|
+
// example, a bare tool call with no agent field). Pass through; no agents
|
|
600
|
+
// to validate means the downstream tool call itself will fail.
|
|
601
|
+
if (requested.length === 0) {
|
|
602
|
+
return { block: false };
|
|
603
|
+
}
|
|
604
|
+
const globallyDisallowed = requested.find(a => !isReadOnlySpecialist(a));
|
|
605
|
+
if (globallyDisallowed) {
|
|
606
|
+
return {
|
|
607
|
+
block: true,
|
|
608
|
+
reason: blockReason(unitType, policy.mode, `subagent dispatch of "${globallyDisallowed}" not permitted; only read-only specialists (${allowedPlanningDispatchAgentsList()}) may be dispatched from planning-dispatch units`),
|
|
609
|
+
};
|
|
610
|
+
}
|
|
611
|
+
const disallowedByPolicy = requested.find(a => !allowed.has(a));
|
|
612
|
+
if (disallowedByPolicy) {
|
|
613
|
+
return {
|
|
614
|
+
block: true,
|
|
615
|
+
reason: blockReason(unitType, policy.mode, `subagent dispatch of "${disallowedByPolicy}" not permitted by ToolsPolicy.allowedSubagents; permitted agents for this unit: ${allowedSubagents.join(", ")}`),
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
return { block: false };
|
|
619
|
+
}
|
|
507
620
|
return { block: true, reason: blockReason(unitType, policy.mode, `subagent dispatch is not permitted in planning units`) };
|
|
508
621
|
}
|
|
509
622
|
if (tool === "bash") {
|
|
@@ -519,8 +632,10 @@ export function shouldBlockPlanningUnit(toolName, pathOrCommand, basePath, unitT
|
|
|
519
632
|
return { block: true, reason: blockReason(unitType, policy.mode, `${tool} called with empty path`) };
|
|
520
633
|
}
|
|
521
634
|
const absPath = isAbsolute(pathOrCommand) ? pathOrCommand : resolve(basePath, pathOrCommand);
|
|
635
|
+
// Always allow .gsd/ writes — that's where planning artifacts live.
|
|
522
636
|
if (isPathUnderGsd(absPath, basePath))
|
|
523
637
|
return { block: false };
|
|
638
|
+
// docs mode additionally allows the manifest's allowedPathGlobs.
|
|
524
639
|
if (policy.mode === "docs" && matchesAllowedGlob(absPath, basePath, policy.allowedPathGlobs)) {
|
|
525
640
|
return { block: false };
|
|
526
641
|
}
|
|
@@ -529,5 +644,8 @@ export function shouldBlockPlanningUnit(toolName, pathOrCommand, basePath, unitT
|
|
|
529
644
|
reason: blockReason(unitType, policy.mode, `cannot ${tool} "${pathOrCommand}" — writes are restricted to .gsd/${policy.mode === "docs" ? " and " + policy.allowedPathGlobs.join(", ") : ""}`),
|
|
530
645
|
};
|
|
531
646
|
}
|
|
647
|
+
// Unknown tool name — pass through. Other layers (queue, pending-gate,
|
|
648
|
+
// CONTEXT.md write) catch known mutating shapes; defaulting to allow here
|
|
649
|
+
// avoids breaking gsd_* MCP tools or future safe additions.
|
|
532
650
|
return { block: false };
|
|
533
651
|
}
|