gsd-pi 2.63.0 → 2.64.0-dev.9c14bd0
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 +46 -134
- package/dist/cli.js +48 -6
- package/dist/headless-query.js +11 -1
- package/dist/help-text.js +4 -1
- package/dist/onboarding.js +15 -8
- package/dist/resource-loader.js +18 -3
- package/dist/resources/extensions/cmux/index.js +21 -12
- package/dist/resources/extensions/gsd/auto/detect-stuck.js +27 -0
- package/dist/resources/extensions/gsd/auto/finalize-timeout.js +40 -0
- package/dist/resources/extensions/gsd/auto/loop.js +4 -0
- package/dist/resources/extensions/gsd/auto/phases.js +157 -22
- package/dist/resources/extensions/gsd/auto/session.js +12 -0
- package/dist/resources/extensions/gsd/auto-dashboard.js +14 -8
- package/dist/resources/extensions/gsd/auto-model-selection.js +32 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +222 -11
- package/dist/resources/extensions/gsd/auto-prompts.js +25 -0
- package/dist/resources/extensions/gsd/auto-recovery.js +15 -7
- package/dist/resources/extensions/gsd/auto-start.js +10 -21
- package/dist/resources/extensions/gsd/auto-timers.js +2 -1
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +17 -0
- package/dist/resources/extensions/gsd/auto-verification.js +138 -1
- package/dist/resources/extensions/gsd/auto-worktree.js +13 -7
- package/dist/resources/extensions/gsd/auto.js +24 -2
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +147 -75
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +13 -0
- package/dist/resources/extensions/gsd/bootstrap/query-tools.js +85 -0
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +3 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +32 -1
- package/dist/resources/extensions/gsd/bootstrap/sanitize-complete-milestone.js +54 -0
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +30 -2
- package/dist/resources/extensions/gsd/commands-handlers.js +9 -4
- package/dist/resources/extensions/gsd/constants.js +42 -0
- package/dist/resources/extensions/gsd/db-writer.js +72 -4
- package/dist/resources/extensions/gsd/forensics.js +20 -4
- package/dist/resources/extensions/gsd/gsd-db.js +64 -17
- package/dist/resources/extensions/gsd/guided-flow.js +19 -0
- package/dist/resources/extensions/gsd/metrics.js +27 -1
- package/dist/resources/extensions/gsd/native-git-bridge.js +5 -3
- package/dist/resources/extensions/gsd/post-execution-checks.js +407 -0
- package/dist/resources/extensions/gsd/pre-execution-checks.js +464 -0
- package/dist/resources/extensions/gsd/preferences-types.js +6 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +33 -0
- package/dist/resources/extensions/gsd/preferences.js +11 -2
- package/dist/resources/extensions/gsd/prompt-loader.js +7 -0
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +2 -0
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +2 -0
- package/dist/resources/extensions/gsd/prompts/doctor-heal.md +1 -0
- package/dist/resources/extensions/gsd/prompts/forensics.md +2 -0
- package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +2 -0
- package/dist/resources/extensions/gsd/prompts/system.md +4 -7
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +2 -0
- package/dist/resources/extensions/gsd/roadmap-mutations.js +1 -1
- package/dist/resources/extensions/gsd/roadmap-slices.js +9 -5
- package/dist/resources/extensions/gsd/safety/content-validator.js +73 -0
- package/dist/resources/extensions/gsd/safety/destructive-guard.js +34 -0
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +109 -0
- package/dist/resources/extensions/gsd/safety/evidence-cross-ref.js +83 -0
- package/dist/resources/extensions/gsd/safety/file-change-validator.js +71 -0
- package/dist/resources/extensions/gsd/safety/git-checkpoint.js +91 -0
- package/dist/resources/extensions/gsd/safety/safety-harness.js +64 -0
- package/dist/resources/extensions/gsd/slice-parallel-conflict.js +67 -0
- package/dist/resources/extensions/gsd/slice-parallel-eligibility.js +51 -0
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +378 -0
- package/dist/resources/extensions/gsd/state.js +74 -14
- package/dist/resources/extensions/gsd/status-guards.js +11 -0
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +17 -12
- package/dist/resources/extensions/gsd/tools/complete-slice.js +40 -26
- package/dist/resources/extensions/gsd/tools/complete-task.js +12 -12
- package/dist/resources/extensions/gsd/tools/plan-milestone.js +33 -25
- package/dist/resources/extensions/gsd/tools/plan-slice.js +5 -8
- package/dist/resources/extensions/gsd/verification-evidence.js +18 -0
- package/dist/resources/extensions/gsd/workflow-projections.js +21 -5
- package/dist/resources/extensions/gsd/worktree-manager.js +82 -29
- package/dist/resources/extensions/gsd/worktree-resolver.js +4 -3
- package/dist/resources/extensions/mcp-client/auth.js +101 -0
- package/dist/resources/extensions/mcp-client/index.js +10 -1
- package/dist/resources/extensions/ollama/index.js +28 -22
- package/dist/resources/extensions/ollama/model-capabilities.js +37 -34
- package/dist/resources/extensions/ollama/ndjson-stream.js +54 -0
- package/dist/resources/extensions/ollama/ollama-chat-provider.js +380 -0
- package/dist/resources/extensions/ollama/ollama-client.js +23 -32
- package/dist/resources/extensions/ollama/ollama-discovery.js +2 -7
- package/dist/resources/extensions/ollama/ollama-tool.js +62 -0
- package/dist/resources/extensions/ollama/thinking-parser.js +104 -0
- package/dist/update-cmd.js +4 -2
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +15 -15
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/required-server-files.json +4 -4
- 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 +2 -2
- 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.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +1 -1
- 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.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +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/onboarding/route.js +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/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.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +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 +2 -2
- 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/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.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +1 -1
- 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.js.nft.json +1 -1
- 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.js.nft.json +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.js.nft.json +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 +15 -15
- package/dist/web/standalone/.next/server/chunks/6897.js +12 -0
- package/dist/web/standalone/.next/server/chunks/7471.js +3 -3
- package/dist/web/standalone/.next/server/middleware-build-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 +2 -2
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- 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-0c485498795110d6.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/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/server.js +1 -1
- package/dist/welcome-screen.js +1 -1
- package/package.json +1 -1
- package/packages/pi-agent-core/dist/agent-loop.d.ts +8 -0
- package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +50 -0
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/src/agent-loop.test.ts +221 -5
- package/packages/pi-agent-core/src/agent-loop.ts +53 -0
- package/packages/pi-ai/dist/types.d.ts +16 -1
- 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/src/types.ts +18 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +9 -0
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.js +50 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.test.js +41 -0
- package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +7 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +31 -4
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.test.js +28 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/provider-registration.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/extensions/provider-registration.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/provider-registration.test.js +46 -0
- package/packages/pi-coding-agent/dist/core/extensions/provider-registration.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts +1 -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 +12 -0
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.js +3 -3
- package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.d.ts +23 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.js +80 -56
- package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +9 -0
- package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/auth-storage.test.ts +53 -0
- package/packages/pi-coding-agent/src/core/auth-storage.ts +66 -1
- package/packages/pi-coding-agent/src/core/extensions/loader.test.ts +39 -1
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +34 -4
- package/packages/pi-coding-agent/src/core/extensions/provider-registration.test.ts +81 -0
- package/packages/pi-coding-agent/src/core/extensions/types.ts +2 -0
- package/packages/pi-coding-agent/src/core/model-registry.ts +14 -0
- package/packages/pi-coding-agent/src/core/model-resolver.ts +3 -3
- package/packages/pi-coding-agent/src/core/resource-loader.ts +89 -56
- package/packages/pi-coding-agent/src/core/sdk.ts +10 -0
- package/pkg/package.json +1 -1
- package/src/resources/extensions/cmux/index.ts +18 -12
- package/src/resources/extensions/gsd/auto/detect-stuck.ts +27 -0
- package/src/resources/extensions/gsd/auto/finalize-timeout.ts +46 -0
- package/src/resources/extensions/gsd/auto/loop.ts +5 -0
- package/src/resources/extensions/gsd/auto/phases.ts +194 -33
- package/src/resources/extensions/gsd/auto/session.ts +14 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +16 -7
- package/src/resources/extensions/gsd/auto-model-selection.ts +36 -0
- package/src/resources/extensions/gsd/auto-post-unit.ts +263 -12
- package/src/resources/extensions/gsd/auto-prompts.ts +21 -0
- package/src/resources/extensions/gsd/auto-recovery.ts +9 -8
- package/src/resources/extensions/gsd/auto-start.ts +11 -20
- package/src/resources/extensions/gsd/auto-timers.ts +2 -1
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +19 -0
- package/src/resources/extensions/gsd/auto-verification.ts +190 -2
- package/src/resources/extensions/gsd/auto-worktree.ts +14 -6
- package/src/resources/extensions/gsd/auto.ts +26 -1
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +160 -88
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +15 -0
- package/src/resources/extensions/gsd/bootstrap/query-tools.ts +98 -0
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +4 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +36 -1
- package/src/resources/extensions/gsd/bootstrap/sanitize-complete-milestone.ts +57 -0
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +31 -2
- package/src/resources/extensions/gsd/commands-handlers.ts +10 -4
- package/src/resources/extensions/gsd/constants.ts +44 -0
- package/src/resources/extensions/gsd/db-writer.ts +78 -4
- package/src/resources/extensions/gsd/forensics.ts +21 -5
- package/src/resources/extensions/gsd/gsd-db.ts +64 -17
- package/src/resources/extensions/gsd/guided-flow.ts +22 -0
- package/src/resources/extensions/gsd/metrics.ts +28 -1
- package/src/resources/extensions/gsd/native-git-bridge.ts +5 -3
- package/src/resources/extensions/gsd/post-execution-checks.ts +539 -0
- package/src/resources/extensions/gsd/pre-execution-checks.ts +573 -0
- package/src/resources/extensions/gsd/preferences-types.ts +44 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +33 -0
- package/src/resources/extensions/gsd/preferences.ts +13 -2
- package/src/resources/extensions/gsd/prompt-loader.ts +8 -0
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +2 -0
- package/src/resources/extensions/gsd/prompts/complete-slice.md +2 -0
- package/src/resources/extensions/gsd/prompts/doctor-heal.md +1 -0
- package/src/resources/extensions/gsd/prompts/forensics.md +2 -0
- package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +2 -0
- package/src/resources/extensions/gsd/prompts/system.md +4 -7
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +2 -0
- package/src/resources/extensions/gsd/roadmap-mutations.ts +1 -1
- package/src/resources/extensions/gsd/roadmap-slices.ts +10 -5
- package/src/resources/extensions/gsd/safety/content-validator.ts +98 -0
- package/src/resources/extensions/gsd/safety/destructive-guard.ts +49 -0
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +151 -0
- package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +120 -0
- package/src/resources/extensions/gsd/safety/file-change-validator.ts +108 -0
- package/src/resources/extensions/gsd/safety/git-checkpoint.ts +106 -0
- package/src/resources/extensions/gsd/safety/safety-harness.ts +105 -0
- package/src/resources/extensions/gsd/slice-parallel-conflict.ts +86 -0
- package/src/resources/extensions/gsd/slice-parallel-eligibility.ts +73 -0
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +477 -0
- package/src/resources/extensions/gsd/state.ts +67 -12
- package/src/resources/extensions/gsd/status-guards.ts +13 -0
- package/src/resources/extensions/gsd/tests/artifact-corruption-2630.test.ts +288 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +34 -13
- package/src/resources/extensions/gsd/tests/auto-start-time-persistence.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/cmux.test.ts +58 -0
- package/src/resources/extensions/gsd/tests/cold-resume-db-reopen.test.ts +51 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +140 -0
- package/src/resources/extensions/gsd/tests/complete-slice-string-coercion.test.ts +211 -0
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/dashboard-model-label-ordering.test.ts +107 -0
- package/src/resources/extensions/gsd/tests/db-access-guardrails.test.ts +109 -0
- package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +13 -9
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +134 -0
- package/src/resources/extensions/gsd/tests/deferred-slice-dispatch.test.ts +203 -0
- package/src/resources/extensions/gsd/tests/discuss-tool-scoping.test.ts +130 -0
- package/src/resources/extensions/gsd/tests/doctor-fix-flag.test.ts +92 -0
- package/src/resources/extensions/gsd/tests/enhanced-verification-integration.test.ts +526 -0
- package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +116 -0
- package/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/forensics-stuck-loops.test.ts +103 -0
- package/src/resources/extensions/gsd/tests/git-checkpoint.test.ts +94 -0
- package/src/resources/extensions/gsd/tests/insert-slice-no-wipe.test.ts +88 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +27 -7
- package/src/resources/extensions/gsd/tests/integration/idle-recovery.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/metrics.test.ts +116 -1
- package/src/resources/extensions/gsd/tests/milestone-status-tool.test.ts +201 -0
- package/src/resources/extensions/gsd/tests/plan-milestone-title.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +82 -18
- package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +312 -0
- package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +813 -0
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +999 -0
- package/src/resources/extensions/gsd/tests/pre-execution-fail-closed.test.ts +266 -0
- package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +457 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +10 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +69 -0
- package/src/resources/extensions/gsd/tests/shared-wal.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/slice-context-injection.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/slice-parallel-conflict.test.ts +92 -0
- package/src/resources/extensions/gsd/tests/slice-parallel-eligibility.test.ts +95 -0
- package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +83 -0
- package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +103 -0
- package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +349 -0
- package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +35 -2
- package/src/resources/extensions/gsd/tests/worktree-health-monorepo.test.ts +73 -0
- package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +148 -0
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +34 -20
- package/src/resources/extensions/gsd/tools/complete-slice.ts +41 -26
- package/src/resources/extensions/gsd/tools/complete-task.ts +12 -12
- package/src/resources/extensions/gsd/tools/plan-milestone.ts +55 -30
- package/src/resources/extensions/gsd/tools/plan-slice.ts +13 -8
- package/src/resources/extensions/gsd/types.ts +44 -22
- package/src/resources/extensions/gsd/verification-evidence.ts +68 -0
- package/src/resources/extensions/gsd/workflow-logger.ts +2 -1
- package/src/resources/extensions/gsd/workflow-projections.ts +23 -5
- package/src/resources/extensions/gsd/worktree-manager.ts +76 -28
- package/src/resources/extensions/gsd/worktree-resolver.ts +4 -3
- package/src/resources/extensions/mcp-client/auth.ts +149 -0
- package/src/resources/extensions/mcp-client/index.ts +16 -1
- package/src/resources/extensions/ollama/index.ts +26 -25
- package/src/resources/extensions/ollama/model-capabilities.ts +41 -34
- package/src/resources/extensions/ollama/ndjson-stream.ts +63 -0
- package/src/resources/extensions/ollama/ollama-auth-mode.test.ts +20 -0
- package/src/resources/extensions/ollama/ollama-chat-provider.ts +459 -0
- package/src/resources/extensions/ollama/ollama-client.ts +30 -30
- package/src/resources/extensions/ollama/ollama-discovery.ts +5 -8
- package/src/resources/extensions/ollama/ollama-tool.ts +69 -0
- package/src/resources/extensions/ollama/tests/ollama-chat-provider-stream.test.ts +82 -0
- package/src/resources/extensions/ollama/tests/ollama-discovery.test.ts +0 -27
- package/src/resources/extensions/ollama/thinking-parser.ts +116 -0
- package/src/resources/extensions/ollama/types.ts +23 -0
- package/dist/web/standalone/.next/server/chunks/2229.js +0 -12
- package/dist/web/standalone/.next/static/chunks/app/page-62be3b5fa91e4c8f.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/{5FLUBNdqolRyyehCyChPd → SoxM61WC_ia7R2gk4VMpJ}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{5FLUBNdqolRyyehCyChPd → SoxM61WC_ia7R2gk4VMpJ}/_ssgManifest.js +0 -0
|
@@ -33,6 +33,7 @@ import { debugLog } from "./debug-logger.js";
|
|
|
33
33
|
import { findMilestoneIds, nextMilestoneId, reserveMilestoneId, getReservedMilestoneIds, clearReservedMilestoneIds } from "./milestone-ids.js";
|
|
34
34
|
import { parkMilestone, discardMilestone } from "./milestone-actions.js";
|
|
35
35
|
import { selectAndApplyModel } from "./auto-model-selection.js";
|
|
36
|
+
import { DISCUSS_TOOLS_ALLOWLIST } from "./constants.js";
|
|
36
37
|
// ─── Re-exports (preserve public API for existing importers) ────────────────
|
|
37
38
|
export { MILESTONE_ID_RE, generateMilestoneSuffix, nextMilestoneId, extractMilestoneSeq, parseMilestoneId, milestoneIdSort, maxMilestoneNum, findMilestoneIds, reserveMilestoneId, claimReservedId, getReservedMilestoneIds, clearReservedMilestoneIds, } from "./milestone-ids.js";
|
|
38
39
|
export { showQueue, handleQueueReorder, showQueueAdd, buildExistingMilestonesContext, } from "./guided-flow-queue.js";
|
|
@@ -242,6 +243,24 @@ async function dispatchWorkflow(pi, note, customType = "gsd-run", ctx, unitType)
|
|
|
242
243
|
});
|
|
243
244
|
}
|
|
244
245
|
}
|
|
246
|
+
// Scope tools for discuss flows (#2949).
|
|
247
|
+
// Providers with grammar-based constrained decoding (xAI/Grok) return
|
|
248
|
+
// "Grammar is too complex" when the combined tool schema is too large.
|
|
249
|
+
// Discuss flows only need a small subset of GSD tools — strip the heavy
|
|
250
|
+
// planning/execution/completion tools to keep the grammar within limits.
|
|
251
|
+
if (unitType?.startsWith("discuss-")) {
|
|
252
|
+
const currentTools = pi.getActiveTools();
|
|
253
|
+
// Keep all non-GSD tools (builtins, other extensions) and only the
|
|
254
|
+
// GSD tools on the discuss allowlist.
|
|
255
|
+
const scopedTools = currentTools.filter((t) => !t.startsWith("gsd_") || DISCUSS_TOOLS_ALLOWLIST.includes(t));
|
|
256
|
+
pi.setActiveTools(scopedTools);
|
|
257
|
+
debugLog("discuss-tool-scoping", {
|
|
258
|
+
unitType,
|
|
259
|
+
before: currentTools.length,
|
|
260
|
+
after: scopedTools.length,
|
|
261
|
+
removed: currentTools.length - scopedTools.length,
|
|
262
|
+
});
|
|
263
|
+
}
|
|
245
264
|
const workflowPath = process.env.GSD_WORKFLOW_PATH ?? join(process.env.HOME ?? "~", ".gsd", "agent", "GSD-WORKFLOW.md");
|
|
246
265
|
const workflow = readFileSync(workflowPath, "utf-8");
|
|
247
266
|
pi.sendMessage({
|
|
@@ -412,7 +412,33 @@ export function loadLedgerFromDisk(base) {
|
|
|
412
412
|
return loadJsonFileOrNull(metricsPath(base), isMetricsLedger);
|
|
413
413
|
}
|
|
414
414
|
function loadLedger(base) {
|
|
415
|
-
|
|
415
|
+
const raw = loadJsonFile(metricsPath(base), isMetricsLedger, defaultLedger);
|
|
416
|
+
const before = raw.units.length;
|
|
417
|
+
raw.units = deduplicateUnits(raw.units);
|
|
418
|
+
if (raw.units.length < before) {
|
|
419
|
+
// Persist the cleaned ledger so duplicates don't re-accumulate
|
|
420
|
+
saveLedger(base, raw);
|
|
421
|
+
}
|
|
422
|
+
return raw;
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Collapse duplicate entries with the same (type, id, startedAt) triple.
|
|
426
|
+
* Keeps the entry with the highest finishedAt (the most complete snapshot).
|
|
427
|
+
*
|
|
428
|
+
* This is a defensive measure against idle-watchdog race conditions that can
|
|
429
|
+
* produce duplicate entries on disk despite the in-memory idempotency guard
|
|
430
|
+
* in snapshotUnitMetrics(). See #1943.
|
|
431
|
+
*/
|
|
432
|
+
function deduplicateUnits(units) {
|
|
433
|
+
const map = new Map();
|
|
434
|
+
for (const u of units) {
|
|
435
|
+
const key = `${u.type}\0${u.id}\0${u.startedAt}`;
|
|
436
|
+
const existing = map.get(key);
|
|
437
|
+
if (!existing || u.finishedAt > existing.finishedAt) {
|
|
438
|
+
map.set(key, u);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
return Array.from(map.values());
|
|
416
442
|
}
|
|
417
443
|
function saveLedger(base, data) {
|
|
418
444
|
saveJsonFile(metricsPath(base), data);
|
|
@@ -569,10 +569,12 @@ export function nativeAddAllWithExclusions(basePath, exclusions) {
|
|
|
569
569
|
return;
|
|
570
570
|
}
|
|
571
571
|
// When .gsd is a symlink, git rejects `:!.gsd/...` pathspecs with
|
|
572
|
-
// "beyond a symbolic link". Fall back to
|
|
573
|
-
//
|
|
572
|
+
// "beyond a symbolic link". Fall back to `git add -u` which only
|
|
573
|
+
// stages changes to already-tracked files — O(tracked) not O(filesystem).
|
|
574
|
+
// Using `git add -A` here would traverse the entire working tree,
|
|
575
|
+
// hanging indefinitely on repos with large untracked data dirs. (#1977)
|
|
574
576
|
if (stderr.includes("beyond a symbolic link")) {
|
|
575
|
-
|
|
577
|
+
gitFileExec(basePath, ["add", "-u"]);
|
|
576
578
|
return;
|
|
577
579
|
}
|
|
578
580
|
throw new GSDError(GSD_GIT_ERROR, `git add -A with exclusions failed in ${basePath}: ${getErrorMessage(err)}`);
|
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Post-Execution Checks — Validate task output after execution completes.
|
|
3
|
+
*
|
|
4
|
+
* Runs these checks against a completed task's output:
|
|
5
|
+
* 1. Import resolution — verify relative imports in key_files resolve to existing files
|
|
6
|
+
* 2. Cross-task signatures — detect hallucination cascades (function exists in task output
|
|
7
|
+
* but doesn't match prior tasks' actual code)
|
|
8
|
+
* 3. Pattern consistency — warn on async style drift, naming convention inconsistencies
|
|
9
|
+
*
|
|
10
|
+
* Design principles:
|
|
11
|
+
* - Pure functions taking (taskRow, priorTasks, basePath) for testability
|
|
12
|
+
* - Import checks are blocking failures; pattern checks are warnings
|
|
13
|
+
* - No AST parsers — uses regex heuristics
|
|
14
|
+
*/
|
|
15
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
16
|
+
import { resolve, dirname, extname } from "node:path";
|
|
17
|
+
// ─── Import Resolution Check ─────────────────────────────────────────────────
|
|
18
|
+
/**
|
|
19
|
+
* Extract relative import paths from TypeScript/JavaScript source code.
|
|
20
|
+
* Returns array of { importPath, lineNum } for relative imports.
|
|
21
|
+
*/
|
|
22
|
+
export function extractRelativeImports(source) {
|
|
23
|
+
const imports = [];
|
|
24
|
+
const lines = source.split("\n");
|
|
25
|
+
// Match:
|
|
26
|
+
// import ... from './path'
|
|
27
|
+
// import ... from "../path"
|
|
28
|
+
// import './path'
|
|
29
|
+
// require('./path')
|
|
30
|
+
// require("../path")
|
|
31
|
+
const importPattern = /(?:import\s+(?:.*?\s+from\s+)?|require\s*\(\s*)(['"])(\.\.?\/[^'"]+)\1/g;
|
|
32
|
+
// Track if we're inside a block comment
|
|
33
|
+
let inBlockComment = false;
|
|
34
|
+
for (let i = 0; i < lines.length; i++) {
|
|
35
|
+
const line = lines[i];
|
|
36
|
+
// Handle block comment boundaries
|
|
37
|
+
if (inBlockComment) {
|
|
38
|
+
if (line.includes("*/")) {
|
|
39
|
+
inBlockComment = false;
|
|
40
|
+
}
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
// Check for block comment start (that doesn't end on same line)
|
|
44
|
+
const blockStart = line.indexOf("/*");
|
|
45
|
+
const blockEnd = line.indexOf("*/");
|
|
46
|
+
if (blockStart !== -1 && (blockEnd === -1 || blockEnd < blockStart)) {
|
|
47
|
+
inBlockComment = true;
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
// Skip single-line comments (// at start or after whitespace)
|
|
51
|
+
const trimmed = line.trimStart();
|
|
52
|
+
if (trimmed.startsWith("//")) {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
// Skip JSDoc-style lines (e.g., " * import ...")
|
|
56
|
+
if (trimmed.startsWith("*")) {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
let match;
|
|
60
|
+
// Reset lastIndex for each line
|
|
61
|
+
importPattern.lastIndex = 0;
|
|
62
|
+
while ((match = importPattern.exec(line)) !== null) {
|
|
63
|
+
// Check if this match is after a // comment marker on the same line
|
|
64
|
+
const beforeMatch = line.substring(0, match.index);
|
|
65
|
+
if (beforeMatch.includes("//")) {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
imports.push({
|
|
69
|
+
importPath: match[2],
|
|
70
|
+
lineNum: i + 1,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return imports;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Check if a relative import resolves to an existing file.
|
|
78
|
+
* Handles .ts, .tsx, .js, .jsx extensions and index files.
|
|
79
|
+
* Also handles TypeScript ESM convention where imports use .js but resolve to .ts.
|
|
80
|
+
*/
|
|
81
|
+
export function resolveImportPath(importPath, sourceFile, basePath) {
|
|
82
|
+
const sourceDir = dirname(resolve(basePath, sourceFile));
|
|
83
|
+
const extensions = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
|
|
84
|
+
// Handle TypeScript ESM convention: .js imports resolve to .ts files
|
|
85
|
+
// e.g., import './types.js' -> ./types.ts
|
|
86
|
+
let normalizedPath = importPath;
|
|
87
|
+
if (importPath.endsWith(".js")) {
|
|
88
|
+
normalizedPath = importPath.slice(0, -3);
|
|
89
|
+
}
|
|
90
|
+
else if (importPath.endsWith(".jsx")) {
|
|
91
|
+
normalizedPath = importPath.slice(0, -4);
|
|
92
|
+
}
|
|
93
|
+
else if (importPath.endsWith(".mjs")) {
|
|
94
|
+
normalizedPath = importPath.slice(0, -4);
|
|
95
|
+
}
|
|
96
|
+
else if (importPath.endsWith(".cjs")) {
|
|
97
|
+
normalizedPath = importPath.slice(0, -4);
|
|
98
|
+
}
|
|
99
|
+
// Try the normalized path with common extensions first
|
|
100
|
+
for (const ext of extensions) {
|
|
101
|
+
const fullPath = resolve(sourceDir, normalizedPath + ext);
|
|
102
|
+
if (existsSync(fullPath)) {
|
|
103
|
+
return { exists: true, resolvedPath: fullPath };
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// Try as a directory with index file
|
|
107
|
+
for (const ext of extensions) {
|
|
108
|
+
const indexPath = resolve(sourceDir, normalizedPath, `index${ext}`);
|
|
109
|
+
if (existsSync(indexPath)) {
|
|
110
|
+
return { exists: true, resolvedPath: indexPath };
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// Check if path already has extension (for .json, etc.)
|
|
114
|
+
const hasExt = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".json"].some((ext) => importPath.endsWith(ext));
|
|
115
|
+
if (hasExt) {
|
|
116
|
+
const fullPath = resolve(sourceDir, importPath);
|
|
117
|
+
if (existsSync(fullPath)) {
|
|
118
|
+
return { exists: true, resolvedPath: fullPath };
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return { exists: false, resolvedPath: null };
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Check that all relative imports in the task's key_files resolve to existing files.
|
|
125
|
+
* Reads modified files from task.key_files, extracts import statements via regex,
|
|
126
|
+
* verifies relative imports resolve to existing files.
|
|
127
|
+
*/
|
|
128
|
+
export function checkImportResolution(taskRow, _priorTasks, basePath) {
|
|
129
|
+
const results = [];
|
|
130
|
+
// Get files from key_files
|
|
131
|
+
const filesToCheck = taskRow.key_files.filter((f) => {
|
|
132
|
+
const ext = extname(f);
|
|
133
|
+
return [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"].includes(ext);
|
|
134
|
+
});
|
|
135
|
+
for (const file of filesToCheck) {
|
|
136
|
+
const absolutePath = resolve(basePath, file);
|
|
137
|
+
// Skip if file doesn't exist (might have been deleted or renamed)
|
|
138
|
+
if (!existsSync(absolutePath)) {
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
let source;
|
|
142
|
+
try {
|
|
143
|
+
source = readFileSync(absolutePath, "utf-8");
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
const imports = extractRelativeImports(source);
|
|
149
|
+
for (const { importPath, lineNum } of imports) {
|
|
150
|
+
const resolution = resolveImportPath(importPath, file, basePath);
|
|
151
|
+
if (!resolution.exists) {
|
|
152
|
+
results.push({
|
|
153
|
+
category: "import",
|
|
154
|
+
target: `${file}:${lineNum}`,
|
|
155
|
+
passed: false,
|
|
156
|
+
message: `Import '${importPath}' in ${file}:${lineNum} does not resolve to an existing file`,
|
|
157
|
+
blocking: true,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return results;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Extract function signatures from TypeScript/JavaScript source code.
|
|
166
|
+
*/
|
|
167
|
+
function extractFunctionSignatures(source, fileName) {
|
|
168
|
+
const signatures = [];
|
|
169
|
+
const lines = source.split("\n");
|
|
170
|
+
// Match function declarations and exports
|
|
171
|
+
// Patterns:
|
|
172
|
+
// function name(params): ReturnType
|
|
173
|
+
// export function name(params): ReturnType
|
|
174
|
+
// export async function name(params): Promise<ReturnType>
|
|
175
|
+
// const name = (params): ReturnType =>
|
|
176
|
+
// export const name = (params): ReturnType =>
|
|
177
|
+
const funcPattern = /(?:export\s+)?(?:async\s+)?(?:function\s+|const\s+)(\w+)(?:\s*=\s*)?\s*\(([^)]*)\)(?:\s*:\s*([^{=>\n]+))?/g;
|
|
178
|
+
for (let i = 0; i < lines.length; i++) {
|
|
179
|
+
const line = lines[i];
|
|
180
|
+
funcPattern.lastIndex = 0;
|
|
181
|
+
let match;
|
|
182
|
+
while ((match = funcPattern.exec(line)) !== null) {
|
|
183
|
+
const [, name, params, returnType] = match;
|
|
184
|
+
signatures.push({
|
|
185
|
+
name,
|
|
186
|
+
params: normalizeParams(params),
|
|
187
|
+
returnType: normalizeType(returnType || "void"),
|
|
188
|
+
file: fileName,
|
|
189
|
+
lineNum: i + 1,
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return signatures;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Normalize parameter list for comparison.
|
|
197
|
+
*/
|
|
198
|
+
function normalizeParams(params) {
|
|
199
|
+
return params
|
|
200
|
+
.replace(/\/\*[\s\S]*?\*\//g, "") // Remove block comments
|
|
201
|
+
.replace(/\/\/[^\n]*/g, "") // Remove line comments
|
|
202
|
+
.replace(/\s*=\s*[^,)]+/g, "") // Remove default values
|
|
203
|
+
.replace(/\s+/g, " ") // Normalize whitespace
|
|
204
|
+
.trim();
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Normalize type for comparison.
|
|
208
|
+
*/
|
|
209
|
+
function normalizeType(type) {
|
|
210
|
+
return type.replace(/\s+/g, " ").trim();
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Compare function signatures in current task's output against prior tasks' key_files
|
|
214
|
+
* to catch hallucination cascades — when a task references functions that don't exist
|
|
215
|
+
* or have different signatures than what was actually created.
|
|
216
|
+
*/
|
|
217
|
+
export function checkCrossTaskSignatures(taskRow, priorTasks, basePath) {
|
|
218
|
+
const results = [];
|
|
219
|
+
// Build map of functions from prior tasks' key_files
|
|
220
|
+
const priorSignatures = new Map();
|
|
221
|
+
for (const task of priorTasks) {
|
|
222
|
+
for (const file of task.key_files) {
|
|
223
|
+
const ext = extname(file);
|
|
224
|
+
if (![".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"].includes(ext))
|
|
225
|
+
continue;
|
|
226
|
+
const absolutePath = resolve(basePath, file);
|
|
227
|
+
if (!existsSync(absolutePath))
|
|
228
|
+
continue;
|
|
229
|
+
try {
|
|
230
|
+
const source = readFileSync(absolutePath, "utf-8");
|
|
231
|
+
const sigs = extractFunctionSignatures(source, file);
|
|
232
|
+
for (const sig of sigs) {
|
|
233
|
+
const existing = priorSignatures.get(sig.name) || [];
|
|
234
|
+
existing.push(sig);
|
|
235
|
+
priorSignatures.set(sig.name, existing);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
catch {
|
|
239
|
+
// Skip unreadable files
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
// Extract function calls/references from current task's key_files
|
|
244
|
+
// and check they match prior definitions
|
|
245
|
+
for (const file of taskRow.key_files) {
|
|
246
|
+
const ext = extname(file);
|
|
247
|
+
if (![".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"].includes(ext))
|
|
248
|
+
continue;
|
|
249
|
+
const absolutePath = resolve(basePath, file);
|
|
250
|
+
if (!existsSync(absolutePath))
|
|
251
|
+
continue;
|
|
252
|
+
try {
|
|
253
|
+
const source = readFileSync(absolutePath, "utf-8");
|
|
254
|
+
const currentSigs = extractFunctionSignatures(source, file);
|
|
255
|
+
// Check each function in current task against prior definitions
|
|
256
|
+
for (const currentSig of currentSigs) {
|
|
257
|
+
const priorDefs = priorSignatures.get(currentSig.name);
|
|
258
|
+
// If this function was defined in a prior task, check for signature drift
|
|
259
|
+
if (priorDefs && priorDefs.length > 0) {
|
|
260
|
+
const priorDef = priorDefs[0]; // Use first definition
|
|
261
|
+
// Check parameter mismatch
|
|
262
|
+
if (currentSig.params !== priorDef.params) {
|
|
263
|
+
results.push({
|
|
264
|
+
category: "signature",
|
|
265
|
+
target: currentSig.name,
|
|
266
|
+
passed: false,
|
|
267
|
+
message: `Function '${currentSig.name}' in ${file}:${currentSig.lineNum} has parameters '${currentSig.params}' but prior definition in ${priorDef.file}:${priorDef.lineNum} has '${priorDef.params}'`,
|
|
268
|
+
blocking: false, // Warn only — may be intentional override
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
// Check return type mismatch
|
|
272
|
+
if (currentSig.returnType !== priorDef.returnType) {
|
|
273
|
+
results.push({
|
|
274
|
+
category: "signature",
|
|
275
|
+
target: currentSig.name,
|
|
276
|
+
passed: false,
|
|
277
|
+
message: `Function '${currentSig.name}' in ${file}:${currentSig.lineNum} returns '${currentSig.returnType}' but prior definition in ${priorDef.file}:${priorDef.lineNum} returns '${priorDef.returnType}'`,
|
|
278
|
+
blocking: false, // Warn only — may be intentional override
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
catch {
|
|
285
|
+
// Skip unreadable files
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
return results;
|
|
289
|
+
}
|
|
290
|
+
// ─── Pattern Consistency Check ───────────────────────────────────────────────
|
|
291
|
+
/**
|
|
292
|
+
* Detect async style drift (mixing async/await with .then()) and
|
|
293
|
+
* naming convention inconsistencies within a task's key_files.
|
|
294
|
+
* Warn only — these are style issues, not correctness issues.
|
|
295
|
+
*/
|
|
296
|
+
export function checkPatternConsistency(taskRow, _priorTasks, basePath) {
|
|
297
|
+
const results = [];
|
|
298
|
+
for (const file of taskRow.key_files) {
|
|
299
|
+
const ext = extname(file);
|
|
300
|
+
if (![".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"].includes(ext))
|
|
301
|
+
continue;
|
|
302
|
+
const absolutePath = resolve(basePath, file);
|
|
303
|
+
if (!existsSync(absolutePath))
|
|
304
|
+
continue;
|
|
305
|
+
try {
|
|
306
|
+
const source = readFileSync(absolutePath, "utf-8");
|
|
307
|
+
// Check for async style drift
|
|
308
|
+
const asyncStyleResult = checkAsyncStyleDrift(source, file);
|
|
309
|
+
if (asyncStyleResult) {
|
|
310
|
+
results.push(asyncStyleResult);
|
|
311
|
+
}
|
|
312
|
+
// Check for naming convention inconsistencies
|
|
313
|
+
const namingResults = checkNamingConsistency(source, file);
|
|
314
|
+
results.push(...namingResults);
|
|
315
|
+
}
|
|
316
|
+
catch {
|
|
317
|
+
// Skip unreadable files
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
return results;
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Detect async style drift within a single file.
|
|
324
|
+
* Returns a warning if both async/await AND .then() promise chaining are used.
|
|
325
|
+
*/
|
|
326
|
+
function checkAsyncStyleDrift(source, fileName) {
|
|
327
|
+
// Check for async/await usage
|
|
328
|
+
const hasAsyncAwait = /\basync\b[\s\S]*?\bawait\b/.test(source);
|
|
329
|
+
// Check for .then() promise chaining (excluding comments)
|
|
330
|
+
// Filter out common false positives like Array.prototype.then doesn't exist
|
|
331
|
+
const hasThenChaining = /\.\s*then\s*\(/.test(source);
|
|
332
|
+
// If both patterns are present, flag as style drift
|
|
333
|
+
if (hasAsyncAwait && hasThenChaining) {
|
|
334
|
+
return {
|
|
335
|
+
category: "pattern",
|
|
336
|
+
target: fileName,
|
|
337
|
+
passed: true, // Warning only
|
|
338
|
+
message: `File ${fileName} mixes async/await with .then() promise chaining — consider using consistent async style`,
|
|
339
|
+
blocking: false,
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
return null;
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Check for naming convention inconsistencies within a file.
|
|
346
|
+
* Detects mixing of camelCase and snake_case for similar identifier types.
|
|
347
|
+
*/
|
|
348
|
+
function checkNamingConsistency(source, fileName) {
|
|
349
|
+
const results = [];
|
|
350
|
+
// Extract function names
|
|
351
|
+
const functionNames = [];
|
|
352
|
+
const funcPattern = /(?:function\s+|const\s+|let\s+|var\s+)(\w+)(?:\s*=\s*(?:async\s*)?\(|\s*\()/g;
|
|
353
|
+
let match;
|
|
354
|
+
while ((match = funcPattern.exec(source)) !== null) {
|
|
355
|
+
functionNames.push(match[1]);
|
|
356
|
+
}
|
|
357
|
+
// Check for mixed naming conventions in functions
|
|
358
|
+
const camelCaseFuncs = functionNames.filter((n) => /^[a-z][a-zA-Z0-9]*$/.test(n) && /[A-Z]/.test(n));
|
|
359
|
+
const snakeCaseFuncs = functionNames.filter((n) => /^[a-z][a-z0-9]*(_[a-z0-9]+)+$/.test(n));
|
|
360
|
+
if (camelCaseFuncs.length > 0 && snakeCaseFuncs.length > 0) {
|
|
361
|
+
results.push({
|
|
362
|
+
category: "pattern",
|
|
363
|
+
target: fileName,
|
|
364
|
+
passed: true, // Warning only
|
|
365
|
+
message: `File ${fileName} mixes camelCase (${camelCaseFuncs.slice(0, 2).join(", ")}) and snake_case (${snakeCaseFuncs.slice(0, 2).join(", ")}) function names`,
|
|
366
|
+
blocking: false,
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
return results;
|
|
370
|
+
}
|
|
371
|
+
// ─── Main Entry Point ────────────────────────────────────────────────────────
|
|
372
|
+
/**
|
|
373
|
+
* Run all post-execution checks against a completed task.
|
|
374
|
+
*
|
|
375
|
+
* @param taskRow - The completed task row
|
|
376
|
+
* @param priorTasks - Array of TaskRow from prior completed tasks in the slice
|
|
377
|
+
* @param basePath - Base path for resolving file references
|
|
378
|
+
* @returns PostExecutionResult with status, checks, and duration
|
|
379
|
+
*/
|
|
380
|
+
export function runPostExecutionChecks(taskRow, priorTasks, basePath) {
|
|
381
|
+
const startTime = Date.now();
|
|
382
|
+
const allChecks = [];
|
|
383
|
+
// Run all checks
|
|
384
|
+
const importChecks = checkImportResolution(taskRow, priorTasks, basePath);
|
|
385
|
+
const signatureChecks = checkCrossTaskSignatures(taskRow, priorTasks, basePath);
|
|
386
|
+
const patternChecks = checkPatternConsistency(taskRow, priorTasks, basePath);
|
|
387
|
+
allChecks.push(...importChecks, ...signatureChecks, ...patternChecks);
|
|
388
|
+
const durationMs = Date.now() - startTime;
|
|
389
|
+
// Determine overall status
|
|
390
|
+
const hasBlockingFailure = allChecks.some((c) => !c.passed && c.blocking);
|
|
391
|
+
const hasNonBlockingIssue = allChecks.some((c) => (!c.passed && !c.blocking) || (c.passed && c.category === "pattern"));
|
|
392
|
+
let status;
|
|
393
|
+
if (hasBlockingFailure) {
|
|
394
|
+
status = "fail";
|
|
395
|
+
}
|
|
396
|
+
else if (hasNonBlockingIssue) {
|
|
397
|
+
status = "warn";
|
|
398
|
+
}
|
|
399
|
+
else {
|
|
400
|
+
status = "pass";
|
|
401
|
+
}
|
|
402
|
+
return {
|
|
403
|
+
status,
|
|
404
|
+
checks: allChecks,
|
|
405
|
+
durationMs,
|
|
406
|
+
};
|
|
407
|
+
}
|