@opengsd/gsd-pi 1.2.0-dev.fb12b103 → 1.2.0-dev.fbdca60b
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli-model-override.d.ts +15 -0
- package/dist/cli-model-override.js +21 -0
- package/dist/cli.js +1 -18
- package/dist/headless-events.js +7 -5
- package/dist/loader.js +6 -4
- package/dist/mcp-server.js +2 -1
- package/dist/register-agent-bundles.d.ts +11 -2
- package/dist/register-agent-bundles.js +18 -4
- package/dist/resource-loader.d.ts +10 -5
- package/dist/resource-loader.js +121 -6
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/GSD-WORKFLOW.md +5 -4
- package/dist/resources/extensions/ask-user-questions.js +3 -2
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +447 -215
- package/dist/resources/extensions/claude-code-cli/turn-assembler.js +33 -1
- package/dist/resources/extensions/gsd/auto/closeout.js +215 -0
- package/dist/resources/extensions/gsd/auto/custom-verify-retry-store.js +17 -2
- package/dist/resources/extensions/gsd/auto/detect-stuck.js +33 -13
- package/dist/resources/extensions/gsd/auto/dispatch-history.js +120 -0
- package/dist/resources/extensions/gsd/auto/dispatch-key.js +37 -0
- package/dist/resources/extensions/gsd/auto/dispatch.js +365 -0
- package/dist/resources/extensions/gsd/auto/finalize.js +347 -0
- package/dist/resources/extensions/gsd/auto/loop.js +7 -1
- package/dist/resources/extensions/gsd/auto/milestone-lease-reclaim.js +56 -0
- package/dist/resources/extensions/gsd/auto/orchestrator.js +167 -64
- package/dist/resources/extensions/gsd/auto/phase-helpers.js +146 -0
- package/dist/resources/extensions/gsd/auto/phases.js +17 -2329
- package/dist/resources/extensions/gsd/auto/pre-dispatch.js +534 -0
- package/dist/resources/extensions/gsd/auto/session.js +3 -0
- package/dist/resources/extensions/gsd/auto/unit-phase.js +694 -0
- package/dist/resources/extensions/gsd/auto/workflow-unit-dispatch.js +1 -1
- package/dist/resources/extensions/gsd/auto/worktree-safety-phase.js +125 -0
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +11 -34
- package/dist/resources/extensions/gsd/auto-dispatch.js +39 -58
- package/dist/resources/extensions/gsd/auto-model-selection.js +11 -7
- package/dist/resources/extensions/gsd/auto-post-unit.js +30 -12
- package/dist/resources/extensions/gsd/auto-prompts.js +66 -9
- package/dist/resources/extensions/gsd/auto-start.js +26 -8
- package/dist/resources/extensions/gsd/auto-unit-closeout.js +45 -21
- package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +5 -4
- package/dist/resources/extensions/gsd/auto-verification.js +23 -30
- package/dist/resources/extensions/gsd/auto-worktree.js +15 -2
- package/dist/resources/extensions/gsd/auto.js +52 -2
- package/dist/resources/extensions/gsd/blocked-models.js +28 -0
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +26 -6
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +37 -7
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +2 -2
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +107 -45
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +302 -80
- package/dist/resources/extensions/gsd/closeout-wizard.js +92 -0
- package/dist/resources/extensions/gsd/commands/context.js +16 -2
- package/dist/resources/extensions/gsd/commands-handlers.js +46 -3
- package/dist/resources/extensions/gsd/commands-mcp-status.js +2 -2
- package/dist/resources/extensions/gsd/commands-workflow-templates.js +9 -2
- package/dist/resources/extensions/gsd/consent-question.js +353 -0
- package/dist/resources/extensions/gsd/consent-verdict.js +63 -0
- package/dist/resources/extensions/gsd/crash-recovery.js +8 -3
- package/dist/resources/extensions/gsd/db/engine.js +24 -6
- package/dist/resources/extensions/gsd/db/queries.js +56 -0
- package/dist/resources/extensions/gsd/db-migration-backup.js +51 -8
- package/dist/resources/extensions/gsd/db-transaction.js +27 -23
- package/dist/resources/extensions/gsd/db-writer.js +8 -17
- package/dist/resources/extensions/gsd/dispatch-guard.js +10 -35
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +5 -5
- package/dist/resources/extensions/gsd/doctor-environment.js +256 -125
- package/dist/resources/extensions/gsd/doctor-git-checks.js +2 -18
- package/dist/resources/extensions/gsd/engine-hook-contract.js +70 -0
- package/dist/resources/extensions/gsd/files.js +33 -19
- package/dist/resources/extensions/gsd/gsd-command-home.js +22 -12
- package/dist/resources/extensions/gsd/gsd-db.js +17 -21
- package/dist/resources/extensions/gsd/guidance.js +60 -0
- package/dist/resources/extensions/gsd/guided-flow.js +93 -4
- package/dist/resources/extensions/gsd/health-widget.js +87 -28
- package/dist/resources/extensions/gsd/markdown-renderer.js +10 -0
- package/dist/resources/extensions/gsd/mcp-bridge.js +10 -0
- package/dist/resources/extensions/gsd/memory-relations.js +1 -1
- package/dist/resources/extensions/gsd/milestone-closeout.js +85 -24
- package/dist/resources/extensions/gsd/milestone-planning-persistence.js +2 -2
- package/dist/resources/extensions/gsd/milestone-reopen-events.js +3 -5
- package/dist/resources/extensions/gsd/milestone-settlement.js +2 -2
- package/dist/resources/extensions/gsd/notifications.js +12 -7
- package/dist/resources/extensions/gsd/parsers-legacy.js +16 -4
- package/dist/resources/extensions/gsd/projection-flush.js +7 -0
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +3 -3
- package/dist/resources/extensions/gsd/prompts/execute-task.md +3 -2
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -1
- package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/replan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/research-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
- package/dist/resources/extensions/gsd/prompts/run-uat.md +8 -4
- package/dist/resources/extensions/gsd/prompts/triage-captures.md +1 -1
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/workflow-start.md +2 -1
- package/dist/resources/extensions/gsd/reactive-graph.js +8 -1
- package/dist/resources/extensions/gsd/roadmap-slices.js +25 -3
- package/dist/resources/extensions/gsd/session-lock.js +1 -1
- package/dist/resources/extensions/gsd/skill-activation.js +3 -6
- package/dist/resources/extensions/gsd/state.js +11 -2
- package/dist/resources/extensions/gsd/tool-contract.js +14 -3
- package/dist/resources/extensions/gsd/tool-presentation-plan.js +4 -4
- package/dist/resources/extensions/gsd/tool-surface-readiness.js +83 -31
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +3 -2
- package/dist/resources/extensions/gsd/tools/complete-slice.js +22 -12
- package/dist/resources/extensions/gsd/tools/complete-task.js +65 -2
- package/dist/resources/extensions/gsd/tools/plan-slice.js +2 -2
- package/dist/resources/extensions/gsd/tools/plan-task.js +2 -2
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +2 -2
- package/dist/resources/extensions/gsd/tools/reopen-milestone.js +2 -2
- package/dist/resources/extensions/gsd/tools/reopen-slice.js +2 -2
- package/dist/resources/extensions/gsd/tools/reopen-task.js +2 -2
- package/dist/resources/extensions/gsd/tools/replan-slice.js +2 -2
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +67 -2
- package/dist/resources/extensions/gsd/uat-policy.js +40 -15
- package/dist/resources/extensions/gsd/unit-context-composer.js +1 -1
- package/dist/resources/extensions/gsd/unit-registry.js +34 -4
- package/dist/resources/extensions/gsd/verdict-parser.js +1 -1
- package/dist/resources/extensions/gsd/verification-verdict.js +2 -1
- package/dist/resources/extensions/gsd/workflow-event-ledger.js +91 -0
- package/dist/resources/extensions/gsd/workflow-event-vocabulary.js +46 -0
- package/dist/resources/extensions/gsd/workflow-events.js +6 -18
- package/dist/resources/extensions/gsd/workflow-mcp-auto-prep.js +2 -0
- package/dist/resources/extensions/gsd/workflow-mcp-readiness-cache.js +105 -0
- package/dist/resources/extensions/gsd/workflow-reconcile.js +21 -56
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +3 -2
- package/dist/resources/extensions/gsd/worktree-manager.js +7 -1
- package/dist/resources/extensions/gsd/worktree-safety.js +28 -26
- package/dist/resources/extensions/gsd/worktree.js +8 -1
- package/dist/resources/extensions/mcp-client/manager.js +6 -1
- package/dist/resources/extensions/shared/gsd-browser-cli.js +21 -2
- package/dist/resources/shared/gsd-browser-path-sync.js +214 -0
- package/dist/resources/shared/package-manager-detection.js +1 -1
- package/dist/resources/skills/create-skill/SKILL.md +3 -0
- package/dist/resources/skills/create-skill/references/skill-structure.md +1 -0
- package/dist/runtime-checks.d.ts +10 -0
- package/dist/runtime-checks.js +27 -0
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/update-check.d.ts +2 -0
- package/dist/update-check.js +24 -1
- package/dist/update-cmd.js +20 -3
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +6 -6
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +6 -6
- package/dist/web/standalone/.next/server/chunks/{5942.js → 1128.js} +1 -1
- package/dist/web/standalone/.next/server/chunks/8357.js +2 -2
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
- package/dist/web/standalone/node_modules/postcss/lib/container.js +26 -18
- package/dist/web/standalone/node_modules/postcss/lib/css-syntax-error.js +47 -14
- package/dist/web/standalone/node_modules/postcss/lib/declaration.js +4 -4
- package/dist/web/standalone/node_modules/postcss/lib/fromJSON.js +3 -3
- package/dist/web/standalone/node_modules/postcss/lib/input.js +54 -29
- package/dist/web/standalone/node_modules/postcss/lib/lazy-result.js +47 -37
- package/dist/web/standalone/node_modules/postcss/lib/map-generator.js +26 -9
- package/dist/web/standalone/node_modules/postcss/lib/no-work-result.js +57 -55
- package/dist/web/standalone/node_modules/postcss/lib/node.js +99 -31
- package/dist/web/standalone/node_modules/postcss/lib/parse.js +1 -1
- package/dist/web/standalone/node_modules/postcss/lib/parser.js +10 -9
- package/dist/web/standalone/node_modules/postcss/lib/postcss.js +12 -12
- package/dist/web/standalone/node_modules/postcss/lib/previous-map.js +30 -11
- package/dist/web/standalone/node_modules/postcss/lib/processor.js +7 -7
- package/dist/web/standalone/node_modules/postcss/lib/result.js +5 -5
- package/dist/web/standalone/node_modules/postcss/lib/rule.js +6 -6
- package/dist/web/standalone/node_modules/postcss/lib/stringifier.js +69 -28
- package/dist/web/standalone/node_modules/postcss/lib/tokenize.js +6 -2
- package/dist/web/standalone/node_modules/postcss/package.json +48 -48
- package/package.json +3 -3
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/dist/sdk.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/sdk.js +6 -4
- package/packages/gsd-agent-core/dist/sdk.js.map +1 -1
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts +2 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js +10 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +8 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +50 -6
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts +2 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +34 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +17 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js +4 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/README.md +12 -3
- package/packages/mcp-server/dist/cli-runner.d.ts +40 -0
- package/packages/mcp-server/dist/cli-runner.d.ts.map +1 -0
- package/packages/mcp-server/dist/cli-runner.js +137 -0
- package/packages/mcp-server/dist/cli-runner.js.map +1 -0
- package/packages/mcp-server/dist/cli.js +2 -53
- package/packages/mcp-server/dist/cli.js.map +1 -1
- package/packages/mcp-server/dist/moonshot-tool-schema.d.ts +29 -0
- package/packages/mcp-server/dist/moonshot-tool-schema.d.ts.map +1 -0
- package/packages/mcp-server/dist/moonshot-tool-schema.js +50 -0
- package/packages/mcp-server/dist/moonshot-tool-schema.js.map +1 -0
- package/packages/mcp-server/dist/pid-registry.d.ts +46 -0
- package/packages/mcp-server/dist/pid-registry.d.ts.map +1 -0
- package/packages/mcp-server/dist/pid-registry.js +459 -0
- package/packages/mcp-server/dist/pid-registry.js.map +1 -0
- package/packages/mcp-server/dist/probe-mode.d.ts +4 -0
- package/packages/mcp-server/dist/probe-mode.d.ts.map +1 -0
- package/packages/mcp-server/dist/probe-mode.js +10 -0
- package/packages/mcp-server/dist/probe-mode.js.map +1 -0
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +4 -0
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/stdio-watchdog.d.ts +8 -0
- package/packages/mcp-server/dist/stdio-watchdog.d.ts.map +1 -0
- package/packages/mcp-server/dist/stdio-watchdog.js +40 -0
- package/packages/mcp-server/dist/stdio-watchdog.js.map +1 -0
- package/packages/mcp-server/dist/workflow-tools.d.ts +18 -18
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +161 -81
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +5 -4
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +43 -2
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/README.md +1 -0
- package/packages/pi-ai/dist/image-models.generated.d.ts +2 -2
- package/packages/pi-ai/dist/image-models.generated.js +6 -6
- package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
- package/packages/pi-ai/dist/index.d.ts +2 -0
- package/packages/pi-ai/dist/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/index.js +2 -0
- package/packages/pi-ai/dist/index.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +419 -221
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +468 -269
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +12 -7
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/providers/google-shared.d.ts +5 -0
- package/packages/pi-ai/dist/providers/google-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/google-shared.js +12 -3
- package/packages/pi-ai/dist/providers/google-shared.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.js +7 -3
- package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
- package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts +9 -0
- package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts.map +1 -0
- package/packages/pi-ai/dist/utils/moonshot-tool-schema.js +34 -0
- package/packages/pi-ai/dist/utils/moonshot-tool-schema.js.map +1 -0
- package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/github-copilot.js +6 -2
- package/packages/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
- package/packages/pi-ai/package.json +3 -2
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +11 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/theme/theme.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/theme/theme.js +45 -17
- package/packages/pi-coding-agent/dist/theme/theme.js.map +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/README.md +15 -0
- package/packages/pi-tui/dist/index.d.ts +2 -2
- package/packages/pi-tui/dist/index.d.ts.map +1 -1
- package/packages/pi-tui/dist/index.js +2 -2
- package/packages/pi-tui/dist/index.js.map +1 -1
- package/packages/pi-tui/dist/terminal-image.d.ts +33 -0
- package/packages/pi-tui/dist/terminal-image.d.ts.map +1 -1
- package/packages/pi-tui/dist/terminal-image.js +54 -2
- package/packages/pi-tui/dist/terminal-image.js.map +1 -1
- package/packages/pi-tui/dist/terminal.d.ts +12 -0
- package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
- package/packages/pi-tui/dist/terminal.js +70 -25
- package/packages/pi-tui/dist/terminal.js.map +1 -1
- package/packages/pi-tui/dist/tui.d.ts +15 -0
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +106 -21
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/dist/utils.d.ts.map +1 -1
- package/packages/pi-tui/dist/utils.js +110 -36
- package/packages/pi-tui/dist/utils.js.map +1 -1
- package/packages/pi-tui/package.json +2 -2
- package/packages/rpc-client/package.json +2 -2
- package/pkg/dist/theme/theme.d.ts.map +1 -1
- package/pkg/dist/theme/theme.js +45 -17
- package/pkg/dist/theme/theme.js.map +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/GSD-WORKFLOW.md +5 -4
- package/src/resources/extensions/ask-user-questions.ts +7 -2
- package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +11 -0
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +531 -226
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +672 -7
- package/src/resources/extensions/claude-code-cli/turn-assembler.ts +38 -1
- package/src/resources/extensions/gsd/auto/closeout.ts +309 -0
- package/src/resources/extensions/gsd/auto/custom-verify-retry-store.ts +21 -3
- package/src/resources/extensions/gsd/auto/detect-stuck.ts +32 -9
- package/src/resources/extensions/gsd/auto/dispatch-history.ts +168 -0
- package/src/resources/extensions/gsd/auto/dispatch-key.ts +39 -0
- package/src/resources/extensions/gsd/auto/dispatch.ts +449 -0
- package/src/resources/extensions/gsd/auto/finalize.ts +445 -0
- package/src/resources/extensions/gsd/auto/loop.ts +7 -1
- package/src/resources/extensions/gsd/auto/milestone-lease-reclaim.ts +74 -0
- package/src/resources/extensions/gsd/auto/orchestrator.ts +186 -66
- package/src/resources/extensions/gsd/auto/phase-helpers.ts +199 -0
- package/src/resources/extensions/gsd/auto/phases.ts +58 -3022
- package/src/resources/extensions/gsd/auto/pre-dispatch.ts +704 -0
- package/src/resources/extensions/gsd/auto/session.ts +3 -0
- package/src/resources/extensions/gsd/auto/unit-phase.ts +910 -0
- package/src/resources/extensions/gsd/auto/workflow-unit-dispatch.ts +1 -1
- package/src/resources/extensions/gsd/auto/worktree-safety-phase.ts +149 -0
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +18 -48
- package/src/resources/extensions/gsd/auto-dispatch.ts +37 -62
- package/src/resources/extensions/gsd/auto-model-selection.ts +16 -7
- package/src/resources/extensions/gsd/auto-post-unit.ts +33 -12
- package/src/resources/extensions/gsd/auto-prompts.ts +78 -9
- package/src/resources/extensions/gsd/auto-start.ts +27 -11
- package/src/resources/extensions/gsd/auto-unit-closeout.ts +83 -28
- package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +4 -4
- package/src/resources/extensions/gsd/auto-verification.ts +26 -28
- package/src/resources/extensions/gsd/auto-worktree.ts +15 -2
- package/src/resources/extensions/gsd/auto.ts +64 -2
- package/src/resources/extensions/gsd/blocked-models.ts +49 -0
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +34 -5
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +56 -6
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +2 -2
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +118 -50
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +350 -86
- package/src/resources/extensions/gsd/closeout-wizard.ts +102 -0
- package/src/resources/extensions/gsd/commands/context.ts +16 -2
- package/src/resources/extensions/gsd/commands-handlers.ts +46 -3
- package/src/resources/extensions/gsd/commands-mcp-status.ts +2 -2
- package/src/resources/extensions/gsd/commands-workflow-templates.ts +11 -4
- package/src/resources/extensions/gsd/consent-question.ts +431 -0
- package/src/resources/extensions/gsd/consent-verdict.ts +86 -0
- package/src/resources/extensions/gsd/crash-recovery.ts +10 -2
- package/src/resources/extensions/gsd/db/engine.ts +26 -6
- package/src/resources/extensions/gsd/db/queries.ts +66 -0
- package/src/resources/extensions/gsd/db-migration-backup.ts +56 -7
- package/src/resources/extensions/gsd/db-transaction.ts +37 -20
- package/src/resources/extensions/gsd/db-writer.ts +11 -19
- package/src/resources/extensions/gsd/dispatch-guard.ts +8 -31
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +5 -4
- package/src/resources/extensions/gsd/doctor-environment.ts +267 -142
- package/src/resources/extensions/gsd/doctor-git-checks.ts +2 -19
- package/src/resources/extensions/gsd/engine-hook-contract.ts +79 -0
- package/src/resources/extensions/gsd/files.ts +33 -12
- package/src/resources/extensions/gsd/gsd-command-home.ts +13 -3
- package/src/resources/extensions/gsd/gsd-db.ts +19 -22
- package/src/resources/extensions/gsd/guidance.ts +78 -0
- package/src/resources/extensions/gsd/guided-flow.ts +145 -24
- package/src/resources/extensions/gsd/health-widget.ts +91 -27
- package/src/resources/extensions/gsd/markdown-renderer.ts +11 -0
- package/src/resources/extensions/gsd/mcp-bridge.ts +39 -0
- package/src/resources/extensions/gsd/memory-relations.ts +1 -1
- package/src/resources/extensions/gsd/milestone-closeout.ts +109 -24
- package/src/resources/extensions/gsd/milestone-planning-persistence.ts +2 -2
- package/src/resources/extensions/gsd/milestone-reopen-events.ts +3 -6
- package/src/resources/extensions/gsd/milestone-settlement.ts +2 -2
- package/src/resources/extensions/gsd/notifications.ts +13 -6
- package/src/resources/extensions/gsd/parsers-legacy.ts +16 -4
- package/src/resources/extensions/gsd/projection-flush.ts +20 -0
- package/src/resources/extensions/gsd/prompts/complete-slice.md +3 -3
- package/src/resources/extensions/gsd/prompts/execute-task.md +3 -2
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/quick-task.md +1 -1
- package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
- package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/replan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/research-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
- package/src/resources/extensions/gsd/prompts/run-uat.md +8 -4
- package/src/resources/extensions/gsd/prompts/triage-captures.md +1 -1
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/workflow-start.md +2 -1
- package/src/resources/extensions/gsd/reactive-graph.ts +11 -1
- package/src/resources/extensions/gsd/roadmap-slices.ts +28 -3
- package/src/resources/extensions/gsd/session-lock.ts +1 -1
- package/src/resources/extensions/gsd/skill-activation.ts +3 -6
- package/src/resources/extensions/gsd/state.ts +12 -1
- package/src/resources/extensions/gsd/tests/auto-abort-pause-regression.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/auto-blocked-remediation-message.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +206 -22
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +75 -1
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +257 -18
- package/src/resources/extensions/gsd/tests/auto-pause-double-entry-guard.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +77 -1
- package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/auto-remote-session-lock-cleanup.test.ts +65 -3
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +236 -0
- package/src/resources/extensions/gsd/tests/auto-unit-closeout.test.ts +169 -1
- package/src/resources/extensions/gsd/tests/blocked-models.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +141 -5
- package/src/resources/extensions/gsd/tests/consent-question.test.ts +351 -0
- package/src/resources/extensions/gsd/tests/custom-verify-retry-store.test.ts +67 -0
- package/src/resources/extensions/gsd/tests/db-migration-backup.test.ts +68 -19
- package/src/resources/extensions/gsd/tests/db-transaction.test.ts +59 -0
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +15 -4
- package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +12 -11
- package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/discuss-routing-fixes.test.ts +12 -2
- package/src/resources/extensions/gsd/tests/dispatch-history.test.ts +328 -0
- package/src/resources/extensions/gsd/tests/dist-redirect.mjs +8 -0
- package/src/resources/extensions/gsd/tests/doctor-git-checks-terminal.test.ts +73 -0
- package/src/resources/extensions/gsd/tests/engine-hook-contract.test.ts +148 -0
- package/src/resources/extensions/gsd/tests/engine-interfaces-contract.test.ts +117 -91
- package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +113 -0
- package/src/resources/extensions/gsd/tests/gsd-command-home.test.ts +120 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/guidance.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +18 -6
- package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-environment-async.test.ts +104 -0
- package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +217 -0
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +47 -16
- package/src/resources/extensions/gsd/tests/mcp-readiness-preflight.test.ts +205 -0
- package/src/resources/extensions/gsd/tests/mcp-status.test.ts +6 -5
- package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +95 -4
- package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/milestone-report-path.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/milestone-settlement.test.ts +92 -0
- package/src/resources/extensions/gsd/tests/milestone-transition-state-rebuild.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/notifications.test.ts +64 -9
- package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +143 -0
- package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/phases-terminal-complete-idempotent.test.ts +242 -0
- package/src/resources/extensions/gsd/tests/plan-gate-failed-doctor-heal-hint.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +63 -2
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +10 -2
- package/src/resources/extensions/gsd/tests/prompt-db.test.ts +124 -6
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +2 -4
- package/src/resources/extensions/gsd/tests/remote-notification-from-desktop.test.ts +31 -81
- package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +68 -0
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +26 -2
- package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +170 -48
- package/src/resources/extensions/gsd/tests/skill-activation.test.ts +20 -17
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +7 -3
- package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/teardown-chdir-failure-clears-registry.test.ts +17 -0
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/tool-surface-readiness.test.ts +184 -10
- package/src/resources/extensions/gsd/tests/tool-unavailable-retry.test.ts +33 -0
- package/src/resources/extensions/gsd/tests/transport-gate-double-complete.test.ts +139 -0
- package/src/resources/extensions/gsd/tests/uat-policy.test.ts +88 -0
- package/src/resources/extensions/gsd/tests/uok-audit-unified.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/workflow-events.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp-readiness-cache.test.ts +119 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +65 -2
- package/src/resources/extensions/gsd/tests/workflow-phase-contract-matrix.test.ts +332 -0
- package/src/resources/extensions/gsd/tests/workflow-reconcile.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +92 -0
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +273 -38
- package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-project-root-degrade.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-safety-phase.test.ts +100 -0
- package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +72 -0
- package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/worktree.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/write-gate-seam.test.ts +358 -0
- package/src/resources/extensions/gsd/tests/write-gate.test.ts +67 -1
- package/src/resources/extensions/gsd/tool-contract.ts +38 -3
- package/src/resources/extensions/gsd/tool-presentation-plan.ts +4 -4
- package/src/resources/extensions/gsd/tool-surface-readiness.ts +126 -19
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -2
- package/src/resources/extensions/gsd/tools/complete-slice.ts +22 -12
- package/src/resources/extensions/gsd/tools/complete-task.ts +90 -2
- package/src/resources/extensions/gsd/tools/plan-slice.ts +2 -2
- package/src/resources/extensions/gsd/tools/plan-task.ts +2 -2
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +2 -2
- package/src/resources/extensions/gsd/tools/reopen-milestone.ts +2 -2
- package/src/resources/extensions/gsd/tools/reopen-slice.ts +2 -2
- package/src/resources/extensions/gsd/tools/reopen-task.ts +2 -2
- package/src/resources/extensions/gsd/tools/replan-slice.ts +2 -2
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +81 -2
- package/src/resources/extensions/gsd/uat-policy.ts +60 -15
- package/src/resources/extensions/gsd/unit-context-composer.ts +1 -1
- package/src/resources/extensions/gsd/unit-registry.ts +34 -4
- package/src/resources/extensions/gsd/verdict-parser.ts +1 -1
- package/src/resources/extensions/gsd/verification-verdict.ts +4 -2
- package/src/resources/extensions/gsd/workflow-event-ledger.ts +131 -0
- package/src/resources/extensions/gsd/workflow-event-vocabulary.ts +59 -0
- package/src/resources/extensions/gsd/workflow-events.ts +12 -20
- package/src/resources/extensions/gsd/workflow-mcp-auto-prep.ts +2 -0
- package/src/resources/extensions/gsd/workflow-mcp-readiness-cache.ts +150 -0
- package/src/resources/extensions/gsd/workflow-reconcile.ts +29 -62
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +3 -8
- package/src/resources/extensions/gsd/worktree-manager.ts +6 -1
- package/src/resources/extensions/gsd/worktree-safety.ts +41 -39
- package/src/resources/extensions/gsd/worktree.ts +7 -1
- package/src/resources/extensions/mcp-client/manager.ts +7 -1
- package/src/resources/extensions/shared/gsd-browser-cli.ts +23 -2
- package/src/resources/shared/gsd-browser-path-sync.ts +273 -0
- package/src/resources/shared/package-manager-detection.ts +1 -1
- package/src/resources/skills/create-skill/SKILL.md +3 -0
- package/src/resources/skills/create-skill/references/skill-structure.md +1 -0
- package/dist/resources/extensions/gsd/user-input-boundary.js +0 -218
- package/dist/resources/skills/gsd-browser/SKILL.md +0 -41
- package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +0 -173
- package/src/resources/extensions/gsd/user-input-boundary.ts +0 -216
- package/src/resources/skills/gsd-browser/SKILL.md +0 -41
- /package/dist/web/standalone/.next/static/{mU4QIDlpVHDdjDpeEKh5W → 2T9IOdiiM3o3gZ4UbPi8E}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{mU4QIDlpVHDdjDpeEKh5W → 2T9IOdiiM3o3gZ4UbPi8E}/_ssgManifest.js +0 -0
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
13
|
-
import { execSync } from "node:child_process";
|
|
13
|
+
import { execFile, execSync } from "node:child_process";
|
|
14
14
|
import { join } from "node:path";
|
|
15
15
|
|
|
16
16
|
import type { DoctorIssue, DoctorIssueCode } from "./doctor-types.js";
|
|
@@ -76,48 +76,47 @@ function commandExists(name: string, cwd: string): boolean {
|
|
|
76
76
|
/**
|
|
77
77
|
* Check that Node.js version meets the project's engines requirement.
|
|
78
78
|
*/
|
|
79
|
-
function
|
|
79
|
+
function readPackageEngineNode(basePath: string): string | null {
|
|
80
80
|
const pkgPath = join(basePath, "package.json");
|
|
81
81
|
if (!existsSync(pkgPath)) return null;
|
|
82
|
-
|
|
83
82
|
try {
|
|
84
83
|
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
85
|
-
|
|
86
|
-
if (!required) return null;
|
|
87
|
-
|
|
88
|
-
const currentVersion = tryExec("node --version", basePath);
|
|
89
|
-
if (!currentVersion) {
|
|
90
|
-
return { name: "node_version", status: "error", message: "Node.js not found in PATH" };
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Parse semver requirement (handles >=X.Y.Z format)
|
|
94
|
-
const reqMatch = required.match(/>=?\s*(\d+)(?:\.(\d+))?/);
|
|
95
|
-
if (!reqMatch) return null;
|
|
96
|
-
|
|
97
|
-
const reqMajor = parseInt(reqMatch[1], 10);
|
|
98
|
-
const reqMinor = parseInt(reqMatch[2] ?? "0", 10);
|
|
99
|
-
|
|
100
|
-
const curMatch = currentVersion.match(/v?(\d+)\.(\d+)/);
|
|
101
|
-
if (!curMatch) return null;
|
|
102
|
-
|
|
103
|
-
const curMajor = parseInt(curMatch[1], 10);
|
|
104
|
-
const curMinor = parseInt(curMatch[2], 10);
|
|
105
|
-
|
|
106
|
-
if (curMajor < reqMajor || (curMajor === reqMajor && curMinor < reqMinor)) {
|
|
107
|
-
return {
|
|
108
|
-
name: "node_version",
|
|
109
|
-
status: "warning",
|
|
110
|
-
message: `Node.js ${currentVersion} does not meet requirement "${required}"`,
|
|
111
|
-
detail: `Current: ${currentVersion}, Required: ${required}`,
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
return { name: "node_version", status: "ok", message: `Node.js ${currentVersion}` };
|
|
84
|
+
return pkg.engines?.node ?? null;
|
|
116
85
|
} catch {
|
|
117
86
|
return null;
|
|
118
87
|
}
|
|
119
88
|
}
|
|
120
89
|
|
|
90
|
+
function buildNodeVersionResult(required: string, currentVersion: string | null): EnvironmentCheckResult | null {
|
|
91
|
+
if (!currentVersion) {
|
|
92
|
+
return { name: "node_version", status: "error", message: "Node.js not found in PATH" };
|
|
93
|
+
}
|
|
94
|
+
// Parse semver requirement (handles >=X.Y.Z format)
|
|
95
|
+
const reqMatch = required.match(/>=?\s*(\d+)(?:\.(\d+))?/);
|
|
96
|
+
if (!reqMatch) return null;
|
|
97
|
+
const reqMajor = parseInt(reqMatch[1], 10);
|
|
98
|
+
const reqMinor = parseInt(reqMatch[2] ?? "0", 10);
|
|
99
|
+
const curMatch = currentVersion.match(/v?(\d+)\.(\d+)/);
|
|
100
|
+
if (!curMatch) return null;
|
|
101
|
+
const curMajor = parseInt(curMatch[1], 10);
|
|
102
|
+
const curMinor = parseInt(curMatch[2], 10);
|
|
103
|
+
if (curMajor < reqMajor || (curMajor === reqMajor && curMinor < reqMinor)) {
|
|
104
|
+
return {
|
|
105
|
+
name: "node_version",
|
|
106
|
+
status: "warning",
|
|
107
|
+
message: `Node.js ${currentVersion} does not meet requirement "${required}"`,
|
|
108
|
+
detail: `Current: ${currentVersion}, Required: ${required}`,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
return { name: "node_version", status: "ok", message: `Node.js ${currentVersion}` };
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function checkNodeVersion(basePath: string): EnvironmentCheckResult | null {
|
|
115
|
+
const required = readPackageEngineNode(basePath);
|
|
116
|
+
if (!required) return null;
|
|
117
|
+
return buildNodeVersionResult(required, tryExec("node --version", basePath));
|
|
118
|
+
}
|
|
119
|
+
|
|
121
120
|
/**
|
|
122
121
|
* Check if node_modules exists and is not stale vs the lockfile.
|
|
123
122
|
*/
|
|
@@ -217,28 +216,19 @@ function checkEnvFiles(basePath: string): EnvironmentCheckResult | null {
|
|
|
217
216
|
* Check for port conflicts on common dev server ports.
|
|
218
217
|
* Only checks ports that appear in package.json scripts.
|
|
219
218
|
*/
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
// Try to detect ports from package.json scripts
|
|
219
|
+
// Detect the dev ports worth checking from package.json scripts, falling back to
|
|
220
|
+
// common defaults. Returns an empty set when there's no Node project (no
|
|
221
|
+
// package.json) or a parse failure — the caller then skips port checks entirely,
|
|
222
|
+
// avoiding false positives from system services (e.g. macOS AirPlay on 5000, #1381).
|
|
223
|
+
function collectPortsToCheck(basePath: string): Set<number> {
|
|
227
224
|
const portsToCheck = new Set<number>();
|
|
228
225
|
const pkgPath = join(basePath, "package.json");
|
|
229
|
-
|
|
230
|
-
if (!existsSync(pkgPath)) {
|
|
231
|
-
// No package.json — this isn't a Node.js project. Skip port checks
|
|
232
|
-
// entirely to avoid false positives from system services (e.g., macOS
|
|
233
|
-
// AirPlay Receiver on port 5000). (#1381)
|
|
234
|
-
return [];
|
|
235
|
-
}
|
|
226
|
+
if (!existsSync(pkgPath)) return portsToCheck;
|
|
236
227
|
|
|
237
228
|
try {
|
|
238
229
|
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
239
230
|
const scripts = pkg.scripts ?? {};
|
|
240
231
|
const scriptText = Object.values(scripts).join(" ");
|
|
241
|
-
|
|
242
232
|
// Look for --port NNNN, -p NNNN, PORT=NNNN, :NNNN patterns
|
|
243
233
|
const portMatches = scriptText.matchAll(/(?:--port\s+|(?:^|[^a-z])PORT[=:]\s*|-p\s+|:)(\d{4,5})\b/gi);
|
|
244
234
|
for (const m of portMatches) {
|
|
@@ -246,48 +236,66 @@ function checkPortConflicts(basePath: string): EnvironmentCheckResult[] {
|
|
|
246
236
|
if (port >= 1024 && port <= 65535) portsToCheck.add(port);
|
|
247
237
|
}
|
|
248
238
|
} catch {
|
|
249
|
-
|
|
250
|
-
return [];
|
|
239
|
+
return new Set();
|
|
251
240
|
}
|
|
252
241
|
|
|
253
|
-
// If no ports found in scripts, check common defaults.
|
|
254
|
-
// Filter out port 5000 on macOS — AirPlay Receiver uses it by default (#1381).
|
|
255
242
|
if (portsToCheck.size === 0) {
|
|
256
243
|
for (const p of DEFAULT_DEV_PORTS) {
|
|
257
244
|
if (p === 5000 && process.platform === "darwin") continue;
|
|
258
245
|
portsToCheck.add(p);
|
|
259
246
|
}
|
|
260
247
|
}
|
|
248
|
+
return portsToCheck;
|
|
249
|
+
}
|
|
261
250
|
|
|
251
|
+
// Parse a single `lsof -nP -iTCP -sTCP:LISTEN` scan and report which of the
|
|
252
|
+
// requested ports are in use. Replaces the old per-port lsof loop (up to ~14
|
|
253
|
+
// system-wide socket scans, ~350ms) with one scan + an in-memory lookup.
|
|
254
|
+
function buildPortConflictResults(
|
|
255
|
+
lsofOut: string | null,
|
|
256
|
+
portsToCheck: Set<number>,
|
|
257
|
+
): EnvironmentCheckResult[] {
|
|
258
|
+
const results: EnvironmentCheckResult[] = [];
|
|
259
|
+
const listening = new Map<number, { pid: string; command: string }>();
|
|
260
|
+
if (lsofOut) {
|
|
261
|
+
for (const line of lsofOut.split("\n")) {
|
|
262
|
+
// COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
|
|
263
|
+
// e.g. `node 12345 user 23u IPv4 0x.. 0t0 TCP *:3000 (LISTEN)`
|
|
264
|
+
const portMatch = line.match(/:(\d+)(?:\s+\(LISTEN\))?\s*$/);
|
|
265
|
+
if (!portMatch) continue;
|
|
266
|
+
const port = parseInt(portMatch[1], 10);
|
|
267
|
+
if (!Number.isFinite(port) || listening.has(port)) continue;
|
|
268
|
+
const cols = line.split(/\s+/);
|
|
269
|
+
listening.set(port, { command: cols[0] ?? "unknown", pid: cols[1] ?? "?" });
|
|
270
|
+
}
|
|
271
|
+
}
|
|
262
272
|
for (const port of portsToCheck) {
|
|
263
|
-
const
|
|
264
|
-
if (
|
|
265
|
-
// Get process name
|
|
266
|
-
const nameResult = tryExec(`lsof -i :${port} -sTCP:LISTEN -Fp | head -2`, basePath);
|
|
267
|
-
const processName = nameResult?.match(/p(\d+)\n?c?(.+)?/)?.[2] ?? "unknown";
|
|
268
|
-
|
|
273
|
+
const hit = listening.get(port);
|
|
274
|
+
if (hit) {
|
|
269
275
|
results.push({
|
|
270
276
|
name: "port_conflict",
|
|
271
277
|
status: "warning",
|
|
272
|
-
message: `Port ${port} is already in use by ${
|
|
278
|
+
message: `Port ${port} is already in use by ${hit.command} (PID ${hit.pid})`,
|
|
273
279
|
detail: `Kill the process or use a different port`,
|
|
274
280
|
});
|
|
275
281
|
}
|
|
276
282
|
}
|
|
277
|
-
|
|
278
283
|
return results;
|
|
279
284
|
}
|
|
280
285
|
|
|
286
|
+
function checkPortConflicts(basePath: string): EnvironmentCheckResult[] {
|
|
287
|
+
// Only run on macOS/Linux — lsof is not available on Windows
|
|
288
|
+
if (process.platform === "win32") return [];
|
|
289
|
+
const portsToCheck = collectPortsToCheck(basePath);
|
|
290
|
+
if (portsToCheck.size === 0) return [];
|
|
291
|
+
return buildPortConflictResults(tryExec("lsof -nP -iTCP -sTCP:LISTEN", basePath), portsToCheck);
|
|
292
|
+
}
|
|
293
|
+
|
|
281
294
|
/**
|
|
282
295
|
* Check available disk space on the working directory partition.
|
|
283
296
|
*/
|
|
284
|
-
function
|
|
285
|
-
// Only run on macOS/Linux
|
|
286
|
-
if (process.platform === "win32") return null;
|
|
287
|
-
|
|
288
|
-
const dfOutput = tryExec(`df -k "${basePath}" | tail -1`, basePath);
|
|
297
|
+
function buildDiskSpaceResult(dfOutput: string | null): EnvironmentCheckResult | null {
|
|
289
298
|
if (!dfOutput) return null;
|
|
290
|
-
|
|
291
299
|
try {
|
|
292
300
|
// df output: filesystem blocks used avail capacity mount
|
|
293
301
|
const parts = dfOutput.split(/\s+/);
|
|
@@ -306,32 +314,34 @@ function checkDiskSpace(basePath: string): EnvironmentCheckResult | null {
|
|
|
306
314
|
detail: `Free up space — builds and git operations may fail`,
|
|
307
315
|
};
|
|
308
316
|
}
|
|
309
|
-
|
|
310
317
|
if (availBytes < MIN_DISK_BYTES * 4) {
|
|
311
|
-
return {
|
|
312
|
-
name: "disk_space",
|
|
313
|
-
status: "warning",
|
|
314
|
-
message: `Disk space getting low: ${availGB}GB free`,
|
|
315
|
-
};
|
|
318
|
+
return { name: "disk_space", status: "warning", message: `Disk space getting low: ${availGB}GB free` };
|
|
316
319
|
}
|
|
317
|
-
|
|
318
320
|
return { name: "disk_space", status: "ok", message: `${availGB}GB free` };
|
|
319
321
|
} catch {
|
|
320
322
|
return null;
|
|
321
323
|
}
|
|
322
324
|
}
|
|
323
325
|
|
|
326
|
+
function checkDiskSpace(basePath: string): EnvironmentCheckResult | null {
|
|
327
|
+
// Only run on macOS/Linux
|
|
328
|
+
if (process.platform === "win32") return null;
|
|
329
|
+
return buildDiskSpaceResult(tryExec(`df -k "${basePath}" | tail -1`, basePath));
|
|
330
|
+
}
|
|
331
|
+
|
|
324
332
|
/**
|
|
325
333
|
* Check if Docker is available when project has a Dockerfile.
|
|
326
334
|
*/
|
|
327
|
-
function
|
|
328
|
-
|
|
335
|
+
function hasDockerConfig(basePath: string): boolean {
|
|
336
|
+
return existsSync(join(basePath, "Dockerfile")) ||
|
|
329
337
|
existsSync(join(basePath, "docker-compose.yml")) ||
|
|
330
338
|
existsSync(join(basePath, "docker-compose.yaml")) ||
|
|
331
339
|
existsSync(join(basePath, "compose.yml")) ||
|
|
332
340
|
existsSync(join(basePath, "compose.yaml"));
|
|
341
|
+
}
|
|
333
342
|
|
|
334
|
-
|
|
343
|
+
function checkDocker(basePath: string): EnvironmentCheckResult | null {
|
|
344
|
+
if (!hasDockerConfig(basePath)) return null;
|
|
335
345
|
|
|
336
346
|
if (!commandExists("docker", basePath)) {
|
|
337
347
|
return {
|
|
@@ -357,78 +367,68 @@ function checkDocker(basePath: string): EnvironmentCheckResult | null {
|
|
|
357
367
|
/**
|
|
358
368
|
* Check for common project tools that should be available.
|
|
359
369
|
*/
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
370
|
+
interface ProjectToolSpec {
|
|
371
|
+
packageManager: string | null; // non-npm manager that must be on PATH, or null
|
|
372
|
+
needsTsc: boolean;
|
|
373
|
+
needsPython: boolean;
|
|
374
|
+
needsCargo: boolean;
|
|
375
|
+
needsGo: boolean;
|
|
376
|
+
}
|
|
365
377
|
|
|
378
|
+
// Decide which project tools to verify from package.json + marker files (pure fs).
|
|
379
|
+
// The actual `command -v` probes are left to the sync/async checkers so both share
|
|
380
|
+
// this logic.
|
|
381
|
+
function readProjectToolSpec(basePath: string): ProjectToolSpec | null {
|
|
382
|
+
const pkgPath = join(basePath, "package.json");
|
|
383
|
+
if (!existsSync(pkgPath)) return null;
|
|
366
384
|
try {
|
|
367
385
|
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
368
|
-
const allDeps = {
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
// Check for package manager
|
|
374
|
-
const packageManager = pkg.packageManager;
|
|
375
|
-
if (packageManager) {
|
|
376
|
-
const managerName = packageManager.split("@")[0];
|
|
377
|
-
if (managerName && managerName !== "npm" && !commandExists(managerName, basePath)) {
|
|
378
|
-
results.push({
|
|
379
|
-
name: "package_manager",
|
|
380
|
-
status: "warning",
|
|
381
|
-
message: `Project requires ${managerName} but it's not installed`,
|
|
382
|
-
detail: `Install with: npm install -g ${managerName}`,
|
|
383
|
-
});
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
// Check for TypeScript if it's a dependency
|
|
388
|
-
if (allDeps["typescript"] && !existsSync(join(basePath, "node_modules", ".bin", "tsc"))) {
|
|
389
|
-
results.push({
|
|
390
|
-
name: "typescript",
|
|
391
|
-
status: "warning",
|
|
392
|
-
message: "TypeScript is a dependency but tsc is not available (run npm install)",
|
|
393
|
-
});
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
// Check for Python if pyproject.toml or requirements.txt exists
|
|
397
|
-
if (existsSync(join(basePath, "pyproject.toml")) || existsSync(join(basePath, "requirements.txt"))) {
|
|
398
|
-
if (detectPythonExecutable() === null) {
|
|
399
|
-
results.push({
|
|
400
|
-
name: "python",
|
|
401
|
-
status: "warning",
|
|
402
|
-
message: "Project has Python config but python is not installed",
|
|
403
|
-
});
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
// Check for Rust if Cargo.toml exists
|
|
408
|
-
if (existsSync(join(basePath, "Cargo.toml"))) {
|
|
409
|
-
if (!commandExists("cargo", basePath)) {
|
|
410
|
-
results.push({
|
|
411
|
-
name: "cargo",
|
|
412
|
-
status: "warning",
|
|
413
|
-
message: "Project has Cargo.toml but cargo is not installed",
|
|
414
|
-
});
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
// Check for Go if go.mod exists
|
|
419
|
-
if (existsSync(join(basePath, "go.mod"))) {
|
|
420
|
-
if (!commandExists("go", basePath)) {
|
|
421
|
-
results.push({
|
|
422
|
-
name: "go",
|
|
423
|
-
status: "warning",
|
|
424
|
-
message: "Project has go.mod but go is not installed",
|
|
425
|
-
});
|
|
426
|
-
}
|
|
386
|
+
const allDeps = { ...(pkg.dependencies ?? {}), ...(pkg.devDependencies ?? {}) };
|
|
387
|
+
let packageManager: string | null = null;
|
|
388
|
+
if (pkg.packageManager) {
|
|
389
|
+
const managerName = String(pkg.packageManager).split("@")[0];
|
|
390
|
+
if (managerName && managerName !== "npm") packageManager = managerName;
|
|
427
391
|
}
|
|
392
|
+
return {
|
|
393
|
+
packageManager,
|
|
394
|
+
needsTsc: Boolean(allDeps["typescript"]) && !existsSync(join(basePath, "node_modules", ".bin", "tsc")),
|
|
395
|
+
needsPython: existsSync(join(basePath, "pyproject.toml")) || existsSync(join(basePath, "requirements.txt")),
|
|
396
|
+
needsCargo: existsSync(join(basePath, "Cargo.toml")),
|
|
397
|
+
needsGo: existsSync(join(basePath, "go.mod")),
|
|
398
|
+
};
|
|
428
399
|
} catch {
|
|
429
|
-
|
|
400
|
+
return null;
|
|
430
401
|
}
|
|
402
|
+
}
|
|
431
403
|
|
|
404
|
+
function checkProjectTools(basePath: string): EnvironmentCheckResult[] {
|
|
405
|
+
const spec = readProjectToolSpec(basePath);
|
|
406
|
+
if (!spec) return [];
|
|
407
|
+
const results: EnvironmentCheckResult[] = [];
|
|
408
|
+
if (spec.packageManager && !commandExists(spec.packageManager, basePath)) {
|
|
409
|
+
results.push({
|
|
410
|
+
name: "package_manager",
|
|
411
|
+
status: "warning",
|
|
412
|
+
message: `Project requires ${spec.packageManager} but it's not installed`,
|
|
413
|
+
detail: `Install with: npm install -g ${spec.packageManager}`,
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
if (spec.needsTsc) {
|
|
417
|
+
results.push({
|
|
418
|
+
name: "typescript",
|
|
419
|
+
status: "warning",
|
|
420
|
+
message: "TypeScript is a dependency but tsc is not available (run npm install)",
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
if (spec.needsPython && detectPythonExecutable() === null) {
|
|
424
|
+
results.push({ name: "python", status: "warning", message: "Project has Python config but python is not installed" });
|
|
425
|
+
}
|
|
426
|
+
if (spec.needsCargo && !commandExists("cargo", basePath)) {
|
|
427
|
+
results.push({ name: "cargo", status: "warning", message: "Project has Cargo.toml but cargo is not installed" });
|
|
428
|
+
}
|
|
429
|
+
if (spec.needsGo && !commandExists("go", basePath)) {
|
|
430
|
+
results.push({ name: "go", status: "warning", message: "Project has go.mod but go is not installed" });
|
|
431
|
+
}
|
|
432
432
|
return results;
|
|
433
433
|
}
|
|
434
434
|
|
|
@@ -517,6 +517,131 @@ function checkTestHealth(basePath: string): EnvironmentCheckResult | null {
|
|
|
517
517
|
* Run all environment health checks. Returns structured results for
|
|
518
518
|
* integration with the doctor pipeline.
|
|
519
519
|
*/
|
|
520
|
+
// ── Async variants ─────────────────────────────────────────────────────────
|
|
521
|
+
// The always-on health widget refreshes off the first-paint path, but the sync
|
|
522
|
+
// `runEnvironmentChecks` blocks the event loop on its subprocess checks (~300ms,
|
|
523
|
+
// and again every 60s). These async siblings run the same checks via non-blocking
|
|
524
|
+
// `execFile` and fan the independent ones out concurrently, so the UI thread never
|
|
525
|
+
// stalls. The sync API above is unchanged for /gsd doctor and the dashboards.
|
|
526
|
+
|
|
527
|
+
function tryExecAsync(cmd: string, cwd: string): Promise<string | null> {
|
|
528
|
+
return new Promise((resolve) => {
|
|
529
|
+
const isWin = process.platform === "win32";
|
|
530
|
+
const child = execFile(
|
|
531
|
+
isWin ? "cmd" : "sh",
|
|
532
|
+
isWin ? ["/c", cmd] : ["-c", cmd],
|
|
533
|
+
{ cwd, timeout: CMD_TIMEOUT, encoding: "utf-8" },
|
|
534
|
+
(err, stdout) => resolve(err ? null : String(stdout).trim()),
|
|
535
|
+
);
|
|
536
|
+
child.on("error", () => resolve(null));
|
|
537
|
+
});
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
async function commandExistsAsync(name: string, cwd: string): Promise<boolean> {
|
|
541
|
+
const whichCmd = process.platform === "win32" ? `where ${name}` : `command -v ${name}`;
|
|
542
|
+
return (await tryExecAsync(whichCmd, cwd)) !== null;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
async function checkNodeVersionAsync(basePath: string): Promise<EnvironmentCheckResult | null> {
|
|
546
|
+
const required = readPackageEngineNode(basePath);
|
|
547
|
+
if (!required) return null;
|
|
548
|
+
const currentVersion = await tryExecAsync("node --version", basePath);
|
|
549
|
+
return buildNodeVersionResult(required, currentVersion);
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
async function checkPortConflictsAsync(basePath: string): Promise<EnvironmentCheckResult[]> {
|
|
553
|
+
if (process.platform === "win32") return [];
|
|
554
|
+
const portsToCheck = collectPortsToCheck(basePath);
|
|
555
|
+
if (portsToCheck.size === 0) return [];
|
|
556
|
+
const lsofOut = await tryExecAsync("lsof -nP -iTCP -sTCP:LISTEN", basePath);
|
|
557
|
+
return buildPortConflictResults(lsofOut, portsToCheck);
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
async function checkDiskSpaceAsync(basePath: string): Promise<EnvironmentCheckResult | null> {
|
|
561
|
+
if (process.platform === "win32") return null;
|
|
562
|
+
return buildDiskSpaceResult(await tryExecAsync(`df -k "${basePath}" | tail -1`, basePath));
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
async function checkDockerAsync(basePath: string): Promise<EnvironmentCheckResult | null> {
|
|
566
|
+
if (!hasDockerConfig(basePath)) return null;
|
|
567
|
+
if (!(await commandExistsAsync("docker", basePath))) {
|
|
568
|
+
return { name: "docker", status: "warning", message: "Project has Docker files but docker is not installed" };
|
|
569
|
+
}
|
|
570
|
+
const info = await tryExecAsync("docker info --format '{{.ServerVersion}}'", basePath);
|
|
571
|
+
if (!info) {
|
|
572
|
+
return {
|
|
573
|
+
name: "docker",
|
|
574
|
+
status: "warning",
|
|
575
|
+
message: "Docker is installed but daemon is not running",
|
|
576
|
+
detail: "Start Docker Desktop or the docker daemon",
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
return { name: "docker", status: "ok", message: `Docker ${info}` };
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
async function checkProjectToolsAsync(basePath: string): Promise<EnvironmentCheckResult[]> {
|
|
583
|
+
const spec = readProjectToolSpec(basePath);
|
|
584
|
+
if (!spec) return [];
|
|
585
|
+
const results: EnvironmentCheckResult[] = [];
|
|
586
|
+
if (spec.packageManager && !(await commandExistsAsync(spec.packageManager, basePath))) {
|
|
587
|
+
results.push({
|
|
588
|
+
name: "package_manager",
|
|
589
|
+
status: "warning",
|
|
590
|
+
message: `Project requires ${spec.packageManager} but it's not installed`,
|
|
591
|
+
detail: `Install with: npm install -g ${spec.packageManager}`,
|
|
592
|
+
});
|
|
593
|
+
}
|
|
594
|
+
if (spec.needsTsc) {
|
|
595
|
+
results.push({
|
|
596
|
+
name: "typescript",
|
|
597
|
+
status: "warning",
|
|
598
|
+
message: "TypeScript is a dependency but tsc is not available (run npm install)",
|
|
599
|
+
});
|
|
600
|
+
}
|
|
601
|
+
if (spec.needsPython && detectPythonExecutable() === null) {
|
|
602
|
+
results.push({ name: "python", status: "warning", message: "Project has Python config but python is not installed" });
|
|
603
|
+
}
|
|
604
|
+
if (spec.needsCargo && !(await commandExistsAsync("cargo", basePath))) {
|
|
605
|
+
results.push({ name: "cargo", status: "warning", message: "Project has Cargo.toml but cargo is not installed" });
|
|
606
|
+
}
|
|
607
|
+
if (spec.needsGo && !(await commandExistsAsync("go", basePath))) {
|
|
608
|
+
results.push({ name: "go", status: "warning", message: "Project has go.mod but go is not installed" });
|
|
609
|
+
}
|
|
610
|
+
return results;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
/**
|
|
614
|
+
* Non-blocking equivalent of `runEnvironmentChecks` for the health-widget
|
|
615
|
+
* background refresh. Cheap fs checks run inline; the subprocess-backed checks
|
|
616
|
+
* fan out concurrently so the whole suite costs ~max(check), not the sum.
|
|
617
|
+
*/
|
|
618
|
+
export async function runEnvironmentChecksAsync(basePath: string): Promise<EnvironmentCheckResult[]> {
|
|
619
|
+
const results: EnvironmentCheckResult[] = [];
|
|
620
|
+
|
|
621
|
+
// fs-only checks — already cheap and synchronous.
|
|
622
|
+
const depsCheck = checkDependenciesInstalled(basePath);
|
|
623
|
+
if (depsCheck) results.push(depsCheck);
|
|
624
|
+
const envCheck = checkEnvFiles(basePath);
|
|
625
|
+
if (envCheck) results.push(envCheck);
|
|
626
|
+
|
|
627
|
+
// subprocess-backed checks — run concurrently, off the event-loop critical path.
|
|
628
|
+
const [nodeCheck, portChecks, diskCheck, dockerCheck, toolChecks] = await Promise.all([
|
|
629
|
+
checkNodeVersionAsync(basePath),
|
|
630
|
+
checkPortConflictsAsync(basePath),
|
|
631
|
+
checkDiskSpaceAsync(basePath),
|
|
632
|
+
checkDockerAsync(basePath),
|
|
633
|
+
checkProjectToolsAsync(basePath),
|
|
634
|
+
]);
|
|
635
|
+
|
|
636
|
+
if (nodeCheck) results.push(nodeCheck);
|
|
637
|
+
results.push(...portChecks);
|
|
638
|
+
if (diskCheck) results.push(diskCheck);
|
|
639
|
+
if (dockerCheck) results.push(dockerCheck);
|
|
640
|
+
results.push(...toolChecks);
|
|
641
|
+
|
|
642
|
+
return results;
|
|
643
|
+
}
|
|
644
|
+
|
|
520
645
|
export function runEnvironmentChecks(basePath: string): EnvironmentCheckResult[] {
|
|
521
646
|
const results: EnvironmentCheckResult[] = [];
|
|
522
647
|
|
|
@@ -5,10 +5,9 @@ import { dirname, join } from "node:path";
|
|
|
5
5
|
|
|
6
6
|
import type { DoctorIssue, DoctorIssueCode } from "./doctor-types.js";
|
|
7
7
|
import { loadFile } from "./files.js";
|
|
8
|
-
import { parseRoadmap as parseLegacyRoadmap } from "./parsers-legacy.js";
|
|
9
|
-
import { isDbAvailable, getMilestone } from "./gsd-db.js";
|
|
10
8
|
import { resolveMilestoneFile } from "./paths.js";
|
|
11
|
-
import {
|
|
9
|
+
import { isCompletedMilestoneTerminal } from "./milestone-closeout.js";
|
|
10
|
+
import { deriveState } from "./state.js";
|
|
12
11
|
import { allWorktreesDirs, createWorktree, listWorktrees, resolveGitDir } from "./worktree-manager.js";
|
|
13
12
|
import { abortAndReset } from "./git-self-heal.js";
|
|
14
13
|
import { RUNTIME_EXCLUSION_PATHS, resolveMilestoneIntegrationBranch, writeIntegrationBranch } from "./git-service.js";
|
|
@@ -146,22 +145,6 @@ function getSnapshotDiffCheckFailure(basePath: string): string | null {
|
|
|
146
145
|
return failures.length > 0 ? failures.join("\n") : null;
|
|
147
146
|
}
|
|
148
147
|
|
|
149
|
-
async function isCompletedMilestoneTerminal(basePath: string, milestoneId: string): Promise<boolean> {
|
|
150
|
-
const summaryPath = resolveMilestoneFile(basePath, milestoneId, "SUMMARY");
|
|
151
|
-
if (!summaryPath) return false;
|
|
152
|
-
|
|
153
|
-
if (isDbAvailable()) {
|
|
154
|
-
const milestone = getMilestone(milestoneId);
|
|
155
|
-
return !!milestone && milestone.status === "complete";
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
const roadmapPath = resolveMilestoneFile(basePath, milestoneId, "ROADMAP");
|
|
159
|
-
const roadmapContent = roadmapPath ? await loadFile(roadmapPath) : null;
|
|
160
|
-
if (!roadmapContent) return false;
|
|
161
|
-
const roadmap = parseLegacyRoadmap(roadmapContent);
|
|
162
|
-
return isMilestoneComplete(roadmap);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
148
|
export async function checkGitHealth(
|
|
166
149
|
basePath: string,
|
|
167
150
|
issues: DoctorIssue[],
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// Project/App: gsd-pi
|
|
2
|
+
// File Purpose: Typed contract for which tool lifecycle hooks fire under which
|
|
3
|
+
// engine, plus the single seam for tool-name normalization.
|
|
4
|
+
//
|
|
5
|
+
// ── Why this contract exists ────────────────────────────────────────────────
|
|
6
|
+
// External engines (claude-code-cli) pre-execute tools inside the vendor CLI
|
|
7
|
+
// and hand the agent loop a `toolCall.externalResult`. The loop short-circuits
|
|
8
|
+
// before `beforeToolCall`/`afterToolCall` ever run for those calls
|
|
9
|
+
// (packages/pi-agent-core/src/agent-loop.ts, prepareToolCall: the
|
|
10
|
+
// externalResult branch returns an "immediate" outcome before the
|
|
11
|
+
// config.beforeToolCall invocation, and "immediate" outcomes skip
|
|
12
|
+
// finalizeExecutedToolCall where config.afterToolCall lives).
|
|
13
|
+
// `beforeToolCall`/`afterToolCall` are exactly what the extension runner maps
|
|
14
|
+
// to the `tool_call`/`tool_result` extension events
|
|
15
|
+
// (packages/gsd-agent-core/src/session/agent-session-extensions.ts,
|
|
16
|
+
// installAgentToolHooks).
|
|
17
|
+
//
|
|
18
|
+
// `tool_execution_start` is emitted unconditionally before prepareToolCall
|
|
19
|
+
// and `tool_execution_end` after every finalized outcome — immediate or
|
|
20
|
+
// executed — so those two are the ONLY tool lifecycle hooks that fire for
|
|
21
|
+
// every tool call on every engine.
|
|
22
|
+
//
|
|
23
|
+
// Consequence: any enforcement attached only to `tool_call` (blocking) or
|
|
24
|
+
// `tool_result` (rewriting) is silently dead under external engines. Safety
|
|
25
|
+
// enforcement must ride `tool_execution_start`/`tool_execution_end`, or
|
|
26
|
+
// mirror across both with toolCallId dedup. See the per-registration contract
|
|
27
|
+
// comments in bootstrap/register-hooks.ts for how each registered hook
|
|
28
|
+
// honors (or knowingly violates) this contract.
|
|
29
|
+
|
|
30
|
+
import { stripMcpToolPrefix } from "./mcp-tool-name.js";
|
|
31
|
+
import { canonicalWorkflowSurfaceToolName } from "./workflow-tool-surface.js";
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Tool lifecycle hooks that fire for EVERY tool call on EVERY engine,
|
|
35
|
+
* including external engines (claude-code-cli) that pre-execute tools.
|
|
36
|
+
* Attach safety-critical enforcement and evidence collection here.
|
|
37
|
+
*/
|
|
38
|
+
export const UNIVERSAL_TOOL_HOOKS = ["tool_execution_start", "tool_execution_end"] as const;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Tool lifecycle hooks that fire ONLY for natively executed tools. External
|
|
42
|
+
* engines pre-execute tools (externalResult), short-circuiting the agent
|
|
43
|
+
* loop's beforeToolCall/afterToolCall — so handlers on these events never run
|
|
44
|
+
* for those calls. Blocking guards attached only here are dead under external
|
|
45
|
+
* engines; they need a tool_execution_start mirror to be universal.
|
|
46
|
+
*/
|
|
47
|
+
export const NATIVE_ONLY_TOOL_HOOKS = ["tool_call", "tool_result"] as const;
|
|
48
|
+
|
|
49
|
+
export type UniversalToolHook = (typeof UNIVERSAL_TOOL_HOOKS)[number];
|
|
50
|
+
export type NativeOnlyToolHook = (typeof NATIVE_ONLY_TOOL_HOOKS)[number];
|
|
51
|
+
|
|
52
|
+
// Non-tool lifecycle events (session_start, agent_end, message_update, ...)
|
|
53
|
+
// are intentionally NOT classified here: they are emitted by the session
|
|
54
|
+
// host / extension runner independent of tool execution, so the external
|
|
55
|
+
// engine short-circuit above does not apply to them. Only classify events
|
|
56
|
+
// whose engine behavior has been verified against the agent loop.
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Canonical tool name: strips the `mcp__<server>__` prefix when present,
|
|
60
|
+
* nothing else. Use for identity checks against host/native tool names and
|
|
61
|
+
* for any guard that must NOT conflate workflow aliases with their canonical
|
|
62
|
+
* tools (e.g. write gates, evidence keys).
|
|
63
|
+
*
|
|
64
|
+
* Malformed MCP names (empty server or empty tool segment, e.g.
|
|
65
|
+
* `mcp____tool` or `mcp__server__`) are returned unchanged.
|
|
66
|
+
*/
|
|
67
|
+
export function canonicalToolName(toolName: string): string {
|
|
68
|
+
return stripMcpToolPrefix(toolName);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Workflow-aware canonical tool name: strips the MCP prefix AND resolves
|
|
73
|
+
* workflow tool aliases to their canonical contract names. Use whenever the
|
|
74
|
+
* name is compared against the workflow tool surface (scoping, presentation,
|
|
75
|
+
* dispatch) — plain {@link canonicalToolName} would miss alias spellings.
|
|
76
|
+
*/
|
|
77
|
+
export function canonicalWorkflowToolName(toolName: string): string {
|
|
78
|
+
return canonicalWorkflowSurfaceToolName(toolName);
|
|
79
|
+
}
|