@opengsd/gsd-pi 1.3.0-dev.eed73bea → 1.4.0-dev.5fc22c6f
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 +11 -11
- 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/onboarding.js +11 -0
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/GSD-WORKFLOW.md +20 -25
- package/dist/resources/extensions/claude-code-cli/models.js +9 -0
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +61 -50
- package/dist/resources/extensions/cursor-cli/index.js +16 -0
- package/dist/resources/extensions/cursor-cli/models.js +63 -0
- package/dist/resources/extensions/cursor-cli/package.json +11 -0
- package/dist/resources/extensions/cursor-cli/readiness.js +128 -0
- package/dist/resources/extensions/cursor-cli/stream-adapter.js +353 -0
- package/dist/resources/extensions/gsd/activity-log.js +4 -1
- package/dist/resources/extensions/gsd/artifact-verification.js +431 -0
- 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 +32 -11
- package/dist/resources/extensions/gsd/auto-model-selection.js +36 -18
- package/dist/resources/extensions/gsd/auto-post-unit.js +1 -1
- package/dist/resources/extensions/gsd/auto-prompts.js +83 -25
- package/dist/resources/extensions/gsd/auto-recovery.js +9 -517
- package/dist/resources/extensions/gsd/auto-runtime-state.js +4 -5
- package/dist/resources/extensions/gsd/auto-start.js +4 -3
- package/dist/resources/extensions/gsd/auto-timeout-recovery.js +7 -3
- package/dist/resources/extensions/gsd/auto-verification.js +5 -2
- package/dist/resources/extensions/gsd/auto-worktree.js +38 -11
- package/dist/resources/extensions/gsd/auto.js +32 -10
- package/dist/resources/extensions/gsd/bootstrap/core-session-tools.js +39 -0
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +8 -4
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +2 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +147 -23
- package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +56 -36
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +29 -5
- package/dist/resources/extensions/gsd/closeout-consistency-gate.js +3 -1
- package/dist/resources/extensions/gsd/codebase-generator.js +157 -19
- package/dist/resources/extensions/gsd/commands/handlers/auto.js +1 -1
- package/dist/resources/extensions/gsd/commands/handlers/core.js +40 -4
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +154 -2
- package/dist/resources/extensions/gsd/commands-usage.js +1 -1
- package/dist/resources/extensions/gsd/commands-worktree.js +11 -2
- package/dist/resources/extensions/gsd/db/engine.js +4 -1
- package/dist/resources/extensions/gsd/db/queries.js +39 -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/discussion-handoff.js +8 -3
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +10 -4
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +227 -5
- package/dist/resources/extensions/gsd/doctor-providers.js +38 -10
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +3 -0
- package/dist/resources/extensions/gsd/doctor.js +93 -3
- package/dist/resources/extensions/gsd/exec-sandbox.js +14 -4
- package/dist/resources/extensions/gsd/flat-phase-migration.js +119 -23
- package/dist/resources/extensions/gsd/git-service.js +61 -8
- package/dist/resources/extensions/gsd/gitignore.js +4 -1
- package/dist/resources/extensions/gsd/guidance.js +1 -0
- package/dist/resources/extensions/gsd/guided-flow-queue.js +20 -13
- package/dist/resources/extensions/gsd/guided-flow.js +40 -2
- package/dist/resources/extensions/gsd/json-persistence.js +20 -0
- package/dist/resources/extensions/gsd/key-manager.js +1 -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 +27 -15
- package/dist/resources/extensions/gsd/memory-backfill.js +28 -21
- package/dist/resources/extensions/gsd/metrics.js +4 -4
- package/dist/resources/extensions/gsd/migrate-external.js +22 -5
- 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/orphan-stash-audit.js +92 -16
- package/dist/resources/extensions/gsd/preferences-diagnostics.js +24 -1
- package/dist/resources/extensions/gsd/preferences-models.js +6 -4
- package/dist/resources/extensions/gsd/preferences-validation.js +25 -2
- package/dist/resources/extensions/gsd/preferences.js +29 -2
- 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 +5 -3
- package/dist/resources/extensions/gsd/redact-secrets.js +37 -0
- package/dist/resources/extensions/gsd/repository-registry.js +6 -1
- package/dist/resources/extensions/gsd/root-write-leak-guard.js +7 -1
- package/dist/resources/extensions/gsd/safe-fs.js +23 -2
- 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/skills/gsd-headless/SKILL.md +7 -9
- package/dist/resources/extensions/gsd/skills/gsd-headless/references/commands.md +2 -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 +27 -33
- 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 +3 -34
- package/dist/resources/extensions/gsd/tools/complete-task.js +8 -41
- package/dist/resources/extensions/gsd/tools/plan-slice.js +59 -44
- package/dist/resources/extensions/gsd/tools/plan-task.js +103 -12
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +40 -0
- package/dist/resources/extensions/gsd/undo.js +43 -6
- package/dist/resources/extensions/gsd/unit-context-manifest.js +5 -4
- package/dist/resources/extensions/gsd/unit-registry.js +11 -3
- package/dist/resources/extensions/gsd/unit-runtime.js +21 -0
- 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.js +26 -8
- package/dist/resources/extensions/gsd/worktree-manager.js +140 -5
- 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 +12 -12
- 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/update/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 +12 -12
- package/dist/web/standalone/.next/server/chunks/8357.js +2 -2
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/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/@gsd/native/package.json +1 -1
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
- package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
- package/dist/wizard.d.ts +8 -0
- package/dist/wizard.js +8 -1
- package/integrations/hermes/__init__.py +31 -0
- package/integrations/hermes/tests/test_directory_loader.py +37 -0
- package/package.json +8 -8
- package/packages/cloud-mcp-gateway/dist/auth-store.d.ts +1 -0
- package/packages/cloud-mcp-gateway/dist/auth-store.d.ts.map +1 -1
- package/packages/cloud-mcp-gateway/dist/auth-store.js +21 -1
- package/packages/cloud-mcp-gateway/dist/auth-store.js.map +1 -1
- package/packages/cloud-mcp-gateway/dist/auth-store.test.js +34 -0
- package/packages/cloud-mcp-gateway/dist/auth-store.test.js.map +1 -1
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/dist/cloud-runtime.d.ts +2 -0
- package/packages/daemon/dist/cloud-runtime.d.ts.map +1 -1
- package/packages/daemon/dist/cloud-runtime.js +25 -1
- package/packages/daemon/dist/cloud-runtime.js.map +1 -1
- package/packages/daemon/dist/cloud-runtime.test.js +51 -0
- package/packages/daemon/dist/cloud-runtime.test.js.map +1 -1
- package/packages/daemon/dist/message-batcher.d.ts +7 -0
- package/packages/daemon/dist/message-batcher.d.ts.map +1 -1
- package/packages/daemon/dist/message-batcher.js +13 -0
- package/packages/daemon/dist/message-batcher.js.map +1 -1
- package/packages/daemon/dist/message-batcher.test.js +48 -0
- package/packages/daemon/dist/message-batcher.test.js.map +1 -1
- package/packages/daemon/package.json +5 -5
- 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/compaction/compaction.d.ts +13 -1
- package/packages/gsd-agent-core/dist/compaction/compaction.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/compaction/compaction.js +15 -1
- package/packages/gsd-agent-core/dist/compaction/compaction.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 -841
- 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 +259 -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 +24 -6
- 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/dist/workflow-tools.js +1 -1
- 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/env-api-keys.d.ts.map +1 -1
- package/packages/pi-ai/dist/env-api-keys.js +3 -0
- package/packages/pi-ai/dist/env-api-keys.js.map +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/dist/types.d.ts +2 -2
- package/packages/pi-ai/dist/types.d.ts.map +1 -1
- package/packages/pi-ai/dist/types.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/model-resolver.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -0
- package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
- 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/dist/rpc-client.js +1 -1
- package/packages/rpc-client/dist/rpc-client.js.map +1 -1
- 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/scripts/link-workspace-packages.cjs +14 -4
- package/src/resources/GSD-WORKFLOW.md +20 -25
- package/src/resources/extensions/claude-code-cli/models.ts +9 -0
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +67 -49
- 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 +159 -0
- package/src/resources/extensions/cursor-cli/index.ts +18 -0
- package/src/resources/extensions/cursor-cli/models.ts +65 -0
- package/src/resources/extensions/cursor-cli/package.json +11 -0
- package/src/resources/extensions/cursor-cli/readiness.ts +143 -0
- package/src/resources/extensions/cursor-cli/stream-adapter.ts +440 -0
- package/src/resources/extensions/cursor-cli/tests/index.test.ts +54 -0
- package/src/resources/extensions/cursor-cli/tests/readiness.test.ts +29 -0
- package/src/resources/extensions/cursor-cli/tests/stream-adapter.test.ts +166 -0
- package/src/resources/extensions/gsd/activity-log.ts +4 -1
- package/src/resources/extensions/gsd/artifact-verification.ts +468 -0
- package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
- 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 +34 -12
- package/src/resources/extensions/gsd/auto-model-selection.ts +49 -18
- package/src/resources/extensions/gsd/auto-post-unit.ts +1 -1
- package/src/resources/extensions/gsd/auto-prompts.ts +80 -25
- package/src/resources/extensions/gsd/auto-recovery.ts +13 -518
- package/src/resources/extensions/gsd/auto-runtime-state.ts +4 -5
- package/src/resources/extensions/gsd/auto-start.ts +4 -3
- package/src/resources/extensions/gsd/auto-timeout-recovery.ts +7 -2
- package/src/resources/extensions/gsd/auto-verification.ts +5 -1
- package/src/resources/extensions/gsd/auto-worktree.ts +50 -11
- package/src/resources/extensions/gsd/auto.ts +36 -8
- package/src/resources/extensions/gsd/bootstrap/core-session-tools.ts +44 -0
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +8 -4
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +2 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +171 -23
- package/src/resources/extensions/gsd/bootstrap/tests/write-gate-basepath.test.ts +49 -1
- package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +60 -37
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +39 -5
- package/src/resources/extensions/gsd/closeout-consistency-gate.ts +2 -1
- package/src/resources/extensions/gsd/codebase-generator.ts +179 -18
- package/src/resources/extensions/gsd/commands/handlers/auto.ts +1 -1
- package/src/resources/extensions/gsd/commands/handlers/core.ts +39 -3
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +136 -2
- package/src/resources/extensions/gsd/commands-usage.ts +1 -1
- package/src/resources/extensions/gsd/commands-worktree.ts +13 -2
- package/src/resources/extensions/gsd/db/engine.ts +8 -1
- package/src/resources/extensions/gsd/db/queries.ts +40 -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/discussion-handoff.ts +10 -2
- package/src/resources/extensions/gsd/docs/preferences-reference.md +10 -4
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +275 -5
- package/src/resources/extensions/gsd/doctor-providers.ts +39 -10
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +3 -0
- package/src/resources/extensions/gsd/doctor-types.ts +8 -1
- package/src/resources/extensions/gsd/doctor.ts +95 -3
- package/src/resources/extensions/gsd/exec-sandbox.ts +13 -4
- package/src/resources/extensions/gsd/flat-phase-migration.ts +142 -22
- package/src/resources/extensions/gsd/git-service.ts +70 -9
- package/src/resources/extensions/gsd/gitignore.ts +4 -1
- package/src/resources/extensions/gsd/guidance.ts +2 -0
- package/src/resources/extensions/gsd/guided-flow-queue.ts +20 -13
- package/src/resources/extensions/gsd/guided-flow.ts +45 -2
- package/src/resources/extensions/gsd/json-persistence.ts +20 -0
- package/src/resources/extensions/gsd/key-manager.ts +1 -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 +27 -17
- package/src/resources/extensions/gsd/memory-backfill.ts +26 -20
- package/src/resources/extensions/gsd/metrics.ts +4 -4
- package/src/resources/extensions/gsd/migrate-external.ts +17 -4
- 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/model-router.ts +4 -5
- package/src/resources/extensions/gsd/orphan-stash-audit.ts +108 -20
- package/src/resources/extensions/gsd/preferences-diagnostics.ts +24 -0
- package/src/resources/extensions/gsd/preferences-models.ts +6 -3
- package/src/resources/extensions/gsd/preferences-validation.ts +28 -2
- package/src/resources/extensions/gsd/preferences.ts +38 -4
- 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 +5 -3
- package/src/resources/extensions/gsd/redact-secrets.ts +40 -0
- package/src/resources/extensions/gsd/repository-registry.ts +7 -1
- package/src/resources/extensions/gsd/root-write-leak-guard.ts +13 -1
- package/src/resources/extensions/gsd/safe-fs.ts +22 -2
- 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/skills/gsd-headless/SKILL.md +7 -9
- package/src/resources/extensions/gsd/skills/gsd-headless/references/commands.md +2 -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 +36 -30
- 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-migrating-recovery.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +178 -0
- 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 +35 -0
- package/src/resources/extensions/gsd/tests/auto-remote-session-lock-cleanup.test.ts +41 -0
- package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +41 -0
- package/src/resources/extensions/gsd/tests/auto-session-scope.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +3 -0
- package/src/resources/extensions/gsd/tests/auto-timeout-recovery-harness-abort.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/batch-task-query.test.ts +85 -0
- package/src/resources/extensions/gsd/tests/check-auto-start-ready-guard.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +365 -0
- package/src/resources/extensions/gsd/tests/commands-gsd-core.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +62 -1
- 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/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/doctor-providers.test.ts +138 -1
- package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +296 -2
- package/src/resources/extensions/gsd/tests/doctor-workspace.test.ts +207 -0
- package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +74 -2
- package/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts +87 -19
- package/src/resources/extensions/gsd/tests/gate-1b-orphan-discrimination.test.ts +89 -0
- package/src/resources/extensions/gsd/tests/gitignore-bg-shell-runtime.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +11 -2
- package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +4 -2
- 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/markdown-renderer.test.ts +122 -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/orphan-stash-audit.test.ts +91 -7
- package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +4 -1
- package/src/resources/extensions/gsd/tests/pending-autostart-scope.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/plan-slice.test.ts +103 -4
- package/src/resources/extensions/gsd/tests/plan-task.test.ts +307 -1
- package/src/resources/extensions/gsd/tests/post-mutation-hook.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/preferences.test.ts +150 -0
- package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +142 -0
- 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/recovery-verify-logs.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/redact-secrets.test.ts +56 -0
- package/src/resources/extensions/gsd/tests/register-hooks-flat-phase-migration.test.ts +73 -0
- package/src/resources/extensions/gsd/tests/register-hooks-loop-guard-auto.test.ts +378 -0
- package/src/resources/extensions/gsd/tests/repository-registry.test.ts +41 -2
- package/src/resources/extensions/gsd/tests/require-slice-discussion-dispatch.test.ts +55 -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 +105 -0
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +115 -0
- package/src/resources/extensions/gsd/tests/status-per-repo.test.ts +94 -0
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +203 -0
- package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +6 -3
- package/src/resources/extensions/gsd/tests/undo.test.ts +74 -0
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +66 -18
- package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +90 -0
- package/src/resources/extensions/gsd/tests/validator-scope-parity.test.ts +53 -1
- package/src/resources/extensions/gsd/tests/verification-retry-policy.test.ts +69 -4
- 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 +214 -6
- package/src/resources/extensions/gsd/tests/workspace.test.ts +18 -4
- package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +31 -1
- package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +32 -0
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -2
- package/src/resources/extensions/gsd/tools/complete-slice.ts +3 -30
- package/src/resources/extensions/gsd/tools/complete-task.ts +7 -39
- package/src/resources/extensions/gsd/tools/plan-slice.ts +60 -47
- package/src/resources/extensions/gsd/tools/plan-task.ts +135 -12
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +58 -0
- package/src/resources/extensions/gsd/undo.ts +47 -6
- package/src/resources/extensions/gsd/unit-context-manifest.ts +11 -5
- package/src/resources/extensions/gsd/unit-registry.ts +11 -3
- package/src/resources/extensions/gsd/unit-runtime.ts +42 -0
- 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.ts +42 -8
- package/src/resources/extensions/gsd/worktree-manager.ts +183 -5
- package/dist/web/standalone/.next/static/chunks/2772.bfa657f49f955239.js +0 -1
- package/dist/web/standalone/.next/static/chunks/796.3976108148518f7d.js +0 -10
- package/dist/web/standalone/.next/static/chunks/webpack-7c1d97e39be2da11.js +0 -1
- /package/dist/web/standalone/.next/static/{SzEuqWX37DR9MEpEuQjP1 → kIEFsCryyGy6RzifULbJl}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{SzEuqWX37DR9MEpEuQjP1 → kIEFsCryyGy6RzifULbJl}/_ssgManifest.js +0 -0
|
@@ -8,6 +8,7 @@ import { tmpdir } from 'node:os';
|
|
|
8
8
|
|
|
9
9
|
import { openDatabase, closeDatabase, insertMilestone, insertSlice, insertTask, getSlice, getSliceTasks, getTask, getGateResults, updateTaskStatus } from '../gsd-db.ts';
|
|
10
10
|
import { handlePlanSlice } from '../tools/plan-slice.ts';
|
|
11
|
+
import { handlePlanTask } from '../tools/plan-task.ts';
|
|
11
12
|
import { parsePlan } from '../parsers-legacy.ts';
|
|
12
13
|
import { deriveState, invalidateStateCache } from '../state.ts';
|
|
13
14
|
|
|
@@ -511,15 +512,113 @@ test('handlePlanSlice leaves omitted enrichment fields empty instead of renderin
|
|
|
511
512
|
}
|
|
512
513
|
});
|
|
513
514
|
|
|
514
|
-
test('handlePlanSlice
|
|
515
|
+
test('handlePlanSlice accepts metadata-only payloads without deleting existing tasks', async () => {
|
|
515
516
|
const base = makeTmpBase();
|
|
516
517
|
openDatabase(join(base, '.gsd', 'gsd.db'));
|
|
517
518
|
|
|
518
519
|
try {
|
|
519
520
|
seedParentSlice();
|
|
520
|
-
const
|
|
521
|
-
assert.ok('error' in
|
|
522
|
-
assert.
|
|
521
|
+
const first = await handlePlanSlice(validParams(), base);
|
|
522
|
+
assert.ok(!('error' in first), `unexpected error: ${'error' in first ? first.error : ''}`);
|
|
523
|
+
assert.equal(getSliceTasks('M001', 'S02').length, 2);
|
|
524
|
+
|
|
525
|
+
const second = await handlePlanSlice({
|
|
526
|
+
milestoneId: 'M001',
|
|
527
|
+
sliceId: 'S02',
|
|
528
|
+
goal: 'Persist updated slice metadata before incremental tasks.',
|
|
529
|
+
successCriteria: '- Metadata renders before task planning',
|
|
530
|
+
proofLevel: 'unit',
|
|
531
|
+
integrationClosure: 'Task details follow through gsd_plan_task.',
|
|
532
|
+
observabilityImpact: 'Progress survives between tool calls.',
|
|
533
|
+
}, base);
|
|
534
|
+
assert.ok(!('error' in second), `unexpected error: ${'error' in second ? second.error : ''}`);
|
|
535
|
+
assert.equal(getSlice('M001', 'S02')?.goal, 'Persist updated slice metadata before incremental tasks.');
|
|
536
|
+
assert.deepEqual(getSliceTasks('M001', 'S02').map((task) => task.id), ['T01', 'T02']);
|
|
537
|
+
|
|
538
|
+
const third = await handlePlanSlice({ ...validParams(), tasks: [] }, base);
|
|
539
|
+
assert.ok(!('error' in third), `unexpected error: ${'error' in third ? third.error : ''}`);
|
|
540
|
+
assert.deepEqual(getSliceTasks('M001', 'S02').map((task) => task.id), ['T01', 'T02']);
|
|
541
|
+
} finally {
|
|
542
|
+
cleanup(base);
|
|
543
|
+
}
|
|
544
|
+
});
|
|
545
|
+
|
|
546
|
+
test('handlePlanSlice metadata-only on a fresh sketch slice keeps is_sketch set and renders no PLAN.md (#1027)', async () => {
|
|
547
|
+
const base = makeTmpBase();
|
|
548
|
+
openDatabase(join(base, '.gsd', 'gsd.db'));
|
|
549
|
+
|
|
550
|
+
try {
|
|
551
|
+
insertMilestone({ id: 'M001', title: 'Milestone', status: 'active' });
|
|
552
|
+
insertSlice({ id: 'S02', milestoneId: 'M001', title: 'Planning slice', status: 'pending', demo: 'Rendered plans exist.', isSketch: true });
|
|
553
|
+
|
|
554
|
+
// The incremental flow's first call carries metadata only (no tasks). It
|
|
555
|
+
// must NOT error (renderPlanFromDb throws on a task-less slice), and it must
|
|
556
|
+
// NOT clear the sketch flag — clearing it without a PLAN.md would leave the
|
|
557
|
+
// slice out of refining with no plan artifact, breaking sketch/plan signaling.
|
|
558
|
+
const result = await handlePlanSlice({
|
|
559
|
+
milestoneId: 'M001',
|
|
560
|
+
sliceId: 'S02',
|
|
561
|
+
goal: 'Persist slice metadata before any tasks exist.',
|
|
562
|
+
}, base);
|
|
563
|
+
assert.ok(!('error' in result), `unexpected error: ${'error' in result ? result.error : ''}`);
|
|
564
|
+
assert.equal(getSlice('M001', 'S02')?.goal, 'Persist slice metadata before any tasks exist.');
|
|
565
|
+
assert.equal(getSliceTasks('M001', 'S02').length, 0);
|
|
566
|
+
assert.equal(getSlice('M001', 'S02')?.is_sketch, 1, 'sketch flag must stay set until a task-bearing plan renders');
|
|
567
|
+
|
|
568
|
+
const planPath = join(base, '.gsd', 'phases', '01-test', '01-02-PLAN.md');
|
|
569
|
+
assert.ok(!existsSync(planPath), 'no PLAN.md should be rendered until the first task is planned');
|
|
570
|
+
|
|
571
|
+
invalidateStateCache();
|
|
572
|
+
const after = await deriveState(base);
|
|
573
|
+
assert.equal(after.phase, 'refining', 'a task-less sketch slice stays in refining');
|
|
574
|
+
} finally {
|
|
575
|
+
cleanup(base);
|
|
576
|
+
}
|
|
577
|
+
});
|
|
578
|
+
|
|
579
|
+
test('handlePlanTask materializes the slice PLAN.md and clears the sketch flag on the incremental path (#1027)', async () => {
|
|
580
|
+
const base = makeTmpBase();
|
|
581
|
+
openDatabase(join(base, '.gsd', 'gsd.db'));
|
|
582
|
+
|
|
583
|
+
try {
|
|
584
|
+
insertMilestone({ id: 'M001', title: 'Milestone', status: 'active' });
|
|
585
|
+
insertSlice({ id: 'S02', milestoneId: 'M001', title: 'Planning slice', status: 'pending', demo: 'Rendered plans exist.', isSketch: true });
|
|
586
|
+
|
|
587
|
+
const sliceResult = await handlePlanSlice({
|
|
588
|
+
milestoneId: 'M001',
|
|
589
|
+
sliceId: 'S02',
|
|
590
|
+
goal: 'Incrementally planned slice.',
|
|
591
|
+
successCriteria: '- The slice plan is built up one task at a time',
|
|
592
|
+
}, base);
|
|
593
|
+
assert.ok(!('error' in sliceResult), `unexpected error: ${'error' in sliceResult ? sliceResult.error : ''}`);
|
|
594
|
+
|
|
595
|
+
const taskResult = await handlePlanTask({
|
|
596
|
+
milestoneId: 'M001',
|
|
597
|
+
sliceId: 'S02',
|
|
598
|
+
taskId: 'T01',
|
|
599
|
+
title: 'First incremental task',
|
|
600
|
+
description: 'Implement the first task added through gsd_plan_task.',
|
|
601
|
+
estimate: '30m',
|
|
602
|
+
files: ['src/resources/extensions/gsd/tools/plan-task.ts'],
|
|
603
|
+
verify: 'node --test src/resources/extensions/gsd/tests/plan-task.test.ts',
|
|
604
|
+
inputs: ['src/resources/extensions/gsd/tools/plan-milestone.ts'],
|
|
605
|
+
expectedOutput: ['src/resources/extensions/gsd/tools/plan-task.ts'],
|
|
606
|
+
}, base);
|
|
607
|
+
assert.ok(!('error' in taskResult), `unexpected error: ${'error' in taskResult ? taskResult.error : ''}`);
|
|
608
|
+
|
|
609
|
+
// The first incremental task materializes the canonical slice PLAN.md with
|
|
610
|
+
// the task present, and clears the sketch flag now that a plan exists.
|
|
611
|
+
const planPath = join(base, '.gsd', 'phases', '01-test', '01-02-PLAN.md');
|
|
612
|
+
assert.ok(existsSync(planPath), 'slice PLAN.md should exist after the first task is planned');
|
|
613
|
+
const parsedPlan = parsePlan(readFileSync(planPath, 'utf-8'));
|
|
614
|
+
assert.equal(parsedPlan.goal, 'Incrementally planned slice.');
|
|
615
|
+
assert.equal(parsedPlan.tasks.length, 1);
|
|
616
|
+
assert.equal(parsedPlan.tasks[0]?.id, 'T01');
|
|
617
|
+
assert.equal(getSlice('M001', 'S02')?.is_sketch, 0, 'sketch flag must clear once the first task renders a plan');
|
|
618
|
+
|
|
619
|
+
invalidateStateCache();
|
|
620
|
+
const after = await deriveState(base);
|
|
621
|
+
assert.notEqual(after.phase, 'refining', 'a planned slice leaves refining');
|
|
523
622
|
} finally {
|
|
524
623
|
cleanup(base);
|
|
525
624
|
}
|
|
@@ -4,7 +4,7 @@ import { mkdtempSync, mkdirSync, rmSync, readFileSync, existsSync, writeFileSync
|
|
|
4
4
|
import { join } from 'node:path';
|
|
5
5
|
import { tmpdir } from 'node:os';
|
|
6
6
|
|
|
7
|
-
import { openDatabase, closeDatabase, insertMilestone, insertSlice, insertTask, getTask } from '../gsd-db.ts';
|
|
7
|
+
import { openDatabase, closeDatabase, insertMilestone, insertSlice, insertTask, getSlice, getTask, getSliceTasks, getGateResults } from '../gsd-db.ts';
|
|
8
8
|
import { handlePlanTask } from '../tools/plan-task.ts';
|
|
9
9
|
import { parseTaskPlanFile } from '../files.ts';
|
|
10
10
|
|
|
@@ -24,6 +24,26 @@ function seedParent(): void {
|
|
|
24
24
|
insertSlice({ id: 'S02', milestoneId: 'M001', title: 'Planning slice', status: 'pending', demo: 'Rendered plans exist.' });
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
function writeParentWorkspacePreferences(base: string): void {
|
|
28
|
+
mkdirSync(join(base, 'frontend', 'src'), { recursive: true });
|
|
29
|
+
mkdirSync(join(base, 'backend', 'src'), { recursive: true });
|
|
30
|
+
writeFileSync(
|
|
31
|
+
join(base, '.gsd', 'PREFERENCES.md'),
|
|
32
|
+
[
|
|
33
|
+
'---',
|
|
34
|
+
'workspace:',
|
|
35
|
+
' mode: parent',
|
|
36
|
+
' repositories:',
|
|
37
|
+
' frontend:',
|
|
38
|
+
' path: frontend',
|
|
39
|
+
' backend:',
|
|
40
|
+
' path: backend',
|
|
41
|
+
'---',
|
|
42
|
+
].join('\n'),
|
|
43
|
+
'utf-8',
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
27
47
|
function validParams() {
|
|
28
48
|
return {
|
|
29
49
|
milestoneId: 'M001',
|
|
@@ -65,6 +85,25 @@ test('handlePlanTask writes planning state and renders task plan', async () => {
|
|
|
65
85
|
}
|
|
66
86
|
});
|
|
67
87
|
|
|
88
|
+
test('handlePlanTask seeds execute-task gate rows for incremental planning', async () => {
|
|
89
|
+
const base = makeTmpBase();
|
|
90
|
+
openDatabase(join(base, '.gsd', 'gsd.db'));
|
|
91
|
+
|
|
92
|
+
try {
|
|
93
|
+
seedParent();
|
|
94
|
+
const result = await handlePlanTask(validParams(), base);
|
|
95
|
+
assert.ok(!('error' in result), `unexpected error: ${'error' in result ? result.error : ''}`);
|
|
96
|
+
|
|
97
|
+
const gateIds = getGateResults('M001', 'S02', 'task')
|
|
98
|
+
.filter((gate) => gate.task_id === 'T02')
|
|
99
|
+
.map((gate) => gate.gate_id)
|
|
100
|
+
.sort();
|
|
101
|
+
assert.deepEqual(gateIds, ['Q5', 'Q6', 'Q7']);
|
|
102
|
+
} finally {
|
|
103
|
+
cleanup(base);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
|
|
68
107
|
test('handlePlanTask rejects invalid payloads', async () => {
|
|
69
108
|
const base = makeTmpBase();
|
|
70
109
|
openDatabase(join(base, '.gsd', 'gsd.db'));
|
|
@@ -136,6 +175,32 @@ test('handlePlanTask rejects absolute task IO paths outside the active worktree'
|
|
|
136
175
|
}
|
|
137
176
|
});
|
|
138
177
|
|
|
178
|
+
test('handlePlanTask rejects parent-checkout task IO paths from an active worktree', async () => {
|
|
179
|
+
const projectRoot = mkdtempSync(join(tmpdir(), 'gsd-plan-task-project-'));
|
|
180
|
+
const worktree = join(projectRoot, '.gsd', 'worktrees', 'M001');
|
|
181
|
+
mkdirSync(join(projectRoot, '.gsd'), { recursive: true });
|
|
182
|
+
mkdirSync(join(worktree, '.gsd', 'phases', '01-test'), { recursive: true });
|
|
183
|
+
openDatabase(join(projectRoot, '.gsd', 'gsd.db'));
|
|
184
|
+
|
|
185
|
+
try {
|
|
186
|
+
seedParent();
|
|
187
|
+
const parentCheckoutPath = join(projectRoot, 'src', 'index.ts');
|
|
188
|
+
const result = await handlePlanTask({
|
|
189
|
+
...validParams(),
|
|
190
|
+
files: [parentCheckoutPath],
|
|
191
|
+
inputs: [parentCheckoutPath],
|
|
192
|
+
expectedOutput: [parentCheckoutPath],
|
|
193
|
+
}, worktree);
|
|
194
|
+
|
|
195
|
+
assert.ok('error' in result);
|
|
196
|
+
assert.match(result.error, /validation failed: files contains path outside allowed repository roots/);
|
|
197
|
+
assert.match(result.error, new RegExp(worktree.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')));
|
|
198
|
+
assert.equal(getTask('M001', 'S02', 'T02'), null, 'parent-checkout paths must not persist worktree task planning');
|
|
199
|
+
} finally {
|
|
200
|
+
cleanup(projectRoot);
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
|
|
139
204
|
test('handlePlanTask rejects missing parent slice', async () => {
|
|
140
205
|
const base = makeTmpBase();
|
|
141
206
|
openDatabase(join(base, '.gsd', 'gsd.db'));
|
|
@@ -170,6 +235,30 @@ test('handlePlanTask surfaces render failures without changing parse-visible tas
|
|
|
170
235
|
}
|
|
171
236
|
});
|
|
172
237
|
|
|
238
|
+
test('handlePlanTask keeps the sketch flag set when the flat-phase slice plan sync fails (#1083)', async () => {
|
|
239
|
+
const base = makeTmpBase();
|
|
240
|
+
openDatabase(join(base, '.gsd', 'gsd.db'));
|
|
241
|
+
|
|
242
|
+
try {
|
|
243
|
+
insertMilestone({ id: 'M001', title: 'Milestone', status: 'active' });
|
|
244
|
+
insertSlice({ id: 'S02', milestoneId: 'M001', title: 'Planning slice', status: 'pending', demo: 'Rendered plans exist.', isSketch: true });
|
|
245
|
+
|
|
246
|
+
// The per-task render writes T02-PLAN.md and succeeds, but the flat-phase
|
|
247
|
+
// slice re-render (the canonical PLAN.md that embeds task checkboxes) targets
|
|
248
|
+
// phases/01-test/01-02-PLAN.md. Pre-creating that path as a directory forces
|
|
249
|
+
// EISDIR on the slice sync, so the canonical slice plan never reflects the
|
|
250
|
+
// task. The sketch flag must therefore stay set — the slice keeps refining —
|
|
251
|
+
// instead of leaving the slice out of refining over a stale plan.
|
|
252
|
+
mkdirSync(join(base, '.gsd', 'phases', '01-test', '01-02-PLAN.md'), { recursive: true });
|
|
253
|
+
|
|
254
|
+
const result = await handlePlanTask(validParams(), base);
|
|
255
|
+
assert.equal(getSlice('M001', 'S02')?.is_sketch, 1, 'sketch flag must stay set when the canonical slice plan could not sync');
|
|
256
|
+
assert.ok(getTask('M001', 'S02', 'T02'), 'the task itself is still persisted so the slice can re-sync on retry');
|
|
257
|
+
} finally {
|
|
258
|
+
cleanup(base);
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
|
|
173
262
|
test('handlePlanTask reruns idempotently and refreshes parse-visible state', async () => {
|
|
174
263
|
const base = makeTmpBase();
|
|
175
264
|
openDatabase(join(base, '.gsd', 'gsd.db'));
|
|
@@ -200,3 +289,220 @@ test('handlePlanTask reruns idempotently and refreshes parse-visible state', asy
|
|
|
200
289
|
cleanup(base);
|
|
201
290
|
}
|
|
202
291
|
});
|
|
292
|
+
|
|
293
|
+
test('handlePlanTask persists targetRepositories for parent-workspace tasks', async () => {
|
|
294
|
+
const base = makeTmpBase();
|
|
295
|
+
openDatabase(join(base, '.gsd', 'gsd.db'));
|
|
296
|
+
|
|
297
|
+
try {
|
|
298
|
+
seedParent();
|
|
299
|
+
const result = await handlePlanTask({
|
|
300
|
+
...validParams(),
|
|
301
|
+
targetRepositories: ['project'],
|
|
302
|
+
}, base);
|
|
303
|
+
assert.ok(!('error' in result), `unexpected error: ${'error' in result ? result.error : ''}`);
|
|
304
|
+
|
|
305
|
+
const tasks = getSliceTasks('M001', 'S02');
|
|
306
|
+
const planned = tasks.find((t) => t.id === 'T02');
|
|
307
|
+
assert.ok(planned, 'planned task should exist');
|
|
308
|
+
assert.deepEqual(planned?.target_repositories, ['project']);
|
|
309
|
+
} finally {
|
|
310
|
+
cleanup(base);
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
test('handlePlanTask rejects non-array targetRepositories', async () => {
|
|
315
|
+
const base = makeTmpBase();
|
|
316
|
+
openDatabase(join(base, '.gsd', 'gsd.db'));
|
|
317
|
+
|
|
318
|
+
try {
|
|
319
|
+
seedParent();
|
|
320
|
+
const result = await handlePlanTask({
|
|
321
|
+
...validParams(),
|
|
322
|
+
targetRepositories: 'frontend' as unknown as string[],
|
|
323
|
+
}, base);
|
|
324
|
+
assert.ok('error' in result);
|
|
325
|
+
assert.match(result.error, /validation failed: targetRepositories/);
|
|
326
|
+
} finally {
|
|
327
|
+
cleanup(base);
|
|
328
|
+
}
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
test('handlePlanTask rejects empty targetRepositories', async () => {
|
|
332
|
+
const base = makeTmpBase();
|
|
333
|
+
openDatabase(join(base, '.gsd', 'gsd.db'));
|
|
334
|
+
|
|
335
|
+
try {
|
|
336
|
+
seedParent();
|
|
337
|
+
const result = await handlePlanTask({
|
|
338
|
+
...validParams(),
|
|
339
|
+
targetRepositories: [],
|
|
340
|
+
}, base);
|
|
341
|
+
assert.ok('error' in result);
|
|
342
|
+
assert.match(result.error, /validation failed: targetRepositories must include at least one repository id when provided/);
|
|
343
|
+
assert.equal(getTask('M001', 'S02', 'T02'), null, 'invalid target repositories must not persist');
|
|
344
|
+
} finally {
|
|
345
|
+
cleanup(base);
|
|
346
|
+
}
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
test('handlePlanTask rejects unknown target repositories', async () => {
|
|
350
|
+
const base = makeTmpBase();
|
|
351
|
+
openDatabase(join(base, '.gsd', 'gsd.db'));
|
|
352
|
+
|
|
353
|
+
try {
|
|
354
|
+
seedParent();
|
|
355
|
+
const result = await handlePlanTask({
|
|
356
|
+
...validParams(),
|
|
357
|
+
targetRepositories: ['frontend'],
|
|
358
|
+
}, base);
|
|
359
|
+
assert.ok('error' in result);
|
|
360
|
+
assert.match(result.error, /validation failed: unknown targetRepositories:/);
|
|
361
|
+
assert.equal(getTask('M001', 'S02', 'T02'), null, 'unknown target repositories must not persist');
|
|
362
|
+
} finally {
|
|
363
|
+
cleanup(base);
|
|
364
|
+
}
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
test('handlePlanTask enforces path scope to declared target repositories', async () => {
|
|
368
|
+
const base = makeTmpBase();
|
|
369
|
+
openDatabase(join(base, '.gsd', 'gsd.db'));
|
|
370
|
+
|
|
371
|
+
try {
|
|
372
|
+
seedParent();
|
|
373
|
+
mkdirSync(join(base, 'frontend', 'src'), { recursive: true });
|
|
374
|
+
mkdirSync(join(base, 'backend', 'src'), { recursive: true });
|
|
375
|
+
writeFileSync(
|
|
376
|
+
join(base, '.gsd', 'PREFERENCES.md'),
|
|
377
|
+
[
|
|
378
|
+
'---',
|
|
379
|
+
'workspace:',
|
|
380
|
+
' mode: parent',
|
|
381
|
+
' repositories:',
|
|
382
|
+
' frontend:',
|
|
383
|
+
' path: frontend',
|
|
384
|
+
' backend:',
|
|
385
|
+
' path: backend',
|
|
386
|
+
'---',
|
|
387
|
+
].join('\n'),
|
|
388
|
+
'utf-8',
|
|
389
|
+
);
|
|
390
|
+
|
|
391
|
+
const result = await handlePlanTask({
|
|
392
|
+
...validParams(),
|
|
393
|
+
targetRepositories: ['frontend'],
|
|
394
|
+
files: [join(base, 'backend', 'src', 'server.ts')],
|
|
395
|
+
inputs: ['app.js'],
|
|
396
|
+
expectedOutput: ['app.js'],
|
|
397
|
+
}, base);
|
|
398
|
+
assert.ok('error' in result);
|
|
399
|
+
assert.match(result.error, /validation failed: files contains path outside allowed repository roots/);
|
|
400
|
+
assert.equal(getTask('M001', 'S02', 'T02'), null, 'invalid scoped paths must not persist');
|
|
401
|
+
} finally {
|
|
402
|
+
cleanup(base);
|
|
403
|
+
}
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
test('handlePlanTask inherits parent slice target repositories for path scope', async () => {
|
|
407
|
+
const base = makeTmpBase();
|
|
408
|
+
openDatabase(join(base, '.gsd', 'gsd.db'));
|
|
409
|
+
|
|
410
|
+
try {
|
|
411
|
+
seedParent();
|
|
412
|
+
insertSlice({
|
|
413
|
+
id: 'S02',
|
|
414
|
+
milestoneId: 'M001',
|
|
415
|
+
planning: { targetRepositories: ['frontend'] },
|
|
416
|
+
});
|
|
417
|
+
writeParentWorkspacePreferences(base);
|
|
418
|
+
|
|
419
|
+
const result = await handlePlanTask({
|
|
420
|
+
...validParams(),
|
|
421
|
+
files: [join(base, 'backend', 'src', 'server.ts')],
|
|
422
|
+
inputs: ['app.js'],
|
|
423
|
+
expectedOutput: ['app.js'],
|
|
424
|
+
}, base);
|
|
425
|
+
assert.ok('error' in result);
|
|
426
|
+
assert.match(result.error, /validation failed: files contains path outside allowed repository roots/);
|
|
427
|
+
assert.equal(getTask('M001', 'S02', 'T02'), null, 'slice-scoped invalid paths must not persist');
|
|
428
|
+
} finally {
|
|
429
|
+
cleanup(base);
|
|
430
|
+
}
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
test('handlePlanTask preserves stored task target repositories when omitted replan needs them for path scope', async () => {
|
|
434
|
+
const base = makeTmpBase();
|
|
435
|
+
openDatabase(join(base, '.gsd', 'gsd.db'));
|
|
436
|
+
|
|
437
|
+
try {
|
|
438
|
+
seedParent();
|
|
439
|
+
writeParentWorkspacePreferences(base);
|
|
440
|
+
insertSlice({
|
|
441
|
+
id: 'S02',
|
|
442
|
+
milestoneId: 'M001',
|
|
443
|
+
planning: { targetRepositories: ['frontend'] },
|
|
444
|
+
});
|
|
445
|
+
insertTask({
|
|
446
|
+
id: 'T02',
|
|
447
|
+
sliceId: 'S02',
|
|
448
|
+
milestoneId: 'M001',
|
|
449
|
+
title: 'Parent root work',
|
|
450
|
+
status: 'pending',
|
|
451
|
+
planning: { targetRepositories: ['project'] },
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
const rootFile = join(base, 'root-config.json');
|
|
455
|
+
const result = await handlePlanTask({
|
|
456
|
+
...validParams(),
|
|
457
|
+
files: [rootFile],
|
|
458
|
+
inputs: [rootFile],
|
|
459
|
+
expectedOutput: [rootFile],
|
|
460
|
+
}, base);
|
|
461
|
+
|
|
462
|
+
assert.ok(!('error' in result), `unexpected error: ${'error' in result ? result.error : ''}`);
|
|
463
|
+
assert.deepEqual(getTask('M001', 'S02', 'T02')?.target_repositories, ['project']);
|
|
464
|
+
} finally {
|
|
465
|
+
cleanup(base);
|
|
466
|
+
}
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
test('handlePlanTask follows the current slice target default when omitted replan paths validate there', async () => {
|
|
470
|
+
const base = makeTmpBase();
|
|
471
|
+
openDatabase(join(base, '.gsd', 'gsd.db'));
|
|
472
|
+
|
|
473
|
+
try {
|
|
474
|
+
seedParent();
|
|
475
|
+
writeParentWorkspacePreferences(base);
|
|
476
|
+
insertSlice({
|
|
477
|
+
id: 'S02',
|
|
478
|
+
milestoneId: 'M001',
|
|
479
|
+
planning: { targetRepositories: ['frontend'] },
|
|
480
|
+
});
|
|
481
|
+
insertTask({
|
|
482
|
+
id: 'T02',
|
|
483
|
+
sliceId: 'S02',
|
|
484
|
+
milestoneId: 'M001',
|
|
485
|
+
title: 'Child repo work',
|
|
486
|
+
status: 'pending',
|
|
487
|
+
planning: { targetRepositories: ['frontend'] },
|
|
488
|
+
});
|
|
489
|
+
insertSlice({
|
|
490
|
+
id: 'S02',
|
|
491
|
+
milestoneId: 'M001',
|
|
492
|
+
planning: { targetRepositories: ['backend'] },
|
|
493
|
+
});
|
|
494
|
+
|
|
495
|
+
const backendFile = join(base, 'backend', 'src', 'server.ts');
|
|
496
|
+
const result = await handlePlanTask({
|
|
497
|
+
...validParams(),
|
|
498
|
+
files: [backendFile],
|
|
499
|
+
inputs: [backendFile],
|
|
500
|
+
expectedOutput: [backendFile],
|
|
501
|
+
}, base);
|
|
502
|
+
|
|
503
|
+
assert.ok(!('error' in result), `unexpected error: ${'error' in result ? result.error : ''}`);
|
|
504
|
+
assert.deepEqual(getTask('M001', 'S02', 'T02')?.target_repositories, ['backend']);
|
|
505
|
+
} finally {
|
|
506
|
+
cleanup(base);
|
|
507
|
+
}
|
|
508
|
+
});
|
|
@@ -10,7 +10,7 @@ import * as os from 'node:os';
|
|
|
10
10
|
import { openDatabase, closeDatabase } from '../gsd-db.ts';
|
|
11
11
|
import { handleCompleteTask } from '../tools/complete-task.ts';
|
|
12
12
|
import { readEvents } from '../workflow-events.ts';
|
|
13
|
-
import { readManifest } from '../workflow-manifest.ts';
|
|
13
|
+
import { flushManifest, readManifest } from '../workflow-manifest.ts';
|
|
14
14
|
|
|
15
15
|
function tempDir(): string {
|
|
16
16
|
return fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-post-hook-'));
|
|
@@ -115,8 +115,9 @@ test('post-mutation-hook: state-manifest.json exists after handleCompleteTask',
|
|
|
115
115
|
const result = await handleCompleteTask(makeCompleteTaskParams(), base);
|
|
116
116
|
assert.ok(!('error' in result), `handler should succeed, got: ${JSON.stringify(result)}`);
|
|
117
117
|
|
|
118
|
+
await flushManifest(base);
|
|
118
119
|
const manifestPath = path.join(base, '.gsd', 'state-manifest.json');
|
|
119
|
-
assert.ok(fs.existsSync(manifestPath), 'state-manifest.json should exist after
|
|
120
|
+
assert.ok(fs.existsSync(manifestPath), 'state-manifest.json should exist after manifest flush');
|
|
120
121
|
} finally {
|
|
121
122
|
closeDatabase();
|
|
122
123
|
cleanupDir(base);
|
|
@@ -131,6 +132,7 @@ test('post-mutation-hook: manifest has version 1 and includes completed task', a
|
|
|
131
132
|
|
|
132
133
|
try {
|
|
133
134
|
await handleCompleteTask(makeCompleteTaskParams(), base);
|
|
135
|
+
await flushManifest(base);
|
|
134
136
|
|
|
135
137
|
const manifest = readManifest(base);
|
|
136
138
|
assert.ok(manifest !== null, 'manifest should be readable');
|
|
@@ -141,6 +141,26 @@ test("invalid value types produce errors and fall back to undefined", () => {
|
|
|
141
141
|
}
|
|
142
142
|
});
|
|
143
143
|
|
|
144
|
+
test("remote_questions accepts object config and false disables without error", () => {
|
|
145
|
+
const disabled = validatePreferences({ remote_questions: false } as any);
|
|
146
|
+
assert.equal(disabled.errors.length, 0);
|
|
147
|
+
assert.equal(disabled.preferences.remote_questions, undefined);
|
|
148
|
+
|
|
149
|
+
const configured = validatePreferences({
|
|
150
|
+
remote_questions: { channel: "telegram", channel_id: "12345" },
|
|
151
|
+
});
|
|
152
|
+
assert.equal(configured.errors.length, 0);
|
|
153
|
+
assert.deepEqual(configured.preferences.remote_questions, {
|
|
154
|
+
channel: "telegram",
|
|
155
|
+
channel_id: "12345",
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
for (const value of ["telegram", 0]) {
|
|
159
|
+
const invalid = validatePreferences({ remote_questions: value } as any);
|
|
160
|
+
assert.ok(invalid.errors.includes("remote_questions must be an object"));
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
|
|
144
164
|
test("flat_rate_providers: accepts string array", () => {
|
|
145
165
|
const { errors, preferences } = validatePreferences({
|
|
146
166
|
flat_rate_providers: ["my-proxy", "private-cli"],
|
|
@@ -327,6 +347,136 @@ test("workspace.repositories duplicate path error includes both repository ids",
|
|
|
327
347
|
);
|
|
328
348
|
});
|
|
329
349
|
|
|
350
|
+
test("workspace.mode parent with no repositories is rejected", () => {
|
|
351
|
+
const { errors } = validatePreferences({
|
|
352
|
+
workspace: {
|
|
353
|
+
mode: "parent",
|
|
354
|
+
},
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
assert.ok(
|
|
358
|
+
errors.some((e) =>
|
|
359
|
+
e.includes('workspace.mode "parent" requires at least one repository under workspace.repositories'),
|
|
360
|
+
),
|
|
361
|
+
);
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
test("workspace.mode parent with empty repositories map is rejected", () => {
|
|
365
|
+
const { errors } = validatePreferences({
|
|
366
|
+
workspace: {
|
|
367
|
+
mode: "parent",
|
|
368
|
+
repositories: {},
|
|
369
|
+
},
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
assert.ok(
|
|
373
|
+
errors.some((e) =>
|
|
374
|
+
e.includes('workspace.mode "parent" requires at least one repository under workspace.repositories'),
|
|
375
|
+
),
|
|
376
|
+
);
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
test("workspace.mode parent with declared repositories is valid", () => {
|
|
380
|
+
const { errors } = validatePreferences({
|
|
381
|
+
workspace: {
|
|
382
|
+
mode: "parent",
|
|
383
|
+
repositories: {
|
|
384
|
+
frontend: { path: "frontend" },
|
|
385
|
+
},
|
|
386
|
+
},
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
assert.equal(errors.length, 0);
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
test("mode:team + workspace.mode:parent warns about root-only push/PR", () => {
|
|
393
|
+
const { warnings } = validatePreferences({
|
|
394
|
+
mode: "team",
|
|
395
|
+
workspace: {
|
|
396
|
+
mode: "parent",
|
|
397
|
+
repositories: {
|
|
398
|
+
frontend: { path: "frontend" },
|
|
399
|
+
},
|
|
400
|
+
},
|
|
401
|
+
});
|
|
402
|
+
const crossAxisWarnings = warnings.filter((w) => w.includes("mode:team + workspace.mode:parent"));
|
|
403
|
+
|
|
404
|
+
assert.ok(
|
|
405
|
+
crossAxisWarnings.some((w) =>
|
|
406
|
+
w.includes("ADR-044"),
|
|
407
|
+
),
|
|
408
|
+
"expected a cross-axis warning naming ADR-044",
|
|
409
|
+
);
|
|
410
|
+
assert.equal(crossAxisWarnings.length, 1, "expected exactly one cross-axis warning");
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
test("mode:team + workspace.mode:parent warns after global/project merge", (t) => {
|
|
414
|
+
const originalCwd = process.cwd();
|
|
415
|
+
const originalGsdHome = process.env.GSD_HOME;
|
|
416
|
+
const tempProject = mkdtempSync(join(tmpdir(), "gsd-prefs-cross-axis-project-"));
|
|
417
|
+
const tempGsdHome = mkdtempSync(join(tmpdir(), "gsd-prefs-cross-axis-home-"));
|
|
418
|
+
|
|
419
|
+
t.after(() => {
|
|
420
|
+
clearGSDPreferencesCache();
|
|
421
|
+
process.chdir(originalCwd);
|
|
422
|
+
if (originalGsdHome === undefined) delete process.env.GSD_HOME;
|
|
423
|
+
else process.env.GSD_HOME = originalGsdHome;
|
|
424
|
+
rmSync(tempProject, { recursive: true, force: true });
|
|
425
|
+
rmSync(tempGsdHome, { recursive: true, force: true });
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
mkdirSync(join(tempProject, ".gsd"), { recursive: true });
|
|
429
|
+
process.env.GSD_HOME = tempGsdHome;
|
|
430
|
+
process.chdir(tempProject);
|
|
431
|
+
clearGSDPreferencesCache();
|
|
432
|
+
|
|
433
|
+
writeFileSync(getGlobalGSDPreferencesPath(), "---\nversion: 1\nmode: team\n---\n", "utf-8");
|
|
434
|
+
writeFileSync(
|
|
435
|
+
getProjectGSDPreferencesPath(tempProject),
|
|
436
|
+
[
|
|
437
|
+
"---",
|
|
438
|
+
"version: 1",
|
|
439
|
+
"workspace:",
|
|
440
|
+
" mode: parent",
|
|
441
|
+
" repositories:",
|
|
442
|
+
" frontend:",
|
|
443
|
+
" path: frontend",
|
|
444
|
+
"---",
|
|
445
|
+
"",
|
|
446
|
+
].join("\n"),
|
|
447
|
+
"utf-8",
|
|
448
|
+
);
|
|
449
|
+
|
|
450
|
+
const rawGlobalWarnings = loadGlobalGSDPreferences()?.warnings ?? [];
|
|
451
|
+
const rawProjectWarnings = loadProjectGSDPreferences(tempProject)?.warnings ?? [];
|
|
452
|
+
assert.equal(rawGlobalWarnings.filter((w) => w.includes("workspace.mode:parent")).length, 0);
|
|
453
|
+
assert.equal(rawProjectWarnings.filter((w) => w.includes("mode:team + workspace.mode:parent")).length, 0);
|
|
454
|
+
|
|
455
|
+
const loaded = loadEffectiveGSDPreferences(tempProject);
|
|
456
|
+
assert.equal(loaded?.preferences.mode, "team");
|
|
457
|
+
assert.equal(loaded?.preferences.workspace?.mode, "parent");
|
|
458
|
+
assert.equal(
|
|
459
|
+
(loaded?.warnings ?? []).filter((w) => w.includes("mode:team + workspace.mode:parent")).length,
|
|
460
|
+
1,
|
|
461
|
+
);
|
|
462
|
+
|
|
463
|
+
const diagnostics = collectPreferenceDiagnostics(tempProject).filter((diagnostic) =>
|
|
464
|
+
diagnostic.message.includes("mode:team + workspace.mode:parent"),
|
|
465
|
+
);
|
|
466
|
+
assert.equal(diagnostics.length, 1);
|
|
467
|
+
assert.equal(diagnostics[0]?.scope, "project");
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
test("mode:team without workspace.mode:parent does not warn about push", () => {
|
|
471
|
+
const { warnings } = validatePreferences({
|
|
472
|
+
mode: "team",
|
|
473
|
+
});
|
|
474
|
+
|
|
475
|
+
assert.ok(
|
|
476
|
+
!warnings.some((w) => w.includes("workspace.mode:parent")),
|
|
477
|
+
"team mode alone must not trigger the parent-workspace push warning",
|
|
478
|
+
);
|
|
479
|
+
});
|
|
330
480
|
|
|
331
481
|
test("workspace is a recognized preference key (no unknown warning)", () => {
|
|
332
482
|
const { warnings } = validatePreferences({
|