@opengsd/gsd-pi 1.5.0-dev.553dc518 → 1.5.0-dev.c4c8885f
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/ask-user-questions.js +1 -1
- package/dist/resources/extensions/browser-tools/engine/managed-gsd-browser.js +114 -36
- package/dist/resources/extensions/gsd/activity-log.js +1 -1
- package/dist/resources/extensions/gsd/auto/orchestrator.js +16 -10
- package/dist/resources/extensions/gsd/auto-artifact-paths.js +14 -5
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +7 -2
- package/dist/resources/extensions/gsd/auto-dispatch.js +69 -17
- package/dist/resources/extensions/gsd/auto-model-selection.js +28 -1
- package/dist/resources/extensions/gsd/auto-post-unit.js +4 -3
- package/dist/resources/extensions/gsd/auto-prompts.js +29 -117
- package/dist/resources/extensions/gsd/auto-recovery.js +50 -6
- package/dist/resources/extensions/gsd/auto-start.js +54 -31
- package/dist/resources/extensions/gsd/auto-timeout-recovery.js +12 -2
- package/dist/resources/extensions/gsd/auto-timers.js +9 -2
- package/dist/resources/extensions/gsd/auto.js +97 -31
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +1 -1
- package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +67 -6
- package/dist/resources/extensions/gsd/codebase-generator.js +7 -1
- package/dist/resources/extensions/gsd/compat/compat-marker.js +44 -0
- package/dist/resources/extensions/gsd/config-overlay.js +7 -2
- package/dist/resources/extensions/gsd/db/engine.js +33 -0
- package/dist/resources/extensions/gsd/db/writers/cascades.js +20 -2
- package/dist/resources/extensions/gsd/db-adapter.js +30 -3
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +3 -3
- package/dist/resources/extensions/gsd/flat-phase-migration.js +18 -0
- package/dist/resources/extensions/gsd/gsd-db.js +12 -11
- package/dist/resources/extensions/gsd/guided-flow.js +16 -7
- package/dist/resources/extensions/gsd/journal.js +1 -1
- package/dist/resources/extensions/gsd/markdown-renderer.js +34 -91
- package/dist/resources/extensions/gsd/md-importer.js +89 -23
- package/dist/resources/extensions/gsd/metrics.js +2 -2
- package/dist/resources/extensions/gsd/migration-auto-check.js +30 -3
- package/dist/resources/extensions/gsd/paths.js +87 -52
- package/dist/resources/extensions/gsd/post-unit-hooks.js +27 -0
- package/dist/resources/extensions/gsd/preferences-models.js +66 -15
- package/dist/resources/extensions/gsd/preferences-skills.js +10 -16
- package/dist/resources/extensions/gsd/preferences-validation.js +66 -10
- package/dist/resources/extensions/gsd/preferences.js +20 -0
- package/dist/resources/extensions/gsd/rule-registry.js +106 -10
- package/dist/resources/extensions/gsd/skill-discovery.js +36 -23
- package/dist/resources/extensions/gsd/state-reconciliation/drift/artifact-db.js +1 -10
- package/dist/resources/extensions/gsd/state-reconciliation/drift/completion.js +3 -24
- package/dist/resources/extensions/gsd/state-reconciliation/index.js +10 -0
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +3 -5
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +16 -10
- 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/tools/validate-milestone.js +3 -8
- package/dist/resources/extensions/gsd/uat-dispatch.js +94 -0
- package/dist/resources/extensions/gsd/uok/audit-toggle.js +31 -2
- package/dist/resources/extensions/gsd/uok/audit.js +3 -0
- package/dist/resources/extensions/gsd/uok/gate-runner.js +22 -30
- package/dist/resources/extensions/gsd/uok/gitops.js +18 -15
- package/dist/resources/extensions/gsd/uok/kernel.js +120 -46
- package/dist/resources/extensions/gsd/uok/model-policy.js +17 -14
- package/dist/resources/extensions/gsd/workflow-event-ledger.js +1 -1
- package/dist/resources/extensions/gsd/workflow-logger.js +1 -1
- package/dist/resources/extensions/gsd/workflow-projections.js +9 -26
- package/dist/resources/extensions/gsd/workspace.js +5 -14
- package/dist/resources/extensions/shared/gsd-browser-cli.js +29 -0
- 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 +10 -10
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +10 -10
- package/dist/web/standalone/.next/server/chunks/{1128.js → 1991.js} +1 -1
- package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/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/worktree-cli-create.d.ts +10 -0
- package/dist/worktree-cli-create.js +11 -0
- package/dist/worktree-cli-format.d.ts +12 -0
- package/dist/worktree-cli-format.js +38 -0
- package/dist/worktree-cli-plan.d.ts +16 -0
- package/dist/worktree-cli-plan.js +19 -0
- package/dist/worktree-cli-session.d.ts +13 -0
- package/dist/worktree-cli-session.js +18 -0
- package/dist/worktree-cli-status.d.ts +35 -0
- package/dist/worktree-cli-status.js +54 -0
- package/dist/worktree-cli.d.ts +1 -16
- package/dist/worktree-cli.js +28 -122
- package/integrations/hermes/open_gsd_hermes/gsd_client.py +1 -1
- package/integrations/hermes/pyproject.toml +1 -1
- package/package.json +1 -1
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/dist/orchestrator-agent.d.ts +21 -0
- package/packages/daemon/dist/orchestrator-agent.d.ts.map +1 -0
- package/packages/daemon/dist/orchestrator-agent.js +113 -0
- package/packages/daemon/dist/orchestrator-agent.js.map +1 -0
- package/packages/daemon/dist/orchestrator-tools.d.ts +12 -0
- package/packages/daemon/dist/orchestrator-tools.d.ts.map +1 -0
- package/packages/daemon/dist/orchestrator-tools.js +137 -0
- package/packages/daemon/dist/orchestrator-tools.js.map +1 -0
- package/packages/daemon/dist/orchestrator.d.ts +4 -56
- package/packages/daemon/dist/orchestrator.d.ts.map +1 -1
- package/packages/daemon/dist/orchestrator.js +13 -303
- package/packages/daemon/dist/orchestrator.js.map +1 -1
- package/packages/daemon/dist/orchestrator.test.js +11 -1
- package/packages/daemon/dist/orchestrator.test.js.map +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/package.json +5 -5
- 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/package.json +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/package.json +1 -1
- package/src/resources/extensions/ask-user-questions.ts +1 -1
- package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +146 -33
- package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +25 -0
- package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +93 -0
- package/src/resources/extensions/gsd/activity-log.ts +1 -1
- package/src/resources/extensions/gsd/auto/orchestrator.ts +17 -11
- package/src/resources/extensions/gsd/auto-artifact-paths.ts +14 -4
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +9 -2
- package/src/resources/extensions/gsd/auto-dispatch.ts +77 -16
- package/src/resources/extensions/gsd/auto-model-selection.ts +33 -1
- package/src/resources/extensions/gsd/auto-post-unit.ts +4 -2
- package/src/resources/extensions/gsd/auto-prompts.ts +53 -113
- package/src/resources/extensions/gsd/auto-recovery.ts +50 -6
- package/src/resources/extensions/gsd/auto-start.ts +58 -29
- package/src/resources/extensions/gsd/auto-timeout-recovery.ts +12 -2
- package/src/resources/extensions/gsd/auto-timers.ts +9 -2
- package/src/resources/extensions/gsd/auto.ts +103 -30
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +1 -1
- package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +66 -6
- package/src/resources/extensions/gsd/codebase-generator.ts +7 -1
- package/src/resources/extensions/gsd/compat/compat-marker.ts +47 -0
- package/src/resources/extensions/gsd/config-overlay.ts +7 -1
- package/src/resources/extensions/gsd/db/engine.ts +36 -0
- package/src/resources/extensions/gsd/db/writers/cascades.ts +23 -1
- package/src/resources/extensions/gsd/db-adapter.ts +29 -3
- package/src/resources/extensions/gsd/docs/preferences-reference.md +3 -3
- package/src/resources/extensions/gsd/flat-phase-migration.ts +20 -0
- package/src/resources/extensions/gsd/gsd-db.ts +20 -11
- package/src/resources/extensions/gsd/guided-flow.ts +19 -7
- package/src/resources/extensions/gsd/journal.ts +1 -1
- package/src/resources/extensions/gsd/markdown-renderer.ts +52 -103
- package/src/resources/extensions/gsd/md-importer.ts +93 -22
- package/src/resources/extensions/gsd/metrics.ts +2 -2
- package/src/resources/extensions/gsd/migration-auto-check.ts +32 -3
- package/src/resources/extensions/gsd/paths.ts +108 -51
- package/src/resources/extensions/gsd/post-unit-hooks.ts +32 -0
- package/src/resources/extensions/gsd/preferences-models.ts +74 -20
- package/src/resources/extensions/gsd/preferences-skills.ts +10 -16
- package/src/resources/extensions/gsd/preferences-types.ts +24 -1
- package/src/resources/extensions/gsd/preferences-validation.ts +77 -9
- package/src/resources/extensions/gsd/preferences.ts +20 -0
- package/src/resources/extensions/gsd/rule-registry.ts +111 -9
- package/src/resources/extensions/gsd/skill-discovery.ts +47 -23
- package/src/resources/extensions/gsd/state-reconciliation/drift/artifact-db.ts +1 -9
- package/src/resources/extensions/gsd/state-reconciliation/drift/completion.ts +2 -22
- package/src/resources/extensions/gsd/state-reconciliation/index.ts +14 -0
- package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +169 -1
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +41 -2
- package/src/resources/extensions/gsd/tests/auto-post-unit-artifact-diagnostic.test.ts +48 -1
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +57 -0
- package/src/resources/extensions/gsd/tests/auto-start-project-milestone-reconcile.test.ts +29 -1
- package/src/resources/extensions/gsd/tests/auto-timeout-recovery-supervisor-inflight-guard.test.ts +159 -0
- package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/compat-marker.test.ts +85 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/db-adapter.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/db-writable-probe.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/flat-phase-renderer.test.ts +22 -1
- package/src/resources/extensions/gsd/tests/flat-phase-validation-path.test.ts +72 -32
- package/src/resources/extensions/gsd/tests/import-completion-lost-update.test.ts +196 -0
- package/src/resources/extensions/gsd/tests/integration/paths.test.ts +88 -1
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +16 -15
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +91 -0
- package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +0 -1
- package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +269 -0
- package/src/resources/extensions/gsd/tests/post-unit-retry-on-orchestrator-bridge.test.ts +8 -1
- package/src/resources/extensions/gsd/tests/preferences.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/read-uat-gate-verdict.test.ts +54 -0
- package/src/resources/extensions/gsd/tests/reassess-handler.test.ts +49 -1
- package/src/resources/extensions/gsd/tests/reopen-slice.test.ts +52 -0
- package/src/resources/extensions/gsd/tests/rule-registry.test.ts +95 -1
- package/src/resources/extensions/gsd/tests/sibling-model-fallbacks.test.ts +189 -0
- package/src/resources/extensions/gsd/tests/single-field-model-thinking.test.ts +156 -0
- package/src/resources/extensions/gsd/tests/skill-discovery.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/skipped-validation-db-atomicity.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/supervisor-model-swap-inflight-guard.test.ts +181 -0
- package/src/resources/extensions/gsd/tests/supervisor-model-swap-thinking-clamp.test.ts +122 -0
- package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/uat-dispatch.test.ts +211 -0
- package/src/resources/extensions/gsd/tests/uok-gate-runner.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/uok-kernel-path.test.ts +226 -2
- package/src/resources/extensions/gsd/tests/uok-model-policy.test.ts +6 -0
- package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +213 -2
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +9 -5
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +19 -8
- 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/tools/validate-milestone.ts +13 -9
- package/src/resources/extensions/gsd/types.ts +23 -4
- package/src/resources/extensions/gsd/uat-dispatch.ts +176 -0
- package/src/resources/extensions/gsd/uok/audit-toggle.ts +32 -2
- package/src/resources/extensions/gsd/uok/audit.ts +2 -0
- package/src/resources/extensions/gsd/uok/gate-runner.ts +26 -36
- package/src/resources/extensions/gsd/uok/gitops.ts +21 -18
- package/src/resources/extensions/gsd/uok/kernel.ts +169 -48
- package/src/resources/extensions/gsd/uok/model-policy.ts +20 -17
- package/src/resources/extensions/gsd/workflow-event-ledger.ts +1 -1
- package/src/resources/extensions/gsd/workflow-logger.ts +1 -1
- package/src/resources/extensions/gsd/workflow-projections.ts +9 -24
- package/src/resources/extensions/gsd/workspace.ts +5 -21
- package/src/resources/extensions/shared/gsd-browser-cli.ts +29 -0
- 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/{ZpFDazP-38PXBPiI_LdZf → NPMNi2HV8BuK3baQsEUhk}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{ZpFDazP-38PXBPiI_LdZf → NPMNi2HV8BuK3baQsEUhk}/_ssgManifest.js +0 -0
|
@@ -1407,7 +1407,7 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
1407
1407
|
}
|
|
1408
1408
|
}
|
|
1409
1409
|
if (!event.isError) {
|
|
1410
|
-
recordToolCallLoopMutation(toolName);
|
|
1410
|
+
recordToolCallLoopMutation(toolName, event.details);
|
|
1411
1411
|
refreshSourceObservationAfterMutation(toolName, event.input, ctx);
|
|
1412
1412
|
clearSourceObservationsAfterShell(toolName);
|
|
1413
1413
|
}
|
|
@@ -14,13 +14,16 @@
|
|
|
14
14
|
* to stop tooling for the rest of that turn and answer in text.
|
|
15
15
|
*
|
|
16
16
|
* The per-tool-name check (#783 Brief C) tracks call counts within a
|
|
17
|
-
* turn regardless of args, decaying after successful state-
|
|
17
|
+
* turn regardless of args, decaying after successful state-progressing tools.
|
|
18
18
|
* This catches improvisation
|
|
19
19
|
* loops where the model attempts the same missing workflow tool through
|
|
20
20
|
* varied surfaces (bash → `node -e` → CLI), each with a different
|
|
21
21
|
* signature, so the identical-args streak never trips, while allowing
|
|
22
|
-
* tool-heavy turns that are making
|
|
23
|
-
*
|
|
22
|
+
* tool-heavy turns that are making progress. Progress means a successful file
|
|
23
|
+
* mutation (edit/write) or a successful shell/exec call (bg_shell,
|
|
24
|
+
* gsd_uat_exec, …) — so a local model running a legitimate iterative
|
|
25
|
+
* debugging loop (restart server, npm install, curl an endpoint) is not
|
|
26
|
+
* blocked as a false loop (#1206). Whichever guard trips first blocks.
|
|
24
27
|
*
|
|
25
28
|
* Thresholds, exempt tools, and enable flags are user-tunable (#1198) via the
|
|
26
29
|
* `tool_call_loop_guard` key in `.gsd/PREFERENCES.md` and `GSD_TOOL_LOOP_*`
|
|
@@ -40,6 +43,52 @@ const DEFAULT_PER_TOOL_CAP_EXEMPT_TOOLS = ["find", "glob", "grep", "ls", "read",
|
|
|
40
43
|
const STRICT_LOOP_TOOLS = new Set(["ask_user_questions"]);
|
|
41
44
|
const MAX_CONSECUTIVE_STRICT = 1;
|
|
42
45
|
const STATE_MUTATING_TOOL_SET = new Set(["edit", "write", "multi_edit", "notebook_edit"]);
|
|
46
|
+
/**
|
|
47
|
+
* Successful shell/exec calls are state progression too (#1206), not just file
|
|
48
|
+
* mutations. A local model debugging a UAT scenario legitimately restarts
|
|
49
|
+
* servers, runs `npm install`, and curls endpoints via bg_shell / gsd_uat_exec
|
|
50
|
+
* with varied args — productive work that never touches a file, so Guard 2's
|
|
51
|
+
* per-tool cap would otherwise misfire as a false loop. Decaying on these
|
|
52
|
+
* successful calls keeps the guard from aborting a progressing turn.
|
|
53
|
+
*
|
|
54
|
+
* Only successful calls reach {@link recordToolCallLoopMutation}: the
|
|
55
|
+
* tool_result hook skips `isError` results, and the bash tool throws on
|
|
56
|
+
* non-zero exit, so a genuinely stuck improvisation loop of failing commands
|
|
57
|
+
* (#783) never decays and still trips the cap. `async_bash` is excluded
|
|
58
|
+
* because it only registers a background job; command success is reported
|
|
59
|
+
* later via `await_job`. `bg_shell` may return `isError: false` for failed
|
|
60
|
+
* `run`/`start` outcomes, so the hook passes `details` for validation.
|
|
61
|
+
*/
|
|
62
|
+
const STATE_PROGRESSING_EXEC_TOOL_SET = new Set([
|
|
63
|
+
"bash",
|
|
64
|
+
"bg_shell",
|
|
65
|
+
"shell",
|
|
66
|
+
"powershell",
|
|
67
|
+
"gsd_exec",
|
|
68
|
+
"gsd_uat_exec",
|
|
69
|
+
]);
|
|
70
|
+
function isSuccessfulBgShellLoopProgress(details) {
|
|
71
|
+
if (!details || typeof details !== "object")
|
|
72
|
+
return false;
|
|
73
|
+
const record = details;
|
|
74
|
+
switch (record.action) {
|
|
75
|
+
case "run":
|
|
76
|
+
return record.exitCode === 0 && record.timedOut !== true;
|
|
77
|
+
case "start":
|
|
78
|
+
case "restart": {
|
|
79
|
+
const process = record.process;
|
|
80
|
+
if (!process || typeof process !== "object")
|
|
81
|
+
return false;
|
|
82
|
+
return process.alive === true;
|
|
83
|
+
}
|
|
84
|
+
case "wait_for_ready":
|
|
85
|
+
return record.ready === true;
|
|
86
|
+
case "send_and_wait":
|
|
87
|
+
return record.matched === true;
|
|
88
|
+
default:
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
43
92
|
function defaultGuardConfig() {
|
|
44
93
|
return {
|
|
45
94
|
guardEnabled: true,
|
|
@@ -235,11 +284,23 @@ export function checkToolCallLoop(toolName, args) {
|
|
|
235
284
|
}
|
|
236
285
|
return { block: false, count: consecutiveCount };
|
|
237
286
|
}
|
|
238
|
-
/**
|
|
239
|
-
|
|
287
|
+
/**
|
|
288
|
+
* Record successful state progress so Guard 2 can decay on the next count.
|
|
289
|
+
* File mutations (edit/write/…) and successful shell/exec calls (bash,
|
|
290
|
+
* bg_shell, gsd_uat_exec, …) both count as progress (#1092, #1206). The caller
|
|
291
|
+
* only invokes this for non-error results, so failing improvisation loops
|
|
292
|
+
* (#783) never decay and still trip the per-tool cap.
|
|
293
|
+
*/
|
|
294
|
+
export function recordToolCallLoopMutation(toolName, details) {
|
|
240
295
|
if (!enabled)
|
|
241
296
|
return;
|
|
242
|
-
if (
|
|
297
|
+
if (STATE_MUTATING_TOOL_SET.has(toolName)) {
|
|
298
|
+
mutationEpoch++;
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
if (!STATE_PROGRESSING_EXEC_TOOL_SET.has(toolName))
|
|
302
|
+
return;
|
|
303
|
+
if (toolName === "bg_shell" && details !== undefined && !isSuccessfulBgShellLoopProgress(details))
|
|
243
304
|
return;
|
|
244
305
|
mutationEpoch++;
|
|
245
306
|
}
|
|
@@ -506,9 +506,15 @@ export function ensureCodebaseMapFresh(basePath, options, ensureOptions) {
|
|
|
506
506
|
}
|
|
507
507
|
const metadata = parseCodebaseMapMetadata(existing);
|
|
508
508
|
const existingDescriptions = parseCodebaseMap(existing);
|
|
509
|
+
// Compare against the truncated count: when the repository has more tracked
|
|
510
|
+
// files than maxFiles, the map only lists the first maxFiles entries, so a
|
|
511
|
+
// stored fileCount above the cap (e.g. from an older map that recorded the
|
|
512
|
+
// full count) still matches the current truncated listing. Comparing raw
|
|
513
|
+
// values would flag "file-count-changed" on every turn, rewriting the
|
|
514
|
+
// timestamp and invalidating the provider KV cache prefix.
|
|
509
515
|
const staleReason = !metadata ? "missing-metadata"
|
|
510
516
|
: metadata.fingerprint !== fingerprint ? "files-changed"
|
|
511
|
-
: metadata.fileCount !== listed.files.length ? "file-count-changed"
|
|
517
|
+
: Math.min(metadata.fileCount, resolved.maxFiles) !== listed.files.length ? "file-count-changed"
|
|
512
518
|
: metadata.truncated !== listed.truncated ? "truncation-changed"
|
|
513
519
|
: undefined;
|
|
514
520
|
if (!staleReason) {
|
|
@@ -98,6 +98,50 @@ export function writeCompatMarker(basePath, marker) {
|
|
|
98
98
|
writeFileSync(tmp, JSON.stringify(marker, null, 2), "utf-8");
|
|
99
99
|
renameSync(tmp, path);
|
|
100
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* Remove projection entries whose backing file no longer exists on disk.
|
|
103
|
+
*
|
|
104
|
+
* gsd-pi never deletes marker entries on its own: both drift detectors skip
|
|
105
|
+
* files missing from disk (`if (!existsSync(abs)) continue;`) and the write-time
|
|
106
|
+
* flush only ever adds or refreshes entries. So when a phase directory is
|
|
107
|
+
* renamed or removed (e.g. `phases/29-new-milestone-m029/` →
|
|
108
|
+
* `phases/29-frontend-code-debt-cleanup/`), the old projection paths linger in
|
|
109
|
+
* `.compat.json` forever as phantom entries pointing at directories that no
|
|
110
|
+
* longer exist (#1257). They never reconcile, and `.compat.json` keeps drifting
|
|
111
|
+
* from disk reality so `git status` stops being a reliable proxy for "did the
|
|
112
|
+
* engine touch my plans?".
|
|
113
|
+
*
|
|
114
|
+
* This prunes those orphaned entries across the `.gsd/` projections and the
|
|
115
|
+
* `.planning/` projections/passthrough maps. It is safe: a missing-file entry is
|
|
116
|
+
* inert (every detector already ignores it), and if the file is later
|
|
117
|
+
* re-projected the write-time flush / unseeded-file detection re-seeds an
|
|
118
|
+
* accurate baseline.
|
|
119
|
+
*
|
|
120
|
+
* Returns the number of entries removed; when nothing is orphaned the marker is
|
|
121
|
+
* left untouched (no needless write, no `lastProjectedAt` churn).
|
|
122
|
+
*/
|
|
123
|
+
export function pruneOrphanedProjectionEntries(basePath) {
|
|
124
|
+
if (!existsSync(compatMarkerPath(basePath)))
|
|
125
|
+
return 0;
|
|
126
|
+
const marker = readCompatMarker(basePath);
|
|
127
|
+
let removed = 0;
|
|
128
|
+
const pruneMap = (map, root) => {
|
|
129
|
+
for (const relPath of Object.keys(map)) {
|
|
130
|
+
if (!existsSync(join(basePath, root, relPath))) {
|
|
131
|
+
delete map[relPath];
|
|
132
|
+
removed++;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
pruneMap(marker.projections, ".gsd");
|
|
137
|
+
if (marker.planning) {
|
|
138
|
+
pruneMap(marker.planning.projections, ".planning");
|
|
139
|
+
pruneMap(marker.planning.passthrough, ".planning");
|
|
140
|
+
}
|
|
141
|
+
if (removed > 0)
|
|
142
|
+
writeCompatMarker(basePath, marker);
|
|
143
|
+
return removed;
|
|
144
|
+
}
|
|
101
145
|
function quarantine(basePath, raw) {
|
|
102
146
|
const path = compatMarkerPath(basePath);
|
|
103
147
|
const badPath = `${path}.bad-${Date.now()}`;
|
|
@@ -121,8 +121,13 @@ function collectConfigSections(options) {
|
|
|
121
121
|
if (prefs?.auto_supervisor) {
|
|
122
122
|
const sup = resolveAutoSupervisorConfig();
|
|
123
123
|
const supRows = [];
|
|
124
|
-
if (sup.model)
|
|
125
|
-
|
|
124
|
+
if (sup.model) {
|
|
125
|
+
let modelVal = sup.model;
|
|
126
|
+
if (sup.modelFallbacks && sup.modelFallbacks.length > 0) {
|
|
127
|
+
modelVal += ` \u2192 ${sup.modelFallbacks.join(" \u2192 ")}`;
|
|
128
|
+
}
|
|
129
|
+
supRows.push({ label: "Model", value: modelVal });
|
|
130
|
+
}
|
|
126
131
|
supRows.push({ label: "Soft timeout", value: `${sup.soft_timeout_minutes}m` });
|
|
127
132
|
supRows.push({ label: "Idle timeout", value: `${sup.idle_timeout_minutes}m` });
|
|
128
133
|
supRows.push({ label: "Stalled tool timeout", value: `${sup.stalled_tool_timeout_minutes}m` });
|
|
@@ -801,3 +801,36 @@ export function getDb() {
|
|
|
801
801
|
export function getDbOrNull() {
|
|
802
802
|
return currentDb;
|
|
803
803
|
}
|
|
804
|
+
/**
|
|
805
|
+
* Confirm the open handle can actually write, not just that it opened.
|
|
806
|
+
*
|
|
807
|
+
* A schema-current database performs zero writes during open, so a handle that
|
|
808
|
+
* opened successfully but is not writable (read-only file, WAL/SHM permission
|
|
809
|
+
* mismatch, or a stale/moved handle → SQLITE_READONLY_DBMOVED) otherwise passes
|
|
810
|
+
* the open-only availability check and only fails much later at the first real
|
|
811
|
+
* write. The probe forces a genuine page write by re-writing the current
|
|
812
|
+
* `PRAGMA user_version` value back inside an IMMEDIATE transaction: a bare
|
|
813
|
+
* `BEGIN IMMEDIATE; ROLLBACK` is not sufficient because a moved handle does not
|
|
814
|
+
* fail until a page is actually dirtied. The value is unchanged, so the probe
|
|
815
|
+
* is idempotent, and the transaction is rolled back so nothing persists.
|
|
816
|
+
*/
|
|
817
|
+
export function probeDbWritable() {
|
|
818
|
+
const db = currentDb;
|
|
819
|
+
if (!db)
|
|
820
|
+
return { ok: false, detail: "No database is open." };
|
|
821
|
+
try {
|
|
822
|
+
const row = db.prepare("PRAGMA user_version").get();
|
|
823
|
+
const current = typeof row?.user_version === "number" ? row.user_version : 0;
|
|
824
|
+
db.exec("BEGIN IMMEDIATE");
|
|
825
|
+
try {
|
|
826
|
+
db.exec(`PRAGMA user_version = ${current}`);
|
|
827
|
+
}
|
|
828
|
+
finally {
|
|
829
|
+
db.exec("ROLLBACK");
|
|
830
|
+
}
|
|
831
|
+
return { ok: true };
|
|
832
|
+
}
|
|
833
|
+
catch (err) {
|
|
834
|
+
return { ok: false, detail: err.message };
|
|
835
|
+
}
|
|
836
|
+
}
|
|
@@ -24,6 +24,17 @@ function requireDb() {
|
|
|
24
24
|
* completion timestamps cleared, in one commit. Folds the hand-rolled
|
|
25
25
|
* transaction-plus-cascade previously in tools/reopen-slice.ts. Guards run
|
|
26
26
|
* inside the transaction (TOCTOU-safe).
|
|
27
|
+
*
|
|
28
|
+
* A closed slice is always reopenable. An open slice is only reopenable when it
|
|
29
|
+
* carries a completed-task state desync (#1205): a UAT→planning fallback can
|
|
30
|
+
* leave the slice "pending" while *all* its tasks stay "complete", which
|
|
31
|
+
* deadlocks every recovery path (plan-slice/replan-slice/complete-task all
|
|
32
|
+
* reject the still-closed tasks, and slice_reopen historically rejected the
|
|
33
|
+
* still-open slice). Resetting those tasks to pending gives the planner the
|
|
34
|
+
* clean slate it needs. An open slice that still has any unfinished
|
|
35
|
+
* (pending/in-progress) task is a normal in-flight slice, not the desync, and
|
|
36
|
+
* stays rejected as "slice-not-complete" so a full reset can't wipe its
|
|
37
|
+
* legitimate progress.
|
|
27
38
|
*/
|
|
28
39
|
export function reopenSliceCascade(milestoneId, sliceId) {
|
|
29
40
|
requireDb();
|
|
@@ -43,11 +54,18 @@ export function reopenSliceCascade(milestoneId, sliceId) {
|
|
|
43
54
|
outcome = { ok: false, reason: "slice-not-found" };
|
|
44
55
|
return;
|
|
45
56
|
}
|
|
46
|
-
|
|
57
|
+
const tasks = getSliceTasks(milestoneId, sliceId);
|
|
58
|
+
// A closed slice is always reopenable. An open slice is only the #1205
|
|
59
|
+
// desync when EVERY task is already closed (a UAT→planning fallback left the
|
|
60
|
+
// slice open with all tasks still "complete"). Requiring *all* tasks closed
|
|
61
|
+
// (not merely one) means a normal in-flight slice — which keeps at least one
|
|
62
|
+
// pending/in-progress task — is rejected, so a full reset can't wipe its
|
|
63
|
+
// legitimate progress.
|
|
64
|
+
const allTasksClosed = tasks.length > 0 && tasks.every((t) => isClosedStatus(t.status));
|
|
65
|
+
if (!isClosedStatus(slice.status) && !allTasksClosed) {
|
|
47
66
|
outcome = { ok: false, reason: "slice-not-complete", status: slice.status };
|
|
48
67
|
return;
|
|
49
68
|
}
|
|
50
|
-
const tasks = getSliceTasks(milestoneId, sliceId);
|
|
51
69
|
getDbOrNull().prepare(`UPDATE slices SET status = 'in_progress', completed_at = NULL WHERE milestone_id = :mid AND id = :sid`).run({ ":mid": milestoneId, ":sid": sliceId });
|
|
52
70
|
getDbOrNull().prepare(`UPDATE tasks SET status = 'pending', completed_at = NULL WHERE milestone_id = :mid AND slice_id = :sid`).run({ ":mid": milestoneId, ":sid": sliceId });
|
|
53
71
|
outcome = { ok: true, tasksReset: tasks.length };
|
|
@@ -11,19 +11,46 @@ export function normalizeDbRow(row) {
|
|
|
11
11
|
export function normalizeDbRows(rows) {
|
|
12
12
|
return rows.map((row) => normalizeDbRow(row));
|
|
13
13
|
}
|
|
14
|
+
function isPlainObject(value) {
|
|
15
|
+
if (value === null || typeof value !== "object")
|
|
16
|
+
return false;
|
|
17
|
+
const proto = Object.getPrototypeOf(value);
|
|
18
|
+
return proto === Object.prototype || proto === null;
|
|
19
|
+
}
|
|
20
|
+
// node:sqlite accepts binding-object keys with or without the ':'/'@'/'$'
|
|
21
|
+
// prefix, but better-sqlite3 accepts only bare keys — strip the prefix so
|
|
22
|
+
// call sites written against node:sqlite also work on the fallback provider.
|
|
23
|
+
function normalizeBindParams(params) {
|
|
24
|
+
return params.map((param) => {
|
|
25
|
+
if (!isPlainObject(param))
|
|
26
|
+
return param;
|
|
27
|
+
let changed = false;
|
|
28
|
+
const normalized = {};
|
|
29
|
+
for (const [key, value] of Object.entries(param)) {
|
|
30
|
+
if (key.length > 1 && (key[0] === ":" || key[0] === "@" || key[0] === "$")) {
|
|
31
|
+
normalized[key.slice(1)] = value;
|
|
32
|
+
changed = true;
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
normalized[key] = value;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return changed ? normalized : param;
|
|
39
|
+
});
|
|
40
|
+
}
|
|
14
41
|
export function createDbAdapter(rawDb) {
|
|
15
42
|
const db = rawDb;
|
|
16
43
|
const stmtCache = new Map();
|
|
17
44
|
function wrapStmt(raw) {
|
|
18
45
|
return {
|
|
19
46
|
run(...params) {
|
|
20
|
-
return raw.run(...params);
|
|
47
|
+
return raw.run(...normalizeBindParams(params));
|
|
21
48
|
},
|
|
22
49
|
get(...params) {
|
|
23
|
-
return normalizeDbRow(raw.get(...params));
|
|
50
|
+
return normalizeDbRow(raw.get(...normalizeBindParams(params)));
|
|
24
51
|
},
|
|
25
52
|
all(...params) {
|
|
26
|
-
return normalizeDbRows(raw.all(...params));
|
|
53
|
+
return normalizeDbRows(raw.all(...normalizeBindParams(params)));
|
|
27
54
|
},
|
|
28
55
|
};
|
|
29
56
|
}
|
|
@@ -138,7 +138,7 @@ Diagnostics record the file path, scope (global/project), severity (error/warnin
|
|
|
138
138
|
- `off` — skill discovery is disabled entirely.
|
|
139
139
|
|
|
140
140
|
- `auto_supervisor`: configures the auto-mode supervisor that monitors agent progress and enforces timeouts. Keys:
|
|
141
|
-
- `model`: model
|
|
141
|
+
- `model`: model to use for the supervisor process (defaults to the currently active model). Accepts a bare model ID **or** the same `{ model, provider?, fallbacks? }` object form as `models.<phase>`, so it honors `fallbacks[]` on a transient provider trip.
|
|
142
142
|
- `soft_timeout_minutes`: minutes before the supervisor issues a soft warning (default: 20).
|
|
143
143
|
- `idle_timeout_minutes`: minutes of inactivity before the supervisor intervenes (default: 10).
|
|
144
144
|
- `hard_timeout_minutes`: minutes before the supervisor forces termination (default: 30).
|
|
@@ -228,7 +228,7 @@ In `"parent"` mode, slice/task `targetRepositories` default to the declared chil
|
|
|
228
228
|
- `enabled`: boolean — set `false` to force sequential task execution. Default: `true`.
|
|
229
229
|
- `max_parallel`: number — maximum tasks to dispatch in one batch, range `1`-`8`. Default: `2`.
|
|
230
230
|
- `isolation_mode`: `"same-tree"` — currently the only supported value.
|
|
231
|
-
- `subagent_model`:
|
|
231
|
+
- `subagent_model`: optional model override for reactive task subagents. Accepts a bare model ID **or** the `{ model, provider?, fallbacks? }` object form (parity with `models.<phase>`). Falls back to the `models.subagent` routing when omitted.
|
|
232
232
|
|
|
233
233
|
- `remote_questions`: route interactive questions to Slack/Discord for headless auto-mode. Keys:
|
|
234
234
|
- `channel`: `"slack"` or `"discord"` — channel type.
|
|
@@ -326,7 +326,7 @@ In `"parent"` mode, slice/task `targetRepositories` default to the declared chil
|
|
|
326
326
|
- `after`: string[] — unit types that trigger this hook (e.g., `["execute-task"]`).
|
|
327
327
|
- `prompt`: string — prompt sent to the LLM. Supports `{milestoneId}`, `{sliceId}`, `{taskId}` substitutions.
|
|
328
328
|
- `max_cycles`: number — max times this hook fires per trigger (default: 1, max: 10).
|
|
329
|
-
- `model`:
|
|
329
|
+
- `model`: optional model override. Accepts a bare model ID **or** the same `{ model, provider?, fallbacks? }` object form as `models.<phase>`. With `fallbacks[]`, a transient trip of the primary provider falls back to the next entry instead of hard-failing the hook — which, for a `blocking` hook with `on_block: { action: pause }`, would otherwise pause the whole run.
|
|
330
330
|
- `artifact`: string — expected output file name (relative to task/slice dir). Hook is skipped if file already exists (idempotent).
|
|
331
331
|
- `criticality`: `"advisory"` or `"blocking"` — advisory preserves current best-effort behavior; blocking requires clean hook completion plus a valid outcome verdict before auto-mode advances. Default: `"advisory"`.
|
|
332
332
|
- `retry_on`: string — if this file is produced instead of the artifact, re-run the trigger unit then re-run hooks.
|
|
@@ -78,15 +78,33 @@ function rollbackPartialMigration(basePath, backupDir, migratingPath) {
|
|
|
78
78
|
catch (removeErr) {
|
|
79
79
|
logWarning("migration", `rollback: could not remove partial ${LAYOUT_SEGMENTS.level1}/: ${removeErr.message}`);
|
|
80
80
|
}
|
|
81
|
+
// Only the standalone .gsd-backups/migrate-<ts>/ copy is disposable once the
|
|
82
|
+
// restore succeeds. When resuming an interrupted migration, backupDir IS the
|
|
83
|
+
// preserved migrating tree (the sole surviving data source) and must never be
|
|
84
|
+
// removed here. Deleting the backup after a successful rollback keeps the gate
|
|
85
|
+
// from leaking one .gsd-backups/migrate-<ts>/ per session_start.
|
|
86
|
+
const isDisposableBackup = Boolean(backupDir) && backupDir !== migratingPath;
|
|
87
|
+
const cleanupBackup = () => {
|
|
88
|
+
if (!isDisposableBackup || !existsSync(backupDir))
|
|
89
|
+
return;
|
|
90
|
+
try {
|
|
91
|
+
removePathWithRetries(backupDir);
|
|
92
|
+
}
|
|
93
|
+
catch (cleanupErr) {
|
|
94
|
+
logWarning("migration", `rollback: could not clean backup ${backupDir}: ${cleanupErr.message}`);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
81
97
|
// Restore milestones/ — prefer renaming the preserved migrating copy back.
|
|
82
98
|
const milestonesPath = join(basePath, ".gsd", "milestones");
|
|
83
99
|
try {
|
|
84
100
|
if (migratingPath && existsSync(migratingPath) && !existsSync(milestonesPath)) {
|
|
85
101
|
movePathWithCopyDeleteFallback(migratingPath, milestonesPath);
|
|
102
|
+
cleanupBackup();
|
|
86
103
|
return;
|
|
87
104
|
}
|
|
88
105
|
if (existsSync(backupDir)) {
|
|
89
106
|
cpSync(backupDir, milestonesPath, { recursive: true });
|
|
107
|
+
cleanupBackup();
|
|
90
108
|
}
|
|
91
109
|
if (migratingPath && existsSync(migratingPath)) {
|
|
92
110
|
removePathWithRetries(migratingPath);
|
|
@@ -352,17 +352,17 @@ export function insertTask(t) {
|
|
|
352
352
|
ON CONFLICT(milestone_id, slice_id, id) DO UPDATE SET
|
|
353
353
|
title = CASE WHEN NULLIF(:title, '') IS NOT NULL THEN :title ELSE tasks.title END,
|
|
354
354
|
status = :status,
|
|
355
|
-
one_liner = :one_liner,
|
|
356
|
-
narrative = :narrative,
|
|
357
|
-
verification_result = :verification_result,
|
|
358
|
-
duration = :duration,
|
|
359
|
-
completed_at = :completed_at,
|
|
360
|
-
blocker_discovered = :blocker_discovered,
|
|
361
|
-
deviations = :deviations,
|
|
362
|
-
known_issues = :known_issues,
|
|
363
|
-
key_files = :key_files,
|
|
364
|
-
key_decisions = :key_decisions,
|
|
365
|
-
full_summary_md = :full_summary_md,
|
|
355
|
+
one_liner = CASE WHEN :preserve_completion = 1 AND NULLIF(:one_liner, '') IS NULL THEN tasks.one_liner ELSE :one_liner END,
|
|
356
|
+
narrative = CASE WHEN :preserve_completion = 1 AND NULLIF(:narrative, '') IS NULL THEN tasks.narrative ELSE :narrative END,
|
|
357
|
+
verification_result = CASE WHEN :preserve_completion = 1 AND NULLIF(:verification_result, '') IS NULL THEN tasks.verification_result ELSE :verification_result END,
|
|
358
|
+
duration = CASE WHEN :preserve_completion = 1 AND NULLIF(:duration, '') IS NULL THEN tasks.duration ELSE :duration END,
|
|
359
|
+
completed_at = CASE WHEN :preserve_completion = 1 AND tasks.completed_at IS NOT NULL THEN tasks.completed_at ELSE :completed_at END,
|
|
360
|
+
blocker_discovered = CASE WHEN :preserve_completion = 1 AND :blocker_discovered = 0 THEN tasks.blocker_discovered ELSE :blocker_discovered END,
|
|
361
|
+
deviations = CASE WHEN :preserve_completion = 1 AND NULLIF(:deviations, '') IS NULL THEN tasks.deviations ELSE :deviations END,
|
|
362
|
+
known_issues = CASE WHEN :preserve_completion = 1 AND NULLIF(:known_issues, '') IS NULL THEN tasks.known_issues ELSE :known_issues END,
|
|
363
|
+
key_files = CASE WHEN :preserve_completion = 1 AND NULLIF(:key_files, '[]') IS NULL THEN tasks.key_files ELSE :key_files END,
|
|
364
|
+
key_decisions = CASE WHEN :preserve_completion = 1 AND NULLIF(:key_decisions, '[]') IS NULL THEN tasks.key_decisions ELSE :key_decisions END,
|
|
365
|
+
full_summary_md = CASE WHEN :preserve_completion = 1 AND NULLIF(:full_summary_md, '') IS NULL THEN tasks.full_summary_md ELSE :full_summary_md END,
|
|
366
366
|
description = CASE WHEN NULLIF(:description, '') IS NOT NULL THEN :description ELSE tasks.description END,
|
|
367
367
|
estimate = CASE WHEN NULLIF(:estimate, '') IS NOT NULL THEN :estimate ELSE tasks.estimate END,
|
|
368
368
|
files = CASE WHEN NULLIF(:files, '[]') IS NOT NULL THEN :files ELSE tasks.files END,
|
|
@@ -401,6 +401,7 @@ export function insertTask(t) {
|
|
|
401
401
|
":observability_impact": t.planning?.observabilityImpact ?? "",
|
|
402
402
|
":full_plan_md": t.planning?.fullPlanMd ?? "",
|
|
403
403
|
":sequence": t.sequence ?? 0,
|
|
404
|
+
":preserve_completion": t.preserveCompletionMetadata && (t.status === "complete" || t.status === "done") ? 1 : 0,
|
|
404
405
|
":target_repositories": JSON.stringify(t.planning?.targetRepositories ?? []),
|
|
405
406
|
":raw_target_repositories": t.planning && "targetRepositories" in t.planning
|
|
406
407
|
? JSON.stringify(t.planning.targetRepositories ?? [])
|
|
@@ -27,7 +27,7 @@ import { readSessionLockData, isSessionLockProcessAlive } from "./session-lock.j
|
|
|
27
27
|
import { nativeAddAll, nativeCommit, nativeHasCommittedHead, nativeIsRepo, nativeInit } from "./native-git-bridge.js";
|
|
28
28
|
import { isInheritedRepo } from "./repo-identity.js";
|
|
29
29
|
import { ensureGitignore, ensurePreferences, untrackRuntimeFiles } from "./gitignore.js";
|
|
30
|
-
import { getIsolationMode, loadEffectiveGSDPreferences } from "./preferences.js";
|
|
30
|
+
import { getIsolationMode, loadEffectiveGSDPreferences, renderLanguageDirectiveForPrompt } from "./preferences.js";
|
|
31
31
|
import { getAutoWorktreePath } from "./auto-worktree-path-resolution.js";
|
|
32
32
|
import { resolveUokFlags } from "./uok/flags.js";
|
|
33
33
|
import { ensurePlanV2Graph, isMissingFinalizedContextResult } from "./uok/plan-v2.js";
|
|
@@ -642,7 +642,7 @@ function resolveAvailableModel(modelId, availableModels, currentProvider) {
|
|
|
642
642
|
* Build the discuss-and-plan prompt for a new milestone.
|
|
643
643
|
* Used by all three "new milestone" paths (first ever, no active, all complete).
|
|
644
644
|
*/
|
|
645
|
-
function buildDiscussPrompt(nextId, preamble,
|
|
645
|
+
function buildDiscussPrompt(nextId, preamble, basePath, pi, ctx, preparationContext) {
|
|
646
646
|
const milestoneRel = `.gsd/milestones/${nextId}`;
|
|
647
647
|
const structuredQuestionsAvailable = getStructuredQuestionsAvailability(pi, ctx);
|
|
648
648
|
const inlinedTemplates = [
|
|
@@ -652,7 +652,7 @@ function buildDiscussPrompt(nextId, preamble, _basePath, pi, ctx, preparationCon
|
|
|
652
652
|
inlineTemplate("roadmap", "Roadmap"),
|
|
653
653
|
inlineTemplate("decisions", "Decisions"),
|
|
654
654
|
].join("\n\n---\n\n");
|
|
655
|
-
return loadPrompt("discuss", {
|
|
655
|
+
return prependLanguageDirective(basePath, loadPrompt("discuss", {
|
|
656
656
|
milestoneId: nextId,
|
|
657
657
|
preamble,
|
|
658
658
|
preparationContext: preparationContext ?? "",
|
|
@@ -662,13 +662,22 @@ function buildDiscussPrompt(nextId, preamble, _basePath, pi, ctx, preparationCon
|
|
|
662
662
|
inlinedTemplates,
|
|
663
663
|
commitInstruction: buildDocsCommitInstruction(`docs(${nextId}): context, requirements, and roadmap`),
|
|
664
664
|
multiMilestoneCommitInstruction: buildDocsCommitInstruction("docs: project plan — N milestones"),
|
|
665
|
-
});
|
|
665
|
+
}));
|
|
666
|
+
}
|
|
667
|
+
/**
|
|
668
|
+
* Prepend the configured response-language directive to a dispatched discuss
|
|
669
|
+
* prompt so the discuss/QA conversation is held in the language set in
|
|
670
|
+
* PREFERENCES.md (#1210). No-op when no language is configured.
|
|
671
|
+
*/
|
|
672
|
+
function prependLanguageDirective(basePath, prompt) {
|
|
673
|
+
const directive = renderLanguageDirectiveForPrompt(loadEffectiveGSDPreferences(basePath)?.preferences);
|
|
674
|
+
return directive ? `${directive}\n\n${prompt}` : prompt;
|
|
666
675
|
}
|
|
667
676
|
/**
|
|
668
677
|
* Build the discuss prompt for headless milestone creation.
|
|
669
678
|
* Uses the discuss-headless prompt template with seed context injected.
|
|
670
679
|
*/
|
|
671
|
-
function buildHeadlessDiscussPrompt(nextId, seedContext,
|
|
680
|
+
function buildHeadlessDiscussPrompt(nextId, seedContext, basePath) {
|
|
672
681
|
const milestoneRel = `.gsd/milestones/${nextId}`;
|
|
673
682
|
const inlinedTemplates = [
|
|
674
683
|
inlineTemplate("project", "Project"),
|
|
@@ -677,7 +686,7 @@ function buildHeadlessDiscussPrompt(nextId, seedContext, _basePath) {
|
|
|
677
686
|
inlineTemplate("roadmap", "Roadmap"),
|
|
678
687
|
inlineTemplate("decisions", "Decisions"),
|
|
679
688
|
].join("\n\n---\n\n");
|
|
680
|
-
return loadPrompt("discuss-headless", {
|
|
689
|
+
return prependLanguageDirective(basePath, loadPrompt("discuss-headless", {
|
|
681
690
|
milestoneId: nextId,
|
|
682
691
|
seedContext,
|
|
683
692
|
contextPath: `${milestoneRel}/${nextId}-CONTEXT.md`,
|
|
@@ -685,7 +694,7 @@ function buildHeadlessDiscussPrompt(nextId, seedContext, _basePath) {
|
|
|
685
694
|
inlinedTemplates,
|
|
686
695
|
commitInstruction: buildDocsCommitInstruction(`docs(${nextId}): context, requirements, and roadmap`),
|
|
687
696
|
multiMilestoneCommitInstruction: buildDocsCommitInstruction("docs: project plan — N milestones"),
|
|
688
|
-
});
|
|
697
|
+
}));
|
|
689
698
|
}
|
|
690
699
|
/**
|
|
691
700
|
* Run preparation phase if enabled, then build the discuss prompt.
|