@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
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
// Project/App: gsd-pi
|
|
2
|
+
// File Purpose: Regression for #1222 — a re-import must not silently downgrade
|
|
3
|
+
// a completed flat-phase task back to pending when its SUMMARY.md attests the
|
|
4
|
+
// completion. gsd_task_complete succeeds and writes TID-SUMMARY.md, but a stale
|
|
5
|
+
// plan checkbox re-imported into the DB would revert the task to pending,
|
|
6
|
+
// hard-stopping auto-mode on its "state did not advance" guard.
|
|
7
|
+
|
|
8
|
+
import test, { afterEach } from "node:test";
|
|
9
|
+
import assert from "node:assert/strict";
|
|
10
|
+
import { cpSync, mkdtempSync, rmSync, writeFileSync, unlinkSync, mkdirSync } from "node:fs";
|
|
11
|
+
import { join, dirname } from "node:path";
|
|
12
|
+
import { tmpdir } from "node:os";
|
|
13
|
+
import { randomUUID } from "node:crypto";
|
|
14
|
+
import { fileURLToPath } from "node:url";
|
|
15
|
+
|
|
16
|
+
import { openDatabase, closeDatabase, getAllMilestones, getMilestoneSlices, getSliceTasks, repairTaskCompletionFromSummary } from "../gsd-db.ts";
|
|
17
|
+
import { migrateHierarchyToDb } from "../md-importer.ts";
|
|
18
|
+
import { invalidateStateCache } from "../state.ts";
|
|
19
|
+
|
|
20
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
21
|
+
const FIXTURE_ROOT = join(__dirname, "__fixtures__", "flat-phase");
|
|
22
|
+
// The flat-phase fixture parses to M001/S01/T01 (phase 01, plan 01, task T01).
|
|
23
|
+
const PHASE_DIR = join(".gsd", "phases", "01-foundation");
|
|
24
|
+
const SUMMARY_REL = join(PHASE_DIR, "T01-SUMMARY.md");
|
|
25
|
+
|
|
26
|
+
const tmpDirs: string[] = [];
|
|
27
|
+
afterEach(() => {
|
|
28
|
+
closeDatabase();
|
|
29
|
+
for (const d of tmpDirs) { try { rmSync(d, { recursive: true, force: true }); } catch { /* */ } }
|
|
30
|
+
tmpDirs.length = 0;
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
function copyFixture(): string {
|
|
34
|
+
const base = mkdtempSync(join(tmpdir(), `gsd-lostupdate-${randomUUID()}`));
|
|
35
|
+
cpSync(FIXTURE_ROOT, base, { recursive: true });
|
|
36
|
+
tmpDirs.push(base);
|
|
37
|
+
return base;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function taskStatus(base: string): string | undefined {
|
|
41
|
+
return t01Row()?.status;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function t01Row() {
|
|
45
|
+
const ms = getAllMilestones();
|
|
46
|
+
if (ms.length === 0) return undefined;
|
|
47
|
+
const slices = getMilestoneSlices(ms[0]!.id);
|
|
48
|
+
if (slices.length === 0) return undefined;
|
|
49
|
+
const tasks = getSliceTasks(ms[0]!.id, slices[0]!.id);
|
|
50
|
+
return tasks.find((t) => t.id === "T01");
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function t01Ids() {
|
|
54
|
+
const ms = getAllMilestones();
|
|
55
|
+
const slices = getMilestoneSlices(ms[0]!.id);
|
|
56
|
+
return { milestoneId: ms[0]!.id, sliceId: slices[0]!.id };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
test("re-import keeps a flat-phase task complete when its SUMMARY.md is present (#1222)", () => {
|
|
60
|
+
const base = copyFixture();
|
|
61
|
+
// The fixture plan leaves T01 unchecked ([ ]). Simulate a completed task: the
|
|
62
|
+
// durable SUMMARY.md exists even though the plan checkbox is stale-unchecked.
|
|
63
|
+
writeFileSync(join(base, SUMMARY_REL), "# T01 SUMMARY\n\nDone.\n");
|
|
64
|
+
|
|
65
|
+
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
66
|
+
migrateHierarchyToDb(base);
|
|
67
|
+
invalidateStateCache();
|
|
68
|
+
|
|
69
|
+
assert.equal(
|
|
70
|
+
taskStatus(base),
|
|
71
|
+
"complete",
|
|
72
|
+
"task with SUMMARY.md on disk must import as complete, not revert to pending",
|
|
73
|
+
);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test("re-import leaves an unchecked flat-phase task pending when no SUMMARY.md exists (#1222)", () => {
|
|
77
|
+
const base = copyFixture();
|
|
78
|
+
// No SUMMARY.md — the unchecked checkbox is the authoritative signal.
|
|
79
|
+
|
|
80
|
+
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
81
|
+
migrateHierarchyToDb(base);
|
|
82
|
+
invalidateStateCache();
|
|
83
|
+
|
|
84
|
+
assert.equal(
|
|
85
|
+
taskStatus(base),
|
|
86
|
+
"pending",
|
|
87
|
+
"unchecked task without a SUMMARY.md must stay pending",
|
|
88
|
+
);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test("re-import keeps a flat-phase task complete even when an auxiliary tasks/ subdir exists (#1222)", () => {
|
|
92
|
+
const base = copyFixture();
|
|
93
|
+
// Flat-phase may keep a tasks/ subdir for gate artifacts (e.g. T01-VERIFY.json)
|
|
94
|
+
// while gsd_task_complete still writes TID-SUMMARY.md at the phase root. The
|
|
95
|
+
// tasks/ subdir must NOT shadow that real summary and downgrade the task.
|
|
96
|
+
mkdirSync(join(base, PHASE_DIR, "tasks"), { recursive: true });
|
|
97
|
+
writeFileSync(join(base, PHASE_DIR, "tasks", "T01-VERIFY.json"), "{}\n");
|
|
98
|
+
writeFileSync(join(base, SUMMARY_REL), "# T01 SUMMARY\n\nDone.\n");
|
|
99
|
+
|
|
100
|
+
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
101
|
+
migrateHierarchyToDb(base);
|
|
102
|
+
invalidateStateCache();
|
|
103
|
+
|
|
104
|
+
assert.equal(
|
|
105
|
+
taskStatus(base),
|
|
106
|
+
"complete",
|
|
107
|
+
"a phase-root SUMMARY.md must win even when a tasks/ subdir exists (no shadowing)",
|
|
108
|
+
);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
test("re-import preserves execution metadata and completed_at of an attested-complete task (#1222)", () => {
|
|
112
|
+
const base = copyFixture();
|
|
113
|
+
// T01 is completed on disk (SUMMARY present) but its plan checkbox is stale-unchecked.
|
|
114
|
+
writeFileSync(join(base, SUMMARY_REL), "# T01 SUMMARY\n\nDone.\n");
|
|
115
|
+
|
|
116
|
+
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
117
|
+
migrateHierarchyToDb(base);
|
|
118
|
+
invalidateStateCache();
|
|
119
|
+
|
|
120
|
+
// Simulate the row gsd_task_complete leaves behind: real execution prose plus
|
|
121
|
+
// a completion timestamp from when the task actually finished.
|
|
122
|
+
const OLD_COMPLETED_AT = "2026-07-01T00:00:00.000Z";
|
|
123
|
+
const REAL_ONE_LINER = "Implemented the widget frobnicator end-to-end";
|
|
124
|
+
const REAL_SUMMARY = "# T01 full summary\n\nEverything about how T01 was done.";
|
|
125
|
+
const REAL_VERIFICATION = "all 12 checks passed";
|
|
126
|
+
const { milestoneId, sliceId } = t01Ids();
|
|
127
|
+
repairTaskCompletionFromSummary({
|
|
128
|
+
milestoneId,
|
|
129
|
+
sliceId,
|
|
130
|
+
taskId: "T01",
|
|
131
|
+
oneLiner: REAL_ONE_LINER,
|
|
132
|
+
verificationResult: REAL_VERIFICATION,
|
|
133
|
+
completedAt: OLD_COMPLETED_AT,
|
|
134
|
+
fullSummaryMd: REAL_SUMMARY,
|
|
135
|
+
});
|
|
136
|
+
invalidateStateCache();
|
|
137
|
+
|
|
138
|
+
const before = t01Row()!;
|
|
139
|
+
assert.equal(before.status, "complete", "precondition: T01 is complete");
|
|
140
|
+
assert.equal(before.one_liner, REAL_ONE_LINER, "precondition: one_liner set");
|
|
141
|
+
assert.equal(before.completed_at, OLD_COMPLETED_AT, "precondition: completed_at set");
|
|
142
|
+
|
|
143
|
+
// The pre-dispatch reconcile re-imports the whole tree (plan checkbox still [ ]).
|
|
144
|
+
migrateHierarchyToDb(base);
|
|
145
|
+
invalidateStateCache();
|
|
146
|
+
|
|
147
|
+
const after = t01Row()!;
|
|
148
|
+
assert.equal(after.status, "complete", "status must survive re-import");
|
|
149
|
+
assert.equal(after.one_liner, REAL_ONE_LINER, "one_liner must survive re-import");
|
|
150
|
+
assert.equal(after.full_summary_md, REAL_SUMMARY, "full_summary_md must survive re-import");
|
|
151
|
+
assert.equal(after.verification_result, REAL_VERIFICATION, "verification_result must survive re-import");
|
|
152
|
+
assert.equal(after.completed_at, OLD_COMPLETED_AT, "completed_at must not be refreshed by re-import");
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
test("removing the SUMMARY.md (reopen) lets a re-import return the task to pending and clears completion metadata (#1222)", () => {
|
|
156
|
+
const base = copyFixture();
|
|
157
|
+
writeFileSync(join(base, SUMMARY_REL), "# T01 SUMMARY\n\nDone.\n");
|
|
158
|
+
|
|
159
|
+
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
160
|
+
migrateHierarchyToDb(base);
|
|
161
|
+
invalidateStateCache();
|
|
162
|
+
assert.equal(taskStatus(base), "complete", "precondition: task imports complete with SUMMARY present");
|
|
163
|
+
|
|
164
|
+
// Simulate the durable completion row gsd_task_complete leaves behind.
|
|
165
|
+
const { milestoneId, sliceId } = t01Ids();
|
|
166
|
+
repairTaskCompletionFromSummary({
|
|
167
|
+
milestoneId,
|
|
168
|
+
sliceId,
|
|
169
|
+
taskId: "T01",
|
|
170
|
+
oneLiner: "Implemented the widget frobnicator end-to-end",
|
|
171
|
+
verificationResult: "all 12 checks passed",
|
|
172
|
+
completedAt: "2026-07-01T00:00:00.000Z",
|
|
173
|
+
fullSummaryMd: "# T01 full summary\n\nEverything about how T01 was done.",
|
|
174
|
+
});
|
|
175
|
+
invalidateStateCache();
|
|
176
|
+
const before = t01Row()!;
|
|
177
|
+
assert.equal(before.status, "complete", "precondition: T01 is complete");
|
|
178
|
+
assert.equal(before.completed_at, "2026-07-01T00:00:00.000Z", "precondition: completed_at set");
|
|
179
|
+
|
|
180
|
+
// reopen-task deletes the flat-phase SUMMARY; the next re-import must respect it.
|
|
181
|
+
unlinkSync(join(base, SUMMARY_REL));
|
|
182
|
+
migrateHierarchyToDb(base);
|
|
183
|
+
invalidateStateCache();
|
|
184
|
+
const after = t01Row()!;
|
|
185
|
+
assert.equal(
|
|
186
|
+
after.status,
|
|
187
|
+
"pending",
|
|
188
|
+
"after the SUMMARY is removed, a re-import must return the unchecked task to pending",
|
|
189
|
+
);
|
|
190
|
+
// A pending re-import must not preserve stale completion metadata (#1228 thread):
|
|
191
|
+
// preserveCompletionMetadata only applies to complete/done imports.
|
|
192
|
+
assert.ok(!after.completed_at, "completed_at must be cleared when the task reverts to pending");
|
|
193
|
+
assert.ok(!after.one_liner, "one_liner must be cleared when the task reverts to pending");
|
|
194
|
+
assert.ok(!after.full_summary_md, "full_summary_md must be cleared when the task reverts to pending");
|
|
195
|
+
assert.ok(!after.verification_result, "verification_result must be cleared when the task reverts to pending");
|
|
196
|
+
});
|
package/src/resources/extensions/gsd/tests/integration/all-milestones-complete-merge.test.ts
CHANGED
|
@@ -25,12 +25,10 @@ import { join } from "node:path";
|
|
|
25
25
|
import { tmpdir } from "node:os";
|
|
26
26
|
import { execSync } from "node:child_process";
|
|
27
27
|
|
|
28
|
-
import {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
mergeMilestoneToMain,
|
|
33
|
-
} from "../../auto-worktree.ts";
|
|
28
|
+
import { createAutoWorktree } from "../../auto-worktree-creation.ts";
|
|
29
|
+
import { isInAutoWorktree } from "../../auto-worktree-entry.ts";
|
|
30
|
+
import { mergeMilestoneToMain } from "../../auto-worktree-merge.ts";
|
|
31
|
+
import { getAutoWorktreeOriginalBase } from "../../auto-worktree-session-registry.ts";
|
|
34
32
|
|
|
35
33
|
function run(command: string, cwd: string): string {
|
|
36
34
|
return execSync(command, {
|
|
@@ -12,7 +12,8 @@ import { join } from "node:path";
|
|
|
12
12
|
import { tmpdir } from "node:os";
|
|
13
13
|
import { execSync } from "node:child_process";
|
|
14
14
|
|
|
15
|
-
import { createAutoWorktree
|
|
15
|
+
import { createAutoWorktree } from "../../auto-worktree-creation.ts";
|
|
16
|
+
import { mergeMilestoneToMain } from "../../auto-worktree-merge.ts";
|
|
16
17
|
import { nativeMergeSquash } from "../../native-git-bridge.ts";
|
|
17
18
|
|
|
18
19
|
function run(cmd: string, cwd: string): string {
|
package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts
CHANGED
|
@@ -19,12 +19,12 @@ import { join } from "node:path";
|
|
|
19
19
|
import { tmpdir } from "node:os";
|
|
20
20
|
import { execSync } from "node:child_process";
|
|
21
21
|
|
|
22
|
+
import { createAutoWorktree } from "../../auto-worktree-creation.ts";
|
|
22
23
|
import {
|
|
23
|
-
createAutoWorktree,
|
|
24
24
|
mergeMilestoneToMain,
|
|
25
|
-
getAutoWorktreeOriginalBase,
|
|
26
25
|
_setRestoreEntryFnForTests,
|
|
27
|
-
} from "../../auto-worktree.ts";
|
|
26
|
+
} from "../../auto-worktree-merge.ts";
|
|
27
|
+
import { getAutoWorktreeOriginalBase } from "../../auto-worktree-session-registry.ts";
|
|
28
28
|
import { getSliceBranchName } from "../../worktree.ts";
|
|
29
29
|
import { nativeMergeSquash } from "../../native-git-bridge.ts";
|
|
30
30
|
import { drainLogs, setStderrLoggingEnabled } from "../../workflow-logger.ts";
|
|
@@ -17,17 +17,16 @@ import {
|
|
|
17
17
|
writeGsdMilestoneContext,
|
|
18
18
|
} from "./gsd-integration-fixture.ts";
|
|
19
19
|
|
|
20
|
+
import { createAutoWorktree } from "../../auto-worktree-creation.ts";
|
|
21
|
+
import { enterAutoWorktree, isInAutoWorktree } from "../../auto-worktree-entry.ts";
|
|
22
|
+
import { getAutoWorktreePath } from "../../auto-worktree-path-resolution.ts";
|
|
20
23
|
import {
|
|
21
|
-
createAutoWorktree,
|
|
22
|
-
teardownAutoWorktree,
|
|
23
|
-
isInAutoWorktree,
|
|
24
|
-
getAutoWorktreePath,
|
|
25
|
-
enterAutoWorktree,
|
|
26
|
-
getAutoWorktreeOriginalBase,
|
|
27
24
|
getActiveAutoWorktreeContext,
|
|
28
|
-
|
|
25
|
+
getAutoWorktreeOriginalBase,
|
|
29
26
|
_resetAutoWorktreeOriginalBaseForTests,
|
|
30
|
-
} from "../../auto-worktree.ts";
|
|
27
|
+
} from "../../auto-worktree-session-registry.ts";
|
|
28
|
+
import { syncGsdStateToWorktree } from "../../auto-worktree-sync.ts";
|
|
29
|
+
import { teardownAutoWorktree } from "../../auto-worktree-teardown.ts";
|
|
31
30
|
|
|
32
31
|
// Note: execSync is used intentionally in tests for git operations with
|
|
33
32
|
// controlled, hardcoded inputs (no user input). This is safe and matches
|
package/src/resources/extensions/gsd/tests/integration/feature-branch-lifecycle-integration.test.ts
CHANGED
|
@@ -22,11 +22,8 @@ import { join } from "node:path";
|
|
|
22
22
|
import { tmpdir } from "node:os";
|
|
23
23
|
import { execSync } from "node:child_process";
|
|
24
24
|
|
|
25
|
-
import {
|
|
26
|
-
|
|
27
|
-
mergeMilestoneToMain,
|
|
28
|
-
autoWorktreeBranch,
|
|
29
|
-
} from "../../auto-worktree.ts";
|
|
25
|
+
import { createAutoWorktree } from "../../auto-worktree-creation.ts";
|
|
26
|
+
import { mergeMilestoneToMain } from "../../auto-worktree-merge.ts";
|
|
30
27
|
import { captureIntegrationBranch, getSliceBranchName } from "../../worktree.ts";
|
|
31
28
|
import { writeIntegrationBranch, readIntegrationBranch } from "../../git-service.ts";
|
|
32
29
|
import { nextMilestoneId, generateMilestoneSuffix } from "../../guided-flow.ts";
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
RUNTIME_EXCLUSION_PATHS,
|
|
16
16
|
VALID_BRANCH_NAME,
|
|
17
17
|
runGit,
|
|
18
|
+
taskBranchArgs,
|
|
18
19
|
readIntegrationBranch,
|
|
19
20
|
resolveMilestoneIntegrationBranch,
|
|
20
21
|
writeIntegrationBranch,
|
|
@@ -1119,6 +1120,81 @@ process.exit(result.status ?? 0);
|
|
|
1119
1120
|
rmSync(repo, { recursive: true, force: true });
|
|
1120
1121
|
}
|
|
1121
1122
|
|
|
1123
|
+
// ─── taskBranchArgs ───────────────────────────────────────────────────
|
|
1124
|
+
|
|
1125
|
+
test('taskBranchArgs starts new workflow branches from the base branch, not from HEAD', () => {
|
|
1126
|
+
const repo = initBranchTestRepo();
|
|
1127
|
+
|
|
1128
|
+
assert.deepStrictEqual(
|
|
1129
|
+
taskBranchArgs(repo, "gsd/spike/first", "main", "main"),
|
|
1130
|
+
["checkout", "-b", "gsd/spike/first"],
|
|
1131
|
+
"branching while on the base branch itself needs no explicit start point",
|
|
1132
|
+
);
|
|
1133
|
+
|
|
1134
|
+
// Simulate a finished workflow left checked out with its own commit.
|
|
1135
|
+
run("git checkout -b gsd/spike/first", repo);
|
|
1136
|
+
createFile(repo, "first.txt", "first workflow output");
|
|
1137
|
+
runGit(repo, ["add", "-A"]);
|
|
1138
|
+
runGit(repo, ["commit", "-m", "first workflow work"]);
|
|
1139
|
+
_resetHasChangesCache();
|
|
1140
|
+
|
|
1141
|
+
const args = taskBranchArgs(repo, "gsd/spike/second", "gsd/spike/first", "main");
|
|
1142
|
+
assert.deepStrictEqual(
|
|
1143
|
+
args,
|
|
1144
|
+
["checkout", "-b", "gsd/spike/second", "main"],
|
|
1145
|
+
"next workflow branch starts from the base so workflows do not stack",
|
|
1146
|
+
);
|
|
1147
|
+
|
|
1148
|
+
runGit(repo, args);
|
|
1149
|
+
assert.deepStrictEqual(
|
|
1150
|
+
run("git rev-parse HEAD", repo),
|
|
1151
|
+
run("git rev-parse main", repo),
|
|
1152
|
+
"second workflow branch points at the base, without the first workflow's commit",
|
|
1153
|
+
);
|
|
1154
|
+
|
|
1155
|
+
rmSync(repo, { recursive: true, force: true });
|
|
1156
|
+
});
|
|
1157
|
+
|
|
1158
|
+
test('taskBranchArgs keeps branch-from-HEAD on user branches and unsafe states', () => {
|
|
1159
|
+
const repo = initBranchTestRepo();
|
|
1160
|
+
|
|
1161
|
+
// Manual feature branch: the user chose to stand here — new workflow
|
|
1162
|
+
// branches base on it, never silently jump to main.
|
|
1163
|
+
run("git checkout -b feature/login", repo);
|
|
1164
|
+
createFile(repo, "feature.txt", "feature work");
|
|
1165
|
+
runGit(repo, ["add", "-A"]);
|
|
1166
|
+
runGit(repo, ["commit", "-m", "feature work"]);
|
|
1167
|
+
_resetHasChangesCache();
|
|
1168
|
+
assert.deepStrictEqual(
|
|
1169
|
+
taskBranchArgs(repo, "gsd/spike/from-feature", "feature/login", "main"),
|
|
1170
|
+
["checkout", "-b", "gsd/spike/from-feature"],
|
|
1171
|
+
"a manual feature branch is a deliberate base — no redirect to main",
|
|
1172
|
+
);
|
|
1173
|
+
|
|
1174
|
+
// Base branch without a local ref (e.g. origin/HEAD names a branch that
|
|
1175
|
+
// was never checked out locally): fall back to HEAD instead of failing.
|
|
1176
|
+
run("git checkout -b gsd/spike/stale", repo);
|
|
1177
|
+
_resetHasChangesCache();
|
|
1178
|
+
assert.deepStrictEqual(
|
|
1179
|
+
taskBranchArgs(repo, "gsd/spike/next", "gsd/spike/stale", "no-such-branch"),
|
|
1180
|
+
["checkout", "-b", "gsd/spike/next"],
|
|
1181
|
+
"missing local base ref falls back to branch-from-HEAD",
|
|
1182
|
+
);
|
|
1183
|
+
|
|
1184
|
+
// Dirty tree on a task branch: a tree-changing start point would abort
|
|
1185
|
+
// the checkout or strand the changes — fall back to HEAD.
|
|
1186
|
+
createFile(repo, "dirty.txt", "uncommitted");
|
|
1187
|
+
runGit(repo, ["add", "-A"]);
|
|
1188
|
+
_resetHasChangesCache();
|
|
1189
|
+
assert.deepStrictEqual(
|
|
1190
|
+
taskBranchArgs(repo, "gsd/spike/next", "gsd/spike/stale", "main"),
|
|
1191
|
+
["checkout", "-b", "gsd/spike/next"],
|
|
1192
|
+
"dirty working tree falls back to branch-from-HEAD",
|
|
1193
|
+
);
|
|
1194
|
+
|
|
1195
|
+
rmSync(repo, { recursive: true, force: true });
|
|
1196
|
+
});
|
|
1197
|
+
|
|
1122
1198
|
// ═══════════════════════════════════════════════════════════════════════
|
|
1123
1199
|
// S05: Enhanced features — snapshots, pre-merge checks
|
|
1124
1200
|
// ═══════════════════════════════════════════════════════════════════════
|
|
@@ -28,7 +28,7 @@ import { join } from "node:path";
|
|
|
28
28
|
import { tmpdir } from "node:os";
|
|
29
29
|
import { execSync } from "node:child_process";
|
|
30
30
|
|
|
31
|
-
import { mergeMilestoneToMain } from "../../auto-worktree.ts";
|
|
31
|
+
import { mergeMilestoneToMain } from "../../auto-worktree-merge.ts";
|
|
32
32
|
import { MergeConflictError } from "../../git-service.ts";
|
|
33
33
|
|
|
34
34
|
function run(cmd: string, cwd: string): string {
|
|
@@ -6,7 +6,7 @@ import { join } from "node:path";
|
|
|
6
6
|
import { tmpdir } from "node:os";
|
|
7
7
|
|
|
8
8
|
import { GSDError } from "../../errors.js";
|
|
9
|
-
import { mergeMilestoneToMain } from "../../auto-worktree.ts";
|
|
9
|
+
import { mergeMilestoneToMain } from "../../auto-worktree-merge.ts";
|
|
10
10
|
|
|
11
11
|
function run(cmd: string, cwd: string): string {
|
|
12
12
|
return execSync(cmd, {
|
|
@@ -29,7 +29,8 @@ import { join } from "node:path";
|
|
|
29
29
|
import { tmpdir } from "node:os";
|
|
30
30
|
import { execSync } from "node:child_process";
|
|
31
31
|
|
|
32
|
-
import { createAutoWorktree
|
|
32
|
+
import { createAutoWorktree } from "../../auto-worktree-creation.ts";
|
|
33
|
+
import { mergeMilestoneToMain } from "../../auto-worktree-merge.ts";
|
|
33
34
|
import { closeDatabase } from "../../gsd-db.ts";
|
|
34
35
|
import { getSliceBranchName } from "../../worktree.ts";
|
|
35
36
|
|
package/src/resources/extensions/gsd/tests/integration/milestone-transition-worktree.test.ts
CHANGED
|
@@ -16,13 +16,11 @@ import { execSync } from "node:child_process";
|
|
|
16
16
|
import { dirname } from "node:path";
|
|
17
17
|
import { fileURLToPath } from "node:url";
|
|
18
18
|
|
|
19
|
-
import {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
mergeMilestoneToMain,
|
|
25
|
-
} from "../../auto-worktree.ts";
|
|
19
|
+
import { createAutoWorktree } from "../../auto-worktree-creation.ts";
|
|
20
|
+
import { isInAutoWorktree } from "../../auto-worktree-entry.ts";
|
|
21
|
+
import { mergeMilestoneToMain } from "../../auto-worktree-merge.ts";
|
|
22
|
+
import { getAutoWorktreeOriginalBase } from "../../auto-worktree-session-registry.ts";
|
|
23
|
+
import { teardownAutoWorktree } from "../../auto-worktree-teardown.ts";
|
|
26
24
|
|
|
27
25
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
28
26
|
|
package/src/resources/extensions/gsd/tests/integration/workspace-collapse-integration.test.ts
CHANGED
|
@@ -25,10 +25,8 @@ import {
|
|
|
25
25
|
markDepthVerified,
|
|
26
26
|
clearDiscussionFlowState,
|
|
27
27
|
} from "../../bootstrap/write-gate.ts";
|
|
28
|
-
import {
|
|
29
|
-
|
|
30
|
-
_resetAutoWorktreeOriginalBaseForTests,
|
|
31
|
-
} from "../../auto-worktree.ts";
|
|
28
|
+
import { _resetAutoWorktreeOriginalBaseForTests } from "../../auto-worktree-session-registry.ts";
|
|
29
|
+
import { teardownAutoWorktree } from "../../auto-worktree-teardown.ts";
|
|
32
30
|
import {
|
|
33
31
|
openDatabaseByWorkspace,
|
|
34
32
|
closeAllDatabases,
|
|
@@ -40,6 +40,7 @@ import { readUnitRuntimeRecord } from "../unit-runtime.js";
|
|
|
40
40
|
import { ModelPolicyDispatchBlockedError } from "../auto-model-selection.js";
|
|
41
41
|
import {
|
|
42
42
|
closeDatabase,
|
|
43
|
+
getTask,
|
|
43
44
|
insertMilestone,
|
|
44
45
|
insertSlice,
|
|
45
46
|
insertTask,
|
|
@@ -445,7 +446,7 @@ test("runDispatch retries when complete-milestone summary exists on disk and stu
|
|
|
445
446
|
assert.equal(stopCalls, 0, "artifact-based recovery should not hard-stop the loop");
|
|
446
447
|
});
|
|
447
448
|
|
|
448
|
-
test("runDispatch
|
|
449
|
+
test("runDispatch promotes execute-task DB status when artifacts exist but DB status is still open (#1204)", async (t) => {
|
|
449
450
|
const capture = createEventCapture();
|
|
450
451
|
let pauseCalls = 0;
|
|
451
452
|
let stopCalls = 0;
|
|
@@ -522,16 +523,16 @@ test("runDispatch pauses when execute-task artifacts exist but DB status is stil
|
|
|
522
523
|
|
|
523
524
|
const result = await runDispatch(ic, preData, loopState);
|
|
524
525
|
|
|
525
|
-
assert.equal(result.action, "
|
|
526
|
-
assert.equal(
|
|
527
|
-
assert.equal(
|
|
528
|
-
assert.equal(
|
|
529
|
-
assert.equal(
|
|
530
|
-
assert.equal(loopState.
|
|
531
|
-
assert.equal(
|
|
526
|
+
assert.equal(result.action, "continue");
|
|
527
|
+
assert.equal(pauseCalls, 0, "disk-verified promotion should not pause auto-mode");
|
|
528
|
+
assert.equal(stopCalls, 0, "disk-verified promotion should not hard-stop the loop");
|
|
529
|
+
assert.equal(invalidateCalls, 1, "successful promotion should invalidate caches before retrying");
|
|
530
|
+
assert.equal(loopState.recentUnits.length, 0, "successful promotion should clear the stuck window");
|
|
531
|
+
assert.equal(loopState.stuckRecoveryAttempts, 1, "Level 1 recovery increments the attempt counter");
|
|
532
|
+
assert.equal(getTask("M001", "S01", "T01")?.status, "complete", "the open DB task should be promoted to complete");
|
|
532
533
|
});
|
|
533
534
|
|
|
534
|
-
test("runDispatch
|
|
535
|
+
test("runDispatch promotes execute-task DB status at Level 2 when artifacts exist but DB status is still open (#1204)", async (t) => {
|
|
535
536
|
const capture = createEventCapture();
|
|
536
537
|
let pauseCalls = 0;
|
|
537
538
|
let stopCalls = 0;
|
|
@@ -601,13 +602,13 @@ test("runDispatch pauses at Level 2 when execute-task artifacts exist but DB sta
|
|
|
601
602
|
|
|
602
603
|
const result = await runDispatch(ic, preData, loopState);
|
|
603
604
|
|
|
604
|
-
assert.equal(result.action, "
|
|
605
|
-
assert.equal(
|
|
606
|
-
assert.equal(
|
|
607
|
-
assert.equal(stopCalls, 0, "Level 2 execute-task disk/db mismatch should not hard-stop the loop");
|
|
605
|
+
assert.equal(result.action, "continue");
|
|
606
|
+
assert.equal(pauseCalls, 0, "Level 2 disk-verified promotion should not pause auto-mode");
|
|
607
|
+
assert.equal(stopCalls, 0, "Level 2 disk-verified promotion should not hard-stop the loop");
|
|
608
608
|
assert.equal(invalidateCalls, 1, "Level 2 should invalidate caches before the final artifact recheck");
|
|
609
|
-
assert.equal(loopState.recentUnits.length,
|
|
610
|
-
assert.equal(loopState.stuckRecoveryAttempts, 1, "Level 2
|
|
609
|
+
assert.equal(loopState.recentUnits.length, 0, "Level 2 successful promotion should clear the stuck window");
|
|
610
|
+
assert.equal(loopState.stuckRecoveryAttempts, 1, "Level 2 does not reset the recovery counter");
|
|
611
|
+
assert.equal(getTask("M001", "S01", "T01")?.status, "complete", "the open DB task should be promoted to complete");
|
|
611
612
|
});
|
|
612
613
|
|
|
613
614
|
test("runDispatch clears execute-task stuck state when artifacts and DB status are complete", async (t) => {
|
|
@@ -8,7 +8,7 @@ import { join } from "node:path";
|
|
|
8
8
|
import { tmpdir } from "node:os";
|
|
9
9
|
import { execFileSync } from "node:child_process";
|
|
10
10
|
|
|
11
|
-
import { mergeMilestoneToMain } from "../auto-worktree.ts";
|
|
11
|
+
import { mergeMilestoneToMain } from "../auto-worktree-merge.ts";
|
|
12
12
|
import { checkCloseoutConsistencyGate } from "../closeout-consistency-gate.ts";
|
|
13
13
|
import {
|
|
14
14
|
closeDatabase,
|
|
@@ -14,7 +14,7 @@ import { tmpdir } from "node:os";
|
|
|
14
14
|
import { delimiter, join } from "node:path";
|
|
15
15
|
import { execFileSync } from "node:child_process";
|
|
16
16
|
|
|
17
|
-
import { mergeMilestoneToMain } from "../auto-worktree.ts";
|
|
17
|
+
import { mergeMilestoneToMain } from "../auto-worktree-merge.ts";
|
|
18
18
|
import { closeDatabase, insertAssessment, insertMilestone, insertSlice, openDatabase } from "../gsd-db.ts";
|
|
19
19
|
import { GIT_NO_PROMPT_ENV } from "../git-constants.js";
|
|
20
20
|
import { _clearGsdRootCache } from "../paths.ts";
|
|
@@ -19,7 +19,7 @@ import { join } from "node:path";
|
|
|
19
19
|
import { tmpdir } from "node:os";
|
|
20
20
|
import { execFileSync } from "node:child_process";
|
|
21
21
|
|
|
22
|
-
import { mergeMilestoneToMain } from "../auto-worktree.ts";
|
|
22
|
+
import { mergeMilestoneToMain } from "../auto-worktree-merge.ts";
|
|
23
23
|
import { _resetServiceCache } from "../worktree.ts";
|
|
24
24
|
import { _clearGsdRootCache } from "../paths.ts";
|
|
25
25
|
|
|
@@ -250,6 +250,73 @@ test("migration auto-check canonicalizes a legacy descriptor milestone dir (no f
|
|
|
250
250
|
}
|
|
251
251
|
});
|
|
252
252
|
|
|
253
|
+
test("migration auto-check recognizes suffixed flat-phase projection directories", async () => {
|
|
254
|
+
const base = makeBase();
|
|
255
|
+
try {
|
|
256
|
+
await writeGSDDirectory({ projectContent: "# P\n", decisionsContent: "", requirements: [], milestones: [] }, base);
|
|
257
|
+
assert.equal(await ensureDbOpen(base), true);
|
|
258
|
+
|
|
259
|
+
insertMilestone({
|
|
260
|
+
id: "M001-re4q3k",
|
|
261
|
+
title: "Clean GSD Continuation Readiness",
|
|
262
|
+
status: "complete",
|
|
263
|
+
planning: { vision: "Keep continuation state readable." },
|
|
264
|
+
});
|
|
265
|
+
insertSlice({
|
|
266
|
+
id: "S01",
|
|
267
|
+
milestoneId: "M001-re4q3k",
|
|
268
|
+
title: "Readiness slice",
|
|
269
|
+
status: "complete",
|
|
270
|
+
risk: "low",
|
|
271
|
+
depends: [],
|
|
272
|
+
demo: "Readable continuation state.",
|
|
273
|
+
sequence: 1,
|
|
274
|
+
});
|
|
275
|
+
insertTask({
|
|
276
|
+
id: "T01",
|
|
277
|
+
sliceId: "S01",
|
|
278
|
+
milestoneId: "M001-re4q3k",
|
|
279
|
+
title: "Readiness task",
|
|
280
|
+
status: "complete",
|
|
281
|
+
});
|
|
282
|
+
insertMilestone({
|
|
283
|
+
id: "M002-a1rwmq",
|
|
284
|
+
title: "Support Command Policy Hardening",
|
|
285
|
+
status: "complete",
|
|
286
|
+
planning: { vision: "Harden support command policy." },
|
|
287
|
+
});
|
|
288
|
+
insertSlice({
|
|
289
|
+
id: "S01",
|
|
290
|
+
milestoneId: "M002-a1rwmq",
|
|
291
|
+
title: "Policy slice",
|
|
292
|
+
status: "complete",
|
|
293
|
+
risk: "low",
|
|
294
|
+
depends: [],
|
|
295
|
+
demo: "Policy is hardened.",
|
|
296
|
+
sequence: 1,
|
|
297
|
+
});
|
|
298
|
+
insertTask({
|
|
299
|
+
id: "T01",
|
|
300
|
+
sliceId: "S01",
|
|
301
|
+
milestoneId: "M002-a1rwmq",
|
|
302
|
+
title: "Policy task",
|
|
303
|
+
status: "complete",
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
const { rebuildMarkdownProjectionsFromDb } = await import("../commands-maintenance.ts");
|
|
307
|
+
const rebuild = await rebuildMarkdownProjectionsFromDb(base);
|
|
308
|
+
assert.ok(rebuild.rendered > 0, "expected flat-phase markdown projections to render");
|
|
309
|
+
|
|
310
|
+
const result = await checkMarkdownHierarchyAgainstDb(base);
|
|
311
|
+
assert.equal(result.action, "none");
|
|
312
|
+
assert.equal(result.reason, "in-sync");
|
|
313
|
+
assert.deepEqual(result.markdown, { milestones: 2, slices: 2, tasks: 2 });
|
|
314
|
+
assert.deepEqual(result.beforeDb, { milestones: 2, slices: 2, tasks: 2 });
|
|
315
|
+
} finally {
|
|
316
|
+
cleanup(base);
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
|
|
253
320
|
test("migration auto-check refreshes a stale open DB handle before comparing", async () => {
|
|
254
321
|
const base = makeBase();
|
|
255
322
|
try {
|
|
@@ -372,6 +439,30 @@ test("migration auto-check still compares a roadmapless milestone that HAS a DB
|
|
|
372
439
|
}
|
|
373
440
|
});
|
|
374
441
|
|
|
442
|
+
test("migration auto-check aligns a roadmapless milestone dir to its suffixed DB row (no false drift)", async () => {
|
|
443
|
+
const base = makeBase();
|
|
444
|
+
try {
|
|
445
|
+
await writeGSDDirectory({ projectContent: "# P\n", decisionsContent: "", requirements: [], milestones: [] }, base);
|
|
446
|
+
assert.equal(await ensureDbOpen(base), true);
|
|
447
|
+
// Team-mode suffixed milestone whose markdown dir has no ROADMAP yet (e.g. a
|
|
448
|
+
// freshly handed-off / zero-slice milestone). Markdown discovers the bare
|
|
449
|
+
// "M001"; the DB stores the authoritative suffixed "M001-re4q3k". The
|
|
450
|
+
// bare-to-suffixed alignment must rewrite EVERY markdown set, including the
|
|
451
|
+
// roadmapless subset, so the discussion-phase exclusion sees the DB row and
|
|
452
|
+
// does not decrement the milestone count into false drift.
|
|
453
|
+
insertMilestone({ id: "M001-re4q3k", title: "Suffixed milestone", status: "queued" });
|
|
454
|
+
writeScratchMilestoneDir(base, "M001", "M001-CONTEXT.md");
|
|
455
|
+
|
|
456
|
+
const result = await checkMarkdownHierarchyAgainstDb(base);
|
|
457
|
+
assert.equal(result.action, "none");
|
|
458
|
+
assert.equal(result.reason, "in-sync");
|
|
459
|
+
assert.deepEqual(result.markdown, { milestones: 1, slices: 0, tasks: 0 });
|
|
460
|
+
assert.deepEqual(result.beforeDb, { milestones: 1, slices: 0, tasks: 0 });
|
|
461
|
+
} finally {
|
|
462
|
+
cleanup(base);
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
|
|
375
466
|
test("rebuildMarkdownProjectionsFromDb realigns markdown when DB holds extra rows", async () => {
|
|
376
467
|
const base = makeBase();
|
|
377
468
|
try {
|