@opengsd/gsd-pi 1.4.0-dev.c18009cd → 1.5.0-dev.4fb2d460
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 +10 -10
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/ask-user-questions.js +1 -1
- package/dist/resources/extensions/gsd/auto/closeout.js +97 -5
- package/dist/resources/extensions/gsd/auto/orchestrator.js +4 -3
- package/dist/resources/extensions/gsd/auto/pre-dispatch.js +6 -3
- package/dist/resources/extensions/gsd/auto/unit-phase.js +5 -9
- package/dist/resources/extensions/gsd/auto-artifact-paths.js +12 -3
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +11 -7
- package/dist/resources/extensions/gsd/auto-dispatch.js +16 -2
- package/dist/resources/extensions/gsd/auto-recovery.js +50 -6
- package/dist/resources/extensions/gsd/auto-start.js +4 -3
- package/dist/resources/extensions/gsd/auto-worktree-branch-lifecycle.js +189 -0
- package/dist/resources/extensions/gsd/auto-worktree-cleanup.js +133 -0
- package/dist/resources/extensions/gsd/auto-worktree-conflict-auto-resolve.js +35 -0
- package/dist/resources/extensions/gsd/auto-worktree-creation.js +130 -0
- package/dist/resources/extensions/gsd/auto-worktree-entry.js +118 -0
- package/dist/resources/extensions/gsd/auto-worktree-merge-already-merged.js +98 -0
- package/dist/resources/extensions/gsd/auto-worktree-merge-branch-head.js +52 -0
- package/dist/resources/extensions/gsd/auto-worktree-merge-cleanup.js +87 -0
- package/dist/resources/extensions/gsd/auto-worktree-merge-code-changes.js +46 -0
- package/dist/resources/extensions/gsd/auto-worktree-merge-db-ready.js +68 -0
- package/dist/resources/extensions/gsd/auto-worktree-merge-integration-branch.js +51 -0
- package/dist/resources/extensions/gsd/auto-worktree-merge-message.js +106 -0
- package/dist/resources/extensions/gsd/auto-worktree-merge-pre-teardown.js +64 -0
- package/dist/resources/extensions/gsd/auto-worktree-merge-stash.js +168 -0
- package/dist/resources/extensions/gsd/auto-worktree-merge.js +302 -0
- package/dist/resources/extensions/gsd/auto-worktree-milestone-shelter.js +119 -0
- package/dist/resources/extensions/gsd/auto-worktree-path-resolution.js +5 -0
- package/dist/resources/extensions/gsd/auto-worktree-path-utils.js +5 -0
- package/dist/resources/extensions/gsd/auto-worktree-resource-version.js +41 -0
- package/dist/resources/extensions/gsd/auto-worktree-runtime-cleanup.js +99 -0
- package/dist/resources/extensions/gsd/auto-worktree-session-registry.js +57 -0
- package/dist/resources/extensions/gsd/auto-worktree-sync.js +249 -0
- package/dist/resources/extensions/gsd/auto-worktree-teardown.js +120 -0
- package/dist/resources/extensions/gsd/auto-worktree.js +20 -2073
- package/dist/resources/extensions/gsd/auto.js +9 -3
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +1 -1
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +20 -2
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +1 -1
- package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +185 -27
- package/dist/resources/extensions/gsd/codebase-generator.js +7 -1
- package/dist/resources/extensions/gsd/commands-handlers.js +1 -1
- package/dist/resources/extensions/gsd/commands-workflow-templates.js +3 -3
- package/dist/resources/extensions/gsd/db/queries.js +9 -9
- package/dist/resources/extensions/gsd/db/writers/cascades.js +20 -2
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +93 -11
- package/dist/resources/extensions/gsd/flat-phase-migration.js +32 -3
- package/dist/resources/extensions/gsd/forensics.js +1 -1
- package/dist/resources/extensions/gsd/git-conflict-resolve.js +2 -2
- package/dist/resources/extensions/gsd/git-service.js +45 -0
- package/dist/resources/extensions/gsd/gsd-db.js +23 -11
- package/dist/resources/extensions/gsd/guided-flow.js +22 -17
- package/dist/resources/extensions/gsd/markdown-renderer.js +15 -3
- package/dist/resources/extensions/gsd/md-importer.js +89 -23
- package/dist/resources/extensions/gsd/migration-auto-check.js +30 -3
- package/dist/resources/extensions/gsd/milestone-merge-transaction.js +11 -0
- package/dist/resources/extensions/gsd/milestone-settlement.js +1 -1
- package/dist/resources/extensions/gsd/parallel-merge.js +1 -1
- package/dist/resources/extensions/gsd/parallel-orchestrator.js +3 -1
- package/dist/resources/extensions/gsd/paths.js +17 -3
- package/dist/resources/extensions/gsd/preferences-skills.js +10 -16
- package/dist/resources/extensions/gsd/preferences-types.js +1 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +82 -0
- package/dist/resources/extensions/gsd/preferences.js +20 -0
- package/dist/resources/extensions/gsd/prompts/system.md +6 -6
- package/dist/resources/extensions/gsd/quick.js +12 -3
- package/dist/resources/extensions/gsd/skill-discovery.js +36 -23
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +2 -1
- package/dist/resources/extensions/gsd/state/derive/from-db.js +88 -153
- package/dist/resources/extensions/gsd/tool-contract.js +14 -0
- package/dist/resources/extensions/gsd/tools/reopen-slice.js +5 -0
- package/dist/resources/extensions/gsd/tools/reopen-task.js +13 -5
- package/dist/resources/extensions/gsd/unit-registry.js +12 -2
- package/dist/resources/extensions/gsd/unmerged-milestone-guard.js +1 -1
- package/dist/resources/extensions/gsd/validation-block-guard.js +2 -1
- package/dist/resources/extensions/gsd/workspace-git-preflight.js +2 -2
- package/dist/resources/extensions/gsd/worktree-command.js +1 -1
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +14 -9
- package/dist/resources/extensions/gsd/worktree-reentry.js +2 -1
- package/dist/resources/extensions/shared/interview-ui.js +62 -9
- 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 +8 -8
- 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/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 +8 -8
- 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/@gsd/native/package.json +1 -1
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
- package/integrations/hermes/open_gsd_hermes/gsd_client.py +24 -35
- package/integrations/hermes/tests/test_gsd_client_timeout.py +4 -4
- package/package.json +6 -6
- 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/export-html/template.js +53 -4
- package/packages/gsd-agent-core/package.json +5 -5
- 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 +3 -2
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/package.json +4 -4
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +14 -9
- 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/index.d.ts +1 -0
- package/packages/pi-ai/dist/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/index.js +1 -0
- package/packages/pi-ai/dist/index.js.map +1 -1
- package/packages/pi-ai/dist/providers/transform-messages.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/transform-messages.js +7 -3
- package/packages/pi-ai/dist/providers/transform-messages.js.map +1 -1
- package/packages/pi-ai/dist/tool-result-content.d.ts +3 -0
- package/packages/pi-ai/dist/tool-result-content.d.ts.map +1 -0
- package/packages/pi-ai/dist/tool-result-content.js +62 -0
- package/packages/pi-ai/dist/tool-result-content.js.map +1 -0
- package/packages/pi-ai/dist/types.d.ts +8 -20
- 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/dist/core/package-manager.d.ts +9 -0
- package/packages/pi-coding-agent/dist/core/package-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/package-manager.js +74 -53
- package/packages/pi-coding-agent/dist/core/package-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.d.ts +6 -0
- package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.js +30 -2
- package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/skill-directories.d.ts +66 -0
- package/packages/pi-coding-agent/dist/core/skill-directories.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/skill-directories.js +138 -0
- package/packages/pi-coding-agent/dist/core/skill-directories.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/skills.d.ts +4 -1
- package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/skills.js +4 -1
- package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts +1 -0
- package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/index.js +1 -0
- package/packages/pi-coding-agent/dist/index.js.map +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/package.json +2 -2
- package/packages/rpc-client/package.json +2 -2
- package/pkg/dist/core/export-html/template.js +53 -4
- package/pkg/package.json +1 -1
- package/src/resources/extensions/ask-user-questions.ts +1 -1
- package/src/resources/extensions/gsd/auto/closeout.ts +114 -7
- package/src/resources/extensions/gsd/auto/orchestrator.ts +4 -3
- package/src/resources/extensions/gsd/auto/pre-dispatch.ts +6 -3
- package/src/resources/extensions/gsd/auto/unit-phase.ts +5 -9
- package/src/resources/extensions/gsd/auto-artifact-paths.ts +12 -3
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +13 -7
- package/src/resources/extensions/gsd/auto-dispatch.ts +18 -2
- package/src/resources/extensions/gsd/auto-recovery.ts +50 -6
- package/src/resources/extensions/gsd/auto-start.ts +5 -3
- package/src/resources/extensions/gsd/auto-worktree-branch-lifecycle.ts +237 -0
- package/src/resources/extensions/gsd/auto-worktree-cleanup.ts +166 -0
- package/src/resources/extensions/gsd/auto-worktree-conflict-auto-resolve.ts +37 -0
- package/src/resources/extensions/gsd/auto-worktree-creation.ts +171 -0
- package/src/resources/extensions/gsd/auto-worktree-entry.ts +154 -0
- package/src/resources/extensions/gsd/auto-worktree-merge-already-merged.ts +161 -0
- package/src/resources/extensions/gsd/auto-worktree-merge-branch-head.ts +83 -0
- package/src/resources/extensions/gsd/auto-worktree-merge-cleanup.ts +132 -0
- package/src/resources/extensions/gsd/auto-worktree-merge-code-changes.ts +71 -0
- package/src/resources/extensions/gsd/auto-worktree-merge-db-ready.ts +112 -0
- package/src/resources/extensions/gsd/auto-worktree-merge-integration-branch.ts +99 -0
- package/src/resources/extensions/gsd/auto-worktree-merge-message.ts +166 -0
- package/src/resources/extensions/gsd/auto-worktree-merge-pre-teardown.ts +93 -0
- package/src/resources/extensions/gsd/auto-worktree-merge-stash.ts +213 -0
- package/src/resources/extensions/gsd/auto-worktree-merge.ts +391 -0
- package/src/resources/extensions/gsd/auto-worktree-milestone-shelter.ts +159 -0
- package/src/resources/extensions/gsd/auto-worktree-path-resolution.ts +6 -0
- package/src/resources/extensions/gsd/auto-worktree-path-utils.ts +10 -0
- package/src/resources/extensions/gsd/auto-worktree-resource-version.ts +44 -0
- package/src/resources/extensions/gsd/auto-worktree-runtime-cleanup.ts +119 -0
- package/src/resources/extensions/gsd/auto-worktree-session-registry.ts +71 -0
- package/src/resources/extensions/gsd/auto-worktree-sync.ts +370 -0
- package/src/resources/extensions/gsd/auto-worktree-teardown.ts +161 -0
- package/src/resources/extensions/gsd/auto-worktree.ts +69 -2429
- package/src/resources/extensions/gsd/auto.ts +11 -17
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +1 -1
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +20 -2
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +1 -1
- package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +218 -27
- package/src/resources/extensions/gsd/codebase-generator.ts +7 -1
- package/src/resources/extensions/gsd/commands-handlers.ts +1 -1
- package/src/resources/extensions/gsd/commands-workflow-templates.ts +3 -3
- package/src/resources/extensions/gsd/db/queries.ts +9 -9
- package/src/resources/extensions/gsd/db/writers/cascades.ts +23 -1
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +109 -10
- package/src/resources/extensions/gsd/flat-phase-migration.ts +34 -3
- package/src/resources/extensions/gsd/forensics.ts +1 -1
- package/src/resources/extensions/gsd/git-conflict-resolve.ts +2 -2
- package/src/resources/extensions/gsd/git-service.ts +53 -0
- package/src/resources/extensions/gsd/gsd-db.ts +33 -11
- package/src/resources/extensions/gsd/guided-flow.ts +26 -18
- package/src/resources/extensions/gsd/markdown-renderer.ts +15 -3
- package/src/resources/extensions/gsd/md-importer.ts +93 -22
- package/src/resources/extensions/gsd/migration-auto-check.ts +32 -3
- package/src/resources/extensions/gsd/milestone-merge-transaction.ts +15 -0
- package/src/resources/extensions/gsd/milestone-settlement.ts +1 -1
- package/src/resources/extensions/gsd/parallel-merge.ts +1 -1
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +3 -1
- package/src/resources/extensions/gsd/paths.ts +21 -3
- package/src/resources/extensions/gsd/preferences-skills.ts +10 -16
- package/src/resources/extensions/gsd/preferences-types.ts +30 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +69 -0
- package/src/resources/extensions/gsd/preferences.ts +20 -0
- package/src/resources/extensions/gsd/prompts/system.md +6 -6
- package/src/resources/extensions/gsd/quick.ts +11 -3
- package/src/resources/extensions/gsd/skill-discovery.ts +47 -23
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +3 -1
- package/src/resources/extensions/gsd/state/derive/from-db.ts +201 -157
- package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +169 -1
- package/src/resources/extensions/gsd/tests/auto-loop-no-copy-artifacts.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +57 -0
- package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/auto-worktree-auto-resolve.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/auto-worktree-merge-already-merged.test.ts +177 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-merge-branch-head.test.ts +118 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-merge-cleanup.test.ts +115 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-merge-code-changes.test.ts +76 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-merge-db-ready.test.ts +140 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-merge-integration-branch.test.ts +123 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-merge-message.test.ts +114 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-merge-pre-teardown.test.ts +84 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-merge-stash.test.ts +70 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-milestone-shelter.test.ts +52 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +6 -6
- package/src/resources/extensions/gsd/tests/auto-worktree-resource-version.test.ts +59 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-untracked-content.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +174 -0
- package/src/resources/extensions/gsd/tests/fast-forward-reused-milestone-branch.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +71 -1
- package/src/resources/extensions/gsd/tests/flat-phase-renderer.test.ts +25 -1
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/import-completion-lost-update.test.ts +196 -0
- package/src/resources/extensions/gsd/tests/integration/all-milestones-complete-merge.test.ts +4 -6
- package/src/resources/extensions/gsd/tests/integration/auto-stash-merge.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +7 -8
- package/src/resources/extensions/gsd/tests/integration/feature-branch-lifecycle-integration.test.ts +2 -5
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +76 -0
- package/src/resources/extensions/gsd/tests/integration/merge-cwd-restore.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/integration/merge-preserve-worktree-on-preteardown-error.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/integration/merge-strategy-regular.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/integration/milestone-transition-worktree.test.ts +5 -7
- package/src/resources/extensions/gsd/tests/integration/workspace-collapse-integration.test.ts +2 -4
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +16 -15
- package/src/resources/extensions/gsd/tests/merge-closeout-consistency-gate.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/merge-db-cycle.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/merge-self-branch-guard.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +91 -0
- package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +439 -0
- package/src/resources/extensions/gsd/tests/milestone-merge-transaction.test.ts +24 -0
- package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/originalbase-path-comparison.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/parallel-worker-lock-contention.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +1 -4
- package/src/resources/extensions/gsd/tests/preferences.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +5 -0
- package/src/resources/extensions/gsd/tests/reopen-slice.test.ts +52 -0
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/skill-discovery.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/stale-worktree-cwd.test.ts +3 -5
- package/src/resources/extensions/gsd/tests/stash-pop-gsd-conflict.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/steer-worktree-path.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/system-flat-phase-layout.test.ts +33 -0
- package/src/resources/extensions/gsd/tests/teardown-chdir-failure-clears-registry.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/teardown-cleanup-parity.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/teardown-failure-clears-registry.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +196 -0
- package/src/resources/extensions/gsd/tests/uat-stuck-loop-orphaned-worktree.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/unit-registry.test.ts +26 -1
- package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-db-respawn-truncation.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-db-same-file.test.ts +1 -3
- package/src/resources/extensions/gsd/tests/worktree-expected-warnings.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-git-pathspec.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-main-branch.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-preferences-sync.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-reentry.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +5 -2
- package/src/resources/extensions/gsd/tests/worktree-sync-overwrite-loop.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-sync-tasks.test.ts +1 -1
- package/src/resources/extensions/gsd/tool-contract.ts +29 -0
- package/src/resources/extensions/gsd/tools/reopen-slice.ts +5 -0
- package/src/resources/extensions/gsd/tools/reopen-task.ts +13 -5
- package/src/resources/extensions/gsd/unit-registry.ts +16 -2
- package/src/resources/extensions/gsd/unmerged-milestone-guard.ts +1 -1
- package/src/resources/extensions/gsd/validation-block-guard.ts +2 -1
- package/src/resources/extensions/gsd/workspace-git-preflight.ts +2 -2
- package/src/resources/extensions/gsd/worktree-command.ts +1 -1
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +19 -15
- package/src/resources/extensions/gsd/worktree-reentry.ts +2 -1
- package/src/resources/extensions/shared/interview-ui.ts +58 -11
- package/src/resources/extensions/shared/tests/interview-ui-border.test.ts +32 -0
- /package/dist/web/standalone/.next/static/{L2UMqXELiDH3oz-7yguXp → gXoWec4UNqcR0tkuHwYCr}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{L2UMqXELiDH3oz-7yguXp → gXoWec4UNqcR0tkuHwYCr}/_ssgManifest.js +0 -0
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
compileUnitContextContract,
|
|
11
11
|
compileUnitToolContract,
|
|
12
12
|
getUnitWorkflowDispatchReadinessError,
|
|
13
|
+
getUnitWorkflowDispatchReadinessErrorForModel,
|
|
13
14
|
} from "../tool-contract.js";
|
|
14
15
|
import { shouldBlockAutoUnitToolCall } from "../auto-unit-tool-scope.js";
|
|
15
16
|
import type { GSDState } from "../types.js";
|
|
@@ -111,6 +112,25 @@ test("Tool Contract derives dispatch readiness from Unit workflow tools", () =>
|
|
|
111
112
|
assert.equal(error, null);
|
|
112
113
|
});
|
|
113
114
|
|
|
115
|
+
test("Tool Contract derives dispatch readiness from selected model context", () => {
|
|
116
|
+
const authLookups: string[] = [];
|
|
117
|
+
const error = getUnitWorkflowDispatchReadinessErrorForModel({
|
|
118
|
+
model: { provider: "claude-code" },
|
|
119
|
+
fallbackModel: { provider: "openai-codex", baseUrl: "local://claude-code" },
|
|
120
|
+
getProviderAuthMode(provider) {
|
|
121
|
+
authLookups.push(provider);
|
|
122
|
+
return provider === "claude-code" ? "externalCli" : "oauth";
|
|
123
|
+
},
|
|
124
|
+
unitType: "plan-slice",
|
|
125
|
+
projectRoot: "/tmp/project",
|
|
126
|
+
env: { GSD_WORKFLOW_MCP_COMMAND: "node" },
|
|
127
|
+
surface: "auto-mode",
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
assert.equal(error, null);
|
|
131
|
+
assert.deepEqual(authLookups, ["claude-code"]);
|
|
132
|
+
});
|
|
133
|
+
|
|
114
134
|
test("Unit Context Contract exposes prompt context without workflow tool surface", () => {
|
|
115
135
|
const result = compileUnitContextContract("execute-task");
|
|
116
136
|
|
|
@@ -109,3 +109,49 @@ test("appendDiscoveredSkillsFallback does not duplicate skills already in the pr
|
|
|
109
109
|
location: "/tmp/already-loaded/SKILL.md",
|
|
110
110
|
}]), prompt);
|
|
111
111
|
});
|
|
112
|
+
|
|
113
|
+
test("snapshotSkills({cwd}) detects skills added to the project .agents/skills/ mid-session", async () => {
|
|
114
|
+
await withTempSkillHome(async (home) => {
|
|
115
|
+
// Use a project dir under the temp home so cwd is isolated.
|
|
116
|
+
const projectDir = join(home, "myproject");
|
|
117
|
+
const projectSkills = join(projectDir, ".agents", "skills");
|
|
118
|
+
snapshotSkills({ cwd: projectDir });
|
|
119
|
+
|
|
120
|
+
// Add a skill to the project skills dir after the snapshot.
|
|
121
|
+
writeDiskSkill(projectSkills, "project-disk-skill", "Project skill added mid-session.");
|
|
122
|
+
const detected = detectNewSkills();
|
|
123
|
+
|
|
124
|
+
assert.deepEqual(detected.map(skill => skill.name), ["project-disk-skill"]);
|
|
125
|
+
assert.equal(detected[0].location, join(projectSkills, "project-disk-skill", "SKILL.md"));
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
test("snapshotSkills({cwd}) detects skills added to the project .claude/skills/ mid-session", async () => {
|
|
130
|
+
await withTempSkillHome(async (home) => {
|
|
131
|
+
const projectDir = join(home, "claude-project");
|
|
132
|
+
const claudeSkills = join(projectDir, ".claude", "skills");
|
|
133
|
+
snapshotSkills({ cwd: projectDir });
|
|
134
|
+
|
|
135
|
+
writeDiskSkill(claudeSkills, "claude-project-skill", "Claude-format skill added mid-session.");
|
|
136
|
+
const detected = detectNewSkills();
|
|
137
|
+
|
|
138
|
+
assert.deepEqual(detected.map(skill => skill.name), ["claude-project-skill"]);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
test("snapshotSkills({cwd}) treats skills already in the project dir as baseline, not newly discovered", async () => {
|
|
143
|
+
await withTempSkillHome(async (home) => {
|
|
144
|
+
// projectDir is intentionally NOT process.cwd(): mirrors auto-mode passing a
|
|
145
|
+
// base path that differs from cwd (e.g. after chdir into a worktree). The
|
|
146
|
+
// baseline must scan the passed cwd's dirs, so a skill present *before* the
|
|
147
|
+
// snapshot is part of the baseline and is never reported as newly discovered.
|
|
148
|
+
// Regresses the fix where snapshotCurrentSkillNames fell back to process.cwd().
|
|
149
|
+
const projectDir = join(home, "preexisting-project");
|
|
150
|
+
const projectSkills = join(projectDir, ".agents", "skills");
|
|
151
|
+
writeDiskSkill(projectSkills, "preexisting-project-skill");
|
|
152
|
+
|
|
153
|
+
snapshotSkills({ cwd: projectDir });
|
|
154
|
+
|
|
155
|
+
assert.deepEqual(detectNewSkills(), []);
|
|
156
|
+
});
|
|
157
|
+
});
|
|
@@ -12,11 +12,9 @@ import { join, sep } from "node:path";
|
|
|
12
12
|
import { tmpdir } from "node:os";
|
|
13
13
|
import { execSync } from "node:child_process";
|
|
14
14
|
|
|
15
|
-
import {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
mergeMilestoneToMain,
|
|
19
|
-
} from "../auto-worktree.ts";
|
|
15
|
+
import { createAutoWorktree } from "../auto-worktree-creation.ts";
|
|
16
|
+
import { mergeMilestoneToMain } from "../auto-worktree-merge.ts";
|
|
17
|
+
import { teardownAutoWorktree } from "../auto-worktree-teardown.ts";
|
|
20
18
|
import { _resetServiceCache } from "../worktree.ts";
|
|
21
19
|
import { _clearGsdRootCache } from "../paths.ts";
|
|
22
20
|
|
|
@@ -14,7 +14,8 @@ import { join } from "node:path";
|
|
|
14
14
|
import { tmpdir } from "node:os";
|
|
15
15
|
import { execSync } from "node:child_process";
|
|
16
16
|
|
|
17
|
-
import { createAutoWorktree
|
|
17
|
+
import { createAutoWorktree } from "../auto-worktree-creation.ts";
|
|
18
|
+
import { mergeMilestoneToMain } from "../auto-worktree-merge.ts";
|
|
18
19
|
import { _resetServiceCache } from "../worktree.ts";
|
|
19
20
|
import { _clearGsdRootCache } from "../paths.ts";
|
|
20
21
|
|
|
@@ -28,7 +28,8 @@ import { join } from "node:path";
|
|
|
28
28
|
import { tmpdir } from "node:os";
|
|
29
29
|
import { execSync } from "node:child_process";
|
|
30
30
|
|
|
31
|
-
import { createAutoWorktree
|
|
31
|
+
import { createAutoWorktree } from "../auto-worktree-creation.ts";
|
|
32
|
+
import { mergeMilestoneToMain } from "../auto-worktree-merge.ts";
|
|
32
33
|
import { _resetServiceCache } from "../worktree.ts";
|
|
33
34
|
import { _clearGsdRootCache } from "../paths.ts";
|
|
34
35
|
|
|
@@ -8,7 +8,7 @@ import { mkdtempSync, mkdirSync, existsSync, readFileSync, rmSync, writeFileSync
|
|
|
8
8
|
import { join } from "node:path";
|
|
9
9
|
import { tmpdir } from "node:os";
|
|
10
10
|
import { appendOverride, loadActiveOverrides } from "../files.ts";
|
|
11
|
-
import { getAutoWorktreePath } from "../auto-worktree.ts";
|
|
11
|
+
import { getAutoWorktreePath } from "../auto-worktree-path-resolution.ts";
|
|
12
12
|
|
|
13
13
|
describe("steer worktree path resolution (#3476)", () => {
|
|
14
14
|
let projectRoot: string;
|
|
@@ -8,7 +8,7 @@ import { existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:
|
|
|
8
8
|
import { join } from "node:path";
|
|
9
9
|
import { tmpdir } from "node:os";
|
|
10
10
|
|
|
11
|
-
import { syncWorktreeStateBack } from "../auto-worktree.ts";
|
|
11
|
+
import { syncWorktreeStateBack } from "../auto-worktree-sync.ts";
|
|
12
12
|
|
|
13
13
|
describe("syncWorktreeStateBack does not copy worktree milestone projections", () => {
|
|
14
14
|
it("copies root diagnostics but leaves milestone markdown directories behind", () => {
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// gsd-pi — Regression tests: system.md documents the flat-phase layout, not legacy milestone/slice/task paths
|
|
2
|
+
|
|
3
|
+
import test from "node:test";
|
|
4
|
+
import assert from "node:assert/strict";
|
|
5
|
+
import { readFileSync } from "node:fs";
|
|
6
|
+
import { join } from "node:path";
|
|
7
|
+
|
|
8
|
+
const promptsDir = join(process.cwd(), "src/resources/extensions/gsd/prompts");
|
|
9
|
+
|
|
10
|
+
function readPrompt(name: string): string {
|
|
11
|
+
return readFileSync(join(promptsDir, `${name}.md`), "utf-8");
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
test("system.md does not advertise legacy milestone/slice/task artifact paths", () => {
|
|
15
|
+
const prompt = readPrompt("system");
|
|
16
|
+
for (const legacy of [".gsd/milestones", "milestones/M001", "slices/S01", "tasks/T01-PLAN.md"]) {
|
|
17
|
+
assert.ok(
|
|
18
|
+
!prompt.includes(legacy),
|
|
19
|
+
`system.md must not reference the legacy path fragment "${legacy}" after flat-phase migration`,
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test("system.md documents the flat-phase directory structure", () => {
|
|
25
|
+
const prompt = readPrompt("system");
|
|
26
|
+
assert.match(prompt, /phases\/\{MM\}-\{slug\}/, "system.md must document phases/{MM}-{slug}/ directories");
|
|
27
|
+
assert.match(prompt, /\{MM\}-\{SS\}-PLAN\.md/, "system.md must document {MM}-{SS}-PLAN.md slice plans");
|
|
28
|
+
assert.match(
|
|
29
|
+
prompt,
|
|
30
|
+
/do not expect `tasks\/T##-PLAN\.md`/,
|
|
31
|
+
"system.md must state task plan content lives inside the slice plan, not tasks/T##-PLAN.md",
|
|
32
|
+
);
|
|
33
|
+
});
|
|
@@ -36,13 +36,13 @@ import { join } from "node:path";
|
|
|
36
36
|
import { tmpdir } from "node:os";
|
|
37
37
|
import { execFileSync } from "node:child_process";
|
|
38
38
|
|
|
39
|
+
import { createAutoWorktree } from "../auto-worktree-creation.ts";
|
|
39
40
|
import {
|
|
40
|
-
createAutoWorktree,
|
|
41
|
-
teardownAutoWorktree,
|
|
42
|
-
getAutoWorktreeOriginalBase,
|
|
43
41
|
getActiveAutoWorktreeContext,
|
|
42
|
+
getAutoWorktreeOriginalBase,
|
|
44
43
|
_resetAutoWorktreeOriginalBaseForTests,
|
|
45
|
-
} from "../auto-worktree.ts";
|
|
44
|
+
} from "../auto-worktree-session-registry.ts";
|
|
45
|
+
import { teardownAutoWorktree } from "../auto-worktree-teardown.ts";
|
|
46
46
|
|
|
47
47
|
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
48
48
|
|
|
@@ -22,7 +22,8 @@ import { join } from "node:path";
|
|
|
22
22
|
import { tmpdir } from "node:os";
|
|
23
23
|
import { execFileSync } from "node:child_process";
|
|
24
24
|
|
|
25
|
-
import {
|
|
25
|
+
import { _resetAutoWorktreeOriginalBaseForTests } from "../auto-worktree-session-registry.ts";
|
|
26
|
+
import { teardownAutoWorktree } from "../auto-worktree-teardown.ts";
|
|
26
27
|
|
|
27
28
|
function git(args: string[], cwd: string): void {
|
|
28
29
|
execFileSync("git", args, { cwd, stdio: ["ignore", "pipe", "pipe"] });
|
|
@@ -38,13 +38,13 @@ import { join } from "node:path";
|
|
|
38
38
|
import { tmpdir } from "node:os";
|
|
39
39
|
import { execFileSync } from "node:child_process";
|
|
40
40
|
|
|
41
|
+
import { createAutoWorktree } from "../auto-worktree-creation.ts";
|
|
41
42
|
import {
|
|
42
|
-
createAutoWorktree,
|
|
43
|
-
teardownAutoWorktree,
|
|
44
|
-
getAutoWorktreeOriginalBase,
|
|
45
43
|
getActiveAutoWorktreeContext,
|
|
44
|
+
getAutoWorktreeOriginalBase,
|
|
46
45
|
_resetAutoWorktreeOriginalBaseForTests,
|
|
47
|
-
} from "../auto-worktree.ts";
|
|
46
|
+
} from "../auto-worktree-session-registry.ts";
|
|
47
|
+
import { teardownAutoWorktree } from "../auto-worktree-teardown.ts";
|
|
48
48
|
|
|
49
49
|
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
50
50
|
|
|
@@ -7,6 +7,7 @@ import { test } from 'node:test';
|
|
|
7
7
|
import assert from 'node:assert/strict';
|
|
8
8
|
import {
|
|
9
9
|
checkToolCallLoop,
|
|
10
|
+
configureToolCallLoopGuard,
|
|
10
11
|
recordToolCallLoopMutation,
|
|
11
12
|
resetToolCallLoopGuard,
|
|
12
13
|
disableToolCallLoopGuard,
|
|
@@ -251,6 +252,99 @@ console.log('\n── Loop guard: mutation progress decays per-tool counts (#109
|
|
|
251
252
|
}
|
|
252
253
|
}
|
|
253
254
|
|
|
255
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
256
|
+
// Successful shell/exec progress decays per-tool counts (#1206)
|
|
257
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
258
|
+
|
|
259
|
+
console.log('\n── Loop guard: successful shell/exec progress decays per-tool counts (#1206) ──');
|
|
260
|
+
|
|
261
|
+
{
|
|
262
|
+
// A local model debugging a UAT scenario runs many varied bg_shell /
|
|
263
|
+
// gsd_uat_exec calls (restart server, npm install, curl an endpoint). Each
|
|
264
|
+
// successful call is state progression, so Guard 2 must decay and never
|
|
265
|
+
// block the productive turn — even past the repeatable cap.
|
|
266
|
+
for (const execTool of ['bg_shell', 'gsd_uat_exec', 'bash', 'gsd_exec']) {
|
|
267
|
+
resetToolCallLoopGuard();
|
|
268
|
+
|
|
269
|
+
for (let i = 1; i <= 20; i++) {
|
|
270
|
+
const result = checkToolCallLoop(execTool, { command: `step ${i}` });
|
|
271
|
+
assert.ok(result.block === false, `${execTool} call ${i} after exec progress should be allowed`);
|
|
272
|
+
assert.deepStrictEqual(getToolCallCountForTool(execTool), 1, `${execTool} count should decay before call ${i}`);
|
|
273
|
+
|
|
274
|
+
// A successful (non-error) exec call records progress, like a file mutation.
|
|
275
|
+
recordToolCallLoopMutation(execTool);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
281
|
+
// Failing exec loops still trip the per-tool cap (#783 vs #1206)
|
|
282
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
283
|
+
|
|
284
|
+
console.log('\n── Loop guard: failing exec loop (no progress recorded) still trips the cap (#783) ──');
|
|
285
|
+
|
|
286
|
+
{
|
|
287
|
+
resetToolCallLoopGuard();
|
|
288
|
+
|
|
289
|
+
// The improvisation loop from #783: the model retries a missing tool through
|
|
290
|
+
// varied bash commands. Those fail (non-zero exit → isError), so the caller
|
|
291
|
+
// never records progress and the per-tool cap must still trip.
|
|
292
|
+
for (let i = 1; i <= 15; i++) {
|
|
293
|
+
const result = checkToolCallLoop('bash', { command: `try-missing-tool ${i}` });
|
|
294
|
+
assert.ok(result.block === false, `failing bash call ${i} should be allowed up to the cap`);
|
|
295
|
+
// No recordToolCallLoopMutation — the command errored.
|
|
296
|
+
}
|
|
297
|
+
const blocked = checkToolCallLoop('bash', { command: 'try-missing-tool 16' });
|
|
298
|
+
assert.ok(blocked.block === true, '16th failing bash call should be blocked by the per-tool cap');
|
|
299
|
+
assert.ok(blocked.reason?.includes('repeated tool'), 'reason should identify the per-tool guard');
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
303
|
+
// bg_shell/async_bash false-success must not decay the per-tool cap (#783)
|
|
304
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
305
|
+
|
|
306
|
+
console.log('\n── Loop guard: bg_shell failed run/start does not decay the cap (#783) ──');
|
|
307
|
+
|
|
308
|
+
{
|
|
309
|
+
resetToolCallLoopGuard();
|
|
310
|
+
|
|
311
|
+
for (let i = 1; i <= 15; i++) {
|
|
312
|
+
const result = checkToolCallLoop('bg_shell', { action: 'run', command: `try-missing-tool ${i}` });
|
|
313
|
+
assert.ok(result.block === false, `failing bg_shell run ${i} should be allowed up to the cap`);
|
|
314
|
+
recordToolCallLoopMutation('bg_shell', { action: 'run', exitCode: 1, timedOut: false });
|
|
315
|
+
}
|
|
316
|
+
const blocked = checkToolCallLoop('bg_shell', { action: 'run', command: 'try-missing-tool 16' });
|
|
317
|
+
assert.ok(blocked.block === true, '16th failing bg_shell run should be blocked by the per-tool cap');
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
{
|
|
321
|
+
resetToolCallLoopGuard();
|
|
322
|
+
|
|
323
|
+
for (let i = 1; i <= 15; i++) {
|
|
324
|
+
checkToolCallLoop('bg_shell', { action: 'start', command: `bad-server ${i}` });
|
|
325
|
+
recordToolCallLoopMutation('bg_shell', {
|
|
326
|
+
action: 'start',
|
|
327
|
+
process: { alive: false, exitCode: 1 },
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
const blocked = checkToolCallLoop('bg_shell', { action: 'start', command: 'bad-server 16' });
|
|
331
|
+
assert.ok(blocked.block === true, '16th dead bg_shell start should be blocked by the per-tool cap');
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
console.log('\n── Loop guard: async_bash job registration does not decay the cap (#783) ──');
|
|
335
|
+
|
|
336
|
+
{
|
|
337
|
+
resetToolCallLoopGuard();
|
|
338
|
+
|
|
339
|
+
for (let i = 1; i <= 6; i++) {
|
|
340
|
+
const result = checkToolCallLoop('async_bash', { command: `try-missing-tool ${i}` });
|
|
341
|
+
assert.ok(result.block === false, `async_bash call ${i} should be allowed up to the cap`);
|
|
342
|
+
recordToolCallLoopMutation('async_bash');
|
|
343
|
+
}
|
|
344
|
+
const blocked = checkToolCallLoop('async_bash', { command: 'try-missing-tool 7' });
|
|
345
|
+
assert.ok(blocked.block === true, '7th async_bash call should be blocked by the per-tool cap');
|
|
346
|
+
}
|
|
347
|
+
|
|
254
348
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
255
349
|
// Distinct read-only navigation calls are context gathering, not repeated-tool loops.
|
|
256
350
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -448,3 +542,105 @@ console.log('\n── Loop guard: browser exemption does not widen to other tool
|
|
|
448
542
|
}
|
|
449
543
|
|
|
450
544
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
545
|
+
// Configurable thresholds (#1198)
|
|
546
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
547
|
+
|
|
548
|
+
console.log('\n── Loop guard: master switch disables both guards (#1198) ──');
|
|
549
|
+
|
|
550
|
+
{
|
|
551
|
+
configureToolCallLoopGuard({ enabled: false });
|
|
552
|
+
resetToolCallLoopGuard();
|
|
553
|
+
// Neither identical-args nor per-tool cap should ever trip while disabled.
|
|
554
|
+
for (let i = 1; i <= 30; i++) {
|
|
555
|
+
const result = checkToolCallLoop('gsd_complete_milestone', { same: 'args' });
|
|
556
|
+
assert.ok(result.block === false, `disabled guard should allow call ${i}`);
|
|
557
|
+
}
|
|
558
|
+
// Restore defaults for subsequent tests.
|
|
559
|
+
configureToolCallLoopGuard(null);
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
console.log('\n── Loop guard: repeated_tool disabled keeps identical-args protection (#1198) ──');
|
|
563
|
+
|
|
564
|
+
{
|
|
565
|
+
configureToolCallLoopGuard({ repeated_tool: { enabled: false } });
|
|
566
|
+
resetToolCallLoopGuard();
|
|
567
|
+
// Per-tool cap is off: many varied-arg calls are allowed.
|
|
568
|
+
for (let i = 1; i <= 20; i++) {
|
|
569
|
+
const result = checkToolCallLoop('gsd_exec', { cmd: `run-${i}` });
|
|
570
|
+
assert.ok(result.block === false, `repeated_tool disabled should allow varied call ${i}`);
|
|
571
|
+
}
|
|
572
|
+
// Identical-args guard is still active.
|
|
573
|
+
resetToolCallLoopGuard();
|
|
574
|
+
for (let i = 1; i <= 4; i++) {
|
|
575
|
+
assert.ok(checkToolCallLoop('gsd_exec', { cmd: 'same' }).block === false);
|
|
576
|
+
}
|
|
577
|
+
const blocked = checkToolCallLoop('gsd_exec', { cmd: 'same' });
|
|
578
|
+
assert.ok(blocked.block === true, 'identical-args guard should still trip when repeated_tool is off');
|
|
579
|
+
assert.ok(blocked.reason?.includes('identical args'));
|
|
580
|
+
configureToolCallLoopGuard(null);
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
console.log('\n── Loop guard: raised caps allow more repeated calls (#1198) ──');
|
|
584
|
+
|
|
585
|
+
{
|
|
586
|
+
configureToolCallLoopGuard({ repeated_tool: { default_cap: 10 } });
|
|
587
|
+
resetToolCallLoopGuard();
|
|
588
|
+
for (let i = 1; i <= 10; i++) {
|
|
589
|
+
const result = checkToolCallLoop('gsd_complete_milestone', { arg: `v${i}` });
|
|
590
|
+
assert.ok(result.block === false, `raised-cap call ${i} should be allowed`);
|
|
591
|
+
}
|
|
592
|
+
const blocked = checkToolCallLoop('gsd_complete_milestone', { arg: 'v11' });
|
|
593
|
+
assert.ok(blocked.block === true, '11th call should trip the raised cap of 10');
|
|
594
|
+
assert.ok(blocked.reason?.includes('cap 10'), 'block message should mention the active cap');
|
|
595
|
+
assert.ok(blocked.reason?.includes('tool_call_loop_guard'), 'block message should mention the config key');
|
|
596
|
+
configureToolCallLoopGuard(null);
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
console.log('\n── Loop guard: user-added exempt tools bypass the per-tool cap (#1198) ──');
|
|
600
|
+
|
|
601
|
+
{
|
|
602
|
+
configureToolCallLoopGuard({ repeated_tool: { exempt_tools: ['ctx_execute'] } });
|
|
603
|
+
resetToolCallLoopGuard();
|
|
604
|
+
for (let i = 1; i <= 30; i++) {
|
|
605
|
+
const result = checkToolCallLoop('ctx_execute', { arg: `v${i}` });
|
|
606
|
+
assert.ok(result.block === false, `exempt tool call ${i} should be allowed`);
|
|
607
|
+
}
|
|
608
|
+
// Built-in exempt defaults are preserved alongside the user-added tool.
|
|
609
|
+
resetToolCallLoopGuard();
|
|
610
|
+
for (let i = 1; i <= 30; i++) {
|
|
611
|
+
assert.ok(checkToolCallLoop('read', { path: `f${i}` }).block === false, 'built-in exempt read should remain exempt');
|
|
612
|
+
}
|
|
613
|
+
configureToolCallLoopGuard(null);
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
console.log('\n── Loop guard: identical-args max is configurable (#1198) ──');
|
|
617
|
+
|
|
618
|
+
{
|
|
619
|
+
configureToolCallLoopGuard({ identical_args: { max_consecutive_calls: 2 } });
|
|
620
|
+
resetToolCallLoopGuard();
|
|
621
|
+
assert.ok(checkToolCallLoop('web_search', { q: 'x' }).block === false, 'call 1 allowed');
|
|
622
|
+
assert.ok(checkToolCallLoop('web_search', { q: 'x' }).block === false, 'call 2 allowed');
|
|
623
|
+
const blocked = checkToolCallLoop('web_search', { q: 'x' });
|
|
624
|
+
assert.ok(blocked.block === true, '3rd identical call should trip lowered max of 2');
|
|
625
|
+
assert.ok(blocked.reason?.includes('max 2'), 'block message should mention active max');
|
|
626
|
+
configureToolCallLoopGuard(null);
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
console.log('\n── Loop guard: env overrides win over preferences (#1198) ──');
|
|
630
|
+
|
|
631
|
+
{
|
|
632
|
+
process.env.GSD_TOOL_LOOP_REPEATED_DEFAULT_CAP = '2';
|
|
633
|
+
configureToolCallLoopGuard({ repeated_tool: { default_cap: 6 } });
|
|
634
|
+
resetToolCallLoopGuard();
|
|
635
|
+
assert.ok(checkToolCallLoop('gsd_complete_milestone', { a: '1' }).block === false, 'call 1 allowed');
|
|
636
|
+
assert.ok(checkToolCallLoop('gsd_complete_milestone', { a: '2' }).block === false, 'call 2 allowed');
|
|
637
|
+
const blocked = checkToolCallLoop('gsd_complete_milestone', { a: '3' });
|
|
638
|
+
assert.ok(blocked.block === true, 'env override cap of 2 should win over preference cap of 6');
|
|
639
|
+
delete process.env.GSD_TOOL_LOOP_REPEATED_DEFAULT_CAP;
|
|
640
|
+
configureToolCallLoopGuard(null);
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
644
|
+
// Reset restores default guard state after configuration tests
|
|
645
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
646
|
+
resetToolCallLoopGuard();
|
|
@@ -30,7 +30,7 @@ import { join } from "node:path";
|
|
|
30
30
|
import { tmpdir } from "node:os";
|
|
31
31
|
import { execFileSync } from "node:child_process";
|
|
32
32
|
|
|
33
|
-
import { syncProjectRootToWorktree } from "../auto-worktree.ts";
|
|
33
|
+
import { syncProjectRootToWorktree } from "../auto-worktree-sync.ts";
|
|
34
34
|
import {
|
|
35
35
|
createWorktree,
|
|
36
36
|
removeWorktree,
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
getUnitDescriptor,
|
|
19
19
|
getUnitPhaseChain,
|
|
20
20
|
getUnitPromptTemplate,
|
|
21
|
+
getUnitPromptTemplates,
|
|
21
22
|
} from "../unit-registry.ts";
|
|
22
23
|
import {
|
|
23
24
|
AUTO_UNIT_SCOPED_TOOLS,
|
|
@@ -123,13 +124,16 @@ const EXPECTED_DIRECT_PROMPT_TEMPLATES: Record<string, string> = {
|
|
|
123
124
|
};
|
|
124
125
|
|
|
125
126
|
const EXPECTED_UNDECLARED_PROMPT_TEMPLATE_TYPES = [
|
|
126
|
-
"discuss-milestone",
|
|
127
127
|
"discuss-slice",
|
|
128
128
|
"execute-task-simple",
|
|
129
129
|
"triage-captures",
|
|
130
130
|
"quick-task",
|
|
131
131
|
];
|
|
132
132
|
|
|
133
|
+
const EXPECTED_CONDITIONAL_PROMPT_TEMPLATES: Record<string, string[]> = {
|
|
134
|
+
"discuss-milestone": ["discuss", "discuss-headless", "guided-discuss-milestone"],
|
|
135
|
+
};
|
|
136
|
+
|
|
133
137
|
// ─── Derived-view parity ──────────────────────────────────────────────────
|
|
134
138
|
|
|
135
139
|
test("KNOWN_UNIT_TYPES derives exactly the pre-registry list, in order", () => {
|
|
@@ -190,6 +194,27 @@ test("direct prompt-template associations live on the Unit Registry", () => {
|
|
|
190
194
|
}
|
|
191
195
|
});
|
|
192
196
|
|
|
197
|
+
test("conditional prompt-template associations live on the Unit Registry without pretending to be direct", () => {
|
|
198
|
+
for (const [unitType, promptTemplates] of Object.entries(EXPECTED_CONDITIONAL_PROMPT_TEMPLATES)) {
|
|
199
|
+
assert.equal(
|
|
200
|
+
getUnitPromptTemplate(unitType),
|
|
201
|
+
undefined,
|
|
202
|
+
`${unitType} must not expose a single direct prompt template`,
|
|
203
|
+
);
|
|
204
|
+
assert.deepEqual(
|
|
205
|
+
getUnitPromptTemplates(unitType),
|
|
206
|
+
promptTemplates,
|
|
207
|
+
`prompt templates for ${unitType}`,
|
|
208
|
+
);
|
|
209
|
+
for (const promptTemplate of promptTemplates) {
|
|
210
|
+
assert.ok(
|
|
211
|
+
existsSync(join(process.cwd(), "src/resources/extensions/gsd/prompts", `${promptTemplate}.md`)),
|
|
212
|
+
`prompt template file must exist for ${unitType}: ${promptTemplate}`,
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
|
|
193
218
|
test("AUTO_UNIT_SCOPED_TOOLS mirrors each contract's allowed tools", () => {
|
|
194
219
|
for (const [unitType, contract] of Object.entries(UNIT_TOOL_CONTRACTS)) {
|
|
195
220
|
assert.deepEqual(AUTO_UNIT_SCOPED_TOOLS[unitType], contract.allowedGsdTools);
|
|
@@ -17,7 +17,7 @@ import { join } from "node:path";
|
|
|
17
17
|
import { tmpdir } from "node:os";
|
|
18
18
|
import { execSync } from "node:child_process";
|
|
19
19
|
|
|
20
|
-
import { createAutoWorktree } from "../auto-worktree.ts";
|
|
20
|
+
import { createAutoWorktree } from "../auto-worktree-creation.ts";
|
|
21
21
|
import { worktreePath } from "../worktree-manager.ts";
|
|
22
22
|
import {
|
|
23
23
|
copyWorktreeDb,
|
|
@@ -17,7 +17,7 @@ import { mkdtempSync, mkdirSync, writeFileSync, rmSync, existsSync, readFileSync
|
|
|
17
17
|
import { join } from 'node:path';
|
|
18
18
|
import { tmpdir } from 'node:os';
|
|
19
19
|
|
|
20
|
-
import { syncProjectRootToWorktree } from '../auto-worktree.ts';
|
|
20
|
+
import { syncProjectRootToWorktree } from '../auto-worktree-sync.ts';
|
|
21
21
|
import { describe, test } from 'node:test';
|
|
22
22
|
import assert from 'node:assert/strict';
|
|
23
23
|
|
|
@@ -18,9 +18,7 @@ import {
|
|
|
18
18
|
reconcileWorktreeDb,
|
|
19
19
|
insertDecision,
|
|
20
20
|
} from "../gsd-db.ts";
|
|
21
|
-
import {
|
|
22
|
-
_shouldReconcileWorktreeDb,
|
|
23
|
-
} from "../auto-worktree.ts";
|
|
21
|
+
import { _shouldReconcileWorktreeDb } from "../auto-worktree-sync.ts";
|
|
24
22
|
import { isInfrastructureError } from "../auto/infra-errors.ts";
|
|
25
23
|
|
|
26
24
|
describe("#2823: reconcileWorktreeDb same-file guard", () => {
|
|
@@ -6,7 +6,7 @@ import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
|
6
6
|
import { join, resolve } from "node:path";
|
|
7
7
|
import { tmpdir } from "node:os";
|
|
8
8
|
|
|
9
|
-
import { _isExpectedWorktreeUnlinkError } from "../auto-worktree.ts";
|
|
9
|
+
import { _isExpectedWorktreeUnlinkError } from "../auto-worktree-path-utils.ts";
|
|
10
10
|
import { resolveGitDir } from "../worktree-manager.ts";
|
|
11
11
|
|
|
12
12
|
describe("worktree expected-condition warning suppression (#3665)", () => {
|
|
@@ -5,7 +5,7 @@ import { join } from "node:path";
|
|
|
5
5
|
import { tmpdir } from "node:os";
|
|
6
6
|
import { execFileSync } from "node:child_process";
|
|
7
7
|
|
|
8
|
-
import { _gitPathspecForWorktreePath } from "../auto-worktree.ts";
|
|
8
|
+
import { _gitPathspecForWorktreePath } from "../auto-worktree-path-utils.ts";
|
|
9
9
|
|
|
10
10
|
function run(cmd: string, args: string[], cwd: string): string {
|
|
11
11
|
return execFileSync(cmd, args, { cwd, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }).trim();
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { test } from "node:test";
|
|
4
4
|
import assert from "node:assert/strict";
|
|
5
5
|
|
|
6
|
-
import { _resolveAutoWorktreeStartPoint } from "../auto-worktree.ts";
|
|
6
|
+
import { _resolveAutoWorktreeStartPoint } from "../auto-worktree-branch-lifecycle.ts";
|
|
7
7
|
|
|
8
8
|
test("auto-worktree start point prefers milestone integration branch", () => {
|
|
9
9
|
const startPoint = _resolveAutoWorktreeStartPoint(
|
|
@@ -13,7 +13,8 @@ import { join } from "node:path";
|
|
|
13
13
|
import { tmpdir } from "node:os";
|
|
14
14
|
import { execFileSync } from "node:child_process";
|
|
15
15
|
|
|
16
|
-
import { createAutoWorktree
|
|
16
|
+
import { createAutoWorktree } from "../auto-worktree-creation.ts";
|
|
17
|
+
import { _resetAutoWorktreeOriginalBaseForTests } from "../auto-worktree-session-registry.ts";
|
|
17
18
|
import { reenterActiveWorktreeIfNeeded } from "../worktree-reentry.ts";
|
|
18
19
|
|
|
19
20
|
// Safe: all inputs below are hardcoded test strings, not user input.
|
|
@@ -27,8 +27,11 @@ import { mkdtempSync, mkdirSync, writeFileSync, rmSync, existsSync, readFileSync
|
|
|
27
27
|
import { join } from 'node:path';
|
|
28
28
|
import { tmpdir } from 'node:os';
|
|
29
29
|
|
|
30
|
-
import {
|
|
31
|
-
|
|
30
|
+
import {
|
|
31
|
+
syncGsdStateToWorktree,
|
|
32
|
+
syncProjectRootToWorktree,
|
|
33
|
+
syncWorktreeStateBack,
|
|
34
|
+
} from '../auto-worktree-sync.ts';
|
|
32
35
|
import { describe, test } from 'node:test';
|
|
33
36
|
import assert from 'node:assert/strict';
|
|
34
37
|
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
import { join } from "node:path";
|
|
26
26
|
import { tmpdir } from "node:os";
|
|
27
27
|
|
|
28
|
-
import { syncProjectRootToWorktree } from "../auto-worktree.ts";
|
|
28
|
+
import { syncProjectRootToWorktree } from "../auto-worktree-sync.ts";
|
|
29
29
|
|
|
30
30
|
function createBase(name: string): string {
|
|
31
31
|
const base = mkdtempSync(join(tmpdir(), `gsd-wt-1886-${name}-`));
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
import { join } from "node:path";
|
|
19
19
|
import { tmpdir } from "node:os";
|
|
20
20
|
|
|
21
|
-
import { syncWorktreeStateBack } from "../auto-worktree.ts";
|
|
21
|
+
import { syncWorktreeStateBack } from "../auto-worktree-sync.ts";
|
|
22
22
|
|
|
23
23
|
function makeTempDir(prefix: string): string {
|
|
24
24
|
return mkdtempSync(join(tmpdir(), `gsd-sync-test-${prefix}-`));
|