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
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* definition-loader.ts — Parse and validate V1 YAML workflow definitions.
|
|
3
|
+
*
|
|
4
|
+
* Loads definition YAML files from `.gsd/workflow-defs/`, validates the
|
|
5
|
+
* V1 schema shape, and returns typed TypeScript objects. Pure functions
|
|
6
|
+
* with no engine or runtime dependencies — just `yaml` and `node:fs`.
|
|
7
|
+
*
|
|
8
|
+
* YAML uses snake_case (`depends_on`, `context_from`) per project convention (P005).
|
|
9
|
+
* TypeScript uses camelCase (`dependsOn`, `contextFrom`).
|
|
10
|
+
*
|
|
11
|
+
* Observability: All validation errors are collected into a string[] — callers
|
|
12
|
+
* can log, surface in dashboards, or return to agents for self-repair.
|
|
13
|
+
* substituteParams errors include the offending key name for traceability.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { parse } from "yaml";
|
|
17
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
18
|
+
import { join } from "node:path";
|
|
19
|
+
|
|
20
|
+
// ─── Public TypeScript Types (camelCase) ─────────────────────────────────
|
|
21
|
+
|
|
22
|
+
export type VerifyPolicy =
|
|
23
|
+
| { policy: "content-heuristic"; minSize?: number; pattern?: string }
|
|
24
|
+
| { policy: "shell-command"; command: string }
|
|
25
|
+
| { policy: "prompt-verify"; prompt: string }
|
|
26
|
+
| { policy: "human-review" };
|
|
27
|
+
|
|
28
|
+
export interface IterateConfig {
|
|
29
|
+
/** Artifact path (relative to run dir) to read and match against. */
|
|
30
|
+
source: string;
|
|
31
|
+
/** Regex pattern string. Must contain at least one capture group. Applied with global flag. */
|
|
32
|
+
pattern: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface StepDefinition {
|
|
36
|
+
/** Unique step identifier within the workflow. */
|
|
37
|
+
id: string;
|
|
38
|
+
/** Human-readable step name. */
|
|
39
|
+
name: string;
|
|
40
|
+
/** The prompt to dispatch for this step. */
|
|
41
|
+
prompt: string;
|
|
42
|
+
/** IDs of steps that must complete before this step can run. */
|
|
43
|
+
requires: string[];
|
|
44
|
+
/** Artifact paths produced by this step (relative to run dir). */
|
|
45
|
+
produces: string[];
|
|
46
|
+
/** Step IDs whose artifacts to include as context (S05 — accepted, not processed). */
|
|
47
|
+
contextFrom?: string[];
|
|
48
|
+
/** Verification policy for this step (S05 — typed + validated). */
|
|
49
|
+
verify?: VerifyPolicy;
|
|
50
|
+
/** Iteration config for this step (S06 — typed + validated). */
|
|
51
|
+
iterate?: IterateConfig;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface WorkflowDefinition {
|
|
55
|
+
/** Schema version — must be 1. */
|
|
56
|
+
version: number;
|
|
57
|
+
/** Workflow name. */
|
|
58
|
+
name: string;
|
|
59
|
+
/** Optional description. */
|
|
60
|
+
description?: string;
|
|
61
|
+
/** Optional parameter map for template substitution (S07). */
|
|
62
|
+
params?: Record<string, string>;
|
|
63
|
+
/** Ordered list of steps. */
|
|
64
|
+
steps: StepDefinition[];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// ─── Internal YAML Types (snake_case) ────────────────────────────────────
|
|
68
|
+
|
|
69
|
+
interface YamlStepDef {
|
|
70
|
+
id?: unknown;
|
|
71
|
+
name?: unknown;
|
|
72
|
+
prompt?: unknown;
|
|
73
|
+
requires?: unknown;
|
|
74
|
+
depends_on?: unknown;
|
|
75
|
+
produces?: unknown;
|
|
76
|
+
context_from?: unknown;
|
|
77
|
+
verify?: unknown;
|
|
78
|
+
iterate?: unknown;
|
|
79
|
+
[key: string]: unknown; // Forward-compat: unknown fields accepted silently
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
interface YamlWorkflowDef {
|
|
83
|
+
version?: unknown;
|
|
84
|
+
name?: unknown;
|
|
85
|
+
description?: unknown;
|
|
86
|
+
params?: unknown;
|
|
87
|
+
steps?: unknown;
|
|
88
|
+
[key: string]: unknown; // Forward-compat: unknown fields accepted silently
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ─── Validation ──────────────────────────────────────────────────────────
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Validate a parsed (but untyped) YAML object against the V1 workflow schema.
|
|
95
|
+
*
|
|
96
|
+
* Collects all errors (does not short-circuit) so a single call reveals
|
|
97
|
+
* every problem with the definition.
|
|
98
|
+
*
|
|
99
|
+
* Unknown fields are silently accepted for forward compatibility with
|
|
100
|
+
* S05/S06 features (`context_from`, `verify`, `iterate`).
|
|
101
|
+
*/
|
|
102
|
+
export function validateDefinition(parsed: unknown): { valid: boolean; errors: string[] } {
|
|
103
|
+
const errors: string[] = [];
|
|
104
|
+
|
|
105
|
+
if (parsed == null || typeof parsed !== "object") {
|
|
106
|
+
return { valid: false, errors: ["Definition must be a non-null object"] };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const def = parsed as YamlWorkflowDef;
|
|
110
|
+
|
|
111
|
+
// version: must be 1 (number)
|
|
112
|
+
if (def.version === undefined || def.version === null) {
|
|
113
|
+
errors.push("Missing required field: version");
|
|
114
|
+
} else if (def.version !== 1) {
|
|
115
|
+
errors.push(`Unsupported version: ${def.version} (expected 1)`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// name: must be a non-empty string
|
|
119
|
+
if (typeof def.name !== "string" || def.name.trim() === "") {
|
|
120
|
+
errors.push("Missing or empty required field: name");
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// steps: must be a non-empty array
|
|
124
|
+
if (!Array.isArray(def.steps)) {
|
|
125
|
+
errors.push("Missing required field: steps (must be an array)");
|
|
126
|
+
} else if (def.steps.length === 0) {
|
|
127
|
+
errors.push("steps must contain at least one step");
|
|
128
|
+
} else {
|
|
129
|
+
// Track whether all steps have valid IDs — graph-level checks only run when true
|
|
130
|
+
let allStepIdsValid = true;
|
|
131
|
+
|
|
132
|
+
for (let i = 0; i < def.steps.length; i++) {
|
|
133
|
+
const step = def.steps[i] as YamlStepDef;
|
|
134
|
+
if (step == null || typeof step !== "object") {
|
|
135
|
+
errors.push(`Step at index ${i} is not an object`);
|
|
136
|
+
allStepIdsValid = false;
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Required step fields
|
|
141
|
+
if (typeof step.id !== "string" || step.id.trim() === "") {
|
|
142
|
+
errors.push(`Step at index ${i} missing required field: id`);
|
|
143
|
+
allStepIdsValid = false;
|
|
144
|
+
}
|
|
145
|
+
if (typeof step.name !== "string" || step.name.trim() === "") {
|
|
146
|
+
errors.push(`Step at index ${i} missing required field: name`);
|
|
147
|
+
}
|
|
148
|
+
if (typeof step.prompt !== "string" || step.prompt.trim() === "") {
|
|
149
|
+
errors.push(`Step at index ${i} missing required field: prompt`);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// produces: path traversal guard
|
|
153
|
+
if (Array.isArray(step.produces)) {
|
|
154
|
+
for (const p of step.produces) {
|
|
155
|
+
if (typeof p === "string" && p.includes("..")) {
|
|
156
|
+
errors.push(`Step "${step.id}" produces path contains disallowed '..': ${p}`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// iterate: optional, but if present must conform to IterateConfig shape
|
|
162
|
+
if (step.iterate !== undefined) {
|
|
163
|
+
const it = step.iterate;
|
|
164
|
+
const sid = typeof step.id === "string" ? step.id : `index ${i}`;
|
|
165
|
+
if (it == null || typeof it !== "object" || Array.isArray(it)) {
|
|
166
|
+
errors.push(`Step "${sid}" iterate must be an object with "source" and "pattern" fields`);
|
|
167
|
+
} else {
|
|
168
|
+
const itObj = it as Record<string, unknown>;
|
|
169
|
+
if (typeof itObj.source !== "string" || (itObj.source as string).trim() === "") {
|
|
170
|
+
errors.push(`Step "${sid}" iterate.source must be a non-empty string`);
|
|
171
|
+
} else if ((itObj.source as string).includes("..")) {
|
|
172
|
+
errors.push(`Step "${sid}" iterate.source contains disallowed '..' path traversal`);
|
|
173
|
+
}
|
|
174
|
+
if (typeof itObj.pattern !== "string" || (itObj.pattern as string).trim() === "") {
|
|
175
|
+
errors.push(`Step "${sid}" iterate.pattern must be a non-empty string`);
|
|
176
|
+
} else {
|
|
177
|
+
const pat = itObj.pattern as string;
|
|
178
|
+
let regexValid = true;
|
|
179
|
+
try {
|
|
180
|
+
new RegExp(pat);
|
|
181
|
+
} catch {
|
|
182
|
+
regexValid = false;
|
|
183
|
+
errors.push(`Step "${sid}" iterate.pattern is not a valid regex: ${pat}`);
|
|
184
|
+
}
|
|
185
|
+
if (regexValid && !/\((?!\?)/.test(pat)) {
|
|
186
|
+
errors.push(`Step "${sid}" iterate.pattern must contain at least one capture group`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// verify: optional, but if present must conform to VerifyPolicy shape
|
|
193
|
+
if (step.verify !== undefined) {
|
|
194
|
+
const v = step.verify;
|
|
195
|
+
const sid = typeof step.id === "string" ? step.id : `index ${i}`;
|
|
196
|
+
if (v == null || typeof v !== "object" || Array.isArray(v)) {
|
|
197
|
+
errors.push(`Step "${sid}" verify must be an object with a "policy" field`);
|
|
198
|
+
} else {
|
|
199
|
+
const vObj = v as Record<string, unknown>;
|
|
200
|
+
const VALID_POLICIES = ["content-heuristic", "shell-command", "prompt-verify", "human-review"];
|
|
201
|
+
if (typeof vObj.policy !== "string" || !VALID_POLICIES.includes(vObj.policy)) {
|
|
202
|
+
errors.push(`Step "${sid}" verify.policy must be one of: ${VALID_POLICIES.join(", ")}`);
|
|
203
|
+
} else {
|
|
204
|
+
// Policy-specific required field checks
|
|
205
|
+
if (vObj.policy === "shell-command") {
|
|
206
|
+
if (typeof vObj.command !== "string" || (vObj.command as string).trim() === "") {
|
|
207
|
+
errors.push(`Step "${sid}" verify policy "shell-command" requires a non-empty "command" field`);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
if (vObj.policy === "prompt-verify") {
|
|
211
|
+
if (typeof vObj.prompt !== "string" || (vObj.prompt as string).trim() === "") {
|
|
212
|
+
errors.push(`Step "${sid}" verify policy "prompt-verify" requires a non-empty "prompt" field`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// ─── Graph-level validations (only when all step IDs are valid) ────
|
|
221
|
+
if (allStepIdsValid) {
|
|
222
|
+
const steps = def.steps as YamlStepDef[];
|
|
223
|
+
|
|
224
|
+
// 1. Duplicate step ID check
|
|
225
|
+
const idCounts = new Map<string, number>();
|
|
226
|
+
for (const step of steps) {
|
|
227
|
+
const id = step.id as string;
|
|
228
|
+
idCounts.set(id, (idCounts.get(id) ?? 0) + 1);
|
|
229
|
+
}
|
|
230
|
+
for (const [id, count] of idCounts) {
|
|
231
|
+
if (count > 1) {
|
|
232
|
+
errors.push(`Duplicate step id: ${id}`);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Build valid ID set for remaining checks
|
|
237
|
+
const validIds = new Set(steps.map((s) => s.id as string));
|
|
238
|
+
|
|
239
|
+
// 2. Dangling dependency check + 3. Self-referencing dependency check
|
|
240
|
+
for (const step of steps) {
|
|
241
|
+
const sid = step.id as string;
|
|
242
|
+
const deps = Array.isArray(step.requires)
|
|
243
|
+
? (step.requires as string[])
|
|
244
|
+
: Array.isArray(step.depends_on)
|
|
245
|
+
? (step.depends_on as string[])
|
|
246
|
+
: [];
|
|
247
|
+
|
|
248
|
+
for (const depId of deps) {
|
|
249
|
+
if (depId === sid) {
|
|
250
|
+
errors.push(`Step '${sid}' depends on itself`);
|
|
251
|
+
} else if (!validIds.has(depId)) {
|
|
252
|
+
errors.push(`Step '${sid}' requires unknown step '${depId}'`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// 4. Cycle detection (DFS) — only when no duplicate IDs
|
|
258
|
+
if (![...idCounts.values()].some((c: number) => c > 1)) {
|
|
259
|
+
// Build adjacency list: step → its dependencies
|
|
260
|
+
const adj = new Map<string, string[]>();
|
|
261
|
+
for (const step of steps) {
|
|
262
|
+
const sid = step.id as string;
|
|
263
|
+
const deps = Array.isArray(step.requires)
|
|
264
|
+
? (step.requires as string[])
|
|
265
|
+
: Array.isArray(step.depends_on)
|
|
266
|
+
? (step.depends_on as string[])
|
|
267
|
+
: [];
|
|
268
|
+
adj.set(sid, deps.filter((d) => validIds.has(d) && d !== sid));
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const WHITE = 0, GRAY = 1, BLACK = 2;
|
|
272
|
+
const color = new Map<string, number>();
|
|
273
|
+
for (const id of validIds) color.set(id, WHITE);
|
|
274
|
+
|
|
275
|
+
const parent = new Map<string, string | null>();
|
|
276
|
+
|
|
277
|
+
function dfs(node: string): string[] | null {
|
|
278
|
+
color.set(node, GRAY);
|
|
279
|
+
for (const dep of adj.get(node) ?? []) {
|
|
280
|
+
if (color.get(dep) === GRAY) {
|
|
281
|
+
// Back edge found — reconstruct cycle path
|
|
282
|
+
const cycle: string[] = [dep, node];
|
|
283
|
+
let cur = node;
|
|
284
|
+
while (parent.has(cur) && parent.get(cur) !== null && parent.get(cur) !== dep) {
|
|
285
|
+
cur = parent.get(cur)!;
|
|
286
|
+
cycle.push(cur);
|
|
287
|
+
}
|
|
288
|
+
cycle.push(dep);
|
|
289
|
+
cycle.reverse();
|
|
290
|
+
return cycle;
|
|
291
|
+
}
|
|
292
|
+
if (color.get(dep) === WHITE) {
|
|
293
|
+
parent.set(dep, node);
|
|
294
|
+
const result = dfs(dep);
|
|
295
|
+
if (result) return result;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
color.set(node, BLACK);
|
|
299
|
+
return null;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
for (const id of validIds) {
|
|
303
|
+
if (color.get(id) === WHITE) {
|
|
304
|
+
parent.set(id, null);
|
|
305
|
+
const cycle = dfs(id);
|
|
306
|
+
if (cycle) {
|
|
307
|
+
errors.push(`Cycle detected: ${cycle.join(" → ")}`);
|
|
308
|
+
break; // One cycle error is enough
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
return { valid: errors.length === 0, errors };
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// ─── Loading ─────────────────────────────────────────────────────────────
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Load and validate a YAML workflow definition from the filesystem.
|
|
323
|
+
*
|
|
324
|
+
* Reads `<defsDir>/<name>.yaml`, parses YAML, validates the V1 schema,
|
|
325
|
+
* and converts snake_case YAML keys to camelCase TypeScript types.
|
|
326
|
+
*
|
|
327
|
+
* @param defsDir — directory containing definition YAML files
|
|
328
|
+
* @param name — definition filename without extension
|
|
329
|
+
* @returns Parsed and validated WorkflowDefinition
|
|
330
|
+
* @throws Error if file is missing, YAML is malformed, or schema is invalid
|
|
331
|
+
*/
|
|
332
|
+
export function loadDefinition(defsDir: string, name: string): WorkflowDefinition {
|
|
333
|
+
const filePath = join(defsDir, `${name}.yaml`);
|
|
334
|
+
|
|
335
|
+
if (!existsSync(filePath)) {
|
|
336
|
+
throw new Error(`Definition file not found: ${filePath}`);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
const raw = readFileSync(filePath, "utf-8");
|
|
340
|
+
let parsed: unknown;
|
|
341
|
+
try {
|
|
342
|
+
parsed = parse(raw);
|
|
343
|
+
} catch (e) {
|
|
344
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
345
|
+
throw new Error(`Failed to parse YAML in ${filePath}: ${msg}`);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
const { valid, errors } = validateDefinition(parsed);
|
|
349
|
+
if (!valid) {
|
|
350
|
+
throw new Error(`Invalid workflow definition in ${filePath}:\n - ${errors.join("\n - ")}`);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// Convert snake_case YAML → camelCase TypeScript
|
|
354
|
+
const yamlDef = parsed as YamlWorkflowDef;
|
|
355
|
+
const yamlSteps = yamlDef.steps as YamlStepDef[];
|
|
356
|
+
|
|
357
|
+
return {
|
|
358
|
+
version: yamlDef.version as number,
|
|
359
|
+
name: yamlDef.name as string,
|
|
360
|
+
description: typeof yamlDef.description === "string" ? yamlDef.description : undefined,
|
|
361
|
+
params: yamlDef.params != null && typeof yamlDef.params === "object"
|
|
362
|
+
? Object.fromEntries(
|
|
363
|
+
Object.entries(yamlDef.params as Record<string, unknown>).map(
|
|
364
|
+
([k, v]) => [k, String(v)],
|
|
365
|
+
),
|
|
366
|
+
)
|
|
367
|
+
: undefined,
|
|
368
|
+
steps: yamlSteps.map((s) => ({
|
|
369
|
+
id: s.id as string,
|
|
370
|
+
name: s.name as string,
|
|
371
|
+
prompt: s.prompt as string,
|
|
372
|
+
requires: Array.isArray(s.requires)
|
|
373
|
+
? (s.requires as string[])
|
|
374
|
+
: Array.isArray(s.depends_on)
|
|
375
|
+
? (s.depends_on as string[])
|
|
376
|
+
: [],
|
|
377
|
+
produces: Array.isArray(s.produces) ? (s.produces as string[]) : [],
|
|
378
|
+
contextFrom: Array.isArray(s.context_from) ? (s.context_from as string[]) : undefined,
|
|
379
|
+
verify: s.verify as VerifyPolicy | undefined,
|
|
380
|
+
iterate: (s.iterate != null && typeof s.iterate === "object")
|
|
381
|
+
? s.iterate as IterateConfig
|
|
382
|
+
: undefined,
|
|
383
|
+
})),
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// ─── Parameter Substitution ──────────────────────────────────────────────
|
|
388
|
+
|
|
389
|
+
/** Regex matching `{{key}}` placeholders — captures the key name. */
|
|
390
|
+
const PARAM_PATTERN = /\{\{(\w+)\}\}/g;
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Replace `{{key}}` placeholders in a single prompt string.
|
|
394
|
+
*
|
|
395
|
+
* Exported for use by the engine on iteration-instance prompts that live
|
|
396
|
+
* in GRAPH.yaml (outside the definition's step list).
|
|
397
|
+
*
|
|
398
|
+
* @throws Error if any merged param value contains `..` (path-traversal guard)
|
|
399
|
+
*/
|
|
400
|
+
export function substitutePromptString(
|
|
401
|
+
prompt: string,
|
|
402
|
+
merged: Record<string, string>,
|
|
403
|
+
): string {
|
|
404
|
+
return prompt.replace(PARAM_PATTERN, (match, key: string) => {
|
|
405
|
+
const value = merged[key];
|
|
406
|
+
return value !== undefined ? value : match;
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Replace `{{key}}` placeholders in all step prompts with param values.
|
|
412
|
+
*
|
|
413
|
+
* Merge order: `definition.params` (defaults) ← `overrides` (CLI wins).
|
|
414
|
+
* Returns a **new** WorkflowDefinition — the input is never mutated.
|
|
415
|
+
*
|
|
416
|
+
* @throws Error if any param value contains `..` (path-traversal guard)
|
|
417
|
+
* @throws Error if any `{{key}}` remains unresolved after substitution
|
|
418
|
+
*/
|
|
419
|
+
export function substituteParams(
|
|
420
|
+
definition: WorkflowDefinition,
|
|
421
|
+
overrides?: Record<string, string>,
|
|
422
|
+
): WorkflowDefinition {
|
|
423
|
+
const merged: Record<string, string> = {
|
|
424
|
+
...(definition.params ?? {}),
|
|
425
|
+
...(overrides ?? {}),
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
// Path-traversal guard: reject any value containing ".."
|
|
429
|
+
for (const [key, value] of Object.entries(merged)) {
|
|
430
|
+
if (value.includes("..")) {
|
|
431
|
+
throw new Error(
|
|
432
|
+
`Parameter "${key}" contains disallowed '..' (path traversal): ${value}`,
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// Substitute in each step prompt
|
|
438
|
+
const substitutedSteps = definition.steps.map((step) => ({
|
|
439
|
+
...step,
|
|
440
|
+
prompt: substitutePromptString(step.prompt, merged),
|
|
441
|
+
}));
|
|
442
|
+
|
|
443
|
+
// Check for unresolved placeholders
|
|
444
|
+
const unresolved = new Set<string>();
|
|
445
|
+
for (const step of substitutedSteps) {
|
|
446
|
+
let m: RegExpExecArray | null;
|
|
447
|
+
const re = new RegExp(PARAM_PATTERN.source, "g");
|
|
448
|
+
while ((m = re.exec(step.prompt)) !== null) {
|
|
449
|
+
unresolved.add(m[1]);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
if (unresolved.size > 0) {
|
|
454
|
+
const keys = [...unresolved].sort().join(", ");
|
|
455
|
+
throw new Error(`Unresolved parameter(s) in step prompts: ${keys}`);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
return {
|
|
459
|
+
...definition,
|
|
460
|
+
steps: substitutedSteps,
|
|
461
|
+
};
|
|
462
|
+
}
|
|
@@ -69,7 +69,7 @@ export interface ProjectSignals {
|
|
|
69
69
|
|
|
70
70
|
// ─── Project File Markers ───────────────────────────────────────────────────────
|
|
71
71
|
|
|
72
|
-
const PROJECT_FILES = [
|
|
72
|
+
export const PROJECT_FILES = [
|
|
73
73
|
"package.json",
|
|
74
74
|
"Cargo.toml",
|
|
75
75
|
"go.mod",
|
|
@@ -87,6 +87,18 @@ const PROJECT_FILES = [
|
|
|
87
87
|
"mix.exs",
|
|
88
88
|
"deno.json",
|
|
89
89
|
"deno.jsonc",
|
|
90
|
+
// .NET
|
|
91
|
+
".sln",
|
|
92
|
+
".csproj",
|
|
93
|
+
"Directory.Build.props",
|
|
94
|
+
// Git submodules
|
|
95
|
+
".gitmodules",
|
|
96
|
+
// Xcode
|
|
97
|
+
"project.yml",
|
|
98
|
+
".xcodeproj",
|
|
99
|
+
".xcworkspace",
|
|
100
|
+
// Docker
|
|
101
|
+
"Dockerfile",
|
|
90
102
|
] as const;
|
|
91
103
|
|
|
92
104
|
const LANGUAGE_MAP: Record<string, string> = {
|
|
@@ -106,6 +118,13 @@ const LANGUAGE_MAP: Record<string, string> = {
|
|
|
106
118
|
"mix.exs": "elixir",
|
|
107
119
|
"deno.json": "typescript/deno",
|
|
108
120
|
"deno.jsonc": "typescript/deno",
|
|
121
|
+
".sln": "dotnet",
|
|
122
|
+
".csproj": "dotnet",
|
|
123
|
+
"Directory.Build.props": "dotnet",
|
|
124
|
+
"project.yml": "swift/xcode",
|
|
125
|
+
".xcodeproj": "swift/xcode",
|
|
126
|
+
".xcworkspace": "swift/xcode",
|
|
127
|
+
"Dockerfile": "docker",
|
|
109
128
|
};
|
|
110
129
|
|
|
111
130
|
const MONOREPO_MARKERS = [
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dev-execution-policy.ts — DevExecutionPolicy implementation.
|
|
3
|
+
*
|
|
4
|
+
* Stub policy for the dev engine. All methods return safe defaults.
|
|
5
|
+
* Real verification/closeout continues running through phases.ts via LoopDeps.
|
|
6
|
+
* Wiring this policy into the loop is S04's responsibility.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { ExecutionPolicy } from "./execution-policy.js";
|
|
10
|
+
import type { RecoveryAction, CloseoutResult } from "./engine-types.js";
|
|
11
|
+
|
|
12
|
+
export class DevExecutionPolicy implements ExecutionPolicy {
|
|
13
|
+
async prepareWorkspace(
|
|
14
|
+
_basePath: string,
|
|
15
|
+
_milestoneId: string,
|
|
16
|
+
): Promise<void> {
|
|
17
|
+
// no-op — workspace preparation handled by existing GSD logic
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async selectModel(
|
|
21
|
+
_unitType: string,
|
|
22
|
+
_unitId: string,
|
|
23
|
+
_context: { basePath: string },
|
|
24
|
+
): Promise<{ tier: string; modelDowngraded: boolean } | null> {
|
|
25
|
+
return null; // use default model selection
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async verify(
|
|
29
|
+
_unitType: string,
|
|
30
|
+
_unitId: string,
|
|
31
|
+
_context: { basePath: string },
|
|
32
|
+
): Promise<"continue" | "retry" | "pause"> {
|
|
33
|
+
return "continue";
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async recover(
|
|
37
|
+
_unitType: string,
|
|
38
|
+
_unitId: string,
|
|
39
|
+
_context: { basePath: string },
|
|
40
|
+
): Promise<RecoveryAction> {
|
|
41
|
+
return { outcome: "retry" };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async closeout(
|
|
45
|
+
_unitType: string,
|
|
46
|
+
_unitId: string,
|
|
47
|
+
_context: { basePath: string; startedAt: number },
|
|
48
|
+
): Promise<CloseoutResult> {
|
|
49
|
+
return { committed: false, artifacts: [] };
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dev-workflow-engine.ts — DevWorkflowEngine implementation.
|
|
3
|
+
*
|
|
4
|
+
* Implements WorkflowEngine by delegating to existing GSD state derivation
|
|
5
|
+
* and dispatch logic. This is the "dev" engine — it wraps the current GSD
|
|
6
|
+
* auto-mode behavior behind the engine-polymorphic interface.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { WorkflowEngine } from "./workflow-engine.js";
|
|
10
|
+
import type {
|
|
11
|
+
EngineState,
|
|
12
|
+
EngineDispatchAction,
|
|
13
|
+
CompletedStep,
|
|
14
|
+
ReconcileResult,
|
|
15
|
+
DisplayMetadata,
|
|
16
|
+
} from "./engine-types.js";
|
|
17
|
+
import type { GSDState } from "./types.js";
|
|
18
|
+
import type { DispatchAction, DispatchContext } from "./auto-dispatch.js";
|
|
19
|
+
|
|
20
|
+
import { deriveState } from "./state.js";
|
|
21
|
+
import { resolveDispatch } from "./auto-dispatch.js";
|
|
22
|
+
import { loadEffectiveGSDPreferences } from "./preferences.js";
|
|
23
|
+
|
|
24
|
+
// ─── Bridge: DispatchAction → EngineDispatchAction ────────────────────────
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Map a GSD-specific DispatchAction (which carries `matchedRule`, `unitType`,
|
|
28
|
+
* etc.) to the engine-generic EngineDispatchAction discriminated union.
|
|
29
|
+
*
|
|
30
|
+
* Exported for unit testing.
|
|
31
|
+
*/
|
|
32
|
+
export function bridgeDispatchAction(da: DispatchAction): EngineDispatchAction {
|
|
33
|
+
switch (da.action) {
|
|
34
|
+
case "dispatch":
|
|
35
|
+
return {
|
|
36
|
+
action: "dispatch",
|
|
37
|
+
step: {
|
|
38
|
+
unitType: da.unitType,
|
|
39
|
+
unitId: da.unitId,
|
|
40
|
+
prompt: da.prompt,
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
case "stop":
|
|
44
|
+
return {
|
|
45
|
+
action: "stop",
|
|
46
|
+
reason: da.reason,
|
|
47
|
+
level: da.level,
|
|
48
|
+
};
|
|
49
|
+
case "skip":
|
|
50
|
+
return { action: "skip" };
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// ─── DevWorkflowEngine ───────────────────────────────────────────────────
|
|
55
|
+
|
|
56
|
+
export class DevWorkflowEngine implements WorkflowEngine {
|
|
57
|
+
readonly engineId = "dev" as const;
|
|
58
|
+
|
|
59
|
+
async deriveState(basePath: string): Promise<EngineState> {
|
|
60
|
+
const gsd: GSDState = await deriveState(basePath);
|
|
61
|
+
return {
|
|
62
|
+
phase: gsd.phase,
|
|
63
|
+
currentMilestoneId: gsd.activeMilestone?.id ?? null,
|
|
64
|
+
activeSliceId: gsd.activeSlice?.id ?? null,
|
|
65
|
+
activeTaskId: gsd.activeTask?.id ?? null,
|
|
66
|
+
isComplete: gsd.phase === "complete",
|
|
67
|
+
raw: gsd,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async resolveDispatch(
|
|
72
|
+
state: EngineState,
|
|
73
|
+
context: { basePath: string },
|
|
74
|
+
): Promise<EngineDispatchAction> {
|
|
75
|
+
const gsd = state.raw as GSDState;
|
|
76
|
+
const mid = gsd.activeMilestone?.id ?? "";
|
|
77
|
+
const midTitle = gsd.activeMilestone?.title ?? "";
|
|
78
|
+
const loaded = loadEffectiveGSDPreferences();
|
|
79
|
+
const prefs = loaded?.preferences ?? undefined;
|
|
80
|
+
|
|
81
|
+
const dispatchCtx: DispatchContext = {
|
|
82
|
+
basePath: context.basePath,
|
|
83
|
+
mid,
|
|
84
|
+
midTitle,
|
|
85
|
+
state: gsd,
|
|
86
|
+
prefs,
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const result = await resolveDispatch(dispatchCtx);
|
|
90
|
+
return bridgeDispatchAction(result);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async reconcile(
|
|
94
|
+
state: EngineState,
|
|
95
|
+
_completedStep: CompletedStep,
|
|
96
|
+
): Promise<ReconcileResult> {
|
|
97
|
+
return {
|
|
98
|
+
outcome: state.isComplete ? "milestone-complete" : "continue",
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
getDisplayMetadata(state: EngineState): DisplayMetadata {
|
|
103
|
+
return {
|
|
104
|
+
engineLabel: "GSD Dev",
|
|
105
|
+
currentPhase: state.phase,
|
|
106
|
+
progressSummary: `${state.currentMilestoneId ?? "no milestone"} / ${state.activeSliceId ?? "—"} / ${state.activeTaskId ?? "—"}`,
|
|
107
|
+
stepCount: null,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
}
|