@opengsd/gsd-pi 1.2.0-dev.fb12b103 → 1.2.0-dev.fbdca60b
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/dist/cli-model-override.d.ts +15 -0
- package/dist/cli-model-override.js +21 -0
- package/dist/cli.js +1 -18
- package/dist/headless-events.js +7 -5
- package/dist/loader.js +6 -4
- package/dist/mcp-server.js +2 -1
- package/dist/register-agent-bundles.d.ts +11 -2
- package/dist/register-agent-bundles.js +18 -4
- package/dist/resource-loader.d.ts +10 -5
- package/dist/resource-loader.js +121 -6
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/GSD-WORKFLOW.md +5 -4
- package/dist/resources/extensions/ask-user-questions.js +3 -2
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +447 -215
- package/dist/resources/extensions/claude-code-cli/turn-assembler.js +33 -1
- package/dist/resources/extensions/gsd/auto/closeout.js +215 -0
- package/dist/resources/extensions/gsd/auto/custom-verify-retry-store.js +17 -2
- package/dist/resources/extensions/gsd/auto/detect-stuck.js +33 -13
- package/dist/resources/extensions/gsd/auto/dispatch-history.js +120 -0
- package/dist/resources/extensions/gsd/auto/dispatch-key.js +37 -0
- package/dist/resources/extensions/gsd/auto/dispatch.js +365 -0
- package/dist/resources/extensions/gsd/auto/finalize.js +347 -0
- package/dist/resources/extensions/gsd/auto/loop.js +7 -1
- package/dist/resources/extensions/gsd/auto/milestone-lease-reclaim.js +56 -0
- package/dist/resources/extensions/gsd/auto/orchestrator.js +167 -64
- package/dist/resources/extensions/gsd/auto/phase-helpers.js +146 -0
- package/dist/resources/extensions/gsd/auto/phases.js +17 -2329
- package/dist/resources/extensions/gsd/auto/pre-dispatch.js +534 -0
- package/dist/resources/extensions/gsd/auto/session.js +3 -0
- package/dist/resources/extensions/gsd/auto/unit-phase.js +694 -0
- package/dist/resources/extensions/gsd/auto/workflow-unit-dispatch.js +1 -1
- package/dist/resources/extensions/gsd/auto/worktree-safety-phase.js +125 -0
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +11 -34
- package/dist/resources/extensions/gsd/auto-dispatch.js +39 -58
- package/dist/resources/extensions/gsd/auto-model-selection.js +11 -7
- package/dist/resources/extensions/gsd/auto-post-unit.js +30 -12
- package/dist/resources/extensions/gsd/auto-prompts.js +66 -9
- package/dist/resources/extensions/gsd/auto-start.js +26 -8
- package/dist/resources/extensions/gsd/auto-unit-closeout.js +45 -21
- package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +5 -4
- package/dist/resources/extensions/gsd/auto-verification.js +23 -30
- package/dist/resources/extensions/gsd/auto-worktree.js +15 -2
- package/dist/resources/extensions/gsd/auto.js +52 -2
- package/dist/resources/extensions/gsd/blocked-models.js +28 -0
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +26 -6
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +37 -7
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +2 -2
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +107 -45
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +302 -80
- package/dist/resources/extensions/gsd/closeout-wizard.js +92 -0
- package/dist/resources/extensions/gsd/commands/context.js +16 -2
- package/dist/resources/extensions/gsd/commands-handlers.js +46 -3
- package/dist/resources/extensions/gsd/commands-mcp-status.js +2 -2
- package/dist/resources/extensions/gsd/commands-workflow-templates.js +9 -2
- package/dist/resources/extensions/gsd/consent-question.js +353 -0
- package/dist/resources/extensions/gsd/consent-verdict.js +63 -0
- package/dist/resources/extensions/gsd/crash-recovery.js +8 -3
- package/dist/resources/extensions/gsd/db/engine.js +24 -6
- package/dist/resources/extensions/gsd/db/queries.js +56 -0
- package/dist/resources/extensions/gsd/db-migration-backup.js +51 -8
- package/dist/resources/extensions/gsd/db-transaction.js +27 -23
- package/dist/resources/extensions/gsd/db-writer.js +8 -17
- package/dist/resources/extensions/gsd/dispatch-guard.js +10 -35
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +5 -5
- package/dist/resources/extensions/gsd/doctor-environment.js +256 -125
- package/dist/resources/extensions/gsd/doctor-git-checks.js +2 -18
- package/dist/resources/extensions/gsd/engine-hook-contract.js +70 -0
- package/dist/resources/extensions/gsd/files.js +33 -19
- package/dist/resources/extensions/gsd/gsd-command-home.js +22 -12
- package/dist/resources/extensions/gsd/gsd-db.js +17 -21
- package/dist/resources/extensions/gsd/guidance.js +60 -0
- package/dist/resources/extensions/gsd/guided-flow.js +93 -4
- package/dist/resources/extensions/gsd/health-widget.js +87 -28
- package/dist/resources/extensions/gsd/markdown-renderer.js +10 -0
- package/dist/resources/extensions/gsd/mcp-bridge.js +10 -0
- package/dist/resources/extensions/gsd/memory-relations.js +1 -1
- package/dist/resources/extensions/gsd/milestone-closeout.js +85 -24
- package/dist/resources/extensions/gsd/milestone-planning-persistence.js +2 -2
- package/dist/resources/extensions/gsd/milestone-reopen-events.js +3 -5
- package/dist/resources/extensions/gsd/milestone-settlement.js +2 -2
- package/dist/resources/extensions/gsd/notifications.js +12 -7
- package/dist/resources/extensions/gsd/parsers-legacy.js +16 -4
- package/dist/resources/extensions/gsd/projection-flush.js +7 -0
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +3 -3
- package/dist/resources/extensions/gsd/prompts/execute-task.md +3 -2
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -1
- package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/replan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/research-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
- package/dist/resources/extensions/gsd/prompts/run-uat.md +8 -4
- package/dist/resources/extensions/gsd/prompts/triage-captures.md +1 -1
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/workflow-start.md +2 -1
- package/dist/resources/extensions/gsd/reactive-graph.js +8 -1
- package/dist/resources/extensions/gsd/roadmap-slices.js +25 -3
- package/dist/resources/extensions/gsd/session-lock.js +1 -1
- package/dist/resources/extensions/gsd/skill-activation.js +3 -6
- package/dist/resources/extensions/gsd/state.js +11 -2
- package/dist/resources/extensions/gsd/tool-contract.js +14 -3
- package/dist/resources/extensions/gsd/tool-presentation-plan.js +4 -4
- package/dist/resources/extensions/gsd/tool-surface-readiness.js +83 -31
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +3 -2
- package/dist/resources/extensions/gsd/tools/complete-slice.js +22 -12
- package/dist/resources/extensions/gsd/tools/complete-task.js +65 -2
- package/dist/resources/extensions/gsd/tools/plan-slice.js +2 -2
- package/dist/resources/extensions/gsd/tools/plan-task.js +2 -2
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +2 -2
- package/dist/resources/extensions/gsd/tools/reopen-milestone.js +2 -2
- package/dist/resources/extensions/gsd/tools/reopen-slice.js +2 -2
- package/dist/resources/extensions/gsd/tools/reopen-task.js +2 -2
- package/dist/resources/extensions/gsd/tools/replan-slice.js +2 -2
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +67 -2
- package/dist/resources/extensions/gsd/uat-policy.js +40 -15
- package/dist/resources/extensions/gsd/unit-context-composer.js +1 -1
- package/dist/resources/extensions/gsd/unit-registry.js +34 -4
- package/dist/resources/extensions/gsd/verdict-parser.js +1 -1
- package/dist/resources/extensions/gsd/verification-verdict.js +2 -1
- package/dist/resources/extensions/gsd/workflow-event-ledger.js +91 -0
- package/dist/resources/extensions/gsd/workflow-event-vocabulary.js +46 -0
- package/dist/resources/extensions/gsd/workflow-events.js +6 -18
- package/dist/resources/extensions/gsd/workflow-mcp-auto-prep.js +2 -0
- package/dist/resources/extensions/gsd/workflow-mcp-readiness-cache.js +105 -0
- package/dist/resources/extensions/gsd/workflow-reconcile.js +21 -56
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +3 -2
- package/dist/resources/extensions/gsd/worktree-manager.js +7 -1
- package/dist/resources/extensions/gsd/worktree-safety.js +28 -26
- package/dist/resources/extensions/gsd/worktree.js +8 -1
- package/dist/resources/extensions/mcp-client/manager.js +6 -1
- package/dist/resources/extensions/shared/gsd-browser-cli.js +21 -2
- package/dist/resources/shared/gsd-browser-path-sync.js +214 -0
- package/dist/resources/shared/package-manager-detection.js +1 -1
- package/dist/resources/skills/create-skill/SKILL.md +3 -0
- package/dist/resources/skills/create-skill/references/skill-structure.md +1 -0
- package/dist/runtime-checks.d.ts +10 -0
- package/dist/runtime-checks.js +27 -0
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/update-check.d.ts +2 -0
- package/dist/update-check.js +24 -1
- package/dist/update-cmd.js +20 -3
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +6 -6
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +6 -6
- package/dist/web/standalone/.next/server/chunks/{5942.js → 1128.js} +1 -1
- 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/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/node_modules/node-pty/build/Makefile +1 -1
- package/dist/web/standalone/node_modules/postcss/lib/container.js +26 -18
- package/dist/web/standalone/node_modules/postcss/lib/css-syntax-error.js +47 -14
- package/dist/web/standalone/node_modules/postcss/lib/declaration.js +4 -4
- package/dist/web/standalone/node_modules/postcss/lib/fromJSON.js +3 -3
- package/dist/web/standalone/node_modules/postcss/lib/input.js +54 -29
- package/dist/web/standalone/node_modules/postcss/lib/lazy-result.js +47 -37
- package/dist/web/standalone/node_modules/postcss/lib/map-generator.js +26 -9
- package/dist/web/standalone/node_modules/postcss/lib/no-work-result.js +57 -55
- package/dist/web/standalone/node_modules/postcss/lib/node.js +99 -31
- package/dist/web/standalone/node_modules/postcss/lib/parse.js +1 -1
- package/dist/web/standalone/node_modules/postcss/lib/parser.js +10 -9
- package/dist/web/standalone/node_modules/postcss/lib/postcss.js +12 -12
- package/dist/web/standalone/node_modules/postcss/lib/previous-map.js +30 -11
- package/dist/web/standalone/node_modules/postcss/lib/processor.js +7 -7
- package/dist/web/standalone/node_modules/postcss/lib/result.js +5 -5
- package/dist/web/standalone/node_modules/postcss/lib/rule.js +6 -6
- package/dist/web/standalone/node_modules/postcss/lib/stringifier.js +69 -28
- package/dist/web/standalone/node_modules/postcss/lib/tokenize.js +6 -2
- package/dist/web/standalone/node_modules/postcss/package.json +48 -48
- package/package.json +3 -3
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/dist/sdk.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/sdk.js +6 -4
- package/packages/gsd-agent-core/dist/sdk.js.map +1 -1
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts +2 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js +10 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +8 -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 +50 -6
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts +2 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +34 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts +1 -0
- 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 +17 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js +4 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/README.md +12 -3
- package/packages/mcp-server/dist/cli-runner.d.ts +40 -0
- package/packages/mcp-server/dist/cli-runner.d.ts.map +1 -0
- package/packages/mcp-server/dist/cli-runner.js +137 -0
- package/packages/mcp-server/dist/cli-runner.js.map +1 -0
- package/packages/mcp-server/dist/cli.js +2 -53
- package/packages/mcp-server/dist/cli.js.map +1 -1
- package/packages/mcp-server/dist/moonshot-tool-schema.d.ts +29 -0
- package/packages/mcp-server/dist/moonshot-tool-schema.d.ts.map +1 -0
- package/packages/mcp-server/dist/moonshot-tool-schema.js +50 -0
- package/packages/mcp-server/dist/moonshot-tool-schema.js.map +1 -0
- package/packages/mcp-server/dist/pid-registry.d.ts +46 -0
- package/packages/mcp-server/dist/pid-registry.d.ts.map +1 -0
- package/packages/mcp-server/dist/pid-registry.js +459 -0
- package/packages/mcp-server/dist/pid-registry.js.map +1 -0
- package/packages/mcp-server/dist/probe-mode.d.ts +4 -0
- package/packages/mcp-server/dist/probe-mode.d.ts.map +1 -0
- package/packages/mcp-server/dist/probe-mode.js +10 -0
- package/packages/mcp-server/dist/probe-mode.js.map +1 -0
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +4 -0
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/stdio-watchdog.d.ts +8 -0
- package/packages/mcp-server/dist/stdio-watchdog.d.ts.map +1 -0
- package/packages/mcp-server/dist/stdio-watchdog.js +40 -0
- package/packages/mcp-server/dist/stdio-watchdog.js.map +1 -0
- package/packages/mcp-server/dist/workflow-tools.d.ts +18 -18
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +161 -81
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +5 -4
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +43 -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/README.md +1 -0
- package/packages/pi-ai/dist/image-models.generated.d.ts +2 -2
- package/packages/pi-ai/dist/image-models.generated.js +6 -6
- package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
- package/packages/pi-ai/dist/index.d.ts +2 -0
- package/packages/pi-ai/dist/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/index.js +2 -0
- package/packages/pi-ai/dist/index.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +419 -221
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +468 -269
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +12 -7
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/providers/google-shared.d.ts +5 -0
- package/packages/pi-ai/dist/providers/google-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/google-shared.js +12 -3
- package/packages/pi-ai/dist/providers/google-shared.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.js +7 -3
- package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
- package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts +9 -0
- package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts.map +1 -0
- package/packages/pi-ai/dist/utils/moonshot-tool-schema.js +34 -0
- package/packages/pi-ai/dist/utils/moonshot-tool-schema.js.map +1 -0
- package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/github-copilot.js +6 -2
- package/packages/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
- package/packages/pi-ai/package.json +3 -2
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +11 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.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 +45 -17
- 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/README.md +15 -0
- package/packages/pi-tui/dist/index.d.ts +2 -2
- package/packages/pi-tui/dist/index.d.ts.map +1 -1
- package/packages/pi-tui/dist/index.js +2 -2
- package/packages/pi-tui/dist/index.js.map +1 -1
- package/packages/pi-tui/dist/terminal-image.d.ts +33 -0
- package/packages/pi-tui/dist/terminal-image.d.ts.map +1 -1
- package/packages/pi-tui/dist/terminal-image.js +54 -2
- package/packages/pi-tui/dist/terminal-image.js.map +1 -1
- package/packages/pi-tui/dist/terminal.d.ts +12 -0
- package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
- package/packages/pi-tui/dist/terminal.js +70 -25
- package/packages/pi-tui/dist/terminal.js.map +1 -1
- package/packages/pi-tui/dist/tui.d.ts +15 -0
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +106 -21
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/dist/utils.d.ts.map +1 -1
- package/packages/pi-tui/dist/utils.js +110 -36
- package/packages/pi-tui/dist/utils.js.map +1 -1
- package/packages/pi-tui/package.json +2 -2
- package/packages/rpc-client/package.json +2 -2
- package/pkg/dist/theme/theme.d.ts.map +1 -1
- package/pkg/dist/theme/theme.js +45 -17
- package/pkg/dist/theme/theme.js.map +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/GSD-WORKFLOW.md +5 -4
- package/src/resources/extensions/ask-user-questions.ts +7 -2
- package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +11 -0
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +531 -226
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +672 -7
- package/src/resources/extensions/claude-code-cli/turn-assembler.ts +38 -1
- package/src/resources/extensions/gsd/auto/closeout.ts +309 -0
- package/src/resources/extensions/gsd/auto/custom-verify-retry-store.ts +21 -3
- package/src/resources/extensions/gsd/auto/detect-stuck.ts +32 -9
- package/src/resources/extensions/gsd/auto/dispatch-history.ts +168 -0
- package/src/resources/extensions/gsd/auto/dispatch-key.ts +39 -0
- package/src/resources/extensions/gsd/auto/dispatch.ts +449 -0
- package/src/resources/extensions/gsd/auto/finalize.ts +445 -0
- package/src/resources/extensions/gsd/auto/loop.ts +7 -1
- package/src/resources/extensions/gsd/auto/milestone-lease-reclaim.ts +74 -0
- package/src/resources/extensions/gsd/auto/orchestrator.ts +186 -66
- package/src/resources/extensions/gsd/auto/phase-helpers.ts +199 -0
- package/src/resources/extensions/gsd/auto/phases.ts +58 -3022
- package/src/resources/extensions/gsd/auto/pre-dispatch.ts +704 -0
- package/src/resources/extensions/gsd/auto/session.ts +3 -0
- package/src/resources/extensions/gsd/auto/unit-phase.ts +910 -0
- package/src/resources/extensions/gsd/auto/workflow-unit-dispatch.ts +1 -1
- package/src/resources/extensions/gsd/auto/worktree-safety-phase.ts +149 -0
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +18 -48
- package/src/resources/extensions/gsd/auto-dispatch.ts +37 -62
- package/src/resources/extensions/gsd/auto-model-selection.ts +16 -7
- package/src/resources/extensions/gsd/auto-post-unit.ts +33 -12
- package/src/resources/extensions/gsd/auto-prompts.ts +78 -9
- package/src/resources/extensions/gsd/auto-start.ts +27 -11
- package/src/resources/extensions/gsd/auto-unit-closeout.ts +83 -28
- package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +4 -4
- package/src/resources/extensions/gsd/auto-verification.ts +26 -28
- package/src/resources/extensions/gsd/auto-worktree.ts +15 -2
- package/src/resources/extensions/gsd/auto.ts +64 -2
- package/src/resources/extensions/gsd/blocked-models.ts +49 -0
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +34 -5
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +56 -6
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +2 -2
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +118 -50
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +350 -86
- package/src/resources/extensions/gsd/closeout-wizard.ts +102 -0
- package/src/resources/extensions/gsd/commands/context.ts +16 -2
- package/src/resources/extensions/gsd/commands-handlers.ts +46 -3
- package/src/resources/extensions/gsd/commands-mcp-status.ts +2 -2
- package/src/resources/extensions/gsd/commands-workflow-templates.ts +11 -4
- package/src/resources/extensions/gsd/consent-question.ts +431 -0
- package/src/resources/extensions/gsd/consent-verdict.ts +86 -0
- package/src/resources/extensions/gsd/crash-recovery.ts +10 -2
- package/src/resources/extensions/gsd/db/engine.ts +26 -6
- package/src/resources/extensions/gsd/db/queries.ts +66 -0
- package/src/resources/extensions/gsd/db-migration-backup.ts +56 -7
- package/src/resources/extensions/gsd/db-transaction.ts +37 -20
- package/src/resources/extensions/gsd/db-writer.ts +11 -19
- package/src/resources/extensions/gsd/dispatch-guard.ts +8 -31
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +5 -4
- package/src/resources/extensions/gsd/doctor-environment.ts +267 -142
- package/src/resources/extensions/gsd/doctor-git-checks.ts +2 -19
- package/src/resources/extensions/gsd/engine-hook-contract.ts +79 -0
- package/src/resources/extensions/gsd/files.ts +33 -12
- package/src/resources/extensions/gsd/gsd-command-home.ts +13 -3
- package/src/resources/extensions/gsd/gsd-db.ts +19 -22
- package/src/resources/extensions/gsd/guidance.ts +78 -0
- package/src/resources/extensions/gsd/guided-flow.ts +145 -24
- package/src/resources/extensions/gsd/health-widget.ts +91 -27
- package/src/resources/extensions/gsd/markdown-renderer.ts +11 -0
- package/src/resources/extensions/gsd/mcp-bridge.ts +39 -0
- package/src/resources/extensions/gsd/memory-relations.ts +1 -1
- package/src/resources/extensions/gsd/milestone-closeout.ts +109 -24
- package/src/resources/extensions/gsd/milestone-planning-persistence.ts +2 -2
- package/src/resources/extensions/gsd/milestone-reopen-events.ts +3 -6
- package/src/resources/extensions/gsd/milestone-settlement.ts +2 -2
- package/src/resources/extensions/gsd/notifications.ts +13 -6
- package/src/resources/extensions/gsd/parsers-legacy.ts +16 -4
- package/src/resources/extensions/gsd/projection-flush.ts +20 -0
- package/src/resources/extensions/gsd/prompts/complete-slice.md +3 -3
- package/src/resources/extensions/gsd/prompts/execute-task.md +3 -2
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/quick-task.md +1 -1
- package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
- package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/replan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/research-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
- package/src/resources/extensions/gsd/prompts/run-uat.md +8 -4
- package/src/resources/extensions/gsd/prompts/triage-captures.md +1 -1
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/workflow-start.md +2 -1
- package/src/resources/extensions/gsd/reactive-graph.ts +11 -1
- package/src/resources/extensions/gsd/roadmap-slices.ts +28 -3
- package/src/resources/extensions/gsd/session-lock.ts +1 -1
- package/src/resources/extensions/gsd/skill-activation.ts +3 -6
- package/src/resources/extensions/gsd/state.ts +12 -1
- package/src/resources/extensions/gsd/tests/auto-abort-pause-regression.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/auto-blocked-remediation-message.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +206 -22
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +75 -1
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +257 -18
- package/src/resources/extensions/gsd/tests/auto-pause-double-entry-guard.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +77 -1
- package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/auto-remote-session-lock-cleanup.test.ts +65 -3
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +236 -0
- package/src/resources/extensions/gsd/tests/auto-unit-closeout.test.ts +169 -1
- package/src/resources/extensions/gsd/tests/blocked-models.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +141 -5
- package/src/resources/extensions/gsd/tests/consent-question.test.ts +351 -0
- package/src/resources/extensions/gsd/tests/custom-verify-retry-store.test.ts +67 -0
- package/src/resources/extensions/gsd/tests/db-migration-backup.test.ts +68 -19
- package/src/resources/extensions/gsd/tests/db-transaction.test.ts +59 -0
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +15 -4
- package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +12 -11
- package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/discuss-routing-fixes.test.ts +12 -2
- package/src/resources/extensions/gsd/tests/dispatch-history.test.ts +328 -0
- package/src/resources/extensions/gsd/tests/dist-redirect.mjs +8 -0
- package/src/resources/extensions/gsd/tests/doctor-git-checks-terminal.test.ts +73 -0
- package/src/resources/extensions/gsd/tests/engine-hook-contract.test.ts +148 -0
- package/src/resources/extensions/gsd/tests/engine-interfaces-contract.test.ts +117 -91
- package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +113 -0
- package/src/resources/extensions/gsd/tests/gsd-command-home.test.ts +120 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/guidance.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +18 -6
- package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-environment-async.test.ts +104 -0
- package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +217 -0
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +47 -16
- package/src/resources/extensions/gsd/tests/mcp-readiness-preflight.test.ts +205 -0
- package/src/resources/extensions/gsd/tests/mcp-status.test.ts +6 -5
- package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +95 -4
- package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/milestone-report-path.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/milestone-settlement.test.ts +92 -0
- package/src/resources/extensions/gsd/tests/milestone-transition-state-rebuild.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/notifications.test.ts +64 -9
- package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +143 -0
- package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/phases-terminal-complete-idempotent.test.ts +242 -0
- package/src/resources/extensions/gsd/tests/plan-gate-failed-doctor-heal-hint.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +63 -2
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +10 -2
- package/src/resources/extensions/gsd/tests/prompt-db.test.ts +124 -6
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +2 -4
- package/src/resources/extensions/gsd/tests/remote-notification-from-desktop.test.ts +31 -81
- package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +68 -0
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +26 -2
- package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +170 -48
- package/src/resources/extensions/gsd/tests/skill-activation.test.ts +20 -17
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +7 -3
- package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/teardown-chdir-failure-clears-registry.test.ts +17 -0
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/tool-surface-readiness.test.ts +184 -10
- package/src/resources/extensions/gsd/tests/tool-unavailable-retry.test.ts +33 -0
- package/src/resources/extensions/gsd/tests/transport-gate-double-complete.test.ts +139 -0
- package/src/resources/extensions/gsd/tests/uat-policy.test.ts +88 -0
- package/src/resources/extensions/gsd/tests/uok-audit-unified.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/workflow-events.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp-readiness-cache.test.ts +119 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +65 -2
- package/src/resources/extensions/gsd/tests/workflow-phase-contract-matrix.test.ts +332 -0
- package/src/resources/extensions/gsd/tests/workflow-reconcile.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +92 -0
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +273 -38
- package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-project-root-degrade.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-safety-phase.test.ts +100 -0
- package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +72 -0
- package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/worktree.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/write-gate-seam.test.ts +358 -0
- package/src/resources/extensions/gsd/tests/write-gate.test.ts +67 -1
- package/src/resources/extensions/gsd/tool-contract.ts +38 -3
- package/src/resources/extensions/gsd/tool-presentation-plan.ts +4 -4
- package/src/resources/extensions/gsd/tool-surface-readiness.ts +126 -19
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -2
- package/src/resources/extensions/gsd/tools/complete-slice.ts +22 -12
- package/src/resources/extensions/gsd/tools/complete-task.ts +90 -2
- package/src/resources/extensions/gsd/tools/plan-slice.ts +2 -2
- package/src/resources/extensions/gsd/tools/plan-task.ts +2 -2
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +2 -2
- package/src/resources/extensions/gsd/tools/reopen-milestone.ts +2 -2
- package/src/resources/extensions/gsd/tools/reopen-slice.ts +2 -2
- package/src/resources/extensions/gsd/tools/reopen-task.ts +2 -2
- package/src/resources/extensions/gsd/tools/replan-slice.ts +2 -2
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +81 -2
- package/src/resources/extensions/gsd/uat-policy.ts +60 -15
- package/src/resources/extensions/gsd/unit-context-composer.ts +1 -1
- package/src/resources/extensions/gsd/unit-registry.ts +34 -4
- package/src/resources/extensions/gsd/verdict-parser.ts +1 -1
- package/src/resources/extensions/gsd/verification-verdict.ts +4 -2
- package/src/resources/extensions/gsd/workflow-event-ledger.ts +131 -0
- package/src/resources/extensions/gsd/workflow-event-vocabulary.ts +59 -0
- package/src/resources/extensions/gsd/workflow-events.ts +12 -20
- package/src/resources/extensions/gsd/workflow-mcp-auto-prep.ts +2 -0
- package/src/resources/extensions/gsd/workflow-mcp-readiness-cache.ts +150 -0
- package/src/resources/extensions/gsd/workflow-reconcile.ts +29 -62
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +3 -8
- package/src/resources/extensions/gsd/worktree-manager.ts +6 -1
- package/src/resources/extensions/gsd/worktree-safety.ts +41 -39
- package/src/resources/extensions/gsd/worktree.ts +7 -1
- package/src/resources/extensions/mcp-client/manager.ts +7 -1
- package/src/resources/extensions/shared/gsd-browser-cli.ts +23 -2
- package/src/resources/shared/gsd-browser-path-sync.ts +273 -0
- package/src/resources/shared/package-manager-detection.ts +1 -1
- package/src/resources/skills/create-skill/SKILL.md +3 -0
- package/src/resources/skills/create-skill/references/skill-structure.md +1 -0
- package/dist/resources/extensions/gsd/user-input-boundary.js +0 -218
- package/dist/resources/skills/gsd-browser/SKILL.md +0 -41
- package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +0 -173
- package/src/resources/extensions/gsd/user-input-boundary.ts +0 -216
- package/src/resources/skills/gsd-browser/SKILL.md +0 -41
- /package/dist/web/standalone/.next/static/{mU4QIDlpVHDdjDpeEKh5W → 2T9IOdiiM3o3gZ4UbPi8E}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{mU4QIDlpVHDdjDpeEKh5W → 2T9IOdiiM3o3gZ4UbPi8E}/_ssgManifest.js +0 -0
|
@@ -80,6 +80,20 @@ function createTempProject(): { basePath: string; planPath: string } {
|
|
|
80
80
|
return { basePath, planPath };
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
function writeProjectPreferences(basePath: string, yaml: string): void {
|
|
84
|
+
fs.writeFileSync(path.join(basePath, '.gsd', 'PREFERENCES.md'), `---\n${yaml}---\n`);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async function withWorkingDirectory<T>(cwd: string, action: () => Promise<T>): Promise<T> {
|
|
88
|
+
const previousCwd = process.cwd();
|
|
89
|
+
process.chdir(cwd);
|
|
90
|
+
try {
|
|
91
|
+
return await action();
|
|
92
|
+
} finally {
|
|
93
|
+
process.chdir(previousCwd);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
83
97
|
function makeValidParams() {
|
|
84
98
|
return {
|
|
85
99
|
taskId: 'T01',
|
|
@@ -104,6 +118,13 @@ function makeValidParams() {
|
|
|
104
118
|
};
|
|
105
119
|
}
|
|
106
120
|
|
|
121
|
+
function makeEscalationOptions() {
|
|
122
|
+
return [
|
|
123
|
+
{ id: 'continue', label: 'Continue', tradeoffs: 'Keeps execution moving with the default path.' },
|
|
124
|
+
{ id: 'pause', label: 'Pause', tradeoffs: 'Stops execution until the blocker is reviewed.' },
|
|
125
|
+
];
|
|
126
|
+
}
|
|
127
|
+
|
|
107
128
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
108
129
|
// complete-task: Fresh DB is migrated to the current schema version
|
|
109
130
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -359,6 +380,105 @@ console.log('\n=== complete-task: handler happy path ===');
|
|
|
359
380
|
cleanup(dbPath);
|
|
360
381
|
}
|
|
361
382
|
|
|
383
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
384
|
+
// complete-task: hard-blocker escalation with mid-execution escalation disabled
|
|
385
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
386
|
+
|
|
387
|
+
console.log('\n=== complete-task: disabled hard-blocker escalation rolls back completion ===');
|
|
388
|
+
{
|
|
389
|
+
const dbPath = tempDbPath();
|
|
390
|
+
openDatabase(dbPath);
|
|
391
|
+
|
|
392
|
+
const { basePath } = createTempProject();
|
|
393
|
+
writeProjectPreferences(basePath, 'phases:\n mid_execution_escalation: false\n');
|
|
394
|
+
|
|
395
|
+
insertMilestone({ id: 'M001', title: 'Test Milestone' });
|
|
396
|
+
insertSlice({ id: 'S01', milestoneId: 'M001', title: 'Test Slice' });
|
|
397
|
+
|
|
398
|
+
const params = {
|
|
399
|
+
...makeValidParams(),
|
|
400
|
+
blockerDiscovered: true,
|
|
401
|
+
escalation: {
|
|
402
|
+
question: 'Should execution pause for the hard blocker?',
|
|
403
|
+
options: makeEscalationOptions(),
|
|
404
|
+
recommendation: 'pause',
|
|
405
|
+
recommendationRationale: 'The blocker should not be silently advanced.',
|
|
406
|
+
continueWithDefault: false,
|
|
407
|
+
},
|
|
408
|
+
};
|
|
409
|
+
|
|
410
|
+
const result = await withWorkingDirectory(basePath, () => handleCompleteTask(params, basePath));
|
|
411
|
+
|
|
412
|
+
assertTrue('error' in result, 'hard-blocker escalation should fail when escalation handling is disabled');
|
|
413
|
+
if ('error' in result) {
|
|
414
|
+
assertMatch(result.error, /hard-blocker escalation/, 'error should mention hard-blocker escalation');
|
|
415
|
+
assertMatch(result.error, /mid_execution_escalation is disabled/, 'error should mention disabled preference');
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
const task = getTask('M001', 'S01', 'T01');
|
|
419
|
+
assertTrue(task !== null, 'task row should remain after rollback');
|
|
420
|
+
assertEq(task!.status, 'pending', 'task status should be rolled back to pending');
|
|
421
|
+
assertEq(task!.blocker_discovered, true, 'blocker flag should remain recorded for visibility');
|
|
422
|
+
assertEq(task!.escalation_pending, 0, 'disabled preference should not create a pending escalation flag');
|
|
423
|
+
assertEq(task!.escalation_awaiting_review, 0, 'disabled preference should not create an awaiting-review flag');
|
|
424
|
+
|
|
425
|
+
const adapter = _getAdapter()!;
|
|
426
|
+
const evRows = adapter.prepare(
|
|
427
|
+
"SELECT * FROM verification_evidence WHERE task_id = 'T01' AND slice_id = 'S01' AND milestone_id = 'M001'"
|
|
428
|
+
).all();
|
|
429
|
+
assertEq(evRows.length, 0, 'verification evidence should be deleted when completion rolls back');
|
|
430
|
+
|
|
431
|
+
cleanupDir(basePath);
|
|
432
|
+
cleanup(dbPath);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
436
|
+
// complete-task: soft escalation with mid-execution escalation disabled
|
|
437
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
438
|
+
|
|
439
|
+
console.log('\n=== complete-task: disabled soft escalation still completes ===');
|
|
440
|
+
{
|
|
441
|
+
const dbPath = tempDbPath();
|
|
442
|
+
openDatabase(dbPath);
|
|
443
|
+
|
|
444
|
+
const { basePath } = createTempProject();
|
|
445
|
+
writeProjectPreferences(basePath, 'phases:\n mid_execution_escalation: false\n');
|
|
446
|
+
|
|
447
|
+
insertMilestone({ id: 'M001', title: 'Test Milestone' });
|
|
448
|
+
insertSlice({ id: 'S01', milestoneId: 'M001', title: 'Test Slice' });
|
|
449
|
+
|
|
450
|
+
const params = {
|
|
451
|
+
...makeValidParams(),
|
|
452
|
+
escalation: {
|
|
453
|
+
question: 'Should execution continue with the default?',
|
|
454
|
+
options: makeEscalationOptions(),
|
|
455
|
+
recommendation: 'continue',
|
|
456
|
+
recommendationRationale: 'The default path is safe enough to continue.',
|
|
457
|
+
continueWithDefault: true,
|
|
458
|
+
},
|
|
459
|
+
};
|
|
460
|
+
|
|
461
|
+
const result = await withWorkingDirectory(basePath, () => handleCompleteTask(params, basePath));
|
|
462
|
+
|
|
463
|
+
assertTrue(!('error' in result), 'soft escalation should still complete when escalation handling is disabled');
|
|
464
|
+
if (!('error' in result)) {
|
|
465
|
+
assertTrue(!result.escalation, 'disabled preference should not return escalation metadata');
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
const task = getTask('M001', 'S01', 'T01');
|
|
469
|
+
assertTrue(task !== null, 'task row should exist');
|
|
470
|
+
assertEq(task!.status, 'complete', 'soft escalation should leave task complete');
|
|
471
|
+
|
|
472
|
+
const adapter = _getAdapter()!;
|
|
473
|
+
const evRows = adapter.prepare(
|
|
474
|
+
"SELECT * FROM verification_evidence WHERE task_id = 'T01' AND slice_id = 'S01' AND milestone_id = 'M001'"
|
|
475
|
+
).all();
|
|
476
|
+
assertEq(evRows.length, 1, 'verification evidence should remain for soft escalation completion');
|
|
477
|
+
|
|
478
|
+
cleanupDir(basePath);
|
|
479
|
+
cleanup(dbPath);
|
|
480
|
+
}
|
|
481
|
+
|
|
362
482
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
363
483
|
// complete-task: Handler validation errors
|
|
364
484
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -414,6 +534,9 @@ console.log('\n=== complete-task: handler idempotency ===');
|
|
|
414
534
|
// First call should succeed
|
|
415
535
|
const r1 = await handleCompleteTask(params, basePath);
|
|
416
536
|
assertTrue(!('error' in r1), 'first call should succeed');
|
|
537
|
+
if ('error' in r1) {
|
|
538
|
+
throw new Error(r1.error);
|
|
539
|
+
}
|
|
417
540
|
|
|
418
541
|
// Verify complete-task did not duplicate T01. S01-PLAN.md is a projection,
|
|
419
542
|
// so the remaining plan task is not imported implicitly.
|
|
@@ -421,16 +544,29 @@ console.log('\n=== complete-task: handler idempotency ===');
|
|
|
421
544
|
assertEq(tasks.length, 1, 'should only have the completed DB task after first call');
|
|
422
545
|
assertEq(tasks.filter(t => t.id === 'T01').length, 1, 'should have exactly one T01 row after first call');
|
|
423
546
|
|
|
424
|
-
//
|
|
547
|
+
// If the DB row is complete but the projection was lost, the duplicate call
|
|
548
|
+
// should repair the missing summary from full_summary_md instead of forcing a
|
|
549
|
+
// reopen/re-complete loop.
|
|
550
|
+
fs.unlinkSync(r1.summaryPath);
|
|
551
|
+
assertTrue(!fs.existsSync(r1.summaryPath), 'fixture should remove the task summary before repair');
|
|
425
552
|
const r2 = await handleCompleteTask(params, basePath);
|
|
426
|
-
assertTrue('error' in r2, 'second call should
|
|
553
|
+
assertTrue(!('error' in r2), 'second call should repair missing summary for DB-complete task');
|
|
427
554
|
if ('error' in r2) {
|
|
428
|
-
|
|
555
|
+
throw new Error(r2.error);
|
|
556
|
+
}
|
|
557
|
+
assertTrue(fs.existsSync(r2.summaryPath), 'missing summary should be restored on disk');
|
|
558
|
+
assertEq(r2.duplicate, true, 'repair should be reported as a duplicate/no-op state mutation');
|
|
559
|
+
|
|
560
|
+
// Third call with the summary present — state machine guard rejects (task is already complete)
|
|
561
|
+
const r3 = await handleCompleteTask(params, basePath);
|
|
562
|
+
assertTrue('error' in r3, 'third call should return error (task already complete)');
|
|
563
|
+
if ('error' in r3) {
|
|
564
|
+
assertMatch(r3.error, /already complete/, 'error should mention already complete');
|
|
429
565
|
}
|
|
430
566
|
|
|
431
|
-
// Still no duplicate rows from the rejected
|
|
567
|
+
// Still no duplicate rows from the repair or rejected third call.
|
|
432
568
|
const tasksAfter = getSliceTasks('M001', 'S01');
|
|
433
|
-
assertEq(tasksAfter.length, 1, 'should still only have T01 after rejected
|
|
569
|
+
assertEq(tasksAfter.length, 1, 'should still only have T01 after duplicate repair and rejected third call');
|
|
434
570
|
assertEq(tasksAfter.filter(t => t.id === 'T01').length, 1, 'should still have exactly one T01 row');
|
|
435
571
|
|
|
436
572
|
cleanupDir(basePath);
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
import test from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
type AnswerOutcome,
|
|
6
|
+
classifyQuestion,
|
|
7
|
+
evaluateAnswer,
|
|
8
|
+
evaluateAskUserQuestionsRound,
|
|
9
|
+
failPolicyForKind,
|
|
10
|
+
formatUnansweredConsentQuestionMessage,
|
|
11
|
+
isAwaitingUserInput,
|
|
12
|
+
lastAssistantText,
|
|
13
|
+
messageHasPendingAskUserQuestionsTool,
|
|
14
|
+
shouldPauseForQuestion,
|
|
15
|
+
} from "../consent-question.ts";
|
|
16
|
+
|
|
17
|
+
const GATE_OPTIONS = [
|
|
18
|
+
{ label: "Yes, you got it (Recommended)" },
|
|
19
|
+
{ label: "Needs adjustment" },
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
const CONSENT_OPTIONS = [
|
|
23
|
+
{ label: "Option A (Recommended)" },
|
|
24
|
+
{ label: "Option B" },
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
function assistantMessage(text: string): unknown {
|
|
28
|
+
return { role: "assistant", content: [{ type: "text", text }] };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// ── Classification ──────────────────────────────────────────────────────────
|
|
32
|
+
|
|
33
|
+
test("classifyQuestion: gate ids, consent defaults, prose kinds", () => {
|
|
34
|
+
assert.deepEqual(
|
|
35
|
+
classifyQuestion({ id: "depth_verification_M001_confirm" }),
|
|
36
|
+
{ kind: "gate", gateSubKind: "approval" },
|
|
37
|
+
);
|
|
38
|
+
assert.deepEqual(
|
|
39
|
+
classifyQuestion({ id: "depth_verification" }),
|
|
40
|
+
{ kind: "gate", gateSubKind: "depth-verification" },
|
|
41
|
+
);
|
|
42
|
+
assert.deepEqual(
|
|
43
|
+
classifyQuestion({ id: "destructive_confirm_rm" }),
|
|
44
|
+
{ kind: "gate", gateSubKind: "destructive-confirm" },
|
|
45
|
+
);
|
|
46
|
+
// Any other structured question is a real elicitation → consent, fail-closed.
|
|
47
|
+
assert.equal(classifyQuestion({ id: "m004_shape", options: CONSENT_OPTIONS }).kind, "consent");
|
|
48
|
+
assert.equal(classifyQuestion({ id: "free_text_q" }).kind, "consent");
|
|
49
|
+
// Prose classification.
|
|
50
|
+
assert.equal(classifyQuestion({ text: "Should I proceed with the write?" }).kind, "consent");
|
|
51
|
+
assert.equal(
|
|
52
|
+
classifyQuestion({ text: "Want me to research this or skip?", unitType: "research-decision" }).kind,
|
|
53
|
+
"decision",
|
|
54
|
+
);
|
|
55
|
+
assert.equal(classifyQuestion({ text: "Here is the summary of changes." }).kind, "informational");
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test("failPolicyForKind: only informational is fail-open", () => {
|
|
59
|
+
assert.equal(failPolicyForKind("gate"), "closed");
|
|
60
|
+
assert.equal(failPolicyForKind("consent"), "closed");
|
|
61
|
+
assert.equal(failPolicyForKind("decision"), "closed");
|
|
62
|
+
assert.equal(failPolicyForKind("informational"), "open");
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// ── Policy table: (kind × answer shape) → outcome ───────────────────────────
|
|
66
|
+
|
|
67
|
+
type Row = {
|
|
68
|
+
name: string;
|
|
69
|
+
question: { id: string; options?: Array<{ label?: string }> };
|
|
70
|
+
details: Parameters<typeof evaluateAnswer>[0]["details"];
|
|
71
|
+
expected: AnswerOutcome;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const gateQ = { id: "depth_verification_M001_confirm", options: GATE_OPTIONS };
|
|
75
|
+
const consentQ = { id: "boundary_choice", options: CONSENT_OPTIONS };
|
|
76
|
+
|
|
77
|
+
const POLICY_TABLE: Row[] = [
|
|
78
|
+
// gate
|
|
79
|
+
{ name: "gate × confirm selected → verified", question: gateQ, details: { response: { answers: { [gateQ.id]: { selected: "Yes, you got it (Recommended)" } } } }, expected: "verified" },
|
|
80
|
+
{ name: "gate × decline selected → declined", question: gateQ, details: { response: { answers: { [gateQ.id]: { selected: "Needs adjustment" } } } }, expected: "declined" },
|
|
81
|
+
{ name: "gate × empty selected → waiting", question: gateQ, details: { response: { answers: { [gateQ.id]: { selected: "" } } } }, expected: "waiting" },
|
|
82
|
+
{ name: "gate × empty selected array → waiting", question: gateQ, details: { response: { answers: { [gateQ.id]: { selected: [] } } } }, expected: "waiting" },
|
|
83
|
+
{ name: "gate × missing response → waiting", question: gateQ, details: {}, expected: "waiting" },
|
|
84
|
+
{ name: "gate × notes-only → waiting (notes never satisfy a gate)", question: gateQ, details: { response: { answers: { [gateQ.id]: { notes: "looks fine" } } } }, expected: "waiting" },
|
|
85
|
+
{ name: "gate × cancelled → cancelled", question: gateQ, details: { cancelled: true, response: null }, expected: "cancelled" },
|
|
86
|
+
// consent
|
|
87
|
+
{ name: "consent × valid selected → answered", question: consentQ, details: { response: { answers: { [consentQ.id]: { selected: "Option B" } } } }, expected: "answered" },
|
|
88
|
+
{ name: "consent × empty selected → waiting (#528)", question: consentQ, details: { response: { answers: { [consentQ.id]: { selected: "" } } } }, expected: "waiting" },
|
|
89
|
+
{ name: "consent × missing answer → waiting", question: consentQ, details: { response: { answers: {} } }, expected: "waiting" },
|
|
90
|
+
{ name: "consent × missing response → waiting", question: consentQ, details: {}, expected: "waiting" },
|
|
91
|
+
{ name: "consent × notes-only → answered (a real user utterance)", question: consentQ, details: { response: { answers: { [consentQ.id]: { notes: "neither — keep it simple" } } } }, expected: "answered" },
|
|
92
|
+
{ name: "consent × cancelled → cancelled", question: consentQ, details: { cancelled: true, response: null }, expected: "cancelled" },
|
|
93
|
+
];
|
|
94
|
+
|
|
95
|
+
for (const row of POLICY_TABLE) {
|
|
96
|
+
test(`policy table: ${row.name}`, () => {
|
|
97
|
+
assert.equal(evaluateAnswer({ question: row.question, details: row.details }), row.expected);
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// ── Round evaluation ────────────────────────────────────────────────────────
|
|
102
|
+
|
|
103
|
+
test("evaluateAskUserQuestionsRound: most blocking outcome wins", () => {
|
|
104
|
+
const details = {
|
|
105
|
+
response: {
|
|
106
|
+
answers: {
|
|
107
|
+
[consentQ.id]: { selected: "Option A (Recommended)" },
|
|
108
|
+
second: { selected: "" },
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
assert.equal(
|
|
113
|
+
evaluateAskUserQuestionsRound([consentQ, { id: "second", options: CONSENT_OPTIONS }], details),
|
|
114
|
+
"waiting",
|
|
115
|
+
);
|
|
116
|
+
assert.equal(evaluateAskUserQuestionsRound([consentQ], { cancelled: true }), "cancelled");
|
|
117
|
+
assert.equal(
|
|
118
|
+
evaluateAskUserQuestionsRound([consentQ], {
|
|
119
|
+
response: { answers: { [consentQ.id]: { selected: "Option A (Recommended)" } } },
|
|
120
|
+
}),
|
|
121
|
+
"answered",
|
|
122
|
+
);
|
|
123
|
+
// Empty round with no response is a no-op for callers.
|
|
124
|
+
assert.equal(evaluateAskUserQuestionsRound([], {}), "answered");
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// ── Regression: #528 empty selected on a consent question never answers ─────
|
|
128
|
+
|
|
129
|
+
test("#528: empty selected on a NON-gate question is waiting, not answered", () => {
|
|
130
|
+
const outcome = evaluateAskUserQuestionsRound(
|
|
131
|
+
[{ id: "scope_check", options: CONSENT_OPTIONS }],
|
|
132
|
+
{ response: { answers: { scope_check: { selected: "" } } } },
|
|
133
|
+
);
|
|
134
|
+
assert.equal(outcome, "waiting");
|
|
135
|
+
const message = formatUnansweredConsentQuestionMessage([{ id: "scope_check" }]);
|
|
136
|
+
assert.match(message, /scope_check/);
|
|
137
|
+
assert.match(message, /not consent/i);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
// ── Regression: #682 pause promotion outside the old unit-type allowlist ────
|
|
141
|
+
|
|
142
|
+
test("#682: consent question in a non-allowlisted unit type pauses", () => {
|
|
143
|
+
const messages = [assistantMessage("The slice is staged. Ready to proceed with the merge?")];
|
|
144
|
+
assert.equal(shouldPauseForQuestion("execute-task", messages), true);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
test("#682: consent question in interactive mode (no unit type) pauses", () => {
|
|
148
|
+
const messages = [assistantMessage("Does this capture your intent correctly?")];
|
|
149
|
+
assert.equal(shouldPauseForQuestion(undefined, messages), true);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
test("#682: cancellation marker pauses regardless of unit type", () => {
|
|
153
|
+
const messages = [assistantMessage("ask_user_questions was cancelled before receiving a response")];
|
|
154
|
+
assert.equal(shouldPauseForQuestion(undefined, messages), true);
|
|
155
|
+
assert.equal(shouldPauseForQuestion("execute-task", messages), true);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
test("shouldPauseForQuestion: informational prose never pauses", () => {
|
|
159
|
+
const messages = [assistantMessage("All tests pass. Moving on to the next task.")];
|
|
160
|
+
assert.equal(shouldPauseForQuestion(undefined, messages), false);
|
|
161
|
+
assert.equal(shouldPauseForQuestion("discuss-project", messages), false);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
test("shouldPauseForQuestion: plain non-approval question does not pause", () => {
|
|
165
|
+
// Generic questions (no approval/consent language) stay informational —
|
|
166
|
+
// matches the historical contract in deep-project-auto-loop tests.
|
|
167
|
+
const messages = [assistantMessage("Which file did you mean?")];
|
|
168
|
+
assert.equal(shouldPauseForQuestion("discuss-project", messages), false);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
test("shouldPauseForQuestion: explicit waiting-for-approval phrase pauses without a question mark", () => {
|
|
172
|
+
// The streaming pre-filter (no "?" → bail) must not skip the explicit
|
|
173
|
+
// wait-phrase boundary, which carries no question mark.
|
|
174
|
+
const messages = [assistantMessage("I am waiting for your approval before writing the file.")];
|
|
175
|
+
assert.equal(shouldPauseForQuestion(undefined, messages), true);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
// ── Message-text extraction (merged from user-input-boundary tests) ─────────
|
|
179
|
+
|
|
180
|
+
test("lastAssistantText extracts the latest assistant text block content", () => {
|
|
181
|
+
assert.equal(
|
|
182
|
+
lastAssistantText([
|
|
183
|
+
{ role: "assistant", content: "Older message" },
|
|
184
|
+
{
|
|
185
|
+
role: "assistant",
|
|
186
|
+
content: [
|
|
187
|
+
{ type: "text", text: "First line" },
|
|
188
|
+
{ type: "text", text: "Second line" },
|
|
189
|
+
],
|
|
190
|
+
},
|
|
191
|
+
]),
|
|
192
|
+
"First line\nSecond line",
|
|
193
|
+
);
|
|
194
|
+
assert.equal(lastAssistantText(null), "");
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
test("lastAssistantText includes thinking blocks so rate-limit notices are not dropped", () => {
|
|
198
|
+
// Turn with only a thinking block (no text block) — must not return ""
|
|
199
|
+
const result = lastAssistantText([
|
|
200
|
+
{
|
|
201
|
+
role: "assistant",
|
|
202
|
+
content: [
|
|
203
|
+
{ type: "thinking", thinking: "You've hit your limit · resets in 2h" },
|
|
204
|
+
],
|
|
205
|
+
},
|
|
206
|
+
]);
|
|
207
|
+
assert.ok(result.includes("You've hit your limit"), `expected rate-limit text, got: ${JSON.stringify(result)}`);
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
// ── Awaiting-input boundaries (merged from user-input-boundary tests) ───────
|
|
211
|
+
|
|
212
|
+
test("isAwaitingUserInput does not trigger on thinking-block question marks", () => {
|
|
213
|
+
// A thinking block with a question mark must NOT pause auto-mode —
|
|
214
|
+
// it's internal reasoning, not a user-visible prompt.
|
|
215
|
+
const messages = [
|
|
216
|
+
{
|
|
217
|
+
role: "assistant",
|
|
218
|
+
content: [
|
|
219
|
+
{ type: "thinking", thinking: "Should I skip research? Let me check the config." },
|
|
220
|
+
],
|
|
221
|
+
},
|
|
222
|
+
];
|
|
223
|
+
assert.equal(isAwaitingUserInput(messages), false);
|
|
224
|
+
assert.equal(shouldPauseForQuestion("discuss-project", messages), false);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
test("isAwaitingUserInput does not trigger on thinking-block approval phrases", () => {
|
|
228
|
+
// A thinking block with approval phrases must NOT pause auto-mode.
|
|
229
|
+
const messages = [
|
|
230
|
+
{
|
|
231
|
+
role: "assistant",
|
|
232
|
+
content: [
|
|
233
|
+
{ type: "thinking", thinking: "The user confirmed and approved the plan. Should I proceed?" },
|
|
234
|
+
],
|
|
235
|
+
},
|
|
236
|
+
];
|
|
237
|
+
assert.equal(isAwaitingUserInput(messages), false);
|
|
238
|
+
assert.equal(shouldPauseForQuestion("discuss-requirements", messages), false);
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
test("isAwaitingUserInput treats plain-text next steps menus as waiting for the user (#454)", () => {
|
|
242
|
+
const messages = [
|
|
243
|
+
{
|
|
244
|
+
role: "assistant",
|
|
245
|
+
content: [
|
|
246
|
+
"Next steps:",
|
|
247
|
+
"1. Walk through the runtime placement check above.",
|
|
248
|
+
"2. Build a release once you're satisfied.",
|
|
249
|
+
"3. Other.",
|
|
250
|
+
].join("\n"),
|
|
251
|
+
},
|
|
252
|
+
];
|
|
253
|
+
assert.equal(isAwaitingUserInput(messages), true);
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
test("isAwaitingUserInput still triggers on text-block question marks when thinking is also present", () => {
|
|
257
|
+
// When thinking + text are both present and the text asks a question, it should still pause.
|
|
258
|
+
const messages = [
|
|
259
|
+
{
|
|
260
|
+
role: "assistant",
|
|
261
|
+
content: [
|
|
262
|
+
{ type: "thinking", thinking: "Internal reasoning without questions." },
|
|
263
|
+
{ type: "text", text: "Does this look correct?" },
|
|
264
|
+
],
|
|
265
|
+
},
|
|
266
|
+
];
|
|
267
|
+
assert.equal(isAwaitingUserInput(messages), true);
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
// ── In-flight ask_user_questions detection (merged from user-input-boundary) ─
|
|
271
|
+
|
|
272
|
+
test("messageHasPendingAskUserQuestionsTool detects in-flight structured question tools", () => {
|
|
273
|
+
// state: "running" with no externalResult → still in-flight
|
|
274
|
+
assert.equal(
|
|
275
|
+
messageHasPendingAskUserQuestionsTool({
|
|
276
|
+
role: "assistant",
|
|
277
|
+
content: [
|
|
278
|
+
{ type: "text", text: "Which direction?" },
|
|
279
|
+
{ type: "toolCall", name: "mcp__gsd-workflow__ask_user_questions", state: "running" },
|
|
280
|
+
],
|
|
281
|
+
}),
|
|
282
|
+
true,
|
|
283
|
+
);
|
|
284
|
+
|
|
285
|
+
// no state, no externalResult — streaming block that hasn't completed yet
|
|
286
|
+
assert.equal(
|
|
287
|
+
messageHasPendingAskUserQuestionsTool({
|
|
288
|
+
role: "assistant",
|
|
289
|
+
content: [
|
|
290
|
+
{ type: "toolCall", name: "ask_user_questions" },
|
|
291
|
+
],
|
|
292
|
+
}),
|
|
293
|
+
true,
|
|
294
|
+
);
|
|
295
|
+
|
|
296
|
+
// state: "completed" — legacy state-based completion
|
|
297
|
+
assert.equal(
|
|
298
|
+
messageHasPendingAskUserQuestionsTool({
|
|
299
|
+
role: "assistant",
|
|
300
|
+
content: [
|
|
301
|
+
{ type: "toolCall", name: "ask_user_questions", state: "completed" },
|
|
302
|
+
],
|
|
303
|
+
}),
|
|
304
|
+
false,
|
|
305
|
+
);
|
|
306
|
+
|
|
307
|
+
// externalResult present — Claude Code signals completion via externalResult, not state
|
|
308
|
+
assert.equal(
|
|
309
|
+
messageHasPendingAskUserQuestionsTool({
|
|
310
|
+
role: "assistant",
|
|
311
|
+
content: [
|
|
312
|
+
{ type: "toolCall", name: "ask_user_questions", externalResult: { content: [], isError: false } },
|
|
313
|
+
],
|
|
314
|
+
}),
|
|
315
|
+
false,
|
|
316
|
+
);
|
|
317
|
+
assert.equal(
|
|
318
|
+
messageHasPendingAskUserQuestionsTool({
|
|
319
|
+
role: "assistant",
|
|
320
|
+
content: [
|
|
321
|
+
{
|
|
322
|
+
type: "toolCall",
|
|
323
|
+
name: "ask_user_questions",
|
|
324
|
+
externalResult: { content: [{ type: "text", text: "answer" }], isError: false },
|
|
325
|
+
},
|
|
326
|
+
],
|
|
327
|
+
}),
|
|
328
|
+
false,
|
|
329
|
+
);
|
|
330
|
+
|
|
331
|
+
// serverToolUse shape (claude-code-cli MCP path) — no externalResult → in-flight
|
|
332
|
+
assert.equal(
|
|
333
|
+
messageHasPendingAskUserQuestionsTool({
|
|
334
|
+
role: "assistant",
|
|
335
|
+
content: [
|
|
336
|
+
{ type: "serverToolUse", name: "mcp__gsd-workflow__ask_user_questions" },
|
|
337
|
+
],
|
|
338
|
+
}),
|
|
339
|
+
true,
|
|
340
|
+
);
|
|
341
|
+
// serverToolUse shape — externalResult present → completed
|
|
342
|
+
assert.equal(
|
|
343
|
+
messageHasPendingAskUserQuestionsTool({
|
|
344
|
+
role: "assistant",
|
|
345
|
+
content: [
|
|
346
|
+
{ type: "serverToolUse", name: "ask_user_questions", externalResult: { content: [], isError: false } },
|
|
347
|
+
],
|
|
348
|
+
}),
|
|
349
|
+
false,
|
|
350
|
+
);
|
|
351
|
+
});
|
|
@@ -17,11 +17,13 @@ function makeSession(activeRunDir: string): {
|
|
|
17
17
|
activeRunDir: string;
|
|
18
18
|
basePath: string;
|
|
19
19
|
verificationRetryCount: Map<string, number>;
|
|
20
|
+
exhaustedVerificationUnits: Set<string>;
|
|
20
21
|
} {
|
|
21
22
|
return {
|
|
22
23
|
activeRunDir,
|
|
23
24
|
basePath: activeRunDir,
|
|
24
25
|
verificationRetryCount: new Map<string, number>(),
|
|
26
|
+
exhaustedVerificationUnits: new Set<string>(),
|
|
25
27
|
};
|
|
26
28
|
}
|
|
27
29
|
|
|
@@ -137,3 +139,68 @@ test("saveCustomVerifyRetryCounts deletes empty retry files and ignores missing
|
|
|
137
139
|
rmSync(dir, { recursive: true, force: true });
|
|
138
140
|
}
|
|
139
141
|
});
|
|
142
|
+
|
|
143
|
+
test("saveCustomVerifyRetryCounts persists exhaustedVerificationUnits and hydrateCustomVerifyRetryCounts restores them", () => {
|
|
144
|
+
const dir = mkdtempSync(join(tmpdir(), "gsd-verify-retries-"));
|
|
145
|
+
try {
|
|
146
|
+
const session = makeSession(dir);
|
|
147
|
+
session.exhaustedVerificationUnits.add("execute-task:M001/S001/T001");
|
|
148
|
+
session.exhaustedVerificationUnits.add("execute-task:M001/S001/T002");
|
|
149
|
+
|
|
150
|
+
saveCustomVerifyRetryCounts(session, {
|
|
151
|
+
logFailure: () => assert.fail("logFailure should not be called"),
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
const session2 = makeSession(dir);
|
|
155
|
+
hydrateCustomVerifyRetryCounts(session2, {
|
|
156
|
+
logFailure: () => assert.fail("logFailure should not be called"),
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
assert.deepEqual(
|
|
160
|
+
[...session2.exhaustedVerificationUnits].sort(),
|
|
161
|
+
["execute-task:M001/S001/T001", "execute-task:M001/S001/T002"],
|
|
162
|
+
);
|
|
163
|
+
assert.equal(session2.verificationRetryCount.size, 0);
|
|
164
|
+
} finally {
|
|
165
|
+
rmSync(dir, { recursive: true, force: true });
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
test("saveCustomVerifyRetryCounts keeps file when only exhaustedVerificationUnits is non-empty", () => {
|
|
170
|
+
const dir = mkdtempSync(join(tmpdir(), "gsd-verify-retries-"));
|
|
171
|
+
try {
|
|
172
|
+
const session = makeSession(dir);
|
|
173
|
+
session.exhaustedVerificationUnits.add("execute-task:M001/S001/T001");
|
|
174
|
+
|
|
175
|
+
saveCustomVerifyRetryCounts(session, {
|
|
176
|
+
logFailure: () => assert.fail("logFailure should not be called"),
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
const saved = JSON.parse(readFileSync(customVerifyRetryStatePath(session), "utf-8"));
|
|
180
|
+
assert.deepEqual(saved.exhausted, ["execute-task:M001/S001/T001"]);
|
|
181
|
+
} finally {
|
|
182
|
+
rmSync(dir, { recursive: true, force: true });
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
test("hydrateCustomVerifyRetryCounts skips hydration when exhaustedVerificationUnits is already populated", () => {
|
|
187
|
+
const dir = mkdtempSync(join(tmpdir(), "gsd-verify-retries-"));
|
|
188
|
+
try {
|
|
189
|
+
const session = makeSession(dir);
|
|
190
|
+
session.exhaustedVerificationUnits.add("pre-existing:key");
|
|
191
|
+
mkdirSync(join(dir, "runtime"));
|
|
192
|
+
writeFileSync(customVerifyRetryStatePath(session), JSON.stringify({
|
|
193
|
+
counts: { "execute-task/M001/S001/T001": 2 },
|
|
194
|
+
exhausted: ["execute-task:M001/S001/T002"],
|
|
195
|
+
}));
|
|
196
|
+
|
|
197
|
+
hydrateCustomVerifyRetryCounts(session, {
|
|
198
|
+
logFailure: () => assert.fail("logFailure should not be called"),
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
assert.deepEqual([...session.exhaustedVerificationUnits], ["pre-existing:key"]);
|
|
202
|
+
assert.equal(session.verificationRetryCount.size, 0);
|
|
203
|
+
} finally {
|
|
204
|
+
rmSync(dir, { recursive: true, force: true });
|
|
205
|
+
}
|
|
206
|
+
});
|