@opengsd/gsd-pi 1.3.0-dev.65546769 → 1.3.0-dev.738160b9
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 +1 -1
- package/dist/cli.js +17 -4
- package/dist/headless-answers.js +1 -1
- package/dist/headless-ui.d.ts +1 -1
- package/dist/headless-ui.js +1 -1
- package/dist/headless.js +1 -1
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/claude-code-cli/models.js +9 -0
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +11 -2
- package/dist/resources/extensions/google-cli/stream-adapter.js +82 -15
- package/dist/resources/extensions/gsd/artifact-verification.js +427 -0
- package/dist/resources/extensions/gsd/auto/orchestrator.js +12 -3
- package/dist/resources/extensions/gsd/auto/session.js +11 -0
- package/dist/resources/extensions/gsd/auto/verification-retry-policy.js +1 -1
- package/dist/resources/extensions/gsd/auto-artifact-paths.js +28 -1
- package/dist/resources/extensions/gsd/auto-budget.js +5 -1
- package/dist/resources/extensions/gsd/auto-dispatch.js +34 -20
- package/dist/resources/extensions/gsd/auto-post-unit.js +1 -1
- package/dist/resources/extensions/gsd/auto-prompts.js +29 -14
- package/dist/resources/extensions/gsd/auto-recovery.js +9 -510
- package/dist/resources/extensions/gsd/auto-runtime-state.js +4 -5
- package/dist/resources/extensions/gsd/auto-timeout-recovery.js +3 -3
- package/dist/resources/extensions/gsd/auto-verification.js +5 -2
- package/dist/resources/extensions/gsd/auto.js +19 -10
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +103 -13
- package/dist/resources/extensions/gsd/bootstrap/core-session-tools.js +39 -0
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +11 -5
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +2 -0
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +2 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +41 -21
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +46 -19
- package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +96 -10
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +1 -1
- package/dist/resources/extensions/gsd/closeout-consistency-gate.js +3 -1
- package/dist/resources/extensions/gsd/commands/handlers/auto.js +1 -1
- package/dist/resources/extensions/gsd/commands-context.js +19 -1
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +17 -11
- package/dist/resources/extensions/gsd/commands-usage.js +1 -1
- package/dist/resources/extensions/gsd/commands-worktree.js +12 -10
- package/dist/resources/extensions/gsd/dashboard-overlay.js +32 -3
- package/dist/resources/extensions/gsd/db/engine.js +4 -1
- package/dist/resources/extensions/gsd/db/queries.js +60 -0
- package/dist/resources/extensions/gsd/db-memory-fts-schema.js +34 -0
- package/dist/resources/extensions/gsd/db-workspace.js +55 -3
- package/dist/resources/extensions/gsd/delegation-policy.js +1 -1
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +2 -2
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +192 -4
- package/dist/resources/extensions/gsd/doctor-providers.js +92 -8
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +3 -0
- package/dist/resources/extensions/gsd/exec-sandbox.js +53 -11
- package/dist/resources/extensions/gsd/flat-phase-migration.js +45 -0
- package/dist/resources/extensions/gsd/forensics.js +2 -32
- package/dist/resources/extensions/gsd/git-service.js +61 -4
- package/dist/resources/extensions/gsd/gitignore.js +4 -1
- package/dist/resources/extensions/gsd/guided-flow-queue.js +66 -5
- package/dist/resources/extensions/gsd/health-widget.js +55 -29
- package/dist/resources/extensions/gsd/json-persistence.js +20 -0
- package/dist/resources/extensions/gsd/knowledge-backfill.js +18 -11
- package/dist/resources/extensions/gsd/layout-policy.js +3 -1
- package/dist/resources/extensions/gsd/markdown-renderer.js +8 -9
- package/dist/resources/extensions/gsd/memory-backfill.js +28 -21
- package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +44 -21
- package/dist/resources/extensions/gsd/metrics.js +4 -4
- package/dist/resources/extensions/gsd/migrate-external.js +11 -2
- package/dist/resources/extensions/gsd/migration-auto-check.js +22 -0
- package/dist/resources/extensions/gsd/milestone-ids.js +32 -2
- package/dist/resources/extensions/gsd/milestone-implementation-evidence.js +26 -20
- package/dist/resources/extensions/gsd/orphan-stash-audit.js +92 -16
- package/dist/resources/extensions/gsd/prompts/code-review.md +6 -4
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +2 -2
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +3 -3
- package/dist/resources/extensions/gsd/quick.js +45 -2
- package/dist/resources/extensions/gsd/root-write-leak-guard.js +7 -1
- package/dist/resources/extensions/gsd/safety/destructive-guard.js +8 -1
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +16 -1
- package/dist/resources/extensions/gsd/safety/file-change-validator.js +5 -2
- package/dist/resources/extensions/gsd/session-forensics.js +11 -1
- package/dist/resources/extensions/gsd/skills/gsd-headless/references/commands.md +1 -1
- package/dist/resources/extensions/gsd/state/derive/cache.js +28 -0
- package/dist/resources/extensions/gsd/state/derive/db-open.js +39 -0
- package/dist/resources/extensions/gsd/state/derive/from-db.js +452 -0
- package/dist/resources/extensions/gsd/state/derive/index.js +75 -0
- package/dist/resources/extensions/gsd/state/derive/interrupted-work.js +21 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-render.js +45 -2
- package/dist/resources/extensions/gsd/state-reconciliation/index.js +48 -23
- package/dist/resources/extensions/gsd/state-reconciliation/registry.js +32 -28
- package/dist/resources/extensions/gsd/state.js +12 -611
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +4 -2
- package/dist/resources/extensions/gsd/tools/complete-slice.js +2 -2
- package/dist/resources/extensions/gsd/tools/complete-task.js +43 -14
- package/dist/resources/extensions/gsd/tools/exec-tool.js +7 -2
- package/dist/resources/extensions/gsd/tools/plan-slice.js +59 -44
- package/dist/resources/extensions/gsd/tools/plan-task.js +28 -5
- package/dist/resources/extensions/gsd/undo.js +43 -6
- package/dist/resources/extensions/gsd/unit-context-composer.js +23 -7
- package/dist/resources/extensions/gsd/unit-registry.js +36 -6
- package/dist/resources/extensions/gsd/unmerged-milestone-guard.js +33 -3
- package/dist/resources/extensions/gsd/validation-block-guard.js +9 -4
- package/dist/resources/extensions/gsd/verification-gate.js +7 -0
- package/dist/resources/extensions/gsd/workflow-manifest.js +126 -13
- package/dist/resources/extensions/gsd/workflow-projections.js +19 -14
- package/dist/resources/extensions/gsd/workspace-git-preflight.js +30 -1
- package/dist/resources/extensions/gsd/worktree-manager.js +44 -2
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +10 -10
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +9 -9
- 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 +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/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 +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +2 -2
- 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 +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +10 -10
- package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
- 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/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/{2659.b7b129ee6a769448.js → 2659.58e950899a9bb82f.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/2772.a7c1fcc69a4685ef.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{3616.3c60753b8ffcbd2e.js → 3616.61a2af74bb8833c8.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/{4283.8e446784528ed9dc.js → 4283.d0d9e0a955e441cb.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/{5826.a46ecdd1cfe8dabc.js → 5826.5421d66c72b9f34e.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/{8785.481aa5869991b760.js → 8785.e29b3134cab1d153.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/8937.640dc9c2aaa1dfad.js +10 -0
- package/dist/web/standalone/.next/static/chunks/app/{page-6644fc6ee8ca1247.js → page-72a856634ad14c10.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/webpack-9c401904f87ded16.js +1 -0
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
- package/package.json +1 -1
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/dist/workflow.d.ts +1 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -1
- package/packages/contracts/dist/workflow.js +2 -0
- package/packages/contracts/dist/workflow.js.map +1 -1
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/dist/agent-session.d.ts +1 -0
- package/packages/gsd-agent-core/dist/agent-session.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/agent-session.js +3 -0
- package/packages/gsd-agent-core/dist/agent-session.js.map +1 -1
- package/packages/gsd-agent-core/dist/extension-ui-snapshot.d.ts +41 -0
- package/packages/gsd-agent-core/dist/extension-ui-snapshot.d.ts.map +1 -0
- package/packages/gsd-agent-core/dist/extension-ui-snapshot.js +62 -0
- package/packages/gsd-agent-core/dist/extension-ui-snapshot.js.map +1 -0
- package/packages/gsd-agent-core/dist/index.d.ts +2 -0
- package/packages/gsd-agent-core/dist/index.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/index.js +2 -0
- package/packages/gsd-agent-core/dist/index.js.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-events.js +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-events.js.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts +1 -0
- package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-host.js.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts +5 -0
- package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-prompt.js +60 -3
- package/packages/gsd-agent-core/dist/session/agent-session-prompt.js.map +1 -1
- package/packages/gsd-agent-core/dist/transcript-store.d.ts +58 -0
- package/packages/gsd-agent-core/dist/transcript-store.d.ts.map +1 -0
- package/packages/gsd-agent-core/dist/transcript-store.js +132 -0
- package/packages/gsd-agent-core/dist/transcript-store.js.map +1 -0
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +2 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +25 -11
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.d.ts +4 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.js +7 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts +3 -24
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +26 -829
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.d.ts +58 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.js +312 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.d.ts +31 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.js +130 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.d.ts +15 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js +258 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.d.ts +13 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.js +118 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.d.ts +9 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.js +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.d.ts +54 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.js +20 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts +4 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +9 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.d.ts +56 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.js +44 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.d.ts +5 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.js +77 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.d.ts +2 -0
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.js +23 -5
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +18 -0
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/README.md +1 -1
- package/packages/mcp-server/dist/server.d.ts +1 -1
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +3 -3
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +13 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +35 -21
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +4 -4
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +3 -2
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +46 -0
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +38 -0
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/README.md +3 -2
- package/packages/pi-coding-agent/dist/core/session-manager-context.d.ts +9 -0
- package/packages/pi-coding-agent/dist/core/session-manager-context.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-context.js +94 -0
- package/packages/pi-coding-agent/dist/core/session-manager-context.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-list.d.ts +8 -0
- package/packages/pi-coding-agent/dist/core/session-manager-list.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-list.js +244 -0
- package/packages/pi-coding-agent/dist/core/session-manager-list.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-migration.d.ts +12 -0
- package/packages/pi-coding-agent/dist/core/session-manager-migration.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-migration.js +84 -0
- package/packages/pi-coding-agent/dist/core/session-manager-migration.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts +135 -0
- package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-types.js +2 -0
- package/packages/pi-coding-agent/dist/core/session-manager-types.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager.d.ts +6 -154
- package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager.js +22 -459
- package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/theme/theme-schema.d.ts +75 -75
- package/packages/pi-coding-agent/dist/theme/theme-schema.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/theme/theme-schema.js +1 -1
- package/packages/pi-coding-agent/dist/theme/theme-schema.js.map +1 -1
- package/packages/pi-coding-agent/dist/theme/theme.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/theme/theme.js +11 -7
- package/packages/pi-coding-agent/dist/theme/theme.js.map +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/package.json +2 -2
- package/packages/rpc-client/package.json +2 -2
- package/pkg/dist/theme/theme-schema.d.ts +75 -75
- package/pkg/dist/theme/theme-schema.d.ts.map +1 -1
- package/pkg/dist/theme/theme-schema.js +1 -1
- package/pkg/dist/theme/theme-schema.js.map +1 -1
- package/pkg/dist/theme/theme.d.ts.map +1 -1
- package/pkg/dist/theme/theme.js +11 -7
- package/pkg/dist/theme/theme.js.map +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/claude-code-cli/models.ts +9 -0
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +20 -2
- package/src/resources/extensions/claude-code-cli/tests/index.test.ts +14 -0
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +80 -0
- package/src/resources/extensions/google-cli/stream-adapter.ts +106 -19
- package/src/resources/extensions/gsd/artifact-verification.ts +464 -0
- package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
- package/src/resources/extensions/gsd/auto/orchestrator.ts +25 -11
- package/src/resources/extensions/gsd/auto/session.ts +14 -0
- package/src/resources/extensions/gsd/auto/verification-retry-policy.ts +3 -1
- package/src/resources/extensions/gsd/auto-artifact-paths.ts +47 -1
- package/src/resources/extensions/gsd/auto-budget.ts +12 -1
- package/src/resources/extensions/gsd/auto-dispatch.ts +35 -24
- package/src/resources/extensions/gsd/auto-post-unit.ts +1 -1
- package/src/resources/extensions/gsd/auto-prompts.ts +41 -15
- package/src/resources/extensions/gsd/auto-recovery.ts +13 -511
- package/src/resources/extensions/gsd/auto-runtime-state.ts +4 -5
- package/src/resources/extensions/gsd/auto-timeout-recovery.ts +3 -2
- package/src/resources/extensions/gsd/auto-verification.ts +5 -1
- package/src/resources/extensions/gsd/auto.ts +23 -8
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +125 -12
- package/src/resources/extensions/gsd/bootstrap/core-session-tools.ts +44 -0
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +11 -5
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +2 -0
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +2 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +52 -21
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +52 -18
- package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +104 -10
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +1 -1
- package/src/resources/extensions/gsd/closeout-consistency-gate.ts +2 -1
- package/src/resources/extensions/gsd/commands/handlers/auto.ts +1 -1
- package/src/resources/extensions/gsd/commands-context.ts +18 -1
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +15 -10
- package/src/resources/extensions/gsd/commands-usage.ts +1 -1
- package/src/resources/extensions/gsd/commands-worktree.ts +12 -10
- package/src/resources/extensions/gsd/dashboard-overlay.ts +32 -3
- package/src/resources/extensions/gsd/db/engine.ts +8 -1
- package/src/resources/extensions/gsd/db/queries.ts +79 -0
- package/src/resources/extensions/gsd/db-memory-fts-schema.ts +45 -0
- package/src/resources/extensions/gsd/db-workspace.ts +61 -3
- package/src/resources/extensions/gsd/delegation-policy.ts +1 -1
- package/src/resources/extensions/gsd/docs/preferences-reference.md +2 -2
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +233 -5
- package/src/resources/extensions/gsd/doctor-providers.ts +103 -9
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +3 -0
- package/src/resources/extensions/gsd/doctor-types.ts +3 -0
- package/src/resources/extensions/gsd/exec-sandbox.ts +56 -11
- package/src/resources/extensions/gsd/flat-phase-migration.ts +44 -0
- package/src/resources/extensions/gsd/forensics.ts +2 -33
- package/src/resources/extensions/gsd/git-service.ts +69 -5
- package/src/resources/extensions/gsd/gitignore.ts +4 -1
- package/src/resources/extensions/gsd/guided-flow-queue.ts +89 -4
- package/src/resources/extensions/gsd/health-widget.ts +69 -32
- package/src/resources/extensions/gsd/json-persistence.ts +20 -0
- package/src/resources/extensions/gsd/knowledge-backfill.ts +16 -10
- package/src/resources/extensions/gsd/layout-policy.ts +2 -1
- package/src/resources/extensions/gsd/markdown-renderer.ts +8 -11
- package/src/resources/extensions/gsd/memory-backfill.ts +26 -20
- package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +51 -19
- package/src/resources/extensions/gsd/metrics.ts +4 -4
- package/src/resources/extensions/gsd/migrate-external.ts +8 -2
- package/src/resources/extensions/gsd/migration-auto-check.ts +23 -0
- package/src/resources/extensions/gsd/milestone-ids.ts +31 -2
- package/src/resources/extensions/gsd/milestone-implementation-evidence.ts +35 -21
- package/src/resources/extensions/gsd/orphan-stash-audit.ts +108 -20
- package/src/resources/extensions/gsd/prompts/code-review.md +6 -4
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +2 -2
- package/src/resources/extensions/gsd/prompts/plan-slice.md +3 -3
- package/src/resources/extensions/gsd/quick.ts +43 -2
- package/src/resources/extensions/gsd/root-write-leak-guard.ts +13 -1
- package/src/resources/extensions/gsd/safety/destructive-guard.ts +9 -1
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +16 -1
- package/src/resources/extensions/gsd/safety/file-change-validator.ts +8 -2
- package/src/resources/extensions/gsd/session-forensics.ts +11 -1
- package/src/resources/extensions/gsd/skills/gsd-headless/references/commands.md +1 -1
- package/src/resources/extensions/gsd/state/derive/cache.ts +46 -0
- package/src/resources/extensions/gsd/state/derive/db-open.ts +45 -0
- package/src/resources/extensions/gsd/state/derive/from-db.ts +561 -0
- package/src/resources/extensions/gsd/state/derive/index.ts +104 -0
- package/src/resources/extensions/gsd/state/derive/interrupted-work.ts +31 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/stale-render.ts +81 -7
- package/src/resources/extensions/gsd/state-reconciliation/index.ts +50 -24
- package/src/resources/extensions/gsd/state-reconciliation/registry.ts +43 -28
- package/src/resources/extensions/gsd/state.ts +32 -732
- package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +98 -1
- package/src/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +14 -5
- package/src/resources/extensions/gsd/tests/auto-pause-double-entry-guard.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +182 -4
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +146 -1
- package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/commands-context.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/commands-gsd-core.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/commands-worktree-clean.test.ts +80 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +28 -0
- package/src/resources/extensions/gsd/tests/complete-slice-reopen-handoff.test.ts +69 -0
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +11 -0
- package/src/resources/extensions/gsd/tests/complete-task-rollback-evidence.test.ts +48 -8
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +55 -2
- package/src/resources/extensions/gsd/tests/db-memory-fts-schema.test.ts +58 -3
- package/src/resources/extensions/gsd/tests/decisions-projection-from-memories.test.ts +51 -0
- package/src/resources/extensions/gsd/tests/destructive-guard.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +143 -0
- package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +26 -1
- package/src/resources/extensions/gsd/tests/doctor-forensics-db-open-regression.test.ts +70 -2
- package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +107 -0
- package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +239 -2
- package/src/resources/extensions/gsd/tests/exec-graceful-kill.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/exec-tool.test.ts +45 -1
- package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +37 -2
- package/src/resources/extensions/gsd/tests/forensics-error-filter.test.ts +88 -0
- package/src/resources/extensions/gsd/tests/gitignore-bg-shell-runtime.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +268 -3
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +130 -3
- package/src/resources/extensions/gsd/tests/integration/queue-active-milestone-context-budget.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/integration/quick-branch-lifecycle.test.ts +56 -9
- package/src/resources/extensions/gsd/tests/json-persistence-atomic.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/knowledge-backfill-projection.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/knowledge-cold-start.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/memory-consolidation-scanner.test.ts +78 -0
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/merge-closeout-consistency-gate.test.ts +31 -1
- package/src/resources/extensions/gsd/tests/metrics-prune-cache-invalidation.test.ts +6 -0
- package/src/resources/extensions/gsd/tests/metrics.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/migrate-external-worktree.test.ts +57 -0
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +70 -0
- package/src/resources/extensions/gsd/tests/orchestrator-logs.test.ts +43 -1
- package/src/resources/extensions/gsd/tests/orphan-stash-audit.test.ts +91 -7
- package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +4 -1
- package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +10 -0
- package/src/resources/extensions/gsd/tests/plan-slice.test.ts +103 -4
- package/src/resources/extensions/gsd/tests/plan-task.test.ts +44 -1
- package/src/resources/extensions/gsd/tests/post-mutation-hook.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +54 -1
- package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +50 -14
- package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +58 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +8 -6
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +195 -1
- package/src/resources/extensions/gsd/tests/read-uat-gate-verdict.test.ts +185 -0
- package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +87 -0
- package/src/resources/extensions/gsd/tests/register-hooks-loop-guard-auto.test.ts +103 -0
- package/src/resources/extensions/gsd/tests/root-write-leak-guard.test.ts +20 -1
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +15 -3
- package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +56 -0
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +191 -0
- package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +208 -0
- package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +32 -3
- package/src/resources/extensions/gsd/tests/undo.test.ts +74 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +193 -14
- package/src/resources/extensions/gsd/tests/unmerged-milestone-guard.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/validation-block-guard.test.ts +79 -0
- package/src/resources/extensions/gsd/tests/verification-retry-policy.test.ts +69 -4
- package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +96 -15
- package/src/resources/extensions/gsd/tests/workflow-mcp-preflight.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +8 -4
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +6 -5
- package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +151 -2
- package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +39 -0
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -2
- package/src/resources/extensions/gsd/tools/complete-slice.ts +2 -2
- package/src/resources/extensions/gsd/tools/complete-task.ts +53 -15
- package/src/resources/extensions/gsd/tools/exec-tool.ts +7 -3
- package/src/resources/extensions/gsd/tools/plan-slice.ts +60 -47
- package/src/resources/extensions/gsd/tools/plan-task.ts +30 -5
- package/src/resources/extensions/gsd/undo.ts +47 -6
- package/src/resources/extensions/gsd/unit-context-composer.ts +33 -7
- package/src/resources/extensions/gsd/unit-registry.ts +36 -6
- package/src/resources/extensions/gsd/unmerged-milestone-guard.ts +41 -5
- package/src/resources/extensions/gsd/validation-block-guard.ts +13 -7
- package/src/resources/extensions/gsd/verification-gate.ts +8 -0
- package/src/resources/extensions/gsd/workflow-manifest.ts +141 -7
- package/src/resources/extensions/gsd/workflow-projections.ts +20 -14
- package/src/resources/extensions/gsd/workspace-git-preflight.ts +31 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +41 -1
- package/dist/web/standalone/.next/static/chunks/2772.bfa657f49f955239.js +0 -1
- package/dist/web/standalone/.next/static/chunks/796.e0bdc932325d7e03.js +0 -10
- package/dist/web/standalone/.next/static/chunks/webpack-f46ea08200a0227e.js +0 -1
- /package/dist/web/standalone/.next/static/{BTKtGFF1Y-hvVJEGhBRo9 → 2A_WqqCS-EoYZxN9_v3d2}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{BTKtGFF1Y-hvVJEGhBRo9 → 2A_WqqCS-EoYZxN9_v3d2}/_ssgManifest.js +0 -0
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
|
|
4
4
|
import test from "node:test";
|
|
5
5
|
import assert from "node:assert/strict";
|
|
6
|
-
import { mkdirSync, writeFileSync } from "node:fs";
|
|
7
|
-
import { join } from "node:path";
|
|
6
|
+
import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
7
|
+
import { delimiter, join } from "node:path";
|
|
8
8
|
|
|
9
|
+
import { GIT_NO_PROMPT_ENV } from "../git-constants.js";
|
|
9
10
|
import { probeGitConflictState } from "../git-conflict-state.js";
|
|
10
11
|
import { ensureWorkspaceGitReadyForPath } from "../workspace-git-preflight.js";
|
|
11
12
|
import { isWorkspaceGitAllowedCommand } from "../workspace-git-guard.js";
|
|
@@ -50,6 +51,38 @@ function seedProductConflict(base: string): void {
|
|
|
50
51
|
}
|
|
51
52
|
}
|
|
52
53
|
|
|
54
|
+
function installCountingGitShim(binDir: string, logPath: string): void {
|
|
55
|
+
const posixShim = join(binDir, "git");
|
|
56
|
+
writeFileSync(
|
|
57
|
+
posixShim,
|
|
58
|
+
[
|
|
59
|
+
"#!/bin/sh",
|
|
60
|
+
'printf "%s\\n" "$*" >> "$GSD_GIT_LOG"',
|
|
61
|
+
'PATH="$GSD_REAL_PATH"',
|
|
62
|
+
"export PATH",
|
|
63
|
+
'exec git "$@"',
|
|
64
|
+
"",
|
|
65
|
+
].join("\n"),
|
|
66
|
+
);
|
|
67
|
+
chmodSync(posixShim, 0o755);
|
|
68
|
+
|
|
69
|
+
writeFileSync(
|
|
70
|
+
join(binDir, "git.cmd"),
|
|
71
|
+
[
|
|
72
|
+
"@echo off",
|
|
73
|
+
'echo %*>>"%GSD_GIT_LOG%"',
|
|
74
|
+
'set "PATH=%GSD_REAL_PATH%"',
|
|
75
|
+
"git %*",
|
|
76
|
+
"",
|
|
77
|
+
].join("\r\n"),
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function countGitShimInvocations(logPath: string): number {
|
|
82
|
+
if (!existsSync(logPath)) return 0;
|
|
83
|
+
return readFileSync(logPath, "utf-8").split(/\r?\n/).filter(Boolean).length;
|
|
84
|
+
}
|
|
85
|
+
|
|
53
86
|
test("probeGitConflictState reports clean repo", () => {
|
|
54
87
|
const base = makeTempRepo("gsd-ws-git-clean-");
|
|
55
88
|
try {
|
|
@@ -60,6 +93,122 @@ test("probeGitConflictState reports clean repo", () => {
|
|
|
60
93
|
}
|
|
61
94
|
});
|
|
62
95
|
|
|
96
|
+
test("ensureWorkspaceGitReadyForPath caches clean target probes briefly", async () => {
|
|
97
|
+
const base = makeTempRepo("gsd-ws-git-clean-cache-");
|
|
98
|
+
const binDir = makeTempDir("gsd-ws-git-shim-");
|
|
99
|
+
const logPath = join(binDir, "git.log");
|
|
100
|
+
const originalProcessPath = process.env.PATH;
|
|
101
|
+
const originalEnvPath = GIT_NO_PROMPT_ENV.PATH;
|
|
102
|
+
const originalEnvGitLog = GIT_NO_PROMPT_ENV.GSD_GIT_LOG;
|
|
103
|
+
const originalEnvRealPath = GIT_NO_PROMPT_ENV.GSD_REAL_PATH;
|
|
104
|
+
|
|
105
|
+
try {
|
|
106
|
+
installCountingGitShim(binDir, logPath);
|
|
107
|
+
const shimmedPath = `${binDir}${delimiter}${originalProcessPath ?? ""}`;
|
|
108
|
+
process.env.PATH = shimmedPath;
|
|
109
|
+
GIT_NO_PROMPT_ENV.PATH = shimmedPath;
|
|
110
|
+
GIT_NO_PROMPT_ENV.GSD_GIT_LOG = logPath;
|
|
111
|
+
GIT_NO_PROMPT_ENV.GSD_REAL_PATH = originalProcessPath ?? "";
|
|
112
|
+
|
|
113
|
+
const first = await ensureWorkspaceGitReadyForPath(base);
|
|
114
|
+
assert.equal(first.ok, true);
|
|
115
|
+
const firstCount = countGitShimInvocations(logPath);
|
|
116
|
+
assert.equal(firstCount, 3, "first clean probe should run the existing conflict checks");
|
|
117
|
+
|
|
118
|
+
const second = await ensureWorkspaceGitReadyForPath(base);
|
|
119
|
+
assert.equal(second.ok, true);
|
|
120
|
+
assert.equal(
|
|
121
|
+
countGitShimInvocations(logPath),
|
|
122
|
+
firstCount,
|
|
123
|
+
"second clean probe within the cache window must not spawn git again",
|
|
124
|
+
);
|
|
125
|
+
} finally {
|
|
126
|
+
if (originalProcessPath === undefined) delete process.env.PATH;
|
|
127
|
+
else process.env.PATH = originalProcessPath;
|
|
128
|
+
if (originalEnvPath === undefined) delete GIT_NO_PROMPT_ENV.PATH;
|
|
129
|
+
else GIT_NO_PROMPT_ENV.PATH = originalEnvPath;
|
|
130
|
+
if (originalEnvGitLog === undefined) delete GIT_NO_PROMPT_ENV.GSD_GIT_LOG;
|
|
131
|
+
else GIT_NO_PROMPT_ENV.GSD_GIT_LOG = originalEnvGitLog;
|
|
132
|
+
if (originalEnvRealPath === undefined) delete GIT_NO_PROMPT_ENV.GSD_REAL_PATH;
|
|
133
|
+
else GIT_NO_PROMPT_ENV.GSD_REAL_PATH = originalEnvRealPath;
|
|
134
|
+
cleanup(binDir);
|
|
135
|
+
cleanup(base);
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test("ensureWorkspaceGitReadyForPath detects merge state that appears after a clean probe", async () => {
|
|
140
|
+
const base = makeTempRepo("gsd-ws-git-cache-stale-");
|
|
141
|
+
const binDir = makeTempDir("gsd-ws-git-shim2-");
|
|
142
|
+
const logPath = join(binDir, "git2.log");
|
|
143
|
+
const originalProcessPath = process.env.PATH;
|
|
144
|
+
const originalEnvPath = GIT_NO_PROMPT_ENV.PATH;
|
|
145
|
+
const originalEnvGitLog = GIT_NO_PROMPT_ENV.GSD_GIT_LOG;
|
|
146
|
+
const originalEnvRealPath = GIT_NO_PROMPT_ENV.GSD_REAL_PATH;
|
|
147
|
+
|
|
148
|
+
try {
|
|
149
|
+
installCountingGitShim(binDir, logPath);
|
|
150
|
+
const shimmedPath = `${binDir}${delimiter}${originalProcessPath ?? ""}`;
|
|
151
|
+
process.env.PATH = shimmedPath;
|
|
152
|
+
GIT_NO_PROMPT_ENV.PATH = shimmedPath;
|
|
153
|
+
GIT_NO_PROMPT_ENV.GSD_GIT_LOG = logPath;
|
|
154
|
+
GIT_NO_PROMPT_ENV.GSD_REAL_PATH = originalProcessPath ?? "";
|
|
155
|
+
|
|
156
|
+
// First call — repo is clean, cache is populated.
|
|
157
|
+
const first = await ensureWorkspaceGitReadyForPath(base);
|
|
158
|
+
assert.equal(first.ok, true);
|
|
159
|
+
const afterFirstCount = countGitShimInvocations(logPath);
|
|
160
|
+
assert.ok(afterFirstCount > 0, "first probe must have called git");
|
|
161
|
+
|
|
162
|
+
// Introduce MERGE_HEAD to simulate merge state appearing mid-TTL window.
|
|
163
|
+
writeFileSync(join(base, ".git", "MERGE_HEAD"), "0000000000000000000000000000000000000000\n");
|
|
164
|
+
|
|
165
|
+
// Second call — cache should be bypassed because merge state markers are present.
|
|
166
|
+
await ensureWorkspaceGitReadyForPath(base);
|
|
167
|
+
const afterSecondCount = countGitShimInvocations(logPath);
|
|
168
|
+
assert.ok(
|
|
169
|
+
afterSecondCount > afterFirstCount,
|
|
170
|
+
"cache must be invalidated when merge state appears, causing a fresh git probe",
|
|
171
|
+
);
|
|
172
|
+
} finally {
|
|
173
|
+
if (originalProcessPath === undefined) delete process.env.PATH;
|
|
174
|
+
else process.env.PATH = originalProcessPath;
|
|
175
|
+
if (originalEnvPath === undefined) delete GIT_NO_PROMPT_ENV.PATH;
|
|
176
|
+
else GIT_NO_PROMPT_ENV.PATH = originalEnvPath;
|
|
177
|
+
if (originalEnvGitLog === undefined) delete GIT_NO_PROMPT_ENV.GSD_GIT_LOG;
|
|
178
|
+
else GIT_NO_PROMPT_ENV.GSD_GIT_LOG = originalEnvGitLog;
|
|
179
|
+
if (originalEnvRealPath === undefined) delete GIT_NO_PROMPT_ENV.GSD_REAL_PATH;
|
|
180
|
+
else GIT_NO_PROMPT_ENV.GSD_REAL_PATH = originalEnvRealPath;
|
|
181
|
+
cleanup(binDir);
|
|
182
|
+
cleanup(base);
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
test("ensureWorkspaceGitReadyForPath detects conflicts after a non-git folder becomes a repo", async () => {
|
|
187
|
+
const base = makeTempDir("gsd-ws-git-non-repo-cache-");
|
|
188
|
+
try {
|
|
189
|
+
const first = await ensureWorkspaceGitReadyForPath(base);
|
|
190
|
+
assert.equal(first.ok, true);
|
|
191
|
+
|
|
192
|
+
git(base, "init");
|
|
193
|
+
git(base, "config", "user.email", "test@test.com");
|
|
194
|
+
git(base, "config", "user.name", "Test");
|
|
195
|
+
git(base, "config", "core.autocrlf", "false");
|
|
196
|
+
writeFileSync(join(base, "README.md"), "# init\n");
|
|
197
|
+
git(base, "add", "-A");
|
|
198
|
+
git(base, "commit", "-m", "init");
|
|
199
|
+
git(base, "branch", "-M", "main");
|
|
200
|
+
seedProductConflict(base);
|
|
201
|
+
|
|
202
|
+
const second = await ensureWorkspaceGitReadyForPath(base);
|
|
203
|
+
assert.equal(second.ok, false);
|
|
204
|
+
if (second.ok) return;
|
|
205
|
+
assert.equal(second.severity, "product-conflicts");
|
|
206
|
+
assert.ok(second.conflictedPaths.includes("app.ts"));
|
|
207
|
+
} finally {
|
|
208
|
+
cleanup(base);
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
|
|
63
212
|
test("ensureWorkspaceGitReadyForPath allows fresh non-git project setup folders", async () => {
|
|
64
213
|
const base = makeTempDir("gsd-ws-git-non-repo-");
|
|
65
214
|
try {
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
diffWorktreeNumstat,
|
|
14
14
|
getWorktreeGSDDiff,
|
|
15
15
|
getWorktreeLog,
|
|
16
|
+
mergeWorktreeToMain,
|
|
16
17
|
worktreeBranchName,
|
|
17
18
|
worktreePath,
|
|
18
19
|
pruneEphemeralGhostWorktreeDirectories,
|
|
@@ -333,6 +334,44 @@ describe("getWorktreeLog", () => {
|
|
|
333
334
|
});
|
|
334
335
|
});
|
|
335
336
|
|
|
337
|
+
// ─── mergeWorktreeToMain ─────────────────────────────────────────────────────
|
|
338
|
+
|
|
339
|
+
describe("mergeWorktreeToMain", () => {
|
|
340
|
+
let base: string;
|
|
341
|
+
let wtPath: string;
|
|
342
|
+
|
|
343
|
+
beforeEach(() => {
|
|
344
|
+
base = makeBaseRepo();
|
|
345
|
+
wtPath = worktreePath(base, "M900");
|
|
346
|
+
mkdirSync(join(base, ".gsd-worktrees"), { recursive: true });
|
|
347
|
+
run(`git worktree add -b milestone/M900 "${wtPath}"`, base);
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
afterEach(() => { rmSync(base, { recursive: true, force: true }); });
|
|
351
|
+
|
|
352
|
+
test("cleans failed milestone squash state and deletes orphan branch", () => {
|
|
353
|
+
writeFileSync(join(wtPath, "README.md"), "# Milestone change\n", "utf-8");
|
|
354
|
+
run("git add README.md", wtPath);
|
|
355
|
+
run('git commit -m "feat: milestone change"', wtPath);
|
|
356
|
+
|
|
357
|
+
writeFileSync(join(base, "README.md"), "# Main change\n", "utf-8");
|
|
358
|
+
run("git add README.md", base);
|
|
359
|
+
run('git commit -m "feat: main change"', base);
|
|
360
|
+
|
|
361
|
+
assert.throws(
|
|
362
|
+
() => mergeWorktreeToMain(base, "M900", "feat: merge M900", "milestone/M900"),
|
|
363
|
+
/Merge conflicts detected/,
|
|
364
|
+
);
|
|
365
|
+
|
|
366
|
+
assert.equal(run("git status --porcelain", base), "", "failed squash cleanup should leave main clean");
|
|
367
|
+
assert.ok(!existsSync(wtPath), "failed milestone worktree should be removed");
|
|
368
|
+
assert.ok(
|
|
369
|
+
!run("git branch", base).includes("milestone/M900"),
|
|
370
|
+
"failed milestone branch should be deleted after worktree removal",
|
|
371
|
+
);
|
|
372
|
+
});
|
|
373
|
+
});
|
|
374
|
+
|
|
336
375
|
// ─── removeWorktree ───────────────────────────────────────────────────────────
|
|
337
376
|
|
|
338
377
|
describe("removeWorktree", () => {
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
} from "../gsd-db.js";
|
|
24
24
|
import { gsdProjectionRoot, clearPathCache, relMilestoneFile } from "../paths.js";
|
|
25
25
|
import { resolveCanonicalMilestoneRoot } from "../worktree-manager.js";
|
|
26
|
-
import { isClosedStatus } from "../status-guards.js";
|
|
26
|
+
import { isClosedStatus, isDeferredStatus } from "../status-guards.js";
|
|
27
27
|
import { saveFile, clearParseCache } from "../files.js";
|
|
28
28
|
import { invalidateStateCache } from "../state.js";
|
|
29
29
|
import { stripIdPrefix } from "../workflow-projections.js";
|
|
@@ -180,7 +180,7 @@ export async function handleCompleteMilestone(
|
|
|
180
180
|
return;
|
|
181
181
|
}
|
|
182
182
|
|
|
183
|
-
const incompleteSlices = slices.filter(s => !isClosedStatus(s.status));
|
|
183
|
+
const incompleteSlices = slices.filter(s => !isClosedStatus(s.status) && !isDeferredStatus(s.status));
|
|
184
184
|
if (incompleteSlices.length > 0) {
|
|
185
185
|
const incompleteIds = incompleteSlices.map(s => `${s.id} (status: ${s.status})`).join(", ");
|
|
186
186
|
guardError = `incomplete slices: ${incompleteIds}`;
|
|
@@ -189,6 +189,7 @@ export async function handleCompleteMilestone(
|
|
|
189
189
|
|
|
190
190
|
// Deep check: verify all tasks in all slices are complete
|
|
191
191
|
for (const slice of slices) {
|
|
192
|
+
if (isDeferredStatus(slice.status)) continue;
|
|
192
193
|
const tasks = getSliceTasks(params.milestoneId, slice.id);
|
|
193
194
|
const incompleteTasks = tasks.filter(t => !isClosedStatus(t.status));
|
|
194
195
|
if (incompleteTasks.length > 0) {
|
|
@@ -30,7 +30,7 @@ import { classifyUatContent, escalatesArtifactUatToBrowser } from "../uat-policy
|
|
|
30
30
|
import { invalidateStateCache } from "../state.js";
|
|
31
31
|
import { renderRoadmapFromDb, roadmapRenderMarksSliceDone } from "../markdown-renderer.js";
|
|
32
32
|
import { isStaleWrite } from "../auto/turn-epoch.js";
|
|
33
|
-
import {
|
|
33
|
+
import { renderMilestoneShellProjections } from "../workflow-projections.js";
|
|
34
34
|
import { writeManifest } from "../workflow-manifest.js";
|
|
35
35
|
import { appendEvent } from "../workflow-events.js";
|
|
36
36
|
import { logWarning, logError } from "../workflow-logger.js";
|
|
@@ -540,7 +540,7 @@ export async function handleCompleteSlice(
|
|
|
540
540
|
// Separate try/catch per step so a projection failure doesn't prevent
|
|
541
541
|
// the event log entry (critical for worktree reconciliation).
|
|
542
542
|
try {
|
|
543
|
-
await
|
|
543
|
+
await renderMilestoneShellProjections(artifactBasePath, params.milestoneId);
|
|
544
544
|
} catch (projErr) {
|
|
545
545
|
logWarning("tool", `complete-slice projection warning for ${params.milestoneId}/${params.sliceId}: ${(projErr as Error).message}`);
|
|
546
546
|
}
|
|
@@ -6,11 +6,12 @@
|
|
|
6
6
|
*
|
|
7
7
|
* Validates inputs, writes task row and rendered SUMMARY.md to DB in a
|
|
8
8
|
* transaction, then renders projections to disk and invalidates caches.
|
|
9
|
-
*
|
|
10
|
-
* back
|
|
9
|
+
* If the critical task summary / plan projection write fails, the DB
|
|
10
|
+
* completion is compensated back to pending so DB state does not drift ahead
|
|
11
|
+
* of PLAN.md.
|
|
11
12
|
*/
|
|
12
13
|
|
|
13
|
-
import { existsSync } from "node:fs";
|
|
14
|
+
import { existsSync, unlinkSync } from "node:fs";
|
|
14
15
|
import { join } from "node:path";
|
|
15
16
|
|
|
16
17
|
import type { CompleteTaskParams, EscalationArtifact } from "../types.js";
|
|
@@ -29,6 +30,7 @@ import {
|
|
|
29
30
|
saveGateResult,
|
|
30
31
|
getPendingGatesForTurn,
|
|
31
32
|
} from "../gsd-db.js";
|
|
33
|
+
import { getWorkflowDatabasePath, ensureWorkflowDbAtPath } from "../db-workspace.js";
|
|
32
34
|
import { getGatesForTurn } from "../gate-registry.js";
|
|
33
35
|
import { gsdProjectionRoot, clearPathCache, resolveMilestonePath, resolveSlicePath } from "../paths.js";
|
|
34
36
|
import { resolveCanonicalMilestoneRoot } from "../worktree-manager.js";
|
|
@@ -36,8 +38,10 @@ import { checkOwnership, taskUnitKey } from "../unit-ownership.js";
|
|
|
36
38
|
import { saveFile, clearParseCache } from "../files.js";
|
|
37
39
|
import { invalidateStateCache } from "../state.js";
|
|
38
40
|
import { renderPlanCheckboxes } from "../markdown-renderer.js";
|
|
39
|
-
import {
|
|
40
|
-
|
|
41
|
+
import {
|
|
42
|
+
renderMilestoneShellProjections,
|
|
43
|
+
renderSummaryContent,
|
|
44
|
+
} from "../workflow-projections.js";
|
|
41
45
|
import { writeManifest } from "../workflow-manifest.js";
|
|
42
46
|
import { appendEvent } from "../workflow-events.js";
|
|
43
47
|
import { logWarning, logError } from "../workflow-logger.js";
|
|
@@ -131,7 +135,7 @@ async function repairMissingTaskSummaryProjection(
|
|
|
131
135
|
clearParseCache();
|
|
132
136
|
|
|
133
137
|
try {
|
|
134
|
-
await
|
|
138
|
+
await renderMilestoneShellProjections(artifactBasePath, taskRow.milestone_id);
|
|
135
139
|
} catch (projErr) {
|
|
136
140
|
logWarning("tool", `complete-task repair projection warning: ${(projErr as Error).message}`);
|
|
137
141
|
}
|
|
@@ -267,6 +271,7 @@ export async function handleCompleteTask(
|
|
|
267
271
|
let guardError: string | null = null;
|
|
268
272
|
let summaryMd = "";
|
|
269
273
|
let repairTaskSummaryRow: TaskRow | null = null;
|
|
274
|
+
const rollbackDbPath = getWorkflowDatabasePath();
|
|
270
275
|
|
|
271
276
|
// ── ADR-011 Phase 2: validate escalation payload BEFORE any side effects ─
|
|
272
277
|
// Building the artifact runs the full shape validation (2-4 options, unique
|
|
@@ -423,8 +428,6 @@ export async function handleCompleteTask(
|
|
|
423
428
|
return { error: guardError };
|
|
424
429
|
}
|
|
425
430
|
|
|
426
|
-
let projectionStale = false;
|
|
427
|
-
|
|
428
431
|
// Resolve and write summary to disk
|
|
429
432
|
const summaryPath = taskSummaryPath(
|
|
430
433
|
artifactBasePath,
|
|
@@ -438,12 +441,48 @@ export async function handleCompleteTask(
|
|
|
438
441
|
|
|
439
442
|
// Toggle or regenerate the plan projection from DB. Missing projection
|
|
440
443
|
// files are rebuilt by the renderer instead of being skipped.
|
|
441
|
-
|
|
444
|
+
if (!ensureWorkflowDbAtPath(rollbackDbPath)) {
|
|
445
|
+
throw new Error(`database unavailable before plan projection render for ${params.milestoneId}/${params.sliceId}`);
|
|
446
|
+
}
|
|
447
|
+
const wrotePlan = await renderPlanCheckboxes(artifactBasePath, params.milestoneId, params.sliceId);
|
|
448
|
+
if (!wrotePlan) {
|
|
449
|
+
throw new Error(`plan projection write returned false for ${params.milestoneId}/${params.sliceId}`);
|
|
450
|
+
}
|
|
442
451
|
} catch (renderErr) {
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
452
|
+
logWarning(
|
|
453
|
+
"projection",
|
|
454
|
+
`complete_task projection write failed for ${params.milestoneId}/${params.sliceId}/${params.taskId}`,
|
|
455
|
+
{ error: (renderErr as Error).message },
|
|
456
|
+
);
|
|
457
|
+
let rollbackSucceeded = false;
|
|
458
|
+
try {
|
|
459
|
+
ensureWorkflowDbAtPath(rollbackDbPath);
|
|
460
|
+
deleteVerificationEvidence(params.milestoneId, params.sliceId, params.taskId);
|
|
461
|
+
updateTaskStatus(params.milestoneId, params.sliceId, params.taskId, "pending");
|
|
462
|
+
invalidateStateCache();
|
|
463
|
+
rollbackSucceeded = true;
|
|
464
|
+
} catch (rollbackErr) {
|
|
465
|
+
logWarning(
|
|
466
|
+
"projection",
|
|
467
|
+
`complete_task rollback failed after projection write failure for ${params.milestoneId}/${params.sliceId}/${params.taskId}: ${(rollbackErr as Error).message}`,
|
|
468
|
+
);
|
|
469
|
+
}
|
|
470
|
+
try {
|
|
471
|
+
if (existsSync(summaryPath)) unlinkSync(summaryPath);
|
|
472
|
+
} catch (summaryErr) {
|
|
473
|
+
logWarning(
|
|
474
|
+
"projection",
|
|
475
|
+
`complete_task could not remove SUMMARY.md after projection write failure for ${params.milestoneId}/${params.sliceId}/${params.taskId}: ${(summaryErr as Error).message}`,
|
|
476
|
+
);
|
|
477
|
+
}
|
|
478
|
+
// Clear path/parse caches regardless of rollback outcome so stale
|
|
479
|
+
// entries from the failed write attempt don't leak into subsequent calls.
|
|
480
|
+
clearPathCache();
|
|
481
|
+
clearParseCache();
|
|
482
|
+
const returnMsg = rollbackSucceeded
|
|
483
|
+
? `complete_task projection write failed for ${params.milestoneId}/${params.sliceId}/${params.taskId}; rolled completion back to pending`
|
|
484
|
+
: `complete_task projection write failed for ${params.milestoneId}/${params.sliceId}/${params.taskId}; rollback also failed — task may remain complete with stale plan`;
|
|
485
|
+
return { error: returnMsg };
|
|
447
486
|
}
|
|
448
487
|
|
|
449
488
|
// ── Close gates owned by execute-task (Q5/Q6/Q7) for this task ────────
|
|
@@ -569,7 +608,7 @@ export async function handleCompleteTask(
|
|
|
569
608
|
// Separate try/catch per step so a projection failure doesn't prevent
|
|
570
609
|
// the event log entry (critical for worktree reconciliation).
|
|
571
610
|
try {
|
|
572
|
-
await
|
|
611
|
+
await renderMilestoneShellProjections(artifactBasePath, params.milestoneId);
|
|
573
612
|
} catch (projErr) {
|
|
574
613
|
logWarning("tool", `complete-task projection warning: ${(projErr as Error).message}`);
|
|
575
614
|
}
|
|
@@ -597,6 +636,5 @@ export async function handleCompleteTask(
|
|
|
597
636
|
milestoneId: params.milestoneId,
|
|
598
637
|
summaryPath,
|
|
599
638
|
...(escalationMetadata ? { escalation: escalationMetadata } : {}),
|
|
600
|
-
...(projectionStale ? { stale: true } : {}),
|
|
601
639
|
};
|
|
602
640
|
}
|
|
@@ -31,6 +31,7 @@ export interface ExecToolDeps {
|
|
|
31
31
|
env?: NodeJS.ProcessEnv;
|
|
32
32
|
now?: () => Date;
|
|
33
33
|
generateId?: () => string;
|
|
34
|
+
signal?: AbortSignal;
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
export type UatExecIntent =
|
|
@@ -74,7 +75,7 @@ const UAT_EXEC_INTENT_ALIASES: Record<string, UatExecIntent> = {
|
|
|
74
75
|
export function buildExecOptions(
|
|
75
76
|
baseDir: string,
|
|
76
77
|
cfg: ContextModeConfig | undefined,
|
|
77
|
-
extras?: Pick<ExecSandboxOptions, "env" | "now" | "generateId">,
|
|
78
|
+
extras?: Pick<ExecSandboxOptions, "env" | "now" | "generateId" | "signal">,
|
|
78
79
|
): ExecSandboxOptions {
|
|
79
80
|
const allowlist = Array.isArray(cfg?.exec_env_allowlist) ? cfg!.exec_env_allowlist! : EXEC_DEFAULTS.envAllowlist;
|
|
80
81
|
const stdoutCap = clampNumber(
|
|
@@ -209,7 +210,7 @@ export async function executeGsdExec(
|
|
|
209
210
|
const opts = buildExecOptions(
|
|
210
211
|
deps.baseDir,
|
|
211
212
|
deps.preferences?.context_mode,
|
|
212
|
-
{ env: deps.env, now: deps.now, generateId: deps.generateId },
|
|
213
|
+
{ env: deps.env, now: deps.now, generateId: deps.generateId, signal: deps.signal },
|
|
213
214
|
);
|
|
214
215
|
const run = deps.run ?? runExecSandbox;
|
|
215
216
|
|
|
@@ -308,6 +309,7 @@ function formatResult(result: ExecSandboxResult): ToolExecutionResult {
|
|
|
308
309
|
exit_code: result.exit_code,
|
|
309
310
|
signal: result.signal,
|
|
310
311
|
timed_out: result.timed_out,
|
|
312
|
+
aborted: result.aborted === true,
|
|
311
313
|
force_resolved: result.force_resolved,
|
|
312
314
|
duration_ms: result.duration_ms,
|
|
313
315
|
stdout_bytes: result.stdout_bytes,
|
|
@@ -318,13 +320,15 @@ function formatResult(result: ExecSandboxResult): ToolExecutionResult {
|
|
|
318
320
|
stderr_path: result.stderr_path,
|
|
319
321
|
meta_path: result.meta_path,
|
|
320
322
|
},
|
|
321
|
-
isError: result.timed_out || result.signal !== null || result.exit_code !== 0,
|
|
323
|
+
isError: result.aborted === true || result.timed_out || result.signal !== null || result.exit_code !== 0,
|
|
322
324
|
};
|
|
323
325
|
}
|
|
324
326
|
|
|
325
327
|
function formatExit(result: ExecSandboxResult): string {
|
|
326
328
|
// force_resolved means a non-closing (D-state) child was force-resolved past its
|
|
327
329
|
// hard deadline rather than observed exiting; distinguish it from a clean timeout.
|
|
330
|
+
if (result.aborted && result.force_resolved) return "aborted(force-killed)";
|
|
331
|
+
if (result.aborted) return "aborted";
|
|
328
332
|
if (result.force_resolved) return "timeout(force-killed)";
|
|
329
333
|
if (result.timed_out) return "timeout";
|
|
330
334
|
if (result.signal) return `signal:${result.signal}`;
|
|
@@ -51,7 +51,7 @@ export interface PlanSliceParams {
|
|
|
51
51
|
milestoneId: string;
|
|
52
52
|
sliceId: string;
|
|
53
53
|
goal: string;
|
|
54
|
-
tasks
|
|
54
|
+
tasks?: PlanSliceTaskInput[];
|
|
55
55
|
/** @optional — omitted fields render as conservative defaults */
|
|
56
56
|
successCriteria?: string;
|
|
57
57
|
/** @optional — omitted fields render as conservative defaults */
|
|
@@ -86,10 +86,12 @@ function validateRepositoryTargetIds(
|
|
|
86
86
|
return deduped;
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
function validateTasks(value: unknown): PlanSliceTaskInput[] {
|
|
90
|
-
if (
|
|
91
|
-
|
|
89
|
+
function validateTasks(value: unknown): PlanSliceTaskInput[] | undefined {
|
|
90
|
+
if (value === undefined) return undefined;
|
|
91
|
+
if (!Array.isArray(value)) {
|
|
92
|
+
throw new Error("tasks must be an array");
|
|
92
93
|
}
|
|
94
|
+
if (value.length === 0) return undefined;
|
|
93
95
|
|
|
94
96
|
const seen = new Set<string>();
|
|
95
97
|
return value.map((entry, index) => {
|
|
@@ -200,7 +202,7 @@ function validateReferencedRepositories(
|
|
|
200
202
|
};
|
|
201
203
|
|
|
202
204
|
for (const id of params.targetRepositories ?? defaultTargets) noteMissing(id);
|
|
203
|
-
for (const task of params.tasks) {
|
|
205
|
+
for (const task of params.tasks ?? []) {
|
|
204
206
|
for (const id of task.targetRepositories ?? params.targetRepositories ?? defaultTargets) noteMissing(id);
|
|
205
207
|
}
|
|
206
208
|
|
|
@@ -211,7 +213,7 @@ function validateReferencedRepositories(
|
|
|
211
213
|
function resolveAllowedRootsForPathScope(params: PlanSliceParams, registry: RepositoryRegistry, defaultTargets: string[]): string[] {
|
|
212
214
|
const requested = new Set<string>();
|
|
213
215
|
for (const id of params.targetRepositories ?? defaultTargets) requested.add(id);
|
|
214
|
-
for (const task of params.tasks) {
|
|
216
|
+
for (const task of params.tasks ?? []) {
|
|
215
217
|
for (const id of task.targetRepositories ?? params.targetRepositories ?? defaultTargets) requested.add(id);
|
|
216
218
|
}
|
|
217
219
|
if (requested.size === 0) return [registry.projectRoot];
|
|
@@ -222,7 +224,7 @@ function resolveAllowedRootsForPathScope(params: PlanSliceParams, registry: Repo
|
|
|
222
224
|
}
|
|
223
225
|
|
|
224
226
|
function toTaskRows(params: PlanSliceParams, defaultTargets: string[]): TaskRow[] {
|
|
225
|
-
return params.tasks.map((task, index) => ({
|
|
227
|
+
return (params.tasks ?? []).map((task, index) => ({
|
|
226
228
|
milestone_id: params.milestoneId,
|
|
227
229
|
slice_id: params.sliceId,
|
|
228
230
|
id: task.taskId,
|
|
@@ -309,6 +311,8 @@ export async function handlePlanSlice(
|
|
|
309
311
|
return { error: `validation failed: ${message}` };
|
|
310
312
|
}
|
|
311
313
|
const defaultTargets = defaultRepositoryTargets(repositoryRegistry);
|
|
314
|
+
const taskPayload = params.tasks ?? [];
|
|
315
|
+
const hasTaskPayload = taskPayload.length > 0;
|
|
312
316
|
const repoValidationError = validateReferencedRepositories(params, repositoryRegistry, defaultTargets);
|
|
313
317
|
if (repoValidationError) {
|
|
314
318
|
return { error: `validation failed: ${repoValidationError}` };
|
|
@@ -317,7 +321,7 @@ export async function handlePlanSlice(
|
|
|
317
321
|
const allowedAbsoluteRoots = resolveAllowedRootsForPathScope(params, repositoryRegistry, defaultTargets);
|
|
318
322
|
|
|
319
323
|
const pathOnlyError = validatePathOnlyPlanningFields(
|
|
320
|
-
|
|
324
|
+
taskPayload.map((task, index) => ({
|
|
321
325
|
field: `tasks[${index}].expectedOutput`,
|
|
322
326
|
values: task.expectedOutput,
|
|
323
327
|
})),
|
|
@@ -328,7 +332,7 @@ export async function handlePlanSlice(
|
|
|
328
332
|
|
|
329
333
|
const pathScopeError = validatePlanningPathScope(
|
|
330
334
|
basePath,
|
|
331
|
-
|
|
335
|
+
taskPayload.flatMap((task, index) => [
|
|
332
336
|
{ field: `tasks[${index}].files`, values: task.files },
|
|
333
337
|
{ field: `tasks[${index}].inputs`, values: task.inputs },
|
|
334
338
|
{ field: `tasks[${index}].expectedOutput`, values: task.expectedOutput },
|
|
@@ -372,16 +376,18 @@ export async function handlePlanSlice(
|
|
|
372
376
|
return;
|
|
373
377
|
}
|
|
374
378
|
|
|
375
|
-
const newTaskIds = new Set(
|
|
379
|
+
const newTaskIds = new Set(taskPayload.map((task) => task.taskId));
|
|
376
380
|
const existingTasks = getSliceTasks(params.milestoneId, params.sliceId);
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
381
|
+
if (hasTaskPayload) {
|
|
382
|
+
omittedTaskIds = existingTasks
|
|
383
|
+
.filter((task) => !newTaskIds.has(task.id))
|
|
384
|
+
.map((task) => task.id);
|
|
385
|
+
|
|
386
|
+
for (const task of existingTasks) {
|
|
387
|
+
if (!newTaskIds.has(task.id) && isClosedStatus(task.status)) {
|
|
388
|
+
guardError = `cannot remove completed task ${task.id}`;
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
385
391
|
}
|
|
386
392
|
}
|
|
387
393
|
|
|
@@ -398,35 +404,37 @@ export async function handlePlanSlice(
|
|
|
398
404
|
targetRepositories: params.targetRepositories ?? defaultTargets,
|
|
399
405
|
});
|
|
400
406
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
407
|
+
if (hasTaskPayload) {
|
|
408
|
+
for (const taskId of omittedTaskIds) {
|
|
409
|
+
deleteTask(params.milestoneId, params.sliceId, taskId);
|
|
410
|
+
}
|
|
404
411
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
title: task.title,
|
|
409
|
-
description: task.description,
|
|
410
|
-
estimate: task.estimate,
|
|
411
|
-
files: task.files,
|
|
412
|
-
verify: task.verify,
|
|
413
|
-
inputs: task.inputs,
|
|
414
|
-
expectedOutput: task.expectedOutput,
|
|
415
|
-
observabilityImpact: task.observabilityImpact ?? "",
|
|
416
|
-
fullPlanMd: task.fullPlanMd,
|
|
417
|
-
targetRepositories: task.targetRepositories ?? params.targetRepositories ?? defaultTargets,
|
|
418
|
-
};
|
|
419
|
-
const existingTask = existingTaskById.get(task.taskId);
|
|
420
|
-
if (!existingTask || !isClosedStatus(existingTask.status)) {
|
|
421
|
-
insertTask({
|
|
422
|
-
id: task.taskId,
|
|
423
|
-
sliceId: params.sliceId,
|
|
424
|
-
milestoneId: params.milestoneId,
|
|
412
|
+
const existingTaskById = new Map(existingTasks.map((task) => [task.id, task]));
|
|
413
|
+
for (const task of taskPayload) {
|
|
414
|
+
const planning = {
|
|
425
415
|
title: task.title,
|
|
426
|
-
|
|
427
|
-
|
|
416
|
+
description: task.description,
|
|
417
|
+
estimate: task.estimate,
|
|
418
|
+
files: task.files,
|
|
419
|
+
verify: task.verify,
|
|
420
|
+
inputs: task.inputs,
|
|
421
|
+
expectedOutput: task.expectedOutput,
|
|
422
|
+
observabilityImpact: task.observabilityImpact ?? "",
|
|
423
|
+
fullPlanMd: task.fullPlanMd,
|
|
424
|
+
targetRepositories: task.targetRepositories ?? params.targetRepositories ?? defaultTargets,
|
|
425
|
+
};
|
|
426
|
+
const existingTask = existingTaskById.get(task.taskId);
|
|
427
|
+
if (!existingTask || !isClosedStatus(existingTask.status)) {
|
|
428
|
+
insertTask({
|
|
429
|
+
id: task.taskId,
|
|
430
|
+
sliceId: params.sliceId,
|
|
431
|
+
milestoneId: params.milestoneId,
|
|
432
|
+
title: task.title,
|
|
433
|
+
status: "pending",
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
upsertTaskPlanning(params.milestoneId, params.sliceId, task.taskId, planning);
|
|
428
437
|
}
|
|
429
|
-
upsertTaskPlanning(params.milestoneId, params.sliceId, task.taskId, planning);
|
|
430
438
|
}
|
|
431
439
|
|
|
432
440
|
// Seed quality gate rows inside the transaction — all-or-nothing with
|
|
@@ -436,7 +444,7 @@ export async function handlePlanSlice(
|
|
|
436
444
|
insertGateRow({ milestoneId: params.milestoneId, sliceId: params.sliceId, gateId: gid, scope: "slice" });
|
|
437
445
|
}
|
|
438
446
|
const taskGates = resolveTaskGates(gateEvaluation);
|
|
439
|
-
for (const task of
|
|
447
|
+
for (const task of taskPayload) {
|
|
440
448
|
for (const gid of taskGates) {
|
|
441
449
|
insertGateRow({ milestoneId: params.milestoneId, sliceId: params.sliceId, gateId: gid, scope: "task", taskId: task.taskId });
|
|
442
450
|
}
|
|
@@ -460,8 +468,13 @@ export async function handlePlanSlice(
|
|
|
460
468
|
deleteArtifactByPath(artifactPath);
|
|
461
469
|
}
|
|
462
470
|
|
|
463
|
-
const
|
|
464
|
-
|
|
471
|
+
const sliceTasks = getSliceTasks(params.milestoneId, params.sliceId);
|
|
472
|
+
const renderResult = sliceTasks.length === 0
|
|
473
|
+
? { planPath: "", taskPlanPaths: [] as string[] }
|
|
474
|
+
: await renderPlanFromDb(basePath, params.milestoneId, params.sliceId);
|
|
475
|
+
if (sliceTasks.length > 0) {
|
|
476
|
+
setSliceSketchFlag(params.milestoneId, params.sliceId, false);
|
|
477
|
+
}
|
|
465
478
|
invalidateStateCache();
|
|
466
479
|
clearParseCache();
|
|
467
480
|
|