gsd-pi 2.76.0 → 2.77.0
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 +45 -25
- package/dist/claude-cli-check.js +32 -3
- package/dist/mcp-server.d.ts +7 -0
- package/dist/mcp-server.js +35 -1
- package/dist/onboarding.js +45 -0
- package/dist/resource-loader.d.ts +1 -1
- package/dist/resource-loader.js +2 -8
- package/dist/resources/agents/researcher.md +1 -1
- package/dist/resources/extensions/claude-code-cli/readiness.js +31 -8
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +77 -17
- package/dist/resources/extensions/gsd/auto/loop.js +9 -0
- package/dist/resources/extensions/gsd/auto/phases.js +104 -11
- package/dist/resources/extensions/gsd/auto/run-unit.js +38 -2
- package/dist/resources/extensions/gsd/auto/session.js +22 -1
- package/dist/resources/extensions/gsd/auto-dispatch.js +16 -3
- package/dist/resources/extensions/gsd/auto-model-selection.js +53 -16
- package/dist/resources/extensions/gsd/auto-post-unit.js +25 -2
- package/dist/resources/extensions/gsd/auto-prompts.js +14 -0
- package/dist/resources/extensions/gsd/auto-recovery.js +32 -1
- package/dist/resources/extensions/gsd/auto-start.js +58 -57
- package/dist/resources/extensions/gsd/auto-verification.js +33 -0
- package/dist/resources/extensions/gsd/auto-worktree.js +51 -53
- package/dist/resources/extensions/gsd/auto.js +70 -28
- package/dist/resources/extensions/gsd/blocked-models.js +68 -0
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +93 -1
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +39 -9
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +93 -0
- package/dist/resources/extensions/gsd/bootstrap/memory-tools.js +3 -0
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +12 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +52 -6
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +84 -23
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +34 -2
- package/dist/resources/extensions/gsd/clean-root-preflight.js +93 -0
- package/dist/resources/extensions/gsd/commands-extract-learnings.js +54 -89
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +968 -23
- package/dist/resources/extensions/gsd/compaction-snapshot.js +121 -0
- package/dist/resources/extensions/gsd/complexity-classifier.js +5 -3
- package/dist/resources/extensions/gsd/db-writer.js +88 -16
- package/dist/resources/extensions/gsd/doctor-git-checks.js +23 -29
- package/dist/resources/extensions/gsd/doctor-providers.js +51 -5
- package/dist/resources/extensions/gsd/ecosystem/gsd-extension-api.js +1 -0
- package/dist/resources/extensions/gsd/error-classifier.js +31 -3
- package/dist/resources/extensions/gsd/exec-history.js +120 -0
- package/dist/resources/extensions/gsd/exec-sandbox.js +258 -0
- package/dist/resources/extensions/gsd/gitignore.js +1 -0
- package/dist/resources/extensions/gsd/gsd-db.js +168 -23
- package/dist/resources/extensions/gsd/guided-flow.js +190 -1
- package/dist/resources/extensions/gsd/health-widget.js +4 -1
- package/dist/resources/extensions/gsd/hook-emitter.js +108 -0
- package/dist/resources/extensions/gsd/init-wizard.js +15 -1
- package/dist/resources/extensions/gsd/key-manager.js +28 -0
- package/dist/resources/extensions/gsd/memory-backfill.js +126 -0
- package/dist/resources/extensions/gsd/memory-store.js +19 -0
- package/dist/resources/extensions/gsd/model-router.js +36 -3
- package/dist/resources/extensions/gsd/pre-execution-checks.js +44 -9
- package/dist/resources/extensions/gsd/preferences-types.js +9 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +83 -0
- package/dist/resources/extensions/gsd/preferences.js +17 -17
- package/dist/resources/extensions/gsd/prompt-loader.js +22 -7
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +2 -2
- package/dist/resources/extensions/gsd/prompts/debug-diagnose.md +2 -0
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +8 -0
- package/dist/resources/extensions/gsd/prompts/discuss.md +29 -2
- package/dist/resources/extensions/gsd/prompts/execute-task.md +3 -2
- package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +5 -2
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -0
- package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -0
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +96 -0
- package/dist/resources/extensions/gsd/safety/file-change-validator.js +13 -5
- package/dist/resources/extensions/gsd/safety/safety-harness.js +5 -1
- package/dist/resources/extensions/gsd/state.js +43 -4
- package/dist/resources/extensions/gsd/token-counter.js +22 -5
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +16 -10
- package/dist/resources/extensions/gsd/tools/exec-search-tool.js +59 -0
- package/dist/resources/extensions/gsd/tools/exec-tool.js +126 -0
- package/dist/resources/extensions/gsd/tools/memory-tools.js +26 -1
- package/dist/resources/extensions/gsd/tools/resume-tool.js +23 -0
- package/dist/resources/extensions/gsd/uok/plan-v2.js +20 -3
- package/dist/resources/extensions/gsd/workflow-mcp.js +3 -0
- package/dist/resources/extensions/gsd/workflow-templates/spike.md +6 -0
- package/dist/resources/extensions/gsd/worktree-resolver.js +50 -10
- package/dist/resources/extensions/search-the-web/command-search-provider.js +5 -4
- package/dist/resources/extensions/search-the-web/native-search.js +45 -13
- package/dist/resources/skills/api-design/SKILL.md +190 -0
- package/dist/resources/skills/create-mcp-server/SKILL.md +121 -0
- package/dist/resources/skills/decompose-into-slices/SKILL.md +139 -0
- package/dist/resources/skills/dependency-upgrade/SKILL.md +158 -0
- package/dist/resources/skills/design-an-interface/SKILL.md +102 -0
- package/dist/resources/skills/forensics/SKILL.md +153 -0
- package/dist/resources/skills/grill-me/SKILL.md +93 -0
- package/dist/resources/skills/handoff/SKILL.md +121 -0
- package/dist/resources/skills/observability/SKILL.md +174 -0
- package/dist/resources/skills/security-review/SKILL.md +181 -0
- package/dist/resources/skills/spike-wrap-up/SKILL.md +138 -0
- package/dist/resources/skills/tdd/SKILL.md +112 -0
- package/dist/resources/skills/verify-before-complete/SKILL.md +98 -0
- package/dist/resources/skills/write-docs/SKILL.md +82 -0
- package/dist/resources/skills/write-milestone-brief/SKILL.md +135 -0
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +10 -10
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/required-server-files.json +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.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/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 +10 -10
- package/dist/web/standalone/.next/server/chunks/6897.js +2 -2
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-manifest.json +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/server.js +1 -1
- package/dist/welcome-screen.js +6 -1
- package/dist/wizard.js +2 -0
- package/package.json +1 -1
- package/packages/daemon/package.json +2 -2
- package/packages/mcp-server/dist/remote-questions.d.ts +45 -0
- package/packages/mcp-server/dist/remote-questions.d.ts.map +1 -0
- package/packages/mcp-server/dist/remote-questions.js +732 -0
- package/packages/mcp-server/dist/remote-questions.js.map +1 -0
- package/packages/mcp-server/dist/server.d.ts +7 -0
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +70 -8
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/session-manager.d.ts +14 -0
- package/packages/mcp-server/dist/session-manager.d.ts.map +1 -1
- package/packages/mcp-server/dist/session-manager.js +49 -1
- package/packages/mcp-server/dist/session-manager.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +163 -25
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +4 -3
- package/packages/mcp-server/src/mcp-server.test.ts +67 -0
- package/packages/mcp-server/src/remote-questions.test.ts +294 -0
- package/packages/mcp-server/src/remote-questions.ts +916 -0
- package/packages/mcp-server/src/server.ts +89 -14
- package/packages/mcp-server/src/session-manager.ts +43 -1
- package/packages/mcp-server/src/workflow-tools.test.ts +146 -1
- package/packages/mcp-server/src/workflow-tools.ts +215 -43
- package/packages/mcp-server/tsconfig.test.json +19 -0
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +12 -0
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/dist/types.d.ts +30 -0
- package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/types.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-agent-core/src/agent-loop.ts +14 -0
- package/packages/pi-agent-core/src/types.ts +34 -0
- package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-ai/dist/models/custom.d.ts +38 -0
- package/packages/pi-ai/dist/models/custom.d.ts.map +1 -1
- package/packages/pi-ai/dist/models/custom.js +41 -0
- package/packages/pi-ai/dist/models/custom.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-auth.test.js +1 -1
- package/packages/pi-ai/dist/providers/anthropic-auth.test.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.js +13 -0
- package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.js.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.js +27 -4
- package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +13 -4
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/providers/minimax-tool-name.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/minimax-tool-name.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/minimax-tool-name.test.js +80 -0
- package/packages/pi-ai/dist/providers/minimax-tool-name.test.js.map +1 -0
- package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.js +60 -15
- package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
- package/packages/pi-ai/dist/providers/simple-options.d.ts +10 -0
- package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/simple-options.js +16 -1
- package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
- package/packages/pi-ai/dist/providers/think-tag-parser.d.ts +17 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.js +75 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.js.map +1 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.test.js +41 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.test.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 +12 -2
- package/packages/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/github-copilot.test.js +164 -14
- package/packages/pi-ai/dist/utils/oauth/github-copilot.test.js.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/google-antigravity.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/google-antigravity.js +15 -3
- package/packages/pi-ai/dist/utils/oauth/google-antigravity.js.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.d.ts +2 -0
- package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.js +67 -0
- package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.js.map +1 -0
- package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.js +16 -3
- package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.js.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.d.ts +2 -0
- package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.js +67 -0
- package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.js.map +1 -0
- package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts +2 -0
- package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js +289 -0
- package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js.map +1 -0
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-ai/src/models/custom.ts +42 -0
- package/packages/pi-ai/src/providers/anthropic-auth.test.ts +1 -1
- package/packages/pi-ai/src/providers/anthropic-bearer-auth.test.ts +26 -0
- package/packages/pi-ai/src/providers/anthropic-shared.ts +26 -5
- package/packages/pi-ai/src/providers/anthropic.ts +15 -4
- package/packages/pi-ai/src/providers/minimax-tool-name.test.ts +98 -0
- package/packages/pi-ai/src/providers/openai-completions.ts +57 -16
- package/packages/pi-ai/src/providers/simple-options.ts +17 -1
- package/packages/pi-ai/src/providers/think-tag-parser.test.ts +44 -0
- package/packages/pi-ai/src/providers/think-tag-parser.ts +94 -0
- package/packages/pi-ai/src/utils/oauth/github-copilot.test.ts +200 -23
- package/packages/pi-ai/src/utils/oauth/github-copilot.ts +12 -2
- package/packages/pi-ai/src/utils/oauth/google-antigravity.test.ts +84 -0
- package/packages/pi-ai/src/utils/oauth/google-antigravity.ts +15 -5
- package/packages/pi-ai/src/utils/oauth/google-gemini-cli.test.ts +84 -0
- package/packages/pi-ai/src/utils/oauth/google-gemini-cli.ts +16 -5
- package/packages/pi-ai/src/utils/oauth/oauth-providers.test.ts +363 -0
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +3 -2
- package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +32 -2
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +4 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +35 -2
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.js +233 -0
- package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +205 -2
- 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/hooks-runner.d.ts +53 -0
- package/packages/pi-coding-agent/dist/core/hooks-runner.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/hooks-runner.js +337 -0
- package/packages/pi-coding-agent/dist/core/hooks-runner.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/hooks-runner.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/hooks-runner.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/hooks-runner.test.js +234 -0
- package/packages/pi-coding-agent/dist/core/hooks-runner.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/index.d.ts +1 -0
- package/packages/pi-coding-agent/dist/core/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/index.js +1 -0
- package/packages/pi-coding-agent/dist/core/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-discovery.d.ts +3 -1
- package/packages/pi-coding-agent/dist/core/model-discovery.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-discovery.js +92 -12
- package/packages/pi-coding-agent/dist/core/model-discovery.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-discovery.test.js +16 -1
- package/packages/pi-coding-agent/dist/core/model-discovery.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry-auth-header.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/model-registry-auth-header.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry-auth-header.test.js +40 -0
- package/packages/pi-coding-agent/dist/core/model-registry-auth-header.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.js +203 -0
- package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry-discovery.test.js +61 -1
- package/packages/pi-coding-agent/dist/core/model-registry-discovery.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts +5 -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 +90 -10
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/redact-secrets.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.js +49 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.test.js +67 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager.js +10 -6
- package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager.test.js +45 -1
- package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +55 -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.map +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js +5 -4
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js +13 -7
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.d.ts +7 -6
- package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.js +29 -21
- package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +13 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +3 -2
- package/packages/pi-coding-agent/src/core/agent-session.ts +38 -2
- package/packages/pi-coding-agent/src/core/extensions/index.ts +16 -0
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +5 -0
- package/packages/pi-coding-agent/src/core/extensions/runner.ts +351 -0
- package/packages/pi-coding-agent/src/core/extensions/types.ts +258 -0
- package/packages/pi-coding-agent/src/core/hooks-runner.test.ts +269 -0
- package/packages/pi-coding-agent/src/core/hooks-runner.ts +460 -0
- package/packages/pi-coding-agent/src/core/index.ts +10 -0
- package/packages/pi-coding-agent/src/core/model-discovery.test.ts +19 -0
- package/packages/pi-coding-agent/src/core/model-discovery.ts +99 -12
- package/packages/pi-coding-agent/src/core/model-registry-auth-header.test.ts +44 -0
- package/packages/pi-coding-agent/src/core/model-registry-custom-caps.test.ts +245 -0
- package/packages/pi-coding-agent/src/core/model-registry-discovery.test.ts +75 -0
- package/packages/pi-coding-agent/src/core/model-registry.ts +102 -10
- package/packages/pi-coding-agent/src/core/redact-secrets.test.ts +86 -0
- package/packages/pi-coding-agent/src/core/redact-secrets.ts +58 -0
- package/packages/pi-coding-agent/src/core/session-manager.test.ts +65 -1
- package/packages/pi-coding-agent/src/core/session-manager.ts +10 -6
- package/packages/pi-coding-agent/src/core/settings-manager.ts +57 -0
- package/packages/pi-coding-agent/src/index.ts +16 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/chat-frame.ts +6 -6
- package/packages/pi-coding-agent/src/modes/interactive/components/provider-manager.ts +16 -7
- package/packages/pi-coding-agent/src/modes/interactive/components/skill-invocation-message.ts +36 -22
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +13 -1
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/package.json +1 -1
- package/packages/rpc-client/package.json +1 -1
- package/pkg/package.json +1 -1
- package/scripts/link-workspace-packages.cjs +1 -0
- package/src/resources/agents/researcher.md +1 -1
- package/src/resources/extensions/claude-code-cli/readiness.ts +32 -8
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +78 -17
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +149 -5
- package/src/resources/extensions/gsd/auto/loop-deps.ts +14 -0
- package/src/resources/extensions/gsd/auto/loop.ts +9 -0
- package/src/resources/extensions/gsd/auto/phases.ts +131 -10
- package/src/resources/extensions/gsd/auto/run-unit.ts +40 -2
- package/src/resources/extensions/gsd/auto/session.ts +35 -2
- package/src/resources/extensions/gsd/auto-dispatch.ts +16 -3
- package/src/resources/extensions/gsd/auto-model-selection.ts +71 -15
- package/src/resources/extensions/gsd/auto-post-unit.ts +29 -3
- package/src/resources/extensions/gsd/auto-prompts.ts +28 -1
- package/src/resources/extensions/gsd/auto-recovery.ts +26 -1
- package/src/resources/extensions/gsd/auto-start.ts +60 -68
- package/src/resources/extensions/gsd/auto-verification.ts +33 -0
- package/src/resources/extensions/gsd/auto-worktree.ts +62 -63
- package/src/resources/extensions/gsd/auto.ts +73 -28
- package/src/resources/extensions/gsd/blocked-models.ts +98 -0
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +120 -1
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +40 -9
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +109 -0
- package/src/resources/extensions/gsd/bootstrap/memory-tools.ts +5 -0
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +15 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +54 -6
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +89 -26
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +35 -2
- package/src/resources/extensions/gsd/clean-root-preflight.ts +111 -0
- package/src/resources/extensions/gsd/commands-extract-learnings.ts +55 -90
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +898 -32
- package/src/resources/extensions/gsd/compaction-snapshot.ts +165 -0
- package/src/resources/extensions/gsd/complexity-classifier.ts +5 -3
- package/src/resources/extensions/gsd/db-writer.ts +88 -17
- package/src/resources/extensions/gsd/doctor-git-checks.ts +23 -27
- package/src/resources/extensions/gsd/doctor-providers.ts +59 -6
- package/src/resources/extensions/gsd/ecosystem/gsd-extension-api.ts +2 -0
- package/src/resources/extensions/gsd/error-classifier.ts +36 -3
- package/src/resources/extensions/gsd/exec-history.ts +153 -0
- package/src/resources/extensions/gsd/exec-sandbox.ts +326 -0
- package/src/resources/extensions/gsd/gitignore.ts +1 -1
- package/src/resources/extensions/gsd/gsd-db.ts +186 -23
- package/src/resources/extensions/gsd/guided-flow.ts +222 -1
- package/src/resources/extensions/gsd/health-widget.ts +3 -1
- package/src/resources/extensions/gsd/hook-emitter.ts +188 -0
- package/src/resources/extensions/gsd/init-wizard.ts +15 -1
- package/src/resources/extensions/gsd/journal.ts +2 -1
- package/src/resources/extensions/gsd/key-manager.ts +28 -0
- package/src/resources/extensions/gsd/memory-backfill.ts +140 -0
- package/src/resources/extensions/gsd/memory-store.ts +26 -0
- package/src/resources/extensions/gsd/model-router.ts +42 -1
- package/src/resources/extensions/gsd/pre-execution-checks.ts +46 -10
- package/src/resources/extensions/gsd/preferences-types.ts +46 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +79 -0
- package/src/resources/extensions/gsd/preferences.ts +17 -17
- package/src/resources/extensions/gsd/prompt-loader.ts +30 -7
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/complete-slice.md +2 -2
- package/src/resources/extensions/gsd/prompts/debug-diagnose.md +2 -0
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +8 -0
- package/src/resources/extensions/gsd/prompts/discuss.md +29 -2
- package/src/resources/extensions/gsd/prompts/execute-task.md +3 -2
- package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +5 -2
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -0
- package/src/resources/extensions/gsd/prompts/research-slice.md +1 -0
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +119 -0
- package/src/resources/extensions/gsd/safety/file-change-validator.ts +17 -4
- package/src/resources/extensions/gsd/safety/safety-harness.ts +9 -0
- package/src/resources/extensions/gsd/state.ts +45 -4
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +188 -2
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +95 -1
- package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +49 -0
- package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +141 -0
- package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +33 -3
- package/src/resources/extensions/gsd/tests/auto-thinking-restore.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/blocked-models.test.ts +98 -0
- package/src/resources/extensions/gsd/tests/bundled-skill-triggers.test.ts +54 -0
- package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +186 -0
- package/src/resources/extensions/gsd/tests/commands-extract-learnings.test.ts +68 -66
- package/src/resources/extensions/gsd/tests/compaction-snapshot.test.ts +123 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +61 -1
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/complexity-classifier.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +8 -4
- package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +148 -3
- package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +306 -1
- package/src/resources/extensions/gsd/tests/escalation.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/exec-history.test.ts +237 -0
- package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +210 -0
- package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +58 -0
- package/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts +40 -9
- package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +447 -1
- package/src/resources/extensions/gsd/tests/init-wizard.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-git-symlink-cwd.test.ts +11 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-git.test.ts +78 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/integration/gitignore-tracked-gsd.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/integration/idle-recovery.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/interactive-routing-bypass.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/issue-4540-regressions.test.ts +288 -0
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/key-manager.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/load-memory-block.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/memory-pressure-stuck-state.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/plan-gate-failed-doctor-heal-hint.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/pre-exec-backtick-strip.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/pre-exec-gate-loop.test.ts +272 -0
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +356 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +110 -0
- package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/prompt-loader-extension-dir.test.ts +49 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +103 -4
- package/src/resources/extensions/gsd/tests/ready-phrase-no-files-4573.test.ts +388 -0
- package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +9 -3
- package/src/resources/extensions/gsd/tests/resume-dispatch-worktree.test.ts +230 -0
- package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +205 -0
- package/src/resources/extensions/gsd/tests/save-gate-result-render.test.ts +95 -0
- package/src/resources/extensions/gsd/tests/schema-v21-sequence.test.ts +413 -0
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +32 -40
- package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +56 -0
- package/src/resources/extensions/gsd/tests/token-counter.test.ts +105 -1
- package/src/resources/extensions/gsd/tests/tool-compatibility.test.ts +107 -0
- package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +9 -3
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +65 -2
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +78 -5
- package/src/resources/extensions/gsd/tests/write-gate.test.ts +64 -0
- package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +3 -1
- package/src/resources/extensions/gsd/token-counter.ts +22 -5
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +15 -9
- package/src/resources/extensions/gsd/tools/exec-search-tool.ts +81 -0
- package/src/resources/extensions/gsd/tools/exec-tool.ts +183 -0
- package/src/resources/extensions/gsd/tools/memory-tools.ts +31 -1
- package/src/resources/extensions/gsd/tools/resume-tool.ts +40 -0
- package/src/resources/extensions/gsd/uok/plan-v2.ts +26 -3
- package/src/resources/extensions/gsd/workflow-logger.ts +4 -1
- package/src/resources/extensions/gsd/workflow-mcp.ts +3 -0
- package/src/resources/extensions/gsd/workflow-templates/spike.md +6 -0
- package/src/resources/extensions/gsd/worktree-resolver.ts +54 -9
- package/src/resources/extensions/search-the-web/command-search-provider.ts +5 -4
- package/src/resources/extensions/search-the-web/native-search.ts +48 -12
- package/src/resources/skills/api-design/SKILL.md +190 -0
- package/src/resources/skills/create-mcp-server/SKILL.md +121 -0
- package/src/resources/skills/decompose-into-slices/SKILL.md +139 -0
- package/src/resources/skills/dependency-upgrade/SKILL.md +158 -0
- package/src/resources/skills/design-an-interface/SKILL.md +102 -0
- package/src/resources/skills/forensics/SKILL.md +153 -0
- package/src/resources/skills/grill-me/SKILL.md +93 -0
- package/src/resources/skills/handoff/SKILL.md +121 -0
- package/src/resources/skills/observability/SKILL.md +174 -0
- package/src/resources/skills/security-review/SKILL.md +181 -0
- package/src/resources/skills/spike-wrap-up/SKILL.md +138 -0
- package/src/resources/skills/tdd/SKILL.md +112 -0
- package/src/resources/skills/verify-before-complete/SKILL.md +98 -0
- package/src/resources/skills/write-docs/SKILL.md +82 -0
- package/src/resources/skills/write-milestone-brief/SKILL.md +135 -0
- /package/dist/web/standalone/.next/static/{ssX7BLv3Dw9Fb4CtrCGeR → pV-mPo7rYGb5JBC09C8GG}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{ssX7BLv3Dw9Fb4CtrCGeR → pV-mPo7rYGb5JBC09C8GG}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
// GSD Exec Sandbox — tool-output sandboxing for sub-sessions.
|
|
2
|
+
//
|
|
3
|
+
// Runs a script in a subprocess and persists stdout/stderr to
|
|
4
|
+
// `.gsd/exec/<id>.{stdout,stderr,meta.json}`. Only a short digest is
|
|
5
|
+
// returned to the calling agent's context, keeping large outputs
|
|
6
|
+
// (e.g. Playwright snapshots, issue dumps) out of the window.
|
|
7
|
+
//
|
|
8
|
+
// Inspired by mksglu/context-mode (Elastic License 2.0). Independent
|
|
9
|
+
// implementation — no upstream code incorporated.
|
|
10
|
+
import { spawn } from "node:child_process";
|
|
11
|
+
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
12
|
+
import { randomUUID } from "node:crypto";
|
|
13
|
+
import { resolve } from "node:path";
|
|
14
|
+
const ALWAYS_FORWARD_ENV = ["PATH", "HOME"];
|
|
15
|
+
export const EXEC_DEFAULTS = {
|
|
16
|
+
clampTimeoutMs: 600_000,
|
|
17
|
+
defaultTimeoutMs: 30_000,
|
|
18
|
+
stdoutCapBytes: 1_048_576,
|
|
19
|
+
stderrCapBytes: 262_144,
|
|
20
|
+
digestChars: 300,
|
|
21
|
+
envAllowlist: [
|
|
22
|
+
"LANG",
|
|
23
|
+
"LC_ALL",
|
|
24
|
+
"TERM",
|
|
25
|
+
"TZ",
|
|
26
|
+
"SHELL",
|
|
27
|
+
"USER",
|
|
28
|
+
"LOGNAME",
|
|
29
|
+
"TMPDIR",
|
|
30
|
+
"NODE_OPTIONS",
|
|
31
|
+
"PYTHONPATH",
|
|
32
|
+
"PYTHONIOENCODING",
|
|
33
|
+
],
|
|
34
|
+
};
|
|
35
|
+
function buildChildEnv(opts) {
|
|
36
|
+
const source = opts.env ?? process.env;
|
|
37
|
+
const out = {};
|
|
38
|
+
const allowed = new Set([...ALWAYS_FORWARD_ENV, ...opts.env_allowlist]);
|
|
39
|
+
for (const key of allowed) {
|
|
40
|
+
const value = source[key];
|
|
41
|
+
if (typeof value === "string")
|
|
42
|
+
out[key] = value;
|
|
43
|
+
}
|
|
44
|
+
return out;
|
|
45
|
+
}
|
|
46
|
+
function clampTimeout(request, opts) {
|
|
47
|
+
const requested = typeof request.timeout_ms === "number" && Number.isFinite(request.timeout_ms)
|
|
48
|
+
? Math.floor(request.timeout_ms)
|
|
49
|
+
: opts.default_timeout_ms;
|
|
50
|
+
if (requested < 1)
|
|
51
|
+
return 1;
|
|
52
|
+
if (requested > opts.clamp_timeout_ms)
|
|
53
|
+
return opts.clamp_timeout_ms;
|
|
54
|
+
return requested;
|
|
55
|
+
}
|
|
56
|
+
function resolveCommand(runtime) {
|
|
57
|
+
switch (runtime) {
|
|
58
|
+
case "bash":
|
|
59
|
+
return { cmd: "bash", args: ["-c"] };
|
|
60
|
+
case "node":
|
|
61
|
+
return { cmd: process.execPath, args: ["-e"] };
|
|
62
|
+
case "python":
|
|
63
|
+
return { cmd: "python3", args: ["-c"] };
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function tail(buf, chars) {
|
|
67
|
+
if (chars <= 0)
|
|
68
|
+
return "";
|
|
69
|
+
const text = buf.toString("utf-8");
|
|
70
|
+
return text.length <= chars ? text : text.slice(text.length - chars);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Run a script in a subprocess, capture stdout/stderr to files under
|
|
74
|
+
* `.gsd/exec/<id>.{stdout,stderr,meta.json}`, and return an `ExecSandboxResult`
|
|
75
|
+
* containing the digest plus metadata.
|
|
76
|
+
*
|
|
77
|
+
* Errors from spawn failures resolve (not reject) with `exit_code=null`.
|
|
78
|
+
* The function is pure with respect to its inputs — no global state beyond
|
|
79
|
+
* filesystem writes under `baseDir`.
|
|
80
|
+
*/
|
|
81
|
+
export function runExecSandbox(request, opts) {
|
|
82
|
+
return new Promise((resolveP) => {
|
|
83
|
+
const id = (opts.generateId ?? defaultGenerateId)();
|
|
84
|
+
const now = (opts.now ?? (() => new Date()))();
|
|
85
|
+
const execDir = resolve(opts.baseDir, ".gsd", "exec");
|
|
86
|
+
if (!existsSync(execDir))
|
|
87
|
+
mkdirSync(execDir, { recursive: true });
|
|
88
|
+
const stdoutPath = resolve(execDir, `${id}.stdout`);
|
|
89
|
+
const stderrPath = resolve(execDir, `${id}.stderr`);
|
|
90
|
+
const metaPath = resolve(execDir, `${id}.meta.json`);
|
|
91
|
+
const timeoutMs = clampTimeout(request, opts);
|
|
92
|
+
const { cmd, args } = resolveCommand(request.runtime);
|
|
93
|
+
const env = buildChildEnv(opts);
|
|
94
|
+
const useProcessGroup = process.platform !== "win32";
|
|
95
|
+
const started = Date.now();
|
|
96
|
+
let child;
|
|
97
|
+
try {
|
|
98
|
+
child = spawn(cmd, [...args, request.script], {
|
|
99
|
+
cwd: opts.baseDir,
|
|
100
|
+
env,
|
|
101
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
102
|
+
...(useProcessGroup ? { detached: true } : {}),
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
catch (err) {
|
|
106
|
+
const duration = Date.now() - started;
|
|
107
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
108
|
+
writeFileSync(stdoutPath, "");
|
|
109
|
+
writeFileSync(stderrPath, `spawn error: ${message}\n`);
|
|
110
|
+
const result = {
|
|
111
|
+
id,
|
|
112
|
+
runtime: request.runtime,
|
|
113
|
+
exit_code: null,
|
|
114
|
+
signal: null,
|
|
115
|
+
timed_out: false,
|
|
116
|
+
duration_ms: duration,
|
|
117
|
+
stdout_bytes: 0,
|
|
118
|
+
stderr_bytes: Buffer.byteLength(`spawn error: ${message}\n`),
|
|
119
|
+
stdout_truncated: false,
|
|
120
|
+
stderr_truncated: false,
|
|
121
|
+
stdout_path: stdoutPath,
|
|
122
|
+
stderr_path: stderrPath,
|
|
123
|
+
meta_path: metaPath,
|
|
124
|
+
digest: `[spawn error: ${message}]`,
|
|
125
|
+
};
|
|
126
|
+
writeMeta(metaPath, result, request, now);
|
|
127
|
+
resolveP(result);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const stdoutChunks = [];
|
|
131
|
+
const stderrChunks = [];
|
|
132
|
+
let stdoutBytes = 0;
|
|
133
|
+
let stderrBytes = 0;
|
|
134
|
+
let stdoutTruncated = false;
|
|
135
|
+
let stderrTruncated = false;
|
|
136
|
+
child.stdout?.on("data", (chunk) => {
|
|
137
|
+
const remaining = opts.stdout_cap_bytes - stdoutBytes;
|
|
138
|
+
if (remaining <= 0) {
|
|
139
|
+
stdoutTruncated = true;
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
if (chunk.length <= remaining) {
|
|
143
|
+
stdoutChunks.push(chunk);
|
|
144
|
+
stdoutBytes += chunk.length;
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
stdoutChunks.push(chunk.subarray(0, remaining));
|
|
148
|
+
stdoutBytes += remaining;
|
|
149
|
+
stdoutTruncated = true;
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
child.stderr?.on("data", (chunk) => {
|
|
153
|
+
const remaining = opts.stderr_cap_bytes - stderrBytes;
|
|
154
|
+
if (remaining <= 0) {
|
|
155
|
+
stderrTruncated = true;
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
if (chunk.length <= remaining) {
|
|
159
|
+
stderrChunks.push(chunk);
|
|
160
|
+
stderrBytes += chunk.length;
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
stderrChunks.push(chunk.subarray(0, remaining));
|
|
164
|
+
stderrBytes += remaining;
|
|
165
|
+
stderrTruncated = true;
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
let timedOut = false;
|
|
169
|
+
const timer = setTimeout(() => {
|
|
170
|
+
timedOut = true;
|
|
171
|
+
if (useProcessGroup && child.pid != null) {
|
|
172
|
+
try {
|
|
173
|
+
process.kill(-child.pid, "SIGKILL");
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
child.kill("SIGKILL");
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
child.kill("SIGKILL");
|
|
181
|
+
}
|
|
182
|
+
}, timeoutMs);
|
|
183
|
+
timer.unref?.();
|
|
184
|
+
const finalize = (exitCode, signal) => {
|
|
185
|
+
clearTimeout(timer);
|
|
186
|
+
const duration = Date.now() - started;
|
|
187
|
+
const stdoutBuf = Buffer.concat(stdoutChunks);
|
|
188
|
+
const stderrBuf = Buffer.concat(stderrChunks);
|
|
189
|
+
const stdoutSuffix = stdoutTruncated ? "\n[truncated: stdout cap reached]\n" : "";
|
|
190
|
+
const stderrSuffix = stderrTruncated ? "\n[truncated: stderr cap reached]\n" : "";
|
|
191
|
+
writeFileSync(stdoutPath, Buffer.concat([stdoutBuf, Buffer.from(stdoutSuffix, "utf-8")]));
|
|
192
|
+
writeFileSync(stderrPath, Buffer.concat([stderrBuf, Buffer.from(stderrSuffix, "utf-8")]));
|
|
193
|
+
const digestBody = tail(stdoutBuf, opts.digest_chars);
|
|
194
|
+
const digest = digestBody.length > 0
|
|
195
|
+
? digestBody
|
|
196
|
+
: timedOut
|
|
197
|
+
? "[no stdout — timed out]"
|
|
198
|
+
: stderrBuf.length > 0
|
|
199
|
+
? `[no stdout — tail of stderr]\n${tail(stderrBuf, opts.digest_chars)}`
|
|
200
|
+
: "[no output]";
|
|
201
|
+
const result = {
|
|
202
|
+
id,
|
|
203
|
+
runtime: request.runtime,
|
|
204
|
+
exit_code: exitCode,
|
|
205
|
+
signal,
|
|
206
|
+
timed_out: timedOut,
|
|
207
|
+
duration_ms: duration,
|
|
208
|
+
stdout_bytes: stdoutBytes,
|
|
209
|
+
stderr_bytes: stderrBytes,
|
|
210
|
+
stdout_truncated: stdoutTruncated,
|
|
211
|
+
stderr_truncated: stderrTruncated,
|
|
212
|
+
stdout_path: stdoutPath,
|
|
213
|
+
stderr_path: stderrPath,
|
|
214
|
+
meta_path: metaPath,
|
|
215
|
+
digest,
|
|
216
|
+
};
|
|
217
|
+
writeMeta(metaPath, result, request, now);
|
|
218
|
+
resolveP(result);
|
|
219
|
+
};
|
|
220
|
+
child.on("error", (err) => {
|
|
221
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
222
|
+
const line = `child error: ${message}\n`;
|
|
223
|
+
const remaining = opts.stderr_cap_bytes - stderrBytes;
|
|
224
|
+
if (remaining > 0) {
|
|
225
|
+
const chunk = Buffer.from(line, "utf-8").subarray(0, remaining);
|
|
226
|
+
stderrChunks.push(chunk);
|
|
227
|
+
stderrBytes += chunk.length;
|
|
228
|
+
if (chunk.length < Buffer.byteLength(line, "utf-8"))
|
|
229
|
+
stderrTruncated = true;
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
child.on("close", (code, signal) => finalize(code, signal));
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
function defaultGenerateId() {
|
|
236
|
+
return randomUUID();
|
|
237
|
+
}
|
|
238
|
+
function writeMeta(path, result, request, now) {
|
|
239
|
+
const meta = {
|
|
240
|
+
id: result.id,
|
|
241
|
+
runtime: result.runtime,
|
|
242
|
+
purpose: request.purpose ?? null,
|
|
243
|
+
script_chars: request.script.length,
|
|
244
|
+
started_at: now.toISOString(),
|
|
245
|
+
finished_at: new Date(now.getTime() + result.duration_ms).toISOString(),
|
|
246
|
+
exit_code: result.exit_code,
|
|
247
|
+
signal: result.signal,
|
|
248
|
+
timed_out: result.timed_out,
|
|
249
|
+
duration_ms: result.duration_ms,
|
|
250
|
+
stdout_bytes: result.stdout_bytes,
|
|
251
|
+
stderr_bytes: result.stderr_bytes,
|
|
252
|
+
stdout_truncated: result.stdout_truncated,
|
|
253
|
+
stderr_truncated: result.stderr_truncated,
|
|
254
|
+
stdout_path: result.stdout_path,
|
|
255
|
+
stderr_path: result.stderr_path,
|
|
256
|
+
};
|
|
257
|
+
writeFileSync(path, `${JSON.stringify(meta, null, 2)}\n`);
|
|
258
|
+
}
|
|
@@ -135,7 +135,7 @@ function openRawDb(path) {
|
|
|
135
135
|
const Database = providerModule;
|
|
136
136
|
return new Database(path);
|
|
137
137
|
}
|
|
138
|
-
const SCHEMA_VERSION =
|
|
138
|
+
const SCHEMA_VERSION = 22;
|
|
139
139
|
function indexExists(db, name) {
|
|
140
140
|
return !!db.prepare("SELECT 1 as present FROM sqlite_master WHERE type = 'index' AND name = ?").get(name);
|
|
141
141
|
}
|
|
@@ -234,7 +234,8 @@ function initSchema(db, fileBacked) {
|
|
|
234
234
|
superseded_by TEXT DEFAULT NULL,
|
|
235
235
|
hit_count INTEGER NOT NULL DEFAULT 0,
|
|
236
236
|
scope TEXT NOT NULL DEFAULT 'project',
|
|
237
|
-
tags TEXT NOT NULL DEFAULT '[]'
|
|
237
|
+
tags TEXT NOT NULL DEFAULT '[]',
|
|
238
|
+
structured_fields TEXT DEFAULT NULL
|
|
238
239
|
)
|
|
239
240
|
`);
|
|
240
241
|
db.exec(`
|
|
@@ -490,11 +491,6 @@ function initSchema(db, fileBacked) {
|
|
|
490
491
|
)
|
|
491
492
|
`);
|
|
492
493
|
db.exec("CREATE INDEX IF NOT EXISTS idx_memories_active ON memories(superseded_by)");
|
|
493
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_memories_scope ON memories(scope)");
|
|
494
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_memory_sources_kind ON memory_sources(kind)");
|
|
495
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_memory_sources_scope ON memory_sources(scope)");
|
|
496
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_memory_relations_from ON memory_relations(from_id)");
|
|
497
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_memory_relations_to ON memory_relations(to_id)");
|
|
498
494
|
db.exec("CREATE INDEX IF NOT EXISTS idx_replan_history_milestone ON replan_history(milestone_id, created_at)");
|
|
499
495
|
// v13 indexes — hot-path dispatch queries
|
|
500
496
|
db.exec("CREATE INDEX IF NOT EXISTS idx_tasks_active ON tasks(milestone_id, slice_id, status)");
|
|
@@ -510,14 +506,21 @@ function initSchema(db, fileBacked) {
|
|
|
510
506
|
db.exec("CREATE INDEX IF NOT EXISTS idx_turn_git_tx_turn ON turn_git_transactions(trace_id, turn_id)");
|
|
511
507
|
db.exec("CREATE INDEX IF NOT EXISTS idx_audit_events_trace ON audit_events(trace_id, ts)");
|
|
512
508
|
db.exec("CREATE INDEX IF NOT EXISTS idx_audit_events_turn ON audit_events(trace_id, turn_id, ts)");
|
|
513
|
-
// ADR-011 Phase 2 — also created by the v17 migration; fresh installs
|
|
514
|
-
// skip migrations so the index must be created here too.
|
|
515
|
-
db.exec("CREATE INDEX IF NOT EXISTS idx_tasks_escalation_pending ON tasks(milestone_id, slice_id, escalation_pending)");
|
|
516
509
|
db.exec(`CREATE VIEW IF NOT EXISTS active_decisions AS SELECT * FROM decisions WHERE superseded_by IS NULL`);
|
|
517
510
|
db.exec(`CREATE VIEW IF NOT EXISTS active_requirements AS SELECT * FROM requirements WHERE superseded_by IS NULL`);
|
|
518
511
|
db.exec(`CREATE VIEW IF NOT EXISTS active_memories AS SELECT * FROM memories WHERE superseded_by IS NULL`);
|
|
519
512
|
const existing = db.prepare("SELECT count(*) as cnt FROM schema_version").get();
|
|
520
513
|
if (existing && existing["cnt"] === 0) {
|
|
514
|
+
// Fresh install — all tables are created above with the full current schema,
|
|
515
|
+
// so it is safe to create all migration-specific indexes here. For existing
|
|
516
|
+
// databases these indexes are created inside the individual migration guards
|
|
517
|
+
// in migrateSchema() after the corresponding columns have been added.
|
|
518
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_tasks_escalation_pending ON tasks(milestone_id, slice_id, escalation_pending)");
|
|
519
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_memories_scope ON memories(scope)");
|
|
520
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_memory_sources_kind ON memory_sources(kind)");
|
|
521
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_memory_sources_scope ON memory_sources(scope)");
|
|
522
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_memory_relations_from ON memory_relations(from_id)");
|
|
523
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_memory_relations_to ON memory_relations(to_id)");
|
|
521
524
|
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
522
525
|
":version": SCHEMA_VERSION,
|
|
523
526
|
":applied_at": new Date().toISOString(),
|
|
@@ -842,19 +845,24 @@ function migrateSchema(db) {
|
|
|
842
845
|
});
|
|
843
846
|
}
|
|
844
847
|
if (currentVersion < 12) {
|
|
848
|
+
// NOTE: The original DDL used COALESCE(task_id, '') in the PRIMARY KEY
|
|
849
|
+
// expression, which is invalid SQLite syntax and causes startup errors on
|
|
850
|
+
// DBs that migrate through v12. The corrected DDL uses
|
|
851
|
+
// task_id TEXT NOT NULL DEFAULT '' with a plain column list PK. DBs that
|
|
852
|
+
// were created with the broken DDL are repaired by the v22 migration below.
|
|
845
853
|
db.exec(`
|
|
846
854
|
CREATE TABLE IF NOT EXISTS quality_gates (
|
|
847
855
|
milestone_id TEXT NOT NULL,
|
|
848
856
|
slice_id TEXT NOT NULL,
|
|
849
857
|
gate_id TEXT NOT NULL,
|
|
850
858
|
scope TEXT NOT NULL DEFAULT 'slice',
|
|
851
|
-
task_id TEXT DEFAULT
|
|
859
|
+
task_id TEXT NOT NULL DEFAULT '',
|
|
852
860
|
status TEXT NOT NULL DEFAULT 'pending',
|
|
853
861
|
verdict TEXT NOT NULL DEFAULT '',
|
|
854
862
|
rationale TEXT NOT NULL DEFAULT '',
|
|
855
863
|
findings TEXT NOT NULL DEFAULT '',
|
|
856
864
|
evaluated_at TEXT DEFAULT NULL,
|
|
857
|
-
PRIMARY KEY (milestone_id, slice_id, gate_id,
|
|
865
|
+
PRIMARY KEY (milestone_id, slice_id, gate_id, task_id),
|
|
858
866
|
FOREIGN KEY (milestone_id, slice_id) REFERENCES slices(milestone_id, id)
|
|
859
867
|
)
|
|
860
868
|
`);
|
|
@@ -1006,6 +1014,10 @@ function migrateSchema(db) {
|
|
|
1006
1014
|
tags TEXT NOT NULL DEFAULT '[]'
|
|
1007
1015
|
)
|
|
1008
1016
|
`);
|
|
1017
|
+
// If memory_sources already existed before v18 (created by an earlier
|
|
1018
|
+
// version of initSchema that lacked scope/tags), add the missing columns.
|
|
1019
|
+
ensureColumn(db, "memory_sources", "scope", `ALTER TABLE memory_sources ADD COLUMN scope TEXT NOT NULL DEFAULT 'project'`);
|
|
1020
|
+
ensureColumn(db, "memory_sources", "tags", `ALTER TABLE memory_sources ADD COLUMN tags TEXT NOT NULL DEFAULT '[]'`);
|
|
1009
1021
|
db.exec("CREATE INDEX IF NOT EXISTS idx_memories_scope ON memories(scope)");
|
|
1010
1022
|
db.exec("CREATE INDEX IF NOT EXISTS idx_memory_sources_kind ON memory_sources(kind)");
|
|
1011
1023
|
db.exec("CREATE INDEX IF NOT EXISTS idx_memory_sources_scope ON memory_sources(scope)");
|
|
@@ -1059,6 +1071,65 @@ function migrateSchema(db) {
|
|
|
1059
1071
|
":applied_at": new Date().toISOString(),
|
|
1060
1072
|
});
|
|
1061
1073
|
}
|
|
1074
|
+
if (currentVersion < 21) {
|
|
1075
|
+
// ADR-013 Step 2: preserve structured fields (gsd_save_decision's
|
|
1076
|
+
// scope/decision/choice/rationale/made_by/revisable) on memories rows so
|
|
1077
|
+
// the eventual decisions->memories cutover does not lose schema fidelity.
|
|
1078
|
+
// Nullable JSON column — existing rows stay NULL until backfilled in Step 5.
|
|
1079
|
+
// Use ensureColumn for race-safety (matches v15-v18 pattern; bare ALTER
|
|
1080
|
+
// throws "duplicate column" on the loser of a concurrent open race even
|
|
1081
|
+
// though the transaction wrapper protects the schema_version row).
|
|
1082
|
+
ensureColumn(db, "memories", "structured_fields", "ALTER TABLE memories ADD COLUMN structured_fields TEXT DEFAULT NULL");
|
|
1083
|
+
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
1084
|
+
":version": 21,
|
|
1085
|
+
":applied_at": new Date().toISOString(),
|
|
1086
|
+
});
|
|
1087
|
+
}
|
|
1088
|
+
if (currentVersion < 22) {
|
|
1089
|
+
// v22: Repair quality_gates tables that were created by the broken v12
|
|
1090
|
+
// migration (which used COALESCE(task_id, '') as a PK expression — invalid
|
|
1091
|
+
// SQLite DDL). Those DBs have task_id nullable (dflt_value NULL, notnull 0).
|
|
1092
|
+
// Rebuild the table with the correct schema, migrating existing rows via
|
|
1093
|
+
// COALESCE so no data is lost.
|
|
1094
|
+
const qgInfo = db.prepare("PRAGMA table_info(quality_gates)").all();
|
|
1095
|
+
const taskIdCol = qgInfo.find((r) => r["name"] === "task_id");
|
|
1096
|
+
const needsRepair = taskIdCol && (taskIdCol["notnull"] === 0 || taskIdCol["notnull"] === "0");
|
|
1097
|
+
if (needsRepair) {
|
|
1098
|
+
db.exec(`
|
|
1099
|
+
CREATE TABLE quality_gates_new (
|
|
1100
|
+
milestone_id TEXT NOT NULL,
|
|
1101
|
+
slice_id TEXT NOT NULL,
|
|
1102
|
+
gate_id TEXT NOT NULL,
|
|
1103
|
+
scope TEXT NOT NULL DEFAULT 'slice',
|
|
1104
|
+
task_id TEXT NOT NULL DEFAULT '',
|
|
1105
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
1106
|
+
verdict TEXT NOT NULL DEFAULT '',
|
|
1107
|
+
rationale TEXT NOT NULL DEFAULT '',
|
|
1108
|
+
findings TEXT NOT NULL DEFAULT '',
|
|
1109
|
+
evaluated_at TEXT DEFAULT NULL,
|
|
1110
|
+
PRIMARY KEY (milestone_id, slice_id, gate_id, task_id),
|
|
1111
|
+
FOREIGN KEY (milestone_id, slice_id) REFERENCES slices(milestone_id, id)
|
|
1112
|
+
)
|
|
1113
|
+
`);
|
|
1114
|
+
db.exec(`
|
|
1115
|
+
INSERT OR IGNORE INTO quality_gates_new
|
|
1116
|
+
(milestone_id, slice_id, gate_id, scope, task_id, status, verdict, rationale, findings, evaluated_at)
|
|
1117
|
+
SELECT milestone_id, slice_id, gate_id, scope, COALESCE(task_id, ''), status, verdict, rationale, findings, evaluated_at
|
|
1118
|
+
FROM quality_gates
|
|
1119
|
+
`);
|
|
1120
|
+
db.exec("DROP TABLE quality_gates");
|
|
1121
|
+
db.exec("ALTER TABLE quality_gates_new RENAME TO quality_gates");
|
|
1122
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_quality_gates_pending ON quality_gates(milestone_id, slice_id, status)");
|
|
1123
|
+
}
|
|
1124
|
+
// Ensure scope column exists on quality_gates and assessments (guard
|
|
1125
|
+
// against DBs that somehow lack it after a partial migration).
|
|
1126
|
+
ensureColumn(db, "quality_gates", "scope", "ALTER TABLE quality_gates ADD COLUMN scope TEXT NOT NULL DEFAULT 'slice'");
|
|
1127
|
+
ensureColumn(db, "assessments", "scope", "ALTER TABLE assessments ADD COLUMN scope TEXT NOT NULL DEFAULT ''");
|
|
1128
|
+
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
1129
|
+
":version": 22,
|
|
1130
|
+
":applied_at": new Date().toISOString(),
|
|
1131
|
+
});
|
|
1132
|
+
}
|
|
1062
1133
|
db.exec("COMMIT");
|
|
1063
1134
|
}
|
|
1064
1135
|
catch (err) {
|
|
@@ -1071,6 +1142,8 @@ let currentPath = null;
|
|
|
1071
1142
|
let currentPid = 0;
|
|
1072
1143
|
let _exitHandlerRegistered = false;
|
|
1073
1144
|
let _dbOpenAttempted = false;
|
|
1145
|
+
let _lastDbError = null;
|
|
1146
|
+
let _lastDbPhase = null;
|
|
1074
1147
|
export function getDbProvider() {
|
|
1075
1148
|
loadProvider();
|
|
1076
1149
|
return providerName;
|
|
@@ -1087,13 +1160,54 @@ export function isDbAvailable() {
|
|
|
1087
1160
|
export function wasDbOpenAttempted() {
|
|
1088
1161
|
return _dbOpenAttempted;
|
|
1089
1162
|
}
|
|
1163
|
+
export function getDbStatus() {
|
|
1164
|
+
loadProvider();
|
|
1165
|
+
return {
|
|
1166
|
+
available: currentDb !== null,
|
|
1167
|
+
provider: providerName,
|
|
1168
|
+
attempted: _dbOpenAttempted,
|
|
1169
|
+
lastError: _lastDbError,
|
|
1170
|
+
lastPhase: _lastDbPhase,
|
|
1171
|
+
};
|
|
1172
|
+
}
|
|
1090
1173
|
export function openDatabase(path) {
|
|
1091
1174
|
_dbOpenAttempted = true;
|
|
1092
1175
|
if (currentDb && currentPath !== path)
|
|
1093
1176
|
closeDatabase();
|
|
1094
1177
|
if (currentDb && currentPath === path)
|
|
1095
1178
|
return true;
|
|
1096
|
-
|
|
1179
|
+
// Reset error state only when a new open attempt is actually going to run.
|
|
1180
|
+
_lastDbError = null;
|
|
1181
|
+
_lastDbPhase = null;
|
|
1182
|
+
let rawDb;
|
|
1183
|
+
let fallbackProvider = null;
|
|
1184
|
+
let fallbackModule = null;
|
|
1185
|
+
try {
|
|
1186
|
+
rawDb = openRawDb(path);
|
|
1187
|
+
}
|
|
1188
|
+
catch (primaryErr) {
|
|
1189
|
+
_lastDbPhase = "open";
|
|
1190
|
+
_lastDbError = primaryErr instanceof Error ? primaryErr : new Error(String(primaryErr));
|
|
1191
|
+
// node:sqlite loaded but failed to open this file — try better-sqlite3 as fallback.
|
|
1192
|
+
if (providerName === "node:sqlite") {
|
|
1193
|
+
try {
|
|
1194
|
+
const mod = _require("better-sqlite3");
|
|
1195
|
+
const Db = (mod && mod.default) ? mod.default : mod;
|
|
1196
|
+
if (typeof Db === "function") {
|
|
1197
|
+
rawDb = new Db(path);
|
|
1198
|
+
fallbackProvider = "better-sqlite3";
|
|
1199
|
+
fallbackModule = Db;
|
|
1200
|
+
_lastDbError = null;
|
|
1201
|
+
_lastDbPhase = null;
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
catch {
|
|
1205
|
+
// fallback unavailable; surface original error
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
if (!rawDb)
|
|
1209
|
+
throw primaryErr;
|
|
1210
|
+
}
|
|
1097
1211
|
if (!rawDb)
|
|
1098
1212
|
return false;
|
|
1099
1213
|
const adapter = createAdapter(rawDb);
|
|
@@ -1111,6 +1225,8 @@ export function openDatabase(path) {
|
|
|
1111
1225
|
process.stderr.write("gsd-db: recovered corrupt database via VACUUM\n");
|
|
1112
1226
|
}
|
|
1113
1227
|
catch (retryErr) {
|
|
1228
|
+
_lastDbPhase = "vacuum-recovery";
|
|
1229
|
+
_lastDbError = retryErr instanceof Error ? retryErr : new Error(String(retryErr));
|
|
1114
1230
|
try {
|
|
1115
1231
|
adapter.close();
|
|
1116
1232
|
}
|
|
@@ -1121,15 +1237,22 @@ export function openDatabase(path) {
|
|
|
1121
1237
|
}
|
|
1122
1238
|
}
|
|
1123
1239
|
else {
|
|
1240
|
+
_lastDbPhase = "initSchema";
|
|
1241
|
+
_lastDbError = err instanceof Error ? err : new Error(String(err));
|
|
1124
1242
|
try {
|
|
1125
1243
|
adapter.close();
|
|
1126
1244
|
}
|
|
1127
1245
|
catch (e) {
|
|
1128
|
-
logWarning("db", `close after
|
|
1246
|
+
logWarning("db", `close after initSchema failed: ${e.message}`);
|
|
1129
1247
|
}
|
|
1130
1248
|
throw err;
|
|
1131
1249
|
}
|
|
1132
1250
|
}
|
|
1251
|
+
// Commit fallback provider switch only after open + schema both succeeded.
|
|
1252
|
+
if (fallbackProvider) {
|
|
1253
|
+
providerName = fallbackProvider;
|
|
1254
|
+
providerModule = fallbackModule;
|
|
1255
|
+
}
|
|
1133
1256
|
currentDb = adapter;
|
|
1134
1257
|
currentPath = path;
|
|
1135
1258
|
currentPid = process.pid;
|
|
@@ -1168,8 +1291,12 @@ export function closeDatabase() {
|
|
|
1168
1291
|
currentDb = null;
|
|
1169
1292
|
currentPath = null;
|
|
1170
1293
|
currentPid = 0;
|
|
1171
|
-
_dbOpenAttempted = false;
|
|
1172
1294
|
}
|
|
1295
|
+
// Reset session-scoped state unconditionally so stale error info from a
|
|
1296
|
+
// failed open doesn't persist into the next open attempt or status check.
|
|
1297
|
+
_dbOpenAttempted = false;
|
|
1298
|
+
_lastDbError = null;
|
|
1299
|
+
_lastDbPhase = null;
|
|
1173
1300
|
}
|
|
1174
1301
|
/** Run a full VACUUM — call sparingly (e.g. after milestone completion). */
|
|
1175
1302
|
export function vacuumDatabase() {
|
|
@@ -2269,7 +2396,10 @@ export function reconcileWorktreeDb(mainDbPath, worktreeDbPath) {
|
|
|
2269
2396
|
SELECT path, artifact_type, milestone_id, slice_id, task_id, full_content, imported_at
|
|
2270
2397
|
FROM wt.artifacts
|
|
2271
2398
|
`).run());
|
|
2272
|
-
// Merge milestones — worktree may have updated status/planning fields
|
|
2399
|
+
// Merge milestones — worktree may have updated status/planning fields.
|
|
2400
|
+
// Never downgrade status: complete > active > pre-planning (#4372).
|
|
2401
|
+
// A stale worktree may carry an older 'active' status for a milestone
|
|
2402
|
+
// that the main DB has already marked 'complete'; preserve the higher status.
|
|
2273
2403
|
merged.milestones = countChanges(adapter.prepare(`
|
|
2274
2404
|
INSERT OR REPLACE INTO milestones (
|
|
2275
2405
|
id, title, status, depends_on, created_at, completed_at,
|
|
@@ -2277,11 +2407,25 @@ export function reconcileWorktreeDb(mainDbPath, worktreeDbPath) {
|
|
|
2277
2407
|
verification_contract, verification_integration, verification_operational, verification_uat,
|
|
2278
2408
|
definition_of_done, requirement_coverage, boundary_map_markdown
|
|
2279
2409
|
)
|
|
2280
|
-
SELECT id, title,
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2410
|
+
SELECT w.id, w.title,
|
|
2411
|
+
CASE
|
|
2412
|
+
WHEN m.status IN ('complete', 'done') AND w.status NOT IN ('complete', 'done')
|
|
2413
|
+
THEN m.status ELSE w.status
|
|
2414
|
+
END,
|
|
2415
|
+
w.depends_on,
|
|
2416
|
+
CASE
|
|
2417
|
+
WHEN m.status IN ('complete', 'done') AND w.status NOT IN ('complete', 'done')
|
|
2418
|
+
THEN m.created_at ELSE w.created_at
|
|
2419
|
+
END,
|
|
2420
|
+
CASE
|
|
2421
|
+
WHEN m.status IN ('complete', 'done') AND w.status NOT IN ('complete', 'done')
|
|
2422
|
+
THEN m.completed_at ELSE w.completed_at
|
|
2423
|
+
END,
|
|
2424
|
+
w.vision, w.success_criteria, w.key_risks, w.proof_strategy,
|
|
2425
|
+
w.verification_contract, w.verification_integration, w.verification_operational, w.verification_uat,
|
|
2426
|
+
w.definition_of_done, w.requirement_coverage, w.boundary_map_markdown
|
|
2427
|
+
FROM wt.milestones w
|
|
2428
|
+
LEFT JOIN milestones m ON m.id = w.id
|
|
2285
2429
|
`).run());
|
|
2286
2430
|
// Merge slices — preserve worktree progress but never downgrade completed status (#2558).
|
|
2287
2431
|
// ADR-011 Phase 1: carry is_sketch + sketch_scope so reconcile doesn't
|
|
@@ -2948,8 +3092,8 @@ export function bulkInsertLegacyHierarchy(payload) {
|
|
|
2948
3092
|
export function insertMemoryRow(args) {
|
|
2949
3093
|
if (!currentDb)
|
|
2950
3094
|
throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
2951
|
-
currentDb.prepare(`INSERT INTO memories (id, category, content, confidence, source_unit_type, source_unit_id, created_at, updated_at, scope, tags)
|
|
2952
|
-
VALUES (:id, :category, :content, :confidence, :source_unit_type, :source_unit_id, :created_at, :updated_at, :scope, :tags)`).run({
|
|
3095
|
+
currentDb.prepare(`INSERT INTO memories (id, category, content, confidence, source_unit_type, source_unit_id, created_at, updated_at, scope, tags, structured_fields)
|
|
3096
|
+
VALUES (:id, :category, :content, :confidence, :source_unit_type, :source_unit_id, :created_at, :updated_at, :scope, :tags, :structured_fields)`).run({
|
|
2953
3097
|
":id": args.id,
|
|
2954
3098
|
":category": args.category,
|
|
2955
3099
|
":content": args.content,
|
|
@@ -2960,6 +3104,7 @@ export function insertMemoryRow(args) {
|
|
|
2960
3104
|
":updated_at": args.updatedAt,
|
|
2961
3105
|
":scope": args.scope ?? "project",
|
|
2962
3106
|
":tags": JSON.stringify(args.tags ?? []),
|
|
3107
|
+
":structured_fields": args.structuredFields == null ? null : JSON.stringify(args.structuredFields),
|
|
2963
3108
|
});
|
|
2964
3109
|
}
|
|
2965
3110
|
export function insertMemorySourceRow(args) {
|