@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
|
@@ -42,6 +42,7 @@ import {
|
|
|
42
42
|
type ReconciliationDeps,
|
|
43
43
|
} from "../state-reconciliation.ts";
|
|
44
44
|
import { classifyFailure } from "../recovery-classification.ts";
|
|
45
|
+
import { handlerPhaseIndex, RECONCILIATION_REPAIR_PHASES } from "../state-reconciliation/registry.ts";
|
|
45
46
|
import { staleRenderHandler } from "../state-reconciliation/drift/stale-render.ts";
|
|
46
47
|
import type { GSDState } from "../types.ts";
|
|
47
48
|
|
|
@@ -160,6 +161,29 @@ test("ADR-017 (#5700): repair failure throws ReconciliationFailedError with shap
|
|
|
160
161
|
);
|
|
161
162
|
});
|
|
162
163
|
|
|
164
|
+
test("ADR-017 (#5700): custom registry handlers outside built-in phases are repaired", async () => {
|
|
165
|
+
const drift = { kind: "custom-drift", id: "D001" } as unknown as DriftRecord;
|
|
166
|
+
let repaired = false;
|
|
167
|
+
const handler = {
|
|
168
|
+
kind: "custom-drift",
|
|
169
|
+
detect: () => (repaired ? [] : [drift]),
|
|
170
|
+
repair: () => {
|
|
171
|
+
repaired = true;
|
|
172
|
+
},
|
|
173
|
+
} as unknown as DriftHandler;
|
|
174
|
+
|
|
175
|
+
const result = await reconcileBeforeDispatch("/project", {
|
|
176
|
+
invalidateStateCache: () => {},
|
|
177
|
+
deriveState: async () => makeState(),
|
|
178
|
+
registry: [handler],
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
assert.equal(result.ok, true);
|
|
182
|
+
assert.equal(repaired, true);
|
|
183
|
+
assert.equal(result.repaired.length, 1);
|
|
184
|
+
assert.equal(result.repaired[0]?.kind, "custom-drift");
|
|
185
|
+
});
|
|
186
|
+
|
|
163
187
|
test("ADR-017 (#5700): a detector failure degrades to a blocker without aborting other handlers", async () => {
|
|
164
188
|
// A single detector throwing (e.g. a transient file read error) must NOT
|
|
165
189
|
// abort the whole cycle and hide every later handler's drift. It is collected
|
|
@@ -772,6 +796,51 @@ test("#1003: stale-render plan repair switches back from an open wrong DB", asyn
|
|
|
772
796
|
assert.equal(getSliceTasks("M001", "S01").length, 1, "repair should leave the project DB active");
|
|
773
797
|
});
|
|
774
798
|
|
|
799
|
+
test("#1034: validation-blocked milestone summary drift returns blocker instead of exhausting repair passes", async () => {
|
|
800
|
+
const drift: Extract<DriftRecord, { kind: "stale-render" }> = {
|
|
801
|
+
kind: "stale-render",
|
|
802
|
+
renderPath: "/repo/.gsd/milestones/M001/M001-SUMMARY.md",
|
|
803
|
+
reason: "M001 is complete with summary in DB but SUMMARY.md missing on disk",
|
|
804
|
+
};
|
|
805
|
+
let repairCalled = false;
|
|
806
|
+
const handler: DriftHandler<Extract<DriftRecord, { kind: "stale-render" }>> = {
|
|
807
|
+
kind: "stale-render",
|
|
808
|
+
detect: () => [drift],
|
|
809
|
+
blocker: staleRenderHandler.blocker!,
|
|
810
|
+
repair: () => {
|
|
811
|
+
repairCalled = true;
|
|
812
|
+
},
|
|
813
|
+
};
|
|
814
|
+
|
|
815
|
+
const validationBlocker = [
|
|
816
|
+
"Milestone M001 is blocked because milestone validation returned needs-attention.",
|
|
817
|
+
"Fix options:",
|
|
818
|
+
"1. Review the validation details: `/gsd status`",
|
|
819
|
+
].join("\n");
|
|
820
|
+
|
|
821
|
+
const result = await reconcileBeforeDispatch("/repo", {
|
|
822
|
+
invalidateStateCache: () => {},
|
|
823
|
+
deriveState: async () =>
|
|
824
|
+
makeState({
|
|
825
|
+
phase: "blocked",
|
|
826
|
+
blockers: [validationBlocker],
|
|
827
|
+
nextAction: "Resolve M001 validation attention before proceeding.",
|
|
828
|
+
}),
|
|
829
|
+
registry: [handler],
|
|
830
|
+
});
|
|
831
|
+
|
|
832
|
+
assert.equal(result.ok, true);
|
|
833
|
+
assert.equal(repairCalled, false, "validation-blocked milestone summary drift should not attempt repair");
|
|
834
|
+
assert.ok(
|
|
835
|
+
result.blockers.some((blocker) => blocker.includes("milestone validation returned needs-attention")),
|
|
836
|
+
"validation blocker should be returned to the caller",
|
|
837
|
+
);
|
|
838
|
+
assert.ok(
|
|
839
|
+
result.blockers.some((blocker) => blocker.includes("Stale milestone summary render")),
|
|
840
|
+
"stale-render blocker should explain why repair did not run",
|
|
841
|
+
);
|
|
842
|
+
});
|
|
843
|
+
|
|
775
844
|
test("ADR-017 (#5702): stale-render detector reason strings match repair contract", (t) => {
|
|
776
845
|
t.skip("TODO(flat-phase): stale-render detection temporarily disabled during layout transition"); return;
|
|
777
846
|
const base = mkdtempSync(join(tmpdir(), "gsd-adr017-render-reasons-"));
|
|
@@ -1887,3 +1956,49 @@ test("ADR-017 (#5700): cascading drift triggers second pass within cap", async (
|
|
|
1887
1956
|
assert.equal(result.repaired.length, 2, "both passes' repairs collected");
|
|
1888
1957
|
assert.equal(repaired.length, 2);
|
|
1889
1958
|
});
|
|
1959
|
+
|
|
1960
|
+
test("deriveState is pure: stale sketch healed only via reconcileBeforeDispatch", async (t) => {
|
|
1961
|
+
const base = makeFixtureBase();
|
|
1962
|
+
t.after(() => cleanup(base));
|
|
1963
|
+
|
|
1964
|
+
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
1965
|
+
insertMilestone({ id: "M001", title: "Test", status: "active" });
|
|
1966
|
+
insertSlice({
|
|
1967
|
+
id: "S02",
|
|
1968
|
+
milestoneId: "M001",
|
|
1969
|
+
title: "Feature",
|
|
1970
|
+
status: "pending",
|
|
1971
|
+
risk: "medium",
|
|
1972
|
+
depends: [],
|
|
1973
|
+
demo: "S02 demo.",
|
|
1974
|
+
sequence: 1,
|
|
1975
|
+
isSketch: true,
|
|
1976
|
+
sketchScope: "limited",
|
|
1977
|
+
});
|
|
1978
|
+
writeFileSync(
|
|
1979
|
+
join(base, ".gsd", "phases", "01-test", "01-02-PLAN.md"),
|
|
1980
|
+
"# S02 Plan\n",
|
|
1981
|
+
);
|
|
1982
|
+
|
|
1983
|
+
const { deriveState } = await import("../state.ts");
|
|
1984
|
+
invalidateStateCache();
|
|
1985
|
+
|
|
1986
|
+
const beforeReconcile = await deriveState(base);
|
|
1987
|
+
assert.equal(beforeReconcile.phase, "refining", "derive alone must not heal stale sketch flag");
|
|
1988
|
+
assert.equal(getSlice("M001", "S02")?.is_sketch, 1, "DB flag unchanged before reconcile");
|
|
1989
|
+
|
|
1990
|
+
const result = await reconcileBeforeDispatch(base);
|
|
1991
|
+
assert.equal(result.ok, true);
|
|
1992
|
+
assert.equal(getSlice("M001", "S02")?.is_sketch, 0, "reconcile clears sketch flag");
|
|
1993
|
+
|
|
1994
|
+
invalidateStateCache();
|
|
1995
|
+
const afterReconcile = await deriveState(base);
|
|
1996
|
+
assert.notEqual(afterReconcile.phase, "refining", "derive after reconcile advances past sketch gate");
|
|
1997
|
+
});
|
|
1998
|
+
|
|
1999
|
+
test("reconciliation repair phases: external edits precede re-project handlers", () => {
|
|
2000
|
+
assert.equal(RECONCILIATION_REPAIR_PHASES.length, 3);
|
|
2001
|
+
assert.ok(handlerPhaseIndex("external-markdown-edit") < handlerPhaseIndex("stale-render"));
|
|
2002
|
+
assert.ok(handlerPhaseIndex("external-planning-edit") < handlerPhaseIndex("roadmap-divergence"));
|
|
2003
|
+
assert.ok(handlerPhaseIndex("stale-sketch-flag") < handlerPhaseIndex("stale-render"));
|
|
2004
|
+
});
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* status-per-repo.test.ts — `/gsd status` per-repository git-health block (#818).
|
|
3
|
+
*
|
|
4
|
+
* Covers the parent-workspace addition to formatTextStatus:
|
|
5
|
+
* - parent mode with child repos → "Repositories:" section listing each
|
|
6
|
+
* - dirty vs clean markers
|
|
7
|
+
* - single-repo (project-mode) project → no Repositories section
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import test from "node:test";
|
|
11
|
+
import assert from "node:assert/strict";
|
|
12
|
+
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
13
|
+
import { join } from "node:path";
|
|
14
|
+
import { tmpdir } from "node:os";
|
|
15
|
+
import { execFileSync } from "node:child_process";
|
|
16
|
+
|
|
17
|
+
import { formatTextStatus } from "../commands/handlers/core.ts";
|
|
18
|
+
import type { GSDState } from "../types.ts";
|
|
19
|
+
|
|
20
|
+
function gitInit(cwd: string): void {
|
|
21
|
+
execFileSync("git", ["init"], { cwd, stdio: "ignore" });
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function makeBaseState(): GSDState {
|
|
25
|
+
return {
|
|
26
|
+
activeMilestone: null,
|
|
27
|
+
activeSlice: null,
|
|
28
|
+
activeTask: null,
|
|
29
|
+
phase: "planning",
|
|
30
|
+
recentDecisions: [],
|
|
31
|
+
blockers: [],
|
|
32
|
+
nextAction: "None",
|
|
33
|
+
registry: [],
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function writeParentPrefs(base: string, repos: Record<string, { path: string; role?: string }>): void {
|
|
38
|
+
const repoLines = Object.entries(repos)
|
|
39
|
+
.map(([id, cfg]) => ` ${id}:\n path: ${cfg.path}${cfg.role ? `\n role: ${cfg.role}` : ""}`)
|
|
40
|
+
.join("\n");
|
|
41
|
+
writeFileSync(
|
|
42
|
+
join(base, ".gsd", "PREFERENCES.md"),
|
|
43
|
+
`---\nversion: 1\nworkspace:\n mode: parent\n repositories:\n${repoLines}\n---\n`,
|
|
44
|
+
"utf-8",
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
test("formatTextStatus shows a Repositories section for a clean parent workspace", () => {
|
|
49
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-status-repo-clean-"));
|
|
50
|
+
try {
|
|
51
|
+
mkdirSync(join(base, ".gsd"), { recursive: true });
|
|
52
|
+
gitInit(base);
|
|
53
|
+
mkdirSync(join(base, "frontend"), { recursive: true });
|
|
54
|
+
gitInit(join(base, "frontend"));
|
|
55
|
+
writeParentPrefs(base, { frontend: { path: "frontend", role: "web UI" } });
|
|
56
|
+
|
|
57
|
+
const out = formatTextStatus(makeBaseState(), base);
|
|
58
|
+
assert.match(out, /Repositories:/);
|
|
59
|
+
assert.match(out, /✓ frontend — web UI \(clean\)/);
|
|
60
|
+
} finally {
|
|
61
|
+
rmSync(base, { recursive: true, force: true });
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
test("formatTextStatus marks a dirty child repo with ✗", () => {
|
|
66
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-status-repo-dirty-"));
|
|
67
|
+
try {
|
|
68
|
+
mkdirSync(join(base, ".gsd"), { recursive: true });
|
|
69
|
+
gitInit(base);
|
|
70
|
+
mkdirSync(join(base, "backend"), { recursive: true });
|
|
71
|
+
gitInit(join(base, "backend"));
|
|
72
|
+
writeParentPrefs(base, { backend: { path: "backend" } });
|
|
73
|
+
// Make the backend repo dirty.
|
|
74
|
+
writeFileSync(join(base, "backend", "README.md"), "# dirty\n", "utf-8");
|
|
75
|
+
|
|
76
|
+
const out = formatTextStatus(makeBaseState(), base);
|
|
77
|
+
assert.match(out, /✗ backend \(uncommitted changes\)/);
|
|
78
|
+
} finally {
|
|
79
|
+
rmSync(base, { recursive: true, force: true });
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test("formatTextStatus omits the Repositories section for single-repo projects", () => {
|
|
84
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-status-repo-single-"));
|
|
85
|
+
try {
|
|
86
|
+
mkdirSync(join(base, ".gsd"), { recursive: true });
|
|
87
|
+
gitInit(base);
|
|
88
|
+
// No workspace config → project mode (default).
|
|
89
|
+
const out = formatTextStatus(makeBaseState(), base);
|
|
90
|
+
assert.doesNotMatch(out, /Repositories:/);
|
|
91
|
+
} finally {
|
|
92
|
+
rmSync(base, { recursive: true, force: true });
|
|
93
|
+
}
|
|
94
|
+
});
|
|
@@ -552,6 +552,41 @@ test("discuss-milestone dispatch keeps required headless milestone tools after t
|
|
|
552
552
|
assert.ok(!activeTools.includes("gsd_complete_milestone"));
|
|
553
553
|
});
|
|
554
554
|
|
|
555
|
+
test("#1157: validate-milestone dispatch surface removes generic write and bash tools", () => {
|
|
556
|
+
const result = buildMinimalAutoGsdToolSet([
|
|
557
|
+
"ask_user_questions",
|
|
558
|
+
"bash",
|
|
559
|
+
"bg_shell",
|
|
560
|
+
"edit",
|
|
561
|
+
"find",
|
|
562
|
+
"glob",
|
|
563
|
+
"grep",
|
|
564
|
+
"ls",
|
|
565
|
+
"read",
|
|
566
|
+
"subagent",
|
|
567
|
+
"write",
|
|
568
|
+
"gsd_exec",
|
|
569
|
+
"gsd_exec_search",
|
|
570
|
+
"gsd_resume",
|
|
571
|
+
"gsd_milestone_status",
|
|
572
|
+
"gsd_validate_milestone",
|
|
573
|
+
"gsd_reassess_roadmap",
|
|
574
|
+
], "validate-milestone");
|
|
575
|
+
|
|
576
|
+
assert.ok(result.includes("read"));
|
|
577
|
+
assert.ok(result.includes("find"));
|
|
578
|
+
assert.ok(result.includes("subagent"));
|
|
579
|
+
assert.ok(result.includes("gsd_validate_milestone"));
|
|
580
|
+
assert.ok(result.includes("gsd_milestone_status"));
|
|
581
|
+
assert.ok(result.includes("gsd_exec"));
|
|
582
|
+
assert.ok(result.includes("gsd_reassess_roadmap"));
|
|
583
|
+
assert.ok(!result.includes("bash"));
|
|
584
|
+
assert.ok(!result.includes("bg_shell"));
|
|
585
|
+
assert.ok(!result.includes("write"));
|
|
586
|
+
assert.ok(!result.includes("edit"));
|
|
587
|
+
assert.ok(!result.includes("ask_user_questions"));
|
|
588
|
+
});
|
|
589
|
+
|
|
555
590
|
test("scopeGsdWorkflowToolsForDispatch applies and restores per-unit skill visibility", () => {
|
|
556
591
|
const calls: Array<{ kind: "tools" | "skills"; value: string[] | undefined }> = [];
|
|
557
592
|
let activeTools = [
|
|
@@ -7,6 +7,7 @@ import { test } from 'node:test';
|
|
|
7
7
|
import assert from 'node:assert/strict';
|
|
8
8
|
import {
|
|
9
9
|
checkToolCallLoop,
|
|
10
|
+
recordToolCallLoopMutation,
|
|
10
11
|
resetToolCallLoopGuard,
|
|
11
12
|
disableToolCallLoopGuard,
|
|
12
13
|
getToolCallLoopCount,
|
|
@@ -223,6 +224,62 @@ console.log('\n── Loop guard: repeatable tools get the higher cap (#783) ─
|
|
|
223
224
|
assert.ok(blocked.reason!.includes('cap 15'), 'reason should mention the repeatable cap');
|
|
224
225
|
}
|
|
225
226
|
|
|
227
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
228
|
+
// Mutation progress decays per-tool counts (#1092)
|
|
229
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
230
|
+
|
|
231
|
+
console.log('\n── Loop guard: mutation progress decays per-tool counts (#1092) ──');
|
|
232
|
+
|
|
233
|
+
{
|
|
234
|
+
resetToolCallLoopGuard();
|
|
235
|
+
|
|
236
|
+
// bash is called more than the repeatable cap, but each count is separated
|
|
237
|
+
// by a successful file mutation. Guard 2 should treat that as progress and
|
|
238
|
+
// avoid blocking the progressing unit.
|
|
239
|
+
for (let i = 1; i <= 20; i++) {
|
|
240
|
+
const result = checkToolCallLoop('bash', { command: `echo ${i}` });
|
|
241
|
+
assert.ok(result.block === false, `bash call ${i} after mutation progress should be allowed`);
|
|
242
|
+
assert.deepStrictEqual(getToolCallCountForTool('bash'), 1, `bash count should decay before call ${i}`);
|
|
243
|
+
|
|
244
|
+
const mutationTool = i % 2 === 0 ? 'write' : 'edit';
|
|
245
|
+
const mutation = checkToolCallLoop(mutationTool, {
|
|
246
|
+
path: `file-${i}.ts`,
|
|
247
|
+
content: `content ${i}`,
|
|
248
|
+
});
|
|
249
|
+
assert.ok(mutation.block === false, `${mutationTool} mutation ${i} should be allowed`);
|
|
250
|
+
recordToolCallLoopMutation(mutationTool);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
255
|
+
// Distinct read-only navigation calls are context gathering, not repeated-tool loops.
|
|
256
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
257
|
+
|
|
258
|
+
console.log('\n── Loop guard: distinct read-only navigation calls are not capped by per-tool count ──');
|
|
259
|
+
|
|
260
|
+
{
|
|
261
|
+
const exemptTools = ['find', 'glob', 'grep', 'ls', 'read', 'search_and_read'];
|
|
262
|
+
|
|
263
|
+
for (const toolName of exemptTools) {
|
|
264
|
+
resetToolCallLoopGuard();
|
|
265
|
+
|
|
266
|
+
for (let i = 1; i <= 20; i++) {
|
|
267
|
+
const result = checkToolCallLoop(toolName, { path: `file-${i}.ts` });
|
|
268
|
+
assert.ok(result.block === false, `distinct ${toolName} call ${i} should be allowed`);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
resetToolCallLoopGuard();
|
|
272
|
+
for (let i = 1; i <= 4; i++) {
|
|
273
|
+
const result = checkToolCallLoop(toolName, { path: 'same-file.ts' });
|
|
274
|
+
assert.ok(result.block === false, `identical ${toolName} call ${i} should be allowed`);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
const blocked = checkToolCallLoop(toolName, { path: 'same-file.ts' });
|
|
278
|
+
assert.ok(blocked.block === true, `5th identical ${toolName} call should still be blocked`);
|
|
279
|
+
assert.ok(blocked.reason?.includes('identical args'), `${toolName} loops should be caught by Guard 1`);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
226
283
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
227
284
|
// Per-tool counts are independent per tool and reset together
|
|
228
285
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -245,3 +302,149 @@ console.log('\n── Loop guard: per-tool counts are independent and reset toge
|
|
|
245
302
|
}
|
|
246
303
|
|
|
247
304
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
305
|
+
// Non-exempt repeatable tools from core-session-tools.ts get the higher cap.
|
|
306
|
+
// Read-only navigation tools are exempted earlier; mutating/execution repeatable
|
|
307
|
+
// tools (e.g. gsd_exec) must still trip the per-tool cap.
|
|
308
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
309
|
+
|
|
310
|
+
console.log('\n── Loop guard: non-exempt repeatable tools get high cap ──');
|
|
311
|
+
|
|
312
|
+
{
|
|
313
|
+
for (const toolName of ['bg_shell', 'gsd_exec', 'write']) {
|
|
314
|
+
resetToolCallLoopGuard();
|
|
315
|
+
|
|
316
|
+
// Should allow up to 15 varied calls without blocking.
|
|
317
|
+
for (let i = 1; i <= 15; i++) {
|
|
318
|
+
const result = checkToolCallLoop(toolName, { arg: `v${i}` });
|
|
319
|
+
assert.ok(result.block === false, `${toolName} call ${i} (varied args) should be allowed`);
|
|
320
|
+
}
|
|
321
|
+
// 16th call with varied args must be blocked by the per-tool repeatable cap.
|
|
322
|
+
const blocked = checkToolCallLoop(toolName, { arg: 'v16' });
|
|
323
|
+
assert.ok(blocked.block === true, `${toolName}: 16th call must be blocked by repeatable cap`);
|
|
324
|
+
assert.ok(blocked.reason?.includes('cap 15'), `${toolName}: reason must mention cap 15`);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
329
|
+
// Non-repeatable tools excluded from INHERENTLY_REPEATABLE_TOOL_SET use the
|
|
330
|
+
// default cap (6), not the repeatable cap (15).
|
|
331
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
332
|
+
|
|
333
|
+
console.log('\n── Loop guard: ToolSearch (excluded from repeatable set) hits default cap ──');
|
|
334
|
+
|
|
335
|
+
{
|
|
336
|
+
// ToolSearch is in MINIMAL_AUTO_BASE but explicitly excluded from repeatable.
|
|
337
|
+
// It should hit the default cap of 6, not 15.
|
|
338
|
+
resetToolCallLoopGuard();
|
|
339
|
+
for (let i = 1; i <= 6; i++) {
|
|
340
|
+
const result = checkToolCallLoop('ToolSearch', { query: `q${i}` });
|
|
341
|
+
assert.ok(result.block === false, `ToolSearch call ${i} should be allowed`);
|
|
342
|
+
}
|
|
343
|
+
const blocked = checkToolCallLoop('ToolSearch', { query: 'q7' });
|
|
344
|
+
assert.ok(blocked.block === true, 'ToolSearch: 7th varied call must be blocked by default cap');
|
|
345
|
+
assert.ok(!blocked.reason?.includes('cap 15'), 'ToolSearch must NOT use the repeatable cap');
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
349
|
+
// Block reasons instruct the model to stop tooling this turn
|
|
350
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
351
|
+
|
|
352
|
+
console.log('\n── Loop guard: block reasons tell model to respond in text ──');
|
|
353
|
+
|
|
354
|
+
{
|
|
355
|
+
resetToolCallLoopGuard();
|
|
356
|
+
|
|
357
|
+
for (let i = 0; i < 4; i++) {
|
|
358
|
+
checkToolCallLoop('web_search', { query: 'same query' });
|
|
359
|
+
}
|
|
360
|
+
const identicalBlocked = checkToolCallLoop('web_search', { query: 'same query' });
|
|
361
|
+
assert.ok(identicalBlocked.block === true, 'identical-args guard should block');
|
|
362
|
+
assert.ok(
|
|
363
|
+
identicalBlocked.reason!.includes('respond to the user in text'),
|
|
364
|
+
'identical-args reason should tell the model to stop tooling',
|
|
365
|
+
);
|
|
366
|
+
assert.ok(
|
|
367
|
+
!identicalBlocked.reason!.includes('Try a different approach'),
|
|
368
|
+
'identical-args reason should not suggest retrying another tool',
|
|
369
|
+
);
|
|
370
|
+
|
|
371
|
+
resetToolCallLoopGuard();
|
|
372
|
+
for (let i = 0; i < 6; i++) {
|
|
373
|
+
checkToolCallLoop('gsd_complete_milestone', { milestone: `M${i}` });
|
|
374
|
+
}
|
|
375
|
+
const perToolBlocked = checkToolCallLoop('gsd_complete_milestone', { milestone: 'M7' });
|
|
376
|
+
assert.ok(perToolBlocked.block === true, 'per-tool guard should block');
|
|
377
|
+
assert.ok(
|
|
378
|
+
perToolBlocked.reason!.includes('respond to the user in text'),
|
|
379
|
+
'per-tool reason should tell the model to stop tooling',
|
|
380
|
+
);
|
|
381
|
+
assert.ok(
|
|
382
|
+
perToolBlocked.reason!.includes('Do not retry this tool'),
|
|
383
|
+
'per-tool reason should forbid retrying the blocked tool',
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
388
|
+
// Distinct-arg browser-automation calls are a legitimate UAT, not a loop (#1120)
|
|
389
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
390
|
+
|
|
391
|
+
console.log('\n── Loop guard: distinct-arg browser automation calls are not capped by per-tool count (#1120) ──');
|
|
392
|
+
|
|
393
|
+
{
|
|
394
|
+
// A browser-backed UAT legitimately calls one browser verb many times with
|
|
395
|
+
// DIFFERENT arguments (read a validation message, count staged edits, inspect
|
|
396
|
+
// a control card, …). Guard 1's identical-signature streak never trips because
|
|
397
|
+
// the args vary; Guard 2's arg-independent per-tool cap must NOT block it.
|
|
398
|
+
for (const toolName of ['browser_evaluate', 'browser_act', 'browser_find']) {
|
|
399
|
+
resetToolCallLoopGuard();
|
|
400
|
+
for (let i = 1; i <= 12; i++) {
|
|
401
|
+
const result = checkToolCallLoop(toolName, { script: `step ${i}` });
|
|
402
|
+
assert.ok(result.block === false, `distinct ${toolName} call ${i} should be allowed`);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// MCP-prefixed browser tools canonicalize to `browser_*` and are exempt too.
|
|
407
|
+
resetToolCallLoopGuard();
|
|
408
|
+
for (let i = 1; i <= 12; i++) {
|
|
409
|
+
const result = checkToolCallLoop('mcp__agent-browser__browser_evaluate', { script: `step ${i}` });
|
|
410
|
+
assert.ok(result.block === false, `distinct MCP-prefixed browser_evaluate call ${i} should be allowed`);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
415
|
+
// Identical-arg browser loops are STILL caught by Guard 1 (#1120)
|
|
416
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
417
|
+
|
|
418
|
+
console.log('\n── Loop guard: identical-arg browser loops are still caught by Guard 1 (#1120) ──');
|
|
419
|
+
|
|
420
|
+
{
|
|
421
|
+
resetToolCallLoopGuard();
|
|
422
|
+
for (let i = 1; i <= 4; i++) {
|
|
423
|
+
const result = checkToolCallLoop('browser_evaluate', { script: 'document.title' });
|
|
424
|
+
assert.ok(result.block === false, `identical browser_evaluate call ${i} should be allowed`);
|
|
425
|
+
}
|
|
426
|
+
const blocked = checkToolCallLoop('browser_evaluate', { script: 'document.title' });
|
|
427
|
+
assert.ok(blocked.block === true, '5th identical browser_evaluate call should be blocked by Guard 1');
|
|
428
|
+
assert.ok(blocked.reason?.includes('identical args'), 'identical browser loops should be caught by Guard 1, not Guard 2');
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
432
|
+
// The browser exemption must NOT widen to other non-exempt tools (#1120)
|
|
433
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
434
|
+
|
|
435
|
+
console.log('\n── Loop guard: browser exemption does not widen to other tools (#1120) ──');
|
|
436
|
+
|
|
437
|
+
{
|
|
438
|
+
// Negative invariant: an arbitrary non-exempt, non-browser tool called past
|
|
439
|
+
// the default cap with varied args must still be blocked by Guard 2.
|
|
440
|
+
resetToolCallLoopGuard();
|
|
441
|
+
for (let i = 1; i <= 6; i++) {
|
|
442
|
+
const result = checkToolCallLoop('some_workflow_tool', { arg: `v${i}` });
|
|
443
|
+
assert.ok(result.block === false, `non-exempt tool call ${i} should be allowed`);
|
|
444
|
+
}
|
|
445
|
+
const blocked = checkToolCallLoop('some_workflow_tool', { arg: 'v7' });
|
|
446
|
+
assert.ok(blocked.block === true, '7th varied-arg non-exempt call must still trip Guard 2');
|
|
447
|
+
assert.ok(blocked.reason?.includes('repeated tool'), 'non-exempt overflow should be caught by Guard 2');
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -385,14 +385,17 @@ test("gsd_plan_slice — enrichment fields are optional", () => {
|
|
|
385
385
|
|
|
386
386
|
const required = new Set(getRequiredProps(tool));
|
|
387
387
|
|
|
388
|
-
// Core fields
|
|
389
|
-
|
|
388
|
+
// Core fields. `tasks` is intentionally NOT here: incremental planning
|
|
389
|
+
// (#1027) lets gsd_plan_slice persist slice metadata only, then add tasks
|
|
390
|
+
// one at a time via gsd_plan_task, so tasks must be optional.
|
|
391
|
+
const coreRequired = ["milestoneId", "sliceId", "goal"];
|
|
390
392
|
for (const field of coreRequired) {
|
|
391
393
|
assert.ok(required.has(field), `core field "${field}" must be required`);
|
|
392
394
|
}
|
|
393
395
|
|
|
394
|
-
// Enrichment fields
|
|
396
|
+
// Enrichment fields (plus tasks, optional for incremental planning).
|
|
395
397
|
const enrichmentFields = [
|
|
398
|
+
"tasks",
|
|
396
399
|
"successCriteria",
|
|
397
400
|
"proofLevel",
|
|
398
401
|
"integrationClosure",
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
handleUndo,
|
|
11
11
|
handleUndoTask,
|
|
12
12
|
handleResetSlice,
|
|
13
|
+
parseActivityLogFilename,
|
|
13
14
|
uncheckTaskInPlan,
|
|
14
15
|
} from "../undo.ts";
|
|
15
16
|
import {
|
|
@@ -67,6 +68,37 @@ test("handleUndo without --force only warns and leaves completed units intact",
|
|
|
67
68
|
}
|
|
68
69
|
});
|
|
69
70
|
|
|
71
|
+
test("handleUndo execute-task with --force reopens the task row and re-renders plan", async () => {
|
|
72
|
+
const base = makeTempDir("gsd-undo-execute-task");
|
|
73
|
+
try {
|
|
74
|
+
setupTaskFixture(base);
|
|
75
|
+
mkdirSync(join(base, ".gsd", "activity"), { recursive: true });
|
|
76
|
+
writeFileSync(
|
|
77
|
+
join(base, ".gsd", "activity", "001-execute-task-M001-S01-T01.jsonl"),
|
|
78
|
+
"",
|
|
79
|
+
"utf-8",
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
const { notifications, ctx } = makeCtx();
|
|
83
|
+
await handleUndo("--force", ctx, {} as any, base);
|
|
84
|
+
|
|
85
|
+
const task = getTask("M001", "S01", "T01");
|
|
86
|
+
assert.equal(task?.status, "pending");
|
|
87
|
+
|
|
88
|
+
const planContent = readFileSync(
|
|
89
|
+
join(base, ".gsd", "phases", "01-test", "01-01-PLAN.md"),
|
|
90
|
+
"utf-8",
|
|
91
|
+
);
|
|
92
|
+
assert.match(planContent, /\[ \] \*\*T01\*\*:/);
|
|
93
|
+
|
|
94
|
+
assert.equal(notifications[0]?.level, "success");
|
|
95
|
+
assert.match(notifications[0]?.message ?? "", /Unchecked task in PLAN/);
|
|
96
|
+
} finally {
|
|
97
|
+
closeDatabase();
|
|
98
|
+
rmSync(base, { recursive: true, force: true });
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
|
|
70
102
|
test("uncheckTaskInPlan flips a checked task back to unchecked", () => {
|
|
71
103
|
const base = makeTempDir("gsd-undo-plan");
|
|
72
104
|
try {
|
|
@@ -154,6 +186,48 @@ test("extractCommitShas ignores malformed commit tokens", () => {
|
|
|
154
186
|
assert.deepEqual(extractCommitShas(content), ["1234567"]);
|
|
155
187
|
});
|
|
156
188
|
|
|
189
|
+
test("parseActivityLogFilename splits hyphenated unit types from their IDs", () => {
|
|
190
|
+
// Task-level: unit type and ID both contain hyphens.
|
|
191
|
+
assert.deepEqual(parseActivityLogFilename("001-execute-task-M001-S01-T01.jsonl"), {
|
|
192
|
+
unitType: "execute-task",
|
|
193
|
+
unitId: "M001-S01-T01",
|
|
194
|
+
});
|
|
195
|
+
// Variant must win over its shorter prefix ("execute-task").
|
|
196
|
+
assert.deepEqual(parseActivityLogFilename("002-execute-task-simple-M001-S02-T03.jsonl"), {
|
|
197
|
+
unitType: "execute-task-simple",
|
|
198
|
+
unitId: "M001-S02-T03",
|
|
199
|
+
});
|
|
200
|
+
// Milestone- and slice-shaped IDs.
|
|
201
|
+
assert.deepEqual(parseActivityLogFilename("003-research-milestone-M001.jsonl"), {
|
|
202
|
+
unitType: "research-milestone",
|
|
203
|
+
unitId: "M001",
|
|
204
|
+
});
|
|
205
|
+
assert.deepEqual(parseActivityLogFilename("004-plan-slice-M001-S01.jsonl"), {
|
|
206
|
+
unitType: "plan-slice",
|
|
207
|
+
unitId: "M001-S01",
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
test("parseActivityLogFilename accepts non-milestone-shaped unit IDs", () => {
|
|
212
|
+
// Regression (#1057): project-level units use IDs that do not start with
|
|
213
|
+
// "M<digit>". A milestone-shaped regex made /gsd undo bail out with
|
|
214
|
+
// "could not parse latest activity log" when one of these was most recent.
|
|
215
|
+
assert.deepEqual(parseActivityLogFilename("005-discuss-project-PROJECT.jsonl"), {
|
|
216
|
+
unitType: "discuss-project",
|
|
217
|
+
unitId: "PROJECT",
|
|
218
|
+
});
|
|
219
|
+
assert.deepEqual(parseActivityLogFilename("006-workflow-preferences-WORKFLOW-PREFS.jsonl"), {
|
|
220
|
+
unitType: "workflow-preferences",
|
|
221
|
+
unitId: "WORKFLOW-PREFS",
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
test("parseActivityLogFilename returns null for unrecognized names", () => {
|
|
226
|
+
assert.equal(parseActivityLogFilename("007-not-a-real-unit-M001.jsonl"), null);
|
|
227
|
+
assert.equal(parseActivityLogFilename("no-sequence-prefix.jsonl"), null);
|
|
228
|
+
assert.equal(parseActivityLogFilename("001-execute-task-M001-S01-T01.txt"), null);
|
|
229
|
+
});
|
|
230
|
+
|
|
157
231
|
// ─── handleUndoTask tests ────────────────────────────────────────────────────
|
|
158
232
|
|
|
159
233
|
function makeCtx(): { notifications: Array<{ message: string; level: string }>; ctx: any } {
|