gsd-pi 2.41.0 → 2.42.0-dev.eedc83f
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 +92 -29
- package/dist/cli-web-branch.d.ts +6 -0
- package/dist/cli-web-branch.js +17 -0
- package/dist/cli.js +15 -1
- package/dist/onboarding.js +2 -1
- package/dist/resource-loader.js +39 -6
- package/dist/resources/extensions/async-jobs/async-bash-tool.js +52 -4
- package/dist/resources/extensions/gsd/auto/loop.js +89 -1
- package/dist/resources/extensions/gsd/auto/phases.js +28 -10
- package/dist/resources/extensions/gsd/auto/session.js +6 -0
- package/dist/resources/extensions/gsd/auto-dashboard.js +8 -2
- package/dist/resources/extensions/gsd/auto-dispatch.js +19 -2
- package/dist/resources/extensions/gsd/auto-post-unit.js +7 -0
- package/dist/resources/extensions/gsd/auto-prompts.js +1 -1
- package/dist/resources/extensions/gsd/auto-recovery.js +12 -4
- package/dist/resources/extensions/gsd/auto-start.js +8 -3
- package/dist/resources/extensions/gsd/auto-worktree.js +147 -13
- package/dist/resources/extensions/gsd/auto.js +64 -2
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +199 -164
- package/dist/resources/extensions/gsd/bootstrap/journal-tools.js +62 -0
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +2 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +25 -3
- package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +7 -2
- package/dist/resources/extensions/gsd/commands/catalog.js +40 -1
- package/dist/resources/extensions/gsd/commands/handlers/core.js +1 -0
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +5 -0
- package/dist/resources/extensions/gsd/commands/handlers/workflow.js +146 -0
- package/dist/resources/extensions/gsd/context-injector.js +74 -0
- package/dist/resources/extensions/gsd/context-store.js +4 -3
- package/dist/resources/extensions/gsd/custom-execution-policy.js +47 -0
- package/dist/resources/extensions/gsd/custom-verification.js +145 -0
- package/dist/resources/extensions/gsd/custom-workflow-engine.js +164 -0
- package/dist/resources/extensions/gsd/dashboard-overlay.js +1 -0
- package/dist/resources/extensions/gsd/db-writer.js +5 -2
- package/dist/resources/extensions/gsd/definition-loader.js +352 -0
- package/dist/resources/extensions/gsd/detection.js +20 -1
- package/dist/resources/extensions/gsd/dev-execution-policy.js +24 -0
- package/dist/resources/extensions/gsd/dev-workflow-engine.js +82 -0
- package/dist/resources/extensions/gsd/doctor-checks.js +31 -1
- package/dist/resources/extensions/gsd/doctor-providers.js +10 -0
- package/dist/resources/extensions/gsd/doctor.js +11 -1
- package/dist/resources/extensions/gsd/engine-resolver.js +40 -0
- package/dist/resources/extensions/gsd/engine-types.js +8 -0
- package/dist/resources/extensions/gsd/execution-policy.js +8 -0
- package/dist/resources/extensions/gsd/exit-command.js +12 -2
- package/dist/resources/extensions/gsd/export.js +9 -13
- package/dist/resources/extensions/gsd/extension-manifest.json +2 -2
- package/dist/resources/extensions/gsd/files.js +28 -11
- package/dist/resources/extensions/gsd/forensics.js +94 -3
- package/dist/resources/extensions/gsd/git-constants.js +1 -0
- package/dist/resources/extensions/gsd/git-service.js +73 -3
- package/dist/resources/extensions/gsd/graph.js +225 -0
- package/dist/resources/extensions/gsd/gsd-db.js +25 -8
- package/dist/resources/extensions/gsd/guided-flow-queue.js +1 -1
- package/dist/resources/extensions/gsd/guided-flow.js +7 -3
- package/dist/resources/extensions/gsd/journal.js +85 -0
- package/dist/resources/extensions/gsd/md-importer.js +5 -0
- package/dist/resources/extensions/gsd/milestone-ids.js +1 -1
- package/dist/resources/extensions/gsd/native-git-bridge.js +3 -2
- package/dist/resources/extensions/gsd/post-unit-hooks.js +24 -412
- package/dist/resources/extensions/gsd/preferences-types.js +2 -0
- package/dist/resources/extensions/gsd/preferences.js +60 -8
- package/dist/resources/extensions/gsd/prompt-loader.js +34 -4
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +11 -10
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +2 -2
- package/dist/resources/extensions/gsd/prompts/discuss.md +1 -1
- package/dist/resources/extensions/gsd/prompts/forensics.md +12 -5
- package/dist/resources/extensions/gsd/prompts/queue.md +1 -1
- package/dist/resources/extensions/gsd/repo-identity.js +92 -7
- package/dist/resources/extensions/gsd/rule-registry.js +489 -0
- package/dist/resources/extensions/gsd/rule-types.js +6 -0
- package/dist/resources/extensions/gsd/run-manager.js +134 -0
- package/dist/resources/extensions/gsd/service-tier.js +147 -0
- package/dist/resources/extensions/gsd/session-lock.js +2 -2
- package/dist/resources/extensions/gsd/structured-data-formatter.js +2 -1
- package/dist/resources/extensions/gsd/templates/decisions.md +2 -2
- package/dist/resources/extensions/gsd/workflow-engine.js +7 -0
- package/dist/resources/extensions/gsd/workflow-templates.js +13 -1
- package/dist/resources/extensions/gsd/worktree-manager.js +20 -6
- package/dist/resources/extensions/gsd/worktree-resolver.js +21 -4
- package/dist/resources/extensions/mcp-client/index.js +2 -1
- package/dist/resources/extensions/search-the-web/tool-search.js +3 -3
- package/dist/resources/extensions/subagent/index.js +7 -3
- package/dist/resources/extensions/voice/index.js +4 -4
- package/dist/resources/skills/create-workflow/SKILL.md +103 -0
- package/dist/resources/skills/create-workflow/references/feature-patterns.md +128 -0
- package/dist/resources/skills/create-workflow/references/verification-policies.md +76 -0
- package/dist/resources/skills/create-workflow/references/yaml-schema-v1.md +46 -0
- package/dist/resources/skills/create-workflow/templates/blog-post-pipeline.yaml +60 -0
- package/dist/resources/skills/create-workflow/templates/code-audit.yaml +60 -0
- package/dist/resources/skills/create-workflow/templates/release-checklist.yaml +66 -0
- package/dist/resources/skills/create-workflow/templates/workflow-definition.yaml +32 -0
- package/dist/resources/skills/create-workflow/workflows/create-from-scratch.md +104 -0
- package/dist/resources/skills/create-workflow/workflows/create-from-template.md +72 -0
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +13 -13
- package/dist/web/standalone/.next/build-manifest.json +4 -4
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
- package/dist/web/standalone/.next/required-server-files.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +5 -5
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +13 -13
- package/dist/web/standalone/.next/server/chunks/229.js +3 -3
- package/dist/web/standalone/.next/server/chunks/471.js +3 -3
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware.js +2 -2
- package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
- package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +2 -2
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/4024.c195dc1fdd2adbea.js +9 -0
- package/dist/web/standalone/.next/static/chunks/app/_not-found/page-f2a7482d42a5614b.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/page-b9367c5ae13b99c6.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{main-app-2f2ee7b85712c2bd.js → main-app-fdab67f7802d7832.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-9afaaebf6042a1d7.js → webpack-fa307370fcf9fb2c.js} +1 -1
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
- package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
- package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
- package/dist/web/standalone/server.js +1 -1
- package/dist/web-mode.d.ts +4 -0
- package/dist/web-mode.js +69 -11
- package/package.json +1 -1
- package/packages/native/src/__tests__/text.test.mjs +33 -0
- package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent.js +2 -0
- package/packages/pi-agent-core/dist/agent.js.map +1 -1
- package/packages/pi-agent-core/dist/types.d.ts +6 -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/src/agent.test.ts +53 -0
- package/packages/pi-agent-core/src/agent.ts +3 -0
- package/packages/pi-agent-core/src/types.ts +6 -0
- package/packages/pi-agent-core/tsconfig.json +1 -1
- package/packages/pi-ai/dist/models.d.ts +5 -3
- package/packages/pi-ai/dist/models.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +801 -1468
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +1135 -1588
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/models.js.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/github-copilot.js +60 -2
- package/packages/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
- package/packages/pi-ai/scripts/generate-models.ts +1543 -0
- package/packages/pi-ai/src/models.generated.ts +1140 -1593
- package/packages/pi-ai/src/models.ts +7 -4
- package/packages/pi-ai/src/utils/oauth/github-copilot.ts +74 -2
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +8 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +7 -0
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.js +29 -2
- package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.test.js +60 -0
- package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/discovery-cache.test.js +3 -1
- package/packages/pi-coding-agent/dist/core/discovery-cache.test.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 +18 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/client.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/client.js +23 -0
- package/packages/pi-coding-agent/dist/core/lsp/client.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +2 -0
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/package-manager.d.ts +6 -0
- package/packages/pi-coding-agent/dist/core/package-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/package-manager.js +63 -11
- package/packages/pi-coding-agent/dist/core/package-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.d.ts +9 -0
- package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.js +20 -6
- package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +6 -5
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/extension-editor.js +3 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +9 -6
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js +10 -7
- package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.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 +34 -10
- 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.ts +7 -1
- package/packages/pi-coding-agent/src/core/auth-storage.test.ts +68 -0
- package/packages/pi-coding-agent/src/core/auth-storage.ts +30 -2
- package/packages/pi-coding-agent/src/core/discovery-cache.test.ts +4 -2
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +18 -0
- package/packages/pi-coding-agent/src/core/lsp/client.ts +29 -0
- package/packages/pi-coding-agent/src/core/model-registry.ts +3 -0
- package/packages/pi-coding-agent/src/core/package-manager.ts +99 -58
- package/packages/pi-coding-agent/src/core/resource-loader.ts +24 -6
- package/packages/pi-coding-agent/src/core/system-prompt.ts +6 -5
- package/packages/pi-coding-agent/src/modes/interactive/components/extension-editor.ts +3 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +10 -6
- package/packages/pi-coding-agent/src/modes/interactive/components/login-dialog.ts +11 -7
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +36 -11
- package/pkg/package.json +1 -1
- package/src/resources/extensions/async-jobs/async-bash-timeout.test.ts +122 -0
- package/src/resources/extensions/async-jobs/async-bash-tool.ts +40 -4
- package/src/resources/extensions/gsd/auto/loop-deps.ts +5 -1
- package/src/resources/extensions/gsd/auto/loop.ts +101 -1
- package/src/resources/extensions/gsd/auto/phases.ts +30 -10
- package/src/resources/extensions/gsd/auto/session.ts +6 -0
- package/src/resources/extensions/gsd/auto/types.ts +4 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +9 -2
- package/src/resources/extensions/gsd/auto-dispatch.ts +25 -5
- package/src/resources/extensions/gsd/auto-post-unit.ts +8 -0
- package/src/resources/extensions/gsd/auto-prompts.ts +1 -1
- package/src/resources/extensions/gsd/auto-recovery.ts +12 -4
- package/src/resources/extensions/gsd/auto-start.ts +8 -3
- package/src/resources/extensions/gsd/auto-worktree.ts +162 -18
- package/src/resources/extensions/gsd/auto.ts +71 -2
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +209 -162
- package/src/resources/extensions/gsd/bootstrap/journal-tools.ts +62 -0
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +2 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +25 -4
- package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +9 -2
- package/src/resources/extensions/gsd/commands/catalog.ts +40 -1
- package/src/resources/extensions/gsd/commands/handlers/core.ts +1 -0
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +5 -0
- package/src/resources/extensions/gsd/commands/handlers/workflow.ts +164 -0
- package/src/resources/extensions/gsd/context-injector.ts +100 -0
- package/src/resources/extensions/gsd/context-store.ts +4 -3
- package/src/resources/extensions/gsd/custom-execution-policy.ts +73 -0
- package/src/resources/extensions/gsd/custom-verification.ts +180 -0
- package/src/resources/extensions/gsd/custom-workflow-engine.ts +216 -0
- package/src/resources/extensions/gsd/dashboard-overlay.ts +1 -0
- package/src/resources/extensions/gsd/db-writer.ts +6 -2
- package/src/resources/extensions/gsd/definition-loader.ts +462 -0
- package/src/resources/extensions/gsd/detection.ts +20 -1
- package/src/resources/extensions/gsd/dev-execution-policy.ts +51 -0
- package/src/resources/extensions/gsd/dev-workflow-engine.ts +110 -0
- package/src/resources/extensions/gsd/doctor-checks.ts +32 -1
- package/src/resources/extensions/gsd/doctor-providers.ts +13 -0
- package/src/resources/extensions/gsd/doctor-types.ts +1 -0
- package/src/resources/extensions/gsd/doctor.ts +12 -1
- package/src/resources/extensions/gsd/engine-resolver.ts +57 -0
- package/src/resources/extensions/gsd/engine-types.ts +71 -0
- package/src/resources/extensions/gsd/execution-policy.ts +43 -0
- package/src/resources/extensions/gsd/exit-command.ts +14 -2
- package/src/resources/extensions/gsd/export.ts +8 -15
- package/src/resources/extensions/gsd/extension-manifest.json +2 -2
- package/src/resources/extensions/gsd/files.ts +29 -12
- package/src/resources/extensions/gsd/forensics.ts +101 -3
- package/src/resources/extensions/gsd/git-constants.ts +1 -0
- package/src/resources/extensions/gsd/git-service.ts +76 -6
- package/src/resources/extensions/gsd/graph.ts +312 -0
- package/src/resources/extensions/gsd/gsd-db.ts +37 -8
- package/src/resources/extensions/gsd/guided-flow-queue.ts +1 -1
- package/src/resources/extensions/gsd/guided-flow.ts +7 -3
- package/src/resources/extensions/gsd/journal.ts +134 -0
- package/src/resources/extensions/gsd/md-importer.ts +6 -0
- package/src/resources/extensions/gsd/milestone-ids.ts +1 -1
- package/src/resources/extensions/gsd/native-git-bridge.ts +3 -2
- package/src/resources/extensions/gsd/post-unit-hooks.ts +24 -462
- package/src/resources/extensions/gsd/preferences-types.ts +6 -0
- package/src/resources/extensions/gsd/preferences.ts +63 -6
- package/src/resources/extensions/gsd/prompt-loader.ts +35 -4
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +11 -10
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +2 -2
- package/src/resources/extensions/gsd/prompts/discuss.md +1 -1
- package/src/resources/extensions/gsd/prompts/forensics.md +12 -5
- package/src/resources/extensions/gsd/prompts/queue.md +1 -1
- package/src/resources/extensions/gsd/repo-identity.ts +95 -7
- package/src/resources/extensions/gsd/rule-registry.ts +599 -0
- package/src/resources/extensions/gsd/rule-types.ts +68 -0
- package/src/resources/extensions/gsd/run-manager.ts +180 -0
- package/src/resources/extensions/gsd/service-tier.ts +184 -0
- package/src/resources/extensions/gsd/session-lock.ts +2 -2
- package/src/resources/extensions/gsd/structured-data-formatter.ts +3 -1
- package/src/resources/extensions/gsd/templates/decisions.md +2 -2
- package/src/resources/extensions/gsd/tests/activity-log.test.ts +31 -69
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +103 -120
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +85 -0
- package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +202 -0
- package/src/resources/extensions/gsd/tests/bundled-workflow-defs.test.ts +180 -0
- package/src/resources/extensions/gsd/tests/captures.test.ts +12 -1
- package/src/resources/extensions/gsd/tests/commands-workflow-custom.test.ts +283 -0
- package/src/resources/extensions/gsd/tests/context-injector.test.ts +313 -0
- package/src/resources/extensions/gsd/tests/context-store.test.ts +10 -5
- package/src/resources/extensions/gsd/tests/continue-here.test.ts +20 -20
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +540 -0
- package/src/resources/extensions/gsd/tests/custom-verification.test.ts +382 -0
- package/src/resources/extensions/gsd/tests/custom-workflow-engine.test.ts +339 -0
- package/src/resources/extensions/gsd/tests/dashboard-custom-engine.test.ts +87 -0
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +10 -0
- package/src/resources/extensions/gsd/tests/definition-loader.test.ts +778 -0
- package/src/resources/extensions/gsd/tests/dev-engine-wrapper.test.ts +318 -0
- package/src/resources/extensions/gsd/tests/doctor-completion-deferral.test.ts +15 -10
- package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +5 -4
- package/src/resources/extensions/gsd/tests/doctor-roadmap-summary-atomicity.test.ts +167 -0
- package/src/resources/extensions/gsd/tests/doctor-task-done-missing-summary-slice-loop.test.ts +174 -0
- package/src/resources/extensions/gsd/tests/e2e-workflow-pipeline-integration.test.ts +476 -0
- package/src/resources/extensions/gsd/tests/engine-interfaces-contract.test.ts +271 -0
- package/src/resources/extensions/gsd/tests/exit-command.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/forensics-dedup.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/forensics-issue-routing.test.ts +43 -0
- package/src/resources/extensions/gsd/tests/git-locale.test.ts +133 -0
- package/src/resources/extensions/gsd/tests/git-service.test.ts +49 -0
- package/src/resources/extensions/gsd/tests/graph-operations.test.ts +599 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +8 -1
- package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +7 -7
- package/src/resources/extensions/gsd/tests/iterate-engine-integration.test.ts +429 -0
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +513 -0
- package/src/resources/extensions/gsd/tests/journal-query-tool.test.ts +147 -0
- package/src/resources/extensions/gsd/tests/journal.test.ts +341 -0
- package/src/resources/extensions/gsd/tests/manifest-status.test.ts +73 -82
- package/src/resources/extensions/gsd/tests/md-importer.test.ts +31 -1
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/milestone-id-reservation.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/parsers.test.ts +110 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +47 -25
- package/src/resources/extensions/gsd/tests/prompt-db.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +61 -1
- package/src/resources/extensions/gsd/tests/routing-history.test.ts +11 -22
- package/src/resources/extensions/gsd/tests/rule-registry.test.ts +413 -0
- package/src/resources/extensions/gsd/tests/run-manager.test.ts +229 -0
- package/src/resources/extensions/gsd/tests/service-tier.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/skill-lifecycle.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +102 -0
- package/src/resources/extensions/gsd/tests/structured-data-formatter.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/symlink-numbered-variants.test.ts +151 -0
- package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +117 -0
- package/src/resources/extensions/gsd/tests/triage-dispatch.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/verification-gate.test.ts +156 -263
- package/src/resources/extensions/gsd/tests/windows-path-normalization.test.ts +99 -0
- package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +135 -0
- package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +203 -106
- package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +78 -3
- package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +140 -0
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +74 -0
- package/src/resources/extensions/gsd/types.ts +3 -0
- package/src/resources/extensions/gsd/workflow-engine.ts +38 -0
- package/src/resources/extensions/gsd/workflow-templates.ts +12 -1
- package/src/resources/extensions/gsd/worktree-manager.ts +21 -6
- package/src/resources/extensions/gsd/worktree-resolver.ts +32 -11
- package/src/resources/extensions/mcp-client/index.ts +5 -1
- package/src/resources/extensions/search-the-web/tool-search.ts +3 -3
- package/src/resources/extensions/subagent/index.ts +7 -3
- package/src/resources/extensions/voice/index.ts +4 -4
- package/src/resources/skills/create-workflow/SKILL.md +103 -0
- package/src/resources/skills/create-workflow/references/feature-patterns.md +128 -0
- package/src/resources/skills/create-workflow/references/verification-policies.md +76 -0
- package/src/resources/skills/create-workflow/references/yaml-schema-v1.md +46 -0
- package/src/resources/skills/create-workflow/templates/blog-post-pipeline.yaml +60 -0
- package/src/resources/skills/create-workflow/templates/code-audit.yaml +60 -0
- package/src/resources/skills/create-workflow/templates/release-checklist.yaml +66 -0
- package/src/resources/skills/create-workflow/templates/workflow-definition.yaml +32 -0
- package/src/resources/skills/create-workflow/workflows/create-from-scratch.md +104 -0
- package/src/resources/skills/create-workflow/workflows/create-from-template.md +72 -0
- package/dist/web/standalone/.next/static/chunks/4024.279c423e4661ece1.js +0 -9
- package/dist/web/standalone/.next/static/chunks/app/_not-found/page-e07acdb7dd069836.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/layout-745c6ed5fea5fb06.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/page-801b53eff6e83579.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-e6255954dccfcf0a.js +0 -1
- /package/dist/web/standalone/.next/static/{Ute3pMouVczQyT15qrBBO → JUBX5FUR73jiViQU5a-Cx}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{Ute3pMouVczQyT15qrBBO → JUBX5FUR73jiViQU5a-Cx}/_ssgManifest.js +0 -0
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import { execFileSync, execSync } from "node:child_process";
|
|
12
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
13
|
-
import { join } from "node:path";
|
|
12
|
+
import { existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
13
|
+
import { join, relative } from "node:path";
|
|
14
14
|
import { gsdRoot } from "./paths.js";
|
|
15
15
|
import { GIT_NO_PROMPT_ENV } from "./git-constants.js";
|
|
16
16
|
import { loadEffectiveGSDPreferences } from "./preferences.js";
|
|
@@ -486,11 +486,80 @@ export class GitServiceImpl {
|
|
|
486
486
|
// git add -A already skips it and the exclusions are harmless no-ops.
|
|
487
487
|
const allExclusions = [...RUNTIME_EXCLUSION_PATHS, ...extraExclusions];
|
|
488
488
|
nativeAddAllWithExclusions(this.basePath, allExclusions);
|
|
489
|
+
|
|
490
|
+
// Force-add .gsd/milestones/ when .gsd is a symlink (#2104).
|
|
491
|
+
// When .gsd is a symlink (external state projects), ensureGitignore adds
|
|
492
|
+
// `.gsd` to .gitignore. The nativeAddAllWithExclusions call above falls
|
|
493
|
+
// back to plain `git add -A` (symlink pathspec rejection), which respects
|
|
494
|
+
// .gitignore and silently skips new .gsd/milestones/ files.
|
|
495
|
+
//
|
|
496
|
+
// `git add -f` also fails with "beyond a symbolic link", so we use
|
|
497
|
+
// `git hash-object -w` + `git update-index --add --cacheinfo` to bypass
|
|
498
|
+
// the symlink restriction entirely. This stages each milestone artifact
|
|
499
|
+
// individually by hashing the file content and updating the index directly.
|
|
500
|
+
const gsdPath = join(this.basePath, ".gsd");
|
|
501
|
+
const milestonesDir = join(gsdPath, "milestones");
|
|
502
|
+
try {
|
|
503
|
+
if (
|
|
504
|
+
existsSync(gsdPath) &&
|
|
505
|
+
lstatSync(gsdPath).isSymbolicLink() &&
|
|
506
|
+
existsSync(milestonesDir)
|
|
507
|
+
) {
|
|
508
|
+
this._forceAddMilestoneArtifacts(milestonesDir);
|
|
509
|
+
}
|
|
510
|
+
} catch {
|
|
511
|
+
// Non-fatal: if force-add fails, the commit proceeds without these files.
|
|
512
|
+
// This matches existing behavior where milestone artifacts were silently
|
|
513
|
+
// omitted — but now we at least attempt to include them.
|
|
514
|
+
}
|
|
489
515
|
}
|
|
490
516
|
|
|
491
517
|
/** Tracks whether runtime file cleanup has run this session. */
|
|
492
518
|
private _runtimeFilesCleanedUp = false;
|
|
493
519
|
|
|
520
|
+
/**
|
|
521
|
+
* Recursively collect all files under a directory.
|
|
522
|
+
* Returns paths relative to `basePath` (e.g. ".gsd/milestones/M009/SUMMARY.md").
|
|
523
|
+
*/
|
|
524
|
+
private _collectFiles(dir: string): string[] {
|
|
525
|
+
const files: string[] = [];
|
|
526
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
527
|
+
const full = join(dir, entry.name);
|
|
528
|
+
if (entry.isDirectory()) {
|
|
529
|
+
files.push(...this._collectFiles(full));
|
|
530
|
+
} else if (entry.isFile()) {
|
|
531
|
+
files.push(relative(this.basePath, full));
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
return files;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
/**
|
|
538
|
+
* Stage milestone artifacts through a symlinked .gsd directory (#2104).
|
|
539
|
+
*
|
|
540
|
+
* `git add` (even with `-f`) refuses to stage files "beyond a symbolic link".
|
|
541
|
+
* This method bypasses that restriction by hashing each file with
|
|
542
|
+
* `git hash-object -w` and inserting the blob into the index with
|
|
543
|
+
* `git update-index --add --cacheinfo 100644 <hash> <path>`.
|
|
544
|
+
*/
|
|
545
|
+
private _forceAddMilestoneArtifacts(milestonesDir: string): void {
|
|
546
|
+
const files = this._collectFiles(milestonesDir);
|
|
547
|
+
for (const filePath of files) {
|
|
548
|
+
const hash = execFileSync("git", ["hash-object", "-w", filePath], {
|
|
549
|
+
cwd: this.basePath,
|
|
550
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
551
|
+
encoding: "utf-8",
|
|
552
|
+
env: GIT_NO_PROMPT_ENV,
|
|
553
|
+
}).trim();
|
|
554
|
+
execFileSync("git", ["update-index", "--add", "--cacheinfo", "100644", hash, filePath], {
|
|
555
|
+
cwd: this.basePath,
|
|
556
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
557
|
+
encoding: "utf-8",
|
|
558
|
+
env: GIT_NO_PROMPT_ENV,
|
|
559
|
+
});
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
|
|
494
563
|
/**
|
|
495
564
|
* Stage files (smart staging) and commit.
|
|
496
565
|
* Returns the commit message string on success, or null if nothing to commit.
|
|
@@ -683,10 +752,11 @@ export function createDraftPR(
|
|
|
683
752
|
body: string,
|
|
684
753
|
): string | null {
|
|
685
754
|
try {
|
|
686
|
-
const result =
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
755
|
+
const result = execFileSync("gh", [
|
|
756
|
+
"pr", "create", "--draft",
|
|
757
|
+
"--title", title,
|
|
758
|
+
"--body", body,
|
|
759
|
+
], { cwd: basePath, encoding: "utf8", timeout: 30000, env: GIT_NO_PROMPT_ENV });
|
|
690
760
|
return result.trim();
|
|
691
761
|
} catch {
|
|
692
762
|
return null;
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* graph.ts — Pure data module for GRAPH.yaml workflow step tracking.
|
|
3
|
+
*
|
|
4
|
+
* Provides types and functions for reading, writing, and querying the
|
|
5
|
+
* step graph that drives CustomWorkflowEngine. Zero engine dependencies.
|
|
6
|
+
*
|
|
7
|
+
* GRAPH.yaml lives in a run directory and tracks step statuses
|
|
8
|
+
* (pending → active → complete) with optional dependency edges.
|
|
9
|
+
*
|
|
10
|
+
* Observability:
|
|
11
|
+
* - readGraph/writeGraph use YAML on disk — human-readable, diffable,
|
|
12
|
+
* inspectable with `cat` or any YAML viewer.
|
|
13
|
+
* - Each GraphStep has status, startedAt, finishedAt fields visible in GRAPH.yaml.
|
|
14
|
+
* - writeGraph uses atomic write (tmp + rename) for crash safety.
|
|
15
|
+
* - All operations are immutable — callers always get a new graph object.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { parse, stringify } from "yaml";
|
|
19
|
+
import { readFileSync, writeFileSync, renameSync, existsSync, mkdirSync } from "node:fs";
|
|
20
|
+
import { join } from "node:path";
|
|
21
|
+
import type { WorkflowDefinition } from "./definition-loader.js";
|
|
22
|
+
|
|
23
|
+
// ─── Types ───────────────────────────────────────────────────────────────
|
|
24
|
+
|
|
25
|
+
export interface GraphStep {
|
|
26
|
+
/** Unique step identifier within the workflow. */
|
|
27
|
+
id: string;
|
|
28
|
+
/** Human-readable step title. */
|
|
29
|
+
title: string;
|
|
30
|
+
/** Current status: pending → active → complete → expanded (iterate parent). */
|
|
31
|
+
status: "pending" | "active" | "complete" | "expanded";
|
|
32
|
+
/** The prompt to dispatch for this step. */
|
|
33
|
+
prompt: string;
|
|
34
|
+
/** IDs of steps that must be "complete" before this step can run. */
|
|
35
|
+
dependsOn: string[];
|
|
36
|
+
/** For iteration instances: ID of the parent step that was expanded. */
|
|
37
|
+
parentStepId?: string;
|
|
38
|
+
/** ISO timestamp when the step started executing. */
|
|
39
|
+
startedAt?: string;
|
|
40
|
+
/** ISO timestamp when the step finished executing. */
|
|
41
|
+
finishedAt?: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface WorkflowGraph {
|
|
45
|
+
/** Ordered list of steps in the workflow. */
|
|
46
|
+
steps: GraphStep[];
|
|
47
|
+
/** Workflow metadata. */
|
|
48
|
+
metadata: {
|
|
49
|
+
name: string;
|
|
50
|
+
createdAt: string;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// ─── YAML schema mapping ─────────────────────────────────────────────────
|
|
55
|
+
|
|
56
|
+
const GRAPH_FILENAME = "GRAPH.yaml";
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Internal YAML shape — uses snake_case for YAML keys.
|
|
60
|
+
* Converted to/from the camelCase TypeScript types on read/write.
|
|
61
|
+
*/
|
|
62
|
+
interface YamlStep {
|
|
63
|
+
id: string;
|
|
64
|
+
title: string;
|
|
65
|
+
status: string;
|
|
66
|
+
prompt: string;
|
|
67
|
+
depends_on?: string[];
|
|
68
|
+
parent_step_id?: string;
|
|
69
|
+
started_at?: string;
|
|
70
|
+
finished_at?: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
interface YamlGraph {
|
|
74
|
+
steps: YamlStep[];
|
|
75
|
+
metadata: { name: string; created_at: string };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// ─── Functions ───────────────────────────────────────────────────────────
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Read and parse GRAPH.yaml from a run directory.
|
|
82
|
+
*
|
|
83
|
+
* @param runDir — directory containing GRAPH.yaml
|
|
84
|
+
* @returns Parsed workflow graph
|
|
85
|
+
* @throws Error if file doesn't exist or YAML is malformed
|
|
86
|
+
*/
|
|
87
|
+
export function readGraph(runDir: string): WorkflowGraph {
|
|
88
|
+
const filePath = join(runDir, GRAPH_FILENAME);
|
|
89
|
+
if (!existsSync(filePath)) {
|
|
90
|
+
throw new Error(`GRAPH.yaml not found: ${filePath}`);
|
|
91
|
+
}
|
|
92
|
+
const raw = readFileSync(filePath, "utf-8");
|
|
93
|
+
const yaml = parse(raw) as YamlGraph;
|
|
94
|
+
|
|
95
|
+
if (!yaml?.steps || !Array.isArray(yaml.steps)) {
|
|
96
|
+
throw new Error(`Invalid GRAPH.yaml: missing or invalid 'steps' array in ${filePath}`);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
steps: yaml.steps.map((s) => ({
|
|
101
|
+
id: s.id,
|
|
102
|
+
title: s.title,
|
|
103
|
+
status: s.status as GraphStep["status"],
|
|
104
|
+
prompt: s.prompt,
|
|
105
|
+
dependsOn: s.depends_on ?? [],
|
|
106
|
+
...(s.parent_step_id != null ? { parentStepId: s.parent_step_id } : {}),
|
|
107
|
+
...(s.started_at != null ? { startedAt: s.started_at } : {}),
|
|
108
|
+
...(s.finished_at != null ? { finishedAt: s.finished_at } : {}),
|
|
109
|
+
})),
|
|
110
|
+
metadata: {
|
|
111
|
+
name: yaml.metadata?.name ?? "unnamed",
|
|
112
|
+
createdAt: yaml.metadata?.created_at ?? new Date().toISOString(),
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Write a workflow graph to GRAPH.yaml in a run directory.
|
|
119
|
+
* Creates the directory if it doesn't exist. Write is atomic (write + rename).
|
|
120
|
+
*
|
|
121
|
+
* @param runDir — directory to write GRAPH.yaml into
|
|
122
|
+
* @param graph — the workflow graph to serialize
|
|
123
|
+
*/
|
|
124
|
+
export function writeGraph(runDir: string, graph: WorkflowGraph): void {
|
|
125
|
+
if (!existsSync(runDir)) {
|
|
126
|
+
mkdirSync(runDir, { recursive: true });
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const yamlData: YamlGraph = {
|
|
130
|
+
steps: graph.steps.map((s) => ({
|
|
131
|
+
id: s.id,
|
|
132
|
+
title: s.title,
|
|
133
|
+
status: s.status,
|
|
134
|
+
prompt: s.prompt,
|
|
135
|
+
depends_on: s.dependsOn.length > 0 ? s.dependsOn : undefined,
|
|
136
|
+
parent_step_id: s.parentStepId ?? undefined,
|
|
137
|
+
started_at: s.startedAt ?? undefined,
|
|
138
|
+
finished_at: s.finishedAt ?? undefined,
|
|
139
|
+
})) as YamlStep[],
|
|
140
|
+
metadata: {
|
|
141
|
+
name: graph.metadata.name,
|
|
142
|
+
created_at: graph.metadata.createdAt,
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const filePath = join(runDir, GRAPH_FILENAME);
|
|
147
|
+
const tmpPath = filePath + ".tmp";
|
|
148
|
+
const content = stringify(yamlData);
|
|
149
|
+
writeFileSync(tmpPath, content, "utf-8");
|
|
150
|
+
// Atomic rename for crash safety
|
|
151
|
+
renameSync(tmpPath, filePath);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Get the next pending step whose dependencies are all complete.
|
|
156
|
+
*
|
|
157
|
+
* Returns the first step (in array order) with status "pending" where
|
|
158
|
+
* every step in its `dependsOn` list has status "complete".
|
|
159
|
+
*
|
|
160
|
+
* @param graph — the workflow graph to query
|
|
161
|
+
* @returns The next dispatchable step, or null if none available
|
|
162
|
+
*/
|
|
163
|
+
export function getNextPendingStep(graph: WorkflowGraph): GraphStep | null {
|
|
164
|
+
const statusMap = new Map(graph.steps.map((s) => [s.id, s.status]));
|
|
165
|
+
|
|
166
|
+
for (const step of graph.steps) {
|
|
167
|
+
if (step.status !== "pending") continue;
|
|
168
|
+
const depsComplete = step.dependsOn.every(
|
|
169
|
+
(depId) => statusMap.get(depId) === "complete",
|
|
170
|
+
);
|
|
171
|
+
if (depsComplete) return step;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Return a new graph with the specified step marked as "complete".
|
|
179
|
+
* Immutable — does not mutate the input graph.
|
|
180
|
+
*
|
|
181
|
+
* @param graph — the current workflow graph
|
|
182
|
+
* @param stepId — ID of the step to mark complete
|
|
183
|
+
* @returns New graph with the step's status set to "complete"
|
|
184
|
+
* @throws Error if stepId is not found in the graph
|
|
185
|
+
*/
|
|
186
|
+
export function markStepComplete(
|
|
187
|
+
graph: WorkflowGraph,
|
|
188
|
+
stepId: string,
|
|
189
|
+
): WorkflowGraph {
|
|
190
|
+
const found = graph.steps.some((s) => s.id === stepId);
|
|
191
|
+
if (!found) {
|
|
192
|
+
throw new Error(`Step not found: ${stepId}`);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return {
|
|
196
|
+
...graph,
|
|
197
|
+
steps: graph.steps.map((s) =>
|
|
198
|
+
s.id === stepId
|
|
199
|
+
? { ...s, status: "complete" as const, finishedAt: new Date().toISOString() }
|
|
200
|
+
: s,
|
|
201
|
+
),
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// ─── Iteration expansion ─────────────────────────────────────────────────
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Expand an iterate step into concrete instances. Pure and deterministic —
|
|
209
|
+
* identical inputs always produce identical output.
|
|
210
|
+
*
|
|
211
|
+
* Given a parent step with status "pending" and an array of matched items,
|
|
212
|
+
* creates one instance step per item, marks the parent as "expanded", and
|
|
213
|
+
* rewrites any downstream dependsOn references from the parent ID to the
|
|
214
|
+
* full set of instance IDs.
|
|
215
|
+
*
|
|
216
|
+
* @param graph — the current workflow graph (not mutated)
|
|
217
|
+
* @param stepId — ID of the iterate step to expand
|
|
218
|
+
* @param items — matched items from the source artifact
|
|
219
|
+
* @param promptTemplate — template with {{item}} placeholders
|
|
220
|
+
* @returns New WorkflowGraph with instances inserted and deps rewritten
|
|
221
|
+
* @throws Error if stepId not found or step is not pending
|
|
222
|
+
*/
|
|
223
|
+
export function expandIteration(
|
|
224
|
+
graph: WorkflowGraph,
|
|
225
|
+
stepId: string,
|
|
226
|
+
items: string[],
|
|
227
|
+
promptTemplate: string,
|
|
228
|
+
): WorkflowGraph {
|
|
229
|
+
const parentIndex = graph.steps.findIndex((s) => s.id === stepId);
|
|
230
|
+
if (parentIndex === -1) {
|
|
231
|
+
throw new Error(`expandIteration: step not found: ${stepId}`);
|
|
232
|
+
}
|
|
233
|
+
const parentStep = graph.steps[parentIndex];
|
|
234
|
+
if (parentStep.status !== "pending") {
|
|
235
|
+
throw new Error(
|
|
236
|
+
`expandIteration: step "${stepId}" has status "${parentStep.status}", expected "pending"`,
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Create instance steps
|
|
241
|
+
const instanceIds: string[] = [];
|
|
242
|
+
const instances: GraphStep[] = items.map((item, i) => {
|
|
243
|
+
const instanceId = `${stepId}--${String(i + 1).padStart(3, "0")}`;
|
|
244
|
+
instanceIds.push(instanceId);
|
|
245
|
+
return {
|
|
246
|
+
id: instanceId,
|
|
247
|
+
title: `${parentStep.title}: ${item}`,
|
|
248
|
+
status: "pending" as const,
|
|
249
|
+
prompt: promptTemplate.replace(/\{\{item\}\}/g, () => item),
|
|
250
|
+
dependsOn: [...parentStep.dependsOn],
|
|
251
|
+
parentStepId: stepId,
|
|
252
|
+
};
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
// Build new steps array: copy everything, mark parent as expanded,
|
|
256
|
+
// insert instances right after the parent, rewrite downstream deps.
|
|
257
|
+
const newSteps: GraphStep[] = [];
|
|
258
|
+
for (let i = 0; i < graph.steps.length; i++) {
|
|
259
|
+
if (i === parentIndex) {
|
|
260
|
+
// Mark parent as expanded
|
|
261
|
+
newSteps.push({ ...parentStep, status: "expanded" as const });
|
|
262
|
+
// Insert instances immediately after parent
|
|
263
|
+
newSteps.push(...instances);
|
|
264
|
+
} else {
|
|
265
|
+
const step = graph.steps[i];
|
|
266
|
+
// Rewrite dependsOn: replace parent ID with all instance IDs
|
|
267
|
+
const hasDep = step.dependsOn.includes(stepId);
|
|
268
|
+
if (hasDep) {
|
|
269
|
+
const rewritten = step.dependsOn.flatMap((dep) =>
|
|
270
|
+
dep === stepId ? instanceIds : [dep],
|
|
271
|
+
);
|
|
272
|
+
newSteps.push({ ...step, dependsOn: rewritten });
|
|
273
|
+
} else {
|
|
274
|
+
newSteps.push(step);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
return {
|
|
280
|
+
...graph,
|
|
281
|
+
steps: newSteps,
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// ─── Definition → Graph conversion ──────────────────────────────────────
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Convert a parsed WorkflowDefinition into a WorkflowGraph with all
|
|
289
|
+
* steps in "pending" status. Used by run-manager to generate the initial
|
|
290
|
+
* GRAPH.yaml for a new run.
|
|
291
|
+
*
|
|
292
|
+
* @param def — a validated WorkflowDefinition from definition-loader
|
|
293
|
+
* @returns WorkflowGraph with pending steps and metadata from the definition
|
|
294
|
+
*/
|
|
295
|
+
export function initializeGraph(def: WorkflowDefinition): WorkflowGraph {
|
|
296
|
+
return {
|
|
297
|
+
steps: def.steps.map((s) => ({
|
|
298
|
+
id: s.id,
|
|
299
|
+
title: s.name,
|
|
300
|
+
status: "pending" as const,
|
|
301
|
+
prompt: s.prompt,
|
|
302
|
+
dependsOn: s.requires ?? [],
|
|
303
|
+
})),
|
|
304
|
+
metadata: {
|
|
305
|
+
name: def.name,
|
|
306
|
+
createdAt: new Date().toISOString(),
|
|
307
|
+
},
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/** @deprecated Use initializeGraph instead. Kept for backward compatibility. */
|
|
312
|
+
export { initializeGraph as graphFromDefinition };
|
|
@@ -168,7 +168,7 @@ function openRawDb(path: string): unknown {
|
|
|
168
168
|
|
|
169
169
|
// ─── Schema ────────────────────────────────────────────────────────────────
|
|
170
170
|
|
|
171
|
-
const SCHEMA_VERSION =
|
|
171
|
+
const SCHEMA_VERSION = 4;
|
|
172
172
|
|
|
173
173
|
function initSchema(db: DbAdapter, fileBacked: boolean): void {
|
|
174
174
|
// WAL mode for file-backed databases (must be outside transaction)
|
|
@@ -195,6 +195,7 @@ function initSchema(db: DbAdapter, fileBacked: boolean): void {
|
|
|
195
195
|
choice TEXT NOT NULL DEFAULT '',
|
|
196
196
|
rationale TEXT NOT NULL DEFAULT '',
|
|
197
197
|
revisable TEXT NOT NULL DEFAULT '',
|
|
198
|
+
made_by TEXT NOT NULL DEFAULT 'agent',
|
|
198
199
|
superseded_by TEXT DEFAULT NULL
|
|
199
200
|
)
|
|
200
201
|
`);
|
|
@@ -360,6 +361,22 @@ function migrateSchema(db: DbAdapter): void {
|
|
|
360
361
|
).run({ ":version": 3, ":applied_at": new Date().toISOString() });
|
|
361
362
|
}
|
|
362
363
|
|
|
364
|
+
// v3 → v4: add made_by column to decisions table
|
|
365
|
+
if (currentVersion < 4) {
|
|
366
|
+
// Add made_by column — default 'agent' for existing rows (pre-attribution decisions)
|
|
367
|
+
db.exec(`ALTER TABLE decisions ADD COLUMN made_by TEXT NOT NULL DEFAULT 'agent'`);
|
|
368
|
+
|
|
369
|
+
// Recreate views to pick up new columns (SQLite expands SELECT * at view creation time)
|
|
370
|
+
db.exec("DROP VIEW IF EXISTS active_decisions");
|
|
371
|
+
db.exec(
|
|
372
|
+
"CREATE VIEW active_decisions AS SELECT * FROM decisions WHERE superseded_by IS NULL",
|
|
373
|
+
);
|
|
374
|
+
|
|
375
|
+
db.prepare(
|
|
376
|
+
"INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)",
|
|
377
|
+
).run({ ":version": 4, ":applied_at": new Date().toISOString() });
|
|
378
|
+
}
|
|
379
|
+
|
|
363
380
|
db.exec("COMMIT");
|
|
364
381
|
} catch (err) {
|
|
365
382
|
db.exec("ROLLBACK");
|
|
@@ -471,8 +488,8 @@ export function insertDecision(d: Omit<Decision, "seq">): void {
|
|
|
471
488
|
throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
472
489
|
currentDb
|
|
473
490
|
.prepare(
|
|
474
|
-
`INSERT INTO decisions (id, when_context, scope, decision, choice, rationale, revisable, superseded_by)
|
|
475
|
-
VALUES (:id, :when_context, :scope, :decision, :choice, :rationale, :revisable, :superseded_by)`,
|
|
491
|
+
`INSERT INTO decisions (id, when_context, scope, decision, choice, rationale, revisable, made_by, superseded_by)
|
|
492
|
+
VALUES (:id, :when_context, :scope, :decision, :choice, :rationale, :revisable, :made_by, :superseded_by)`,
|
|
476
493
|
)
|
|
477
494
|
.run({
|
|
478
495
|
":id": d.id,
|
|
@@ -482,6 +499,7 @@ export function insertDecision(d: Omit<Decision, "seq">): void {
|
|
|
482
499
|
":choice": d.choice,
|
|
483
500
|
":rationale": d.rationale,
|
|
484
501
|
":revisable": d.revisable,
|
|
502
|
+
":made_by": d.made_by ?? "agent",
|
|
485
503
|
":superseded_by": d.superseded_by,
|
|
486
504
|
});
|
|
487
505
|
}
|
|
@@ -502,6 +520,7 @@ export function getDecisionById(id: string): Decision | null {
|
|
|
502
520
|
choice: row["choice"] as string,
|
|
503
521
|
rationale: row["rationale"] as string,
|
|
504
522
|
revisable: row["revisable"] as string,
|
|
523
|
+
made_by: (row["made_by"] as string as import("./types.js").DecisionMadeBy) ?? "agent",
|
|
505
524
|
superseded_by: (row["superseded_by"] as string) ?? null,
|
|
506
525
|
};
|
|
507
526
|
}
|
|
@@ -521,6 +540,7 @@ export function getActiveDecisions(): Decision[] {
|
|
|
521
540
|
choice: row["choice"] as string,
|
|
522
541
|
rationale: row["rationale"] as string,
|
|
523
542
|
revisable: row["revisable"] as string,
|
|
543
|
+
made_by: (row["made_by"] as string as import("./types.js").DecisionMadeBy) ?? "agent",
|
|
524
544
|
superseded_by: null,
|
|
525
545
|
}));
|
|
526
546
|
}
|
|
@@ -644,8 +664,8 @@ export function upsertDecision(d: Omit<Decision, "seq">): void {
|
|
|
644
664
|
throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
645
665
|
currentDb
|
|
646
666
|
.prepare(
|
|
647
|
-
`INSERT OR REPLACE INTO decisions (id, when_context, scope, decision, choice, rationale, revisable, superseded_by)
|
|
648
|
-
VALUES (:id, :when_context, :scope, :decision, :choice, :rationale, :revisable, :superseded_by)`,
|
|
667
|
+
`INSERT OR REPLACE INTO decisions (id, when_context, scope, decision, choice, rationale, revisable, made_by, superseded_by)
|
|
668
|
+
VALUES (:id, :when_context, :scope, :decision, :choice, :rationale, :revisable, :made_by, :superseded_by)`,
|
|
649
669
|
)
|
|
650
670
|
.run({
|
|
651
671
|
":id": d.id,
|
|
@@ -655,6 +675,7 @@ export function upsertDecision(d: Omit<Decision, "seq">): void {
|
|
|
655
675
|
":choice": d.choice,
|
|
656
676
|
":rationale": d.rationale,
|
|
657
677
|
":revisable": d.revisable,
|
|
678
|
+
":made_by": d.made_by ?? "agent",
|
|
658
679
|
":superseded_by": d.superseded_by ?? null,
|
|
659
680
|
});
|
|
660
681
|
}
|
|
@@ -783,9 +804,15 @@ export function reconcileWorktreeDb(
|
|
|
783
804
|
try {
|
|
784
805
|
adapter.exec(`ATTACH DATABASE '${worktreeDbPath}' AS wt`);
|
|
785
806
|
try {
|
|
807
|
+
// Check if attached wt database has the made_by column (legacy v3 worktrees won't)
|
|
808
|
+
const wtInfo = adapter.prepare("PRAGMA wt.table_info('decisions')").all();
|
|
809
|
+
const hasMadeBy = wtInfo.some((col) => col["name"] === "made_by");
|
|
810
|
+
|
|
786
811
|
const decConf = adapter
|
|
787
812
|
.prepare(
|
|
788
|
-
`SELECT m.id FROM decisions m INNER JOIN wt.decisions w ON m.id = w.id WHERE m.decision != w.decision OR m.choice != w.choice OR m.rationale != w.rationale OR
|
|
813
|
+
`SELECT m.id FROM decisions m INNER JOIN wt.decisions w ON m.id = w.id WHERE m.decision != w.decision OR m.choice != w.choice OR m.rationale != w.rationale OR ${
|
|
814
|
+
hasMadeBy ? "m.made_by != w.made_by" : "'agent' != 'agent'"
|
|
815
|
+
} OR m.superseded_by IS NOT w.superseded_by`,
|
|
789
816
|
)
|
|
790
817
|
.all();
|
|
791
818
|
for (const row of decConf)
|
|
@@ -808,10 +835,12 @@ export function reconcileWorktreeDb(
|
|
|
808
835
|
.prepare(
|
|
809
836
|
`
|
|
810
837
|
INSERT OR REPLACE INTO decisions (
|
|
811
|
-
id, when_context, scope, decision, choice, rationale, revisable, superseded_by
|
|
838
|
+
id, when_context, scope, decision, choice, rationale, revisable, made_by, superseded_by
|
|
812
839
|
)
|
|
813
840
|
SELECT
|
|
814
|
-
id, when_context, scope, decision, choice, rationale, revisable,
|
|
841
|
+
id, when_context, scope, decision, choice, rationale, revisable, ${
|
|
842
|
+
hasMadeBy ? "made_by" : "'agent'"
|
|
843
|
+
}, superseded_by
|
|
815
844
|
FROM wt.decisions
|
|
816
845
|
`,
|
|
817
846
|
)
|
|
@@ -170,7 +170,7 @@ export async function showQueueAdd(
|
|
|
170
170
|
const existingContext = await buildExistingMilestonesContext(basePath, milestoneIds, state);
|
|
171
171
|
|
|
172
172
|
// ── Determine next milestone ID ─────────────────────────────────────
|
|
173
|
-
// Note: the LLM will use the
|
|
173
|
+
// Note: the LLM will use the gsd_milestone_generate_id tool to get IDs
|
|
174
174
|
// at creation time, but we still mention the next ID in the preamble
|
|
175
175
|
// for context about where the sequence is.
|
|
176
176
|
const uniqueEnabled = !!loadEffectiveGSDPreferences()?.preferences?.unique_milestone_ids;
|
|
@@ -26,6 +26,7 @@ import { join } from "node:path";
|
|
|
26
26
|
import { readFileSync, existsSync, mkdirSync, readdirSync, rmSync, unlinkSync } from "node:fs";
|
|
27
27
|
import { readSessionLockData, isSessionLockProcessAlive } from "./session-lock.js";
|
|
28
28
|
import { nativeIsRepo, nativeInit } from "./native-git-bridge.js";
|
|
29
|
+
import { isInheritedRepo } from "./repo-identity.js";
|
|
29
30
|
import { ensureGitignore, ensurePreferences, untrackRuntimeFiles } from "./gitignore.js";
|
|
30
31
|
import { loadEffectiveGSDPreferences } from "./preferences.js";
|
|
31
32
|
import { detectProjectState } from "./detection.js";
|
|
@@ -54,7 +55,7 @@ import { getErrorMessage } from "./error-utils.js";
|
|
|
54
55
|
|
|
55
56
|
/**
|
|
56
57
|
* Generate the next milestone ID, accounting for reserved IDs, and reserve it.
|
|
57
|
-
* Ensures any preview ID shown in the UI matches what `
|
|
58
|
+
* Ensures any preview ID shown in the UI matches what `gsd_milestone_generate_id`
|
|
58
59
|
* will later return.
|
|
59
60
|
*/
|
|
60
61
|
function nextMilestoneIdReserved(existingIds: string[], uniqueEnabled: boolean): string {
|
|
@@ -346,7 +347,7 @@ function buildHeadlessDiscussPrompt(nextId: string, seedContext: string, _basePa
|
|
|
346
347
|
* Ensures git repo, .gsd/ structure, gitignore, and preferences all exist.
|
|
347
348
|
*/
|
|
348
349
|
function bootstrapGsdProject(basePath: string): void {
|
|
349
|
-
if (!nativeIsRepo(basePath)) {
|
|
350
|
+
if (!nativeIsRepo(basePath) || isInheritedRepo(basePath)) {
|
|
350
351
|
const mainBranch = loadEffectiveGSDPreferences()?.preferences?.git?.main_branch || "main";
|
|
351
352
|
nativeInit(basePath, mainBranch);
|
|
352
353
|
}
|
|
@@ -870,7 +871,10 @@ export async function showSmartEntry(
|
|
|
870
871
|
}
|
|
871
872
|
|
|
872
873
|
// ── Ensure git repo exists — GSD needs it for worktree isolation ──────
|
|
873
|
-
if
|
|
874
|
+
// Also handle inherited repos: if basePath is a subdirectory of another
|
|
875
|
+
// git repo that has no .gsd, create a fresh repo to prevent cross-project
|
|
876
|
+
// state leaks (#1639).
|
|
877
|
+
if (!nativeIsRepo(basePath) || isInheritedRepo(basePath)) {
|
|
874
878
|
const mainBranch = loadEffectiveGSDPreferences()?.preferences?.git?.main_branch || "main";
|
|
875
879
|
nativeInit(basePath, mainBranch);
|
|
876
880
|
}
|