@opengsd/gsd-pi 1.4.0 → 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 +11 -11
- package/dist/onboarding.js +11 -0
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/GSD-WORKFLOW.md +20 -25
- package/dist/resources/extensions/ask-user-questions.js +1 -1
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +118 -53
- package/dist/resources/extensions/cursor-cli/index.js +16 -0
- package/dist/resources/extensions/cursor-cli/models.js +63 -0
- package/dist/resources/extensions/cursor-cli/package.json +11 -0
- package/dist/resources/extensions/cursor-cli/readiness.js +128 -0
- package/dist/resources/extensions/cursor-cli/stream-adapter.js +353 -0
- package/dist/resources/extensions/gsd/activity-log.js +4 -1
- package/dist/resources/extensions/gsd/artifact-verification.js +25 -9
- package/dist/resources/extensions/gsd/auto/closeout.js +137 -42
- package/dist/resources/extensions/gsd/auto/finalize.js +9 -0
- 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/run-unit.js +5 -2
- package/dist/resources/extensions/gsd/auto/schedule-wakeup.js +3 -0
- 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 +31 -7
- package/dist/resources/extensions/gsd/auto-model-selection.js +36 -18
- package/dist/resources/extensions/gsd/auto-prompts.js +76 -2
- package/dist/resources/extensions/gsd/auto-recovery.js +50 -6
- package/dist/resources/extensions/gsd/auto-start.js +8 -6
- package/dist/resources/extensions/gsd/auto-timeout-recovery.js +4 -0
- 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 -2046
- package/dist/resources/extensions/gsd/auto.js +31 -5
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +3 -0
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +1 -1
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +134 -7
- package/dist/resources/extensions/gsd/bootstrap/schedule-wakeup-tool.js +58 -9
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +1 -1
- package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +194 -28
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +14 -1
- package/dist/resources/extensions/gsd/codebase-generator.js +164 -20
- package/dist/resources/extensions/gsd/commands/handlers/core.js +40 -4
- package/dist/resources/extensions/gsd/commands-handlers.js +1 -1
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +153 -1
- package/dist/resources/extensions/gsd/commands-workflow-templates.js +3 -3
- package/dist/resources/extensions/gsd/commands-worktree.js +11 -2
- package/dist/resources/extensions/gsd/db/queries.js +48 -9
- package/dist/resources/extensions/gsd/db/writers/cascades.js +20 -2
- package/dist/resources/extensions/gsd/discussion-handoff.js +8 -3
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +8 -2
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +292 -18
- package/dist/resources/extensions/gsd/doctor-providers.js +38 -10
- package/dist/resources/extensions/gsd/doctor.js +93 -3
- package/dist/resources/extensions/gsd/exec-sandbox.js +6 -2
- package/dist/resources/extensions/gsd/flat-phase-migration.js +106 -26
- 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 +59 -18
- package/dist/resources/extensions/gsd/gsd-db.js +75 -11
- package/dist/resources/extensions/gsd/guidance.js +1 -0
- package/dist/resources/extensions/gsd/guided-flow.js +62 -19
- package/dist/resources/extensions/gsd/key-manager.js +1 -0
- package/dist/resources/extensions/gsd/markdown-renderer.js +40 -11
- package/dist/resources/extensions/gsd/md-importer.js +89 -23
- package/dist/resources/extensions/gsd/migrate-external.js +24 -7
- package/dist/resources/extensions/gsd/migration-auto-check.js +30 -3
- package/dist/resources/extensions/gsd/milestone-merge-transaction.js +14 -3
- 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-diagnostics.js +24 -1
- package/dist/resources/extensions/gsd/preferences-models.js +6 -4
- 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 +107 -2
- package/dist/resources/extensions/gsd/preferences.js +49 -2
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +4 -2
- package/dist/resources/extensions/gsd/prompts/system.md +6 -6
- package/dist/resources/extensions/gsd/quick.js +12 -3
- package/dist/resources/extensions/gsd/redact-secrets.js +37 -0
- package/dist/resources/extensions/gsd/repo-identity.js +16 -0
- package/dist/resources/extensions/gsd/repository-registry.js +6 -1
- package/dist/resources/extensions/gsd/root-write-leak-guard.js +4 -2
- package/dist/resources/extensions/gsd/safe-fs.js +23 -2
- package/dist/resources/extensions/gsd/skill-discovery.js +36 -23
- package/dist/resources/extensions/gsd/skills/gsd-headless/SKILL.md +7 -9
- package/dist/resources/extensions/gsd/skills/gsd-headless/references/commands.md +1 -0
- 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/plan-task.js +76 -8
- 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/workflow-tool-executors.js +40 -0
- package/dist/resources/extensions/gsd/unit-context-manifest.js +5 -4
- package/dist/resources/extensions/gsd/unit-registry.js +37 -2
- package/dist/resources/extensions/gsd/unit-runtime.js +21 -0
- 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/workspace.js +26 -8
- package/dist/resources/extensions/gsd/worktree-command.js +1 -1
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +81 -14
- package/dist/resources/extensions/gsd/worktree-manager.js +97 -4
- 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 +9 -9
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/required-server-files.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- 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 +3 -3
- 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 +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/mcp-connections/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
- 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 +3 -3
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +9 -9
- package/dist/web/standalone/.next/server/chunks/2842.js +4 -4
- package/dist/web/standalone/.next/server/chunks/8357.js +2 -2
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware.js +3 -3
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/app/_not-found/page-a6fb1847f67f167c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/{layout-b35cbfff38aaf4cf.js → layout-4ae2d68984392bbf.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/page-72a856634ad14c10.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{main-app-590a74400e35f685.js → main-app-90d1d8d5e5d2dc6b.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-1115d46ac61b9823.js +1 -0
- package/dist/web/standalone/node_modules/@gsd/native/package.json +1 -1
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
- package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
- package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
- package/dist/web/standalone/server.js +1 -1
- package/dist/wizard.d.ts +8 -0
- package/dist/wizard.js +8 -1
- package/integrations/hermes/CONTEXT.md +47 -0
- package/integrations/hermes/README.md +21 -0
- package/integrations/hermes/__init__.py +31 -0
- package/integrations/hermes/docs/issue-1162-grilling.md +197 -0
- package/integrations/hermes/docs/setup.md +4 -0
- package/integrations/hermes/open_gsd_hermes/commands.py +141 -0
- package/integrations/hermes/open_gsd_hermes/config.py +2 -0
- package/integrations/hermes/open_gsd_hermes/gsd_client.py +591 -39
- package/integrations/hermes/open_gsd_hermes/notifications.py +10 -1
- package/integrations/hermes/plugin.yaml +4 -0
- package/integrations/hermes/tests/test_config.py +6 -0
- package/integrations/hermes/tests/test_directory_loader.py +37 -0
- package/integrations/hermes/tests/test_gsd_client_cache.py +3 -0
- package/integrations/hermes/tests/test_gsd_client_execute.py +35 -0
- package/integrations/hermes/tests/test_gsd_client_process_cwd.py +22 -0
- package/integrations/hermes/tests/test_gsd_client_timeout.py +98 -0
- package/integrations/hermes/tests/test_milestone_client.py +447 -0
- package/integrations/hermes/tests/test_new_milestone_command.py +313 -0
- package/integrations/hermes/tests/test_supervisor_fsm.py +40 -0
- package/package.json +8 -8
- package/packages/cloud-mcp-gateway/dist/auth-store.d.ts +1 -0
- package/packages/cloud-mcp-gateway/dist/auth-store.d.ts.map +1 -1
- package/packages/cloud-mcp-gateway/dist/auth-store.js +21 -1
- package/packages/cloud-mcp-gateway/dist/auth-store.js.map +1 -1
- package/packages/cloud-mcp-gateway/dist/auth-store.test.js +34 -0
- package/packages/cloud-mcp-gateway/dist/auth-store.test.js.map +1 -1
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/dist/cloud-runtime.d.ts +2 -0
- package/packages/daemon/dist/cloud-runtime.d.ts.map +1 -1
- package/packages/daemon/dist/cloud-runtime.js +25 -1
- package/packages/daemon/dist/cloud-runtime.js.map +1 -1
- package/packages/daemon/dist/cloud-runtime.test.js +51 -0
- package/packages/daemon/dist/cloud-runtime.test.js.map +1 -1
- package/packages/daemon/dist/message-batcher.d.ts +7 -0
- package/packages/daemon/dist/message-batcher.d.ts.map +1 -1
- package/packages/daemon/dist/message-batcher.js +13 -0
- package/packages/daemon/dist/message-batcher.js.map +1 -1
- package/packages/daemon/dist/message-batcher.test.js +48 -0
- package/packages/daemon/dist/message-batcher.test.js.map +1 -1
- package/packages/daemon/dist/session-manager.js +1 -1
- package/packages/daemon/dist/session-manager.js.map +1 -1
- package/packages/daemon/package.json +5 -5
- package/packages/gsd-agent-core/dist/compaction/compaction.d.ts +13 -1
- package/packages/gsd-agent-core/dist/compaction/compaction.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/compaction/compaction.js +15 -1
- package/packages/gsd-agent-core/dist/compaction/compaction.js.map +1 -1
- package/packages/gsd-agent-core/dist/export-html/template.js +53 -4
- package/packages/gsd-agent-core/dist/session/agent-session-navigation.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-navigation.js +4 -1
- package/packages/gsd-agent-core/dist/session/agent-session-navigation.js.map +1 -1
- 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/dist/modes/interactive/controllers/chat-segment-walker.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.js +1 -1
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/dist/server.d.ts +18 -5
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +46 -5
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/session-manager.js +1 -1
- package/packages/mcp-server/dist/session-manager.js.map +1 -1
- package/packages/mcp-server/package.json +4 -4
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/dist/agent-loop.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/env-api-keys.d.ts.map +1 -1
- package/packages/pi-ai/dist/env-api-keys.js +3 -0
- package/packages/pi-ai/dist/env-api-keys.js.map +1 -1
- package/packages/pi-ai/dist/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 +10 -22
- 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/model-resolver.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -0
- package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/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/session-manager-types.d.ts +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager-types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager.js +3 -0
- package/packages/pi-coding-agent/dist/core/session-manager.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/dist/rpc-client.js +1 -1
- package/packages/rpc-client/dist/rpc-client.js.map +1 -1
- package/packages/rpc-client/package.json +2 -2
- package/pkg/dist/core/export-html/template.js +53 -4
- package/pkg/package.json +1 -1
- package/scripts/link-workspace-packages.cjs +14 -4
- package/src/resources/GSD-WORKFLOW.md +20 -25
- package/src/resources/extensions/ask-user-questions.ts +1 -1
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +130 -51
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +371 -39
- package/src/resources/extensions/cursor-cli/index.ts +18 -0
- package/src/resources/extensions/cursor-cli/models.ts +65 -0
- package/src/resources/extensions/cursor-cli/package.json +11 -0
- package/src/resources/extensions/cursor-cli/readiness.ts +143 -0
- package/src/resources/extensions/cursor-cli/stream-adapter.ts +440 -0
- package/src/resources/extensions/cursor-cli/tests/index.test.ts +54 -0
- package/src/resources/extensions/cursor-cli/tests/readiness.test.ts +29 -0
- package/src/resources/extensions/cursor-cli/tests/stream-adapter.test.ts +166 -0
- package/src/resources/extensions/gsd/activity-log.ts +4 -1
- package/src/resources/extensions/gsd/artifact-verification.ts +25 -9
- package/src/resources/extensions/gsd/auto/closeout.ts +163 -58
- package/src/resources/extensions/gsd/auto/finalize.ts +8 -0
- package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
- 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/run-unit.ts +5 -2
- package/src/resources/extensions/gsd/auto/schedule-wakeup.ts +8 -0
- 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 +35 -7
- package/src/resources/extensions/gsd/auto-model-selection.ts +49 -18
- package/src/resources/extensions/gsd/auto-prompts.ts +73 -2
- package/src/resources/extensions/gsd/auto-recovery.ts +50 -6
- package/src/resources/extensions/gsd/auto-start.ts +9 -6
- package/src/resources/extensions/gsd/auto-timeout-recovery.ts +4 -0
- 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 -2390
- package/src/resources/extensions/gsd/auto.ts +32 -19
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +3 -0
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +1 -1
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +148 -7
- package/src/resources/extensions/gsd/bootstrap/schedule-wakeup-tool.ts +80 -12
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +1 -1
- package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +229 -28
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +23 -1
- package/src/resources/extensions/gsd/codebase-generator.ts +186 -19
- package/src/resources/extensions/gsd/commands/handlers/core.ts +39 -3
- package/src/resources/extensions/gsd/commands-handlers.ts +1 -1
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +135 -1
- package/src/resources/extensions/gsd/commands-workflow-templates.ts +3 -3
- package/src/resources/extensions/gsd/commands-worktree.ts +13 -2
- package/src/resources/extensions/gsd/db/queries.ts +49 -9
- package/src/resources/extensions/gsd/db/writers/cascades.ts +23 -1
- package/src/resources/extensions/gsd/discussion-handoff.ts +10 -2
- package/src/resources/extensions/gsd/docs/preferences-reference.md +8 -2
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +372 -22
- package/src/resources/extensions/gsd/doctor-providers.ts +39 -10
- package/src/resources/extensions/gsd/doctor-types.ts +5 -1
- package/src/resources/extensions/gsd/doctor.ts +95 -3
- package/src/resources/extensions/gsd/exec-sandbox.ts +6 -2
- package/src/resources/extensions/gsd/flat-phase-migration.ts +132 -25
- 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 +67 -17
- package/src/resources/extensions/gsd/gsd-db.ts +105 -11
- package/src/resources/extensions/gsd/guidance.ts +2 -0
- package/src/resources/extensions/gsd/guided-flow.ts +71 -20
- package/src/resources/extensions/gsd/key-manager.ts +1 -0
- package/src/resources/extensions/gsd/markdown-renderer.ts +40 -10
- package/src/resources/extensions/gsd/md-importer.ts +93 -22
- package/src/resources/extensions/gsd/migrate-external.ts +23 -6
- package/src/resources/extensions/gsd/migration-auto-check.ts +32 -3
- package/src/resources/extensions/gsd/milestone-merge-transaction.ts +19 -4
- package/src/resources/extensions/gsd/milestone-settlement.ts +1 -1
- package/src/resources/extensions/gsd/model-router.ts +4 -5
- 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-diagnostics.ts +24 -0
- package/src/resources/extensions/gsd/preferences-models.ts +6 -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 +97 -2
- package/src/resources/extensions/gsd/preferences.ts +58 -4
- package/src/resources/extensions/gsd/prompts/plan-slice.md +4 -2
- package/src/resources/extensions/gsd/prompts/system.md +6 -6
- package/src/resources/extensions/gsd/quick.ts +11 -3
- package/src/resources/extensions/gsd/redact-secrets.ts +40 -0
- package/src/resources/extensions/gsd/repo-identity.ts +17 -0
- package/src/resources/extensions/gsd/repository-registry.ts +7 -1
- package/src/resources/extensions/gsd/root-write-leak-guard.ts +3 -2
- package/src/resources/extensions/gsd/safe-fs.ts +22 -2
- package/src/resources/extensions/gsd/skill-discovery.ts +47 -23
- package/src/resources/extensions/gsd/skills/gsd-headless/SKILL.md +7 -9
- package/src/resources/extensions/gsd/skills/gsd-headless/references/commands.md +1 -0
- 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-loop.test.ts +131 -5
- package/src/resources/extensions/gsd/tests/auto-migrating-recovery.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +178 -0
- package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +43 -1
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +111 -0
- package/src/resources/extensions/gsd/tests/auto-remote-session-lock-cleanup.test.ts +41 -0
- package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +41 -0
- package/src/resources/extensions/gsd/tests/auto-session-scope.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +3 -0
- package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/auto-timeout-recovery-harness-abort.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +10 -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/batch-task-query.test.ts +85 -0
- package/src/resources/extensions/gsd/tests/check-auto-start-ready-guard.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +387 -0
- package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +62 -1
- 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-providers.test.ts +138 -1
- package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +571 -5
- package/src/resources/extensions/gsd/tests/doctor-workspace.test.ts +207 -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 +109 -2
- package/src/resources/extensions/gsd/tests/flat-phase-renderer.test.ts +25 -1
- package/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts +87 -19
- package/src/resources/extensions/gsd/tests/gate-1b-orphan-discrimination.test.ts +89 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +9 -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/state-machine-edge-cases.test.ts +4 -2
- 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/markdown-renderer.test.ts +122 -0
- package/src/resources/extensions/gsd/tests/merge-closeout-consistency-gate.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +4 -4
- 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/migrate-external-worktree.test.ts +116 -0
- 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 +592 -23
- package/src/resources/extensions/gsd/tests/milestone-merge-transaction.test.ts +25 -1
- 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/pending-autostart-scope.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +50 -6
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +17 -0
- package/src/resources/extensions/gsd/tests/plan-task.test.ts +264 -1
- package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +1 -4
- package/src/resources/extensions/gsd/tests/preferences.test.ts +169 -0
- package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +147 -0
- package/src/resources/extensions/gsd/tests/recovery-verify-logs.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/redact-secrets.test.ts +56 -0
- package/src/resources/extensions/gsd/tests/register-hooks-flat-phase-migration.test.ts +73 -0
- package/src/resources/extensions/gsd/tests/register-hooks-loop-guard-auto.test.ts +275 -0
- package/src/resources/extensions/gsd/tests/reopen-slice.test.ts +52 -0
- package/src/resources/extensions/gsd/tests/repository-registry.test.ts +41 -2
- package/src/resources/extensions/gsd/tests/require-slice-discussion-dispatch.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/root-write-leak-guard.test.ts +31 -9
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/schedule-wakeup-tool.test.ts +167 -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/stalled-tool-recovery.test.ts +49 -0
- 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/state-corruption-2945.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/status-per-repo.test.ts +94 -0
- 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/token-tool-gating.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +259 -0
- package/src/resources/extensions/gsd/tests/uat-stuck-loop-orphaned-worktree.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +66 -18
- package/src/resources/extensions/gsd/tests/unit-registry.test.ts +81 -0
- package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +52 -0
- package/src/resources/extensions/gsd/tests/validator-scope-parity.test.ts +53 -1
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +208 -1
- package/src/resources/extensions/gsd/tests/workspace.test.ts +18 -4
- 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-journal-events.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +2 -2
- 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 +36 -3
- 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/tests/worktree-teardown-safety.test.ts +32 -0
- package/src/resources/extensions/gsd/tool-contract.ts +29 -0
- package/src/resources/extensions/gsd/tools/plan-task.ts +107 -9
- 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/workflow-tool-executors.ts +58 -0
- package/src/resources/extensions/gsd/unit-context-manifest.ts +11 -5
- package/src/resources/extensions/gsd/unit-registry.ts +48 -2
- package/src/resources/extensions/gsd/unit-runtime.ts +42 -0
- 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/workspace.ts +42 -8
- package/src/resources/extensions/gsd/worktree-command.ts +1 -1
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +154 -26
- package/src/resources/extensions/gsd/worktree-manager.ts +143 -5
- 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/chunks/app/_not-found/page-49f565245e1e4afe.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/page-bc4c723c6a19c6f0.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ec3eaffc9785ba48.js +0 -1
- /package/dist/web/standalone/.next/static/{zQLcXm0Za8lexoXtgDpMG → gXoWec4UNqcR0tkuHwYCr}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{zQLcXm0Za8lexoXtgDpMG → gXoWec4UNqcR0tkuHwYCr}/_ssgManifest.js +0 -0
|
@@ -454,6 +454,14 @@ export function insertTask(t: {
|
|
|
454
454
|
fullSummaryMd?: string;
|
|
455
455
|
sequence?: number;
|
|
456
456
|
planning?: Partial<TaskPlanningRecord>;
|
|
457
|
+
// #1222 (metadata half): when re-importing from markdown, the caller only
|
|
458
|
+
// knows the plan/status — not the execution prose that gsd_task_complete
|
|
459
|
+
// wrote to the DB. Setting this preserves the existing row's execution
|
|
460
|
+
// columns (and completed_at) whenever the incoming value is empty/default,
|
|
461
|
+
// so a re-import cannot silently blank a completed task's summary metadata
|
|
462
|
+
// or refresh its completion timestamp. Off by default: callers that own the
|
|
463
|
+
// execution metadata (gsd_task_complete, planning) keep overwrite semantics.
|
|
464
|
+
preserveCompletionMetadata?: boolean;
|
|
457
465
|
}): void {
|
|
458
466
|
if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
459
467
|
getDbOrNull()!.prepare(
|
|
@@ -473,17 +481,17 @@ export function insertTask(t: {
|
|
|
473
481
|
ON CONFLICT(milestone_id, slice_id, id) DO UPDATE SET
|
|
474
482
|
title = CASE WHEN NULLIF(:title, '') IS NOT NULL THEN :title ELSE tasks.title END,
|
|
475
483
|
status = :status,
|
|
476
|
-
one_liner = :one_liner,
|
|
477
|
-
narrative = :narrative,
|
|
478
|
-
verification_result = :verification_result,
|
|
479
|
-
duration = :duration,
|
|
480
|
-
completed_at = :completed_at,
|
|
481
|
-
blocker_discovered = :blocker_discovered,
|
|
482
|
-
deviations = :deviations,
|
|
483
|
-
known_issues = :known_issues,
|
|
484
|
-
key_files = :key_files,
|
|
485
|
-
key_decisions = :key_decisions,
|
|
486
|
-
full_summary_md = :full_summary_md,
|
|
484
|
+
one_liner = CASE WHEN :preserve_completion = 1 AND NULLIF(:one_liner, '') IS NULL THEN tasks.one_liner ELSE :one_liner END,
|
|
485
|
+
narrative = CASE WHEN :preserve_completion = 1 AND NULLIF(:narrative, '') IS NULL THEN tasks.narrative ELSE :narrative END,
|
|
486
|
+
verification_result = CASE WHEN :preserve_completion = 1 AND NULLIF(:verification_result, '') IS NULL THEN tasks.verification_result ELSE :verification_result END,
|
|
487
|
+
duration = CASE WHEN :preserve_completion = 1 AND NULLIF(:duration, '') IS NULL THEN tasks.duration ELSE :duration END,
|
|
488
|
+
completed_at = CASE WHEN :preserve_completion = 1 AND tasks.completed_at IS NOT NULL THEN tasks.completed_at ELSE :completed_at END,
|
|
489
|
+
blocker_discovered = CASE WHEN :preserve_completion = 1 AND :blocker_discovered = 0 THEN tasks.blocker_discovered ELSE :blocker_discovered END,
|
|
490
|
+
deviations = CASE WHEN :preserve_completion = 1 AND NULLIF(:deviations, '') IS NULL THEN tasks.deviations ELSE :deviations END,
|
|
491
|
+
known_issues = CASE WHEN :preserve_completion = 1 AND NULLIF(:known_issues, '') IS NULL THEN tasks.known_issues ELSE :known_issues END,
|
|
492
|
+
key_files = CASE WHEN :preserve_completion = 1 AND NULLIF(:key_files, '[]') IS NULL THEN tasks.key_files ELSE :key_files END,
|
|
493
|
+
key_decisions = CASE WHEN :preserve_completion = 1 AND NULLIF(:key_decisions, '[]') IS NULL THEN tasks.key_decisions ELSE :key_decisions END,
|
|
494
|
+
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,
|
|
487
495
|
description = CASE WHEN NULLIF(:description, '') IS NOT NULL THEN :description ELSE tasks.description END,
|
|
488
496
|
estimate = CASE WHEN NULLIF(:estimate, '') IS NOT NULL THEN :estimate ELSE tasks.estimate END,
|
|
489
497
|
files = CASE WHEN NULLIF(:files, '[]') IS NOT NULL THEN :files ELSE tasks.files END,
|
|
@@ -523,6 +531,7 @@ export function insertTask(t: {
|
|
|
523
531
|
":observability_impact": t.planning?.observabilityImpact ?? "",
|
|
524
532
|
":full_plan_md": t.planning?.fullPlanMd ?? "",
|
|
525
533
|
":sequence": t.sequence ?? 0,
|
|
534
|
+
":preserve_completion": t.preserveCompletionMetadata && (t.status === "complete" || t.status === "done") ? 1 : 0,
|
|
526
535
|
":target_repositories": JSON.stringify(t.planning?.targetRepositories ?? []),
|
|
527
536
|
":raw_target_repositories":
|
|
528
537
|
t.planning && "targetRepositories" in t.planning
|
|
@@ -535,6 +544,78 @@ export function updateTaskStatus(milestoneId: string, sliceId: string, taskId: s
|
|
|
535
544
|
applyStatusTransition({ entity: "task", milestoneId, sliceId, taskId, status, completedAt });
|
|
536
545
|
}
|
|
537
546
|
|
|
547
|
+
export function repairTaskCompletionFromSummary(t: {
|
|
548
|
+
milestoneId: string;
|
|
549
|
+
sliceId: string;
|
|
550
|
+
taskId: string;
|
|
551
|
+
title?: string;
|
|
552
|
+
oneLiner?: string;
|
|
553
|
+
narrative?: string;
|
|
554
|
+
verificationResult: string;
|
|
555
|
+
duration?: string;
|
|
556
|
+
completedAt: string;
|
|
557
|
+
blockerDiscovered?: boolean;
|
|
558
|
+
deviations?: string;
|
|
559
|
+
knownIssues?: string;
|
|
560
|
+
keyFiles?: string[];
|
|
561
|
+
keyDecisions?: string[];
|
|
562
|
+
fullSummaryMd: string;
|
|
563
|
+
}): void {
|
|
564
|
+
const db = getDbOrNull();
|
|
565
|
+
if (!db) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
566
|
+
transaction(() => {
|
|
567
|
+
const seq = db.prepare(
|
|
568
|
+
`SELECT COALESCE(MAX(sequence), 0) + 1 AS next_sequence
|
|
569
|
+
FROM tasks
|
|
570
|
+
WHERE milestone_id = :mid AND slice_id = :sid`,
|
|
571
|
+
).get({ ":mid": t.milestoneId, ":sid": t.sliceId }) as { next_sequence?: number } | undefined;
|
|
572
|
+
db.prepare(
|
|
573
|
+
`INSERT INTO tasks (
|
|
574
|
+
milestone_id, slice_id, id, title, status, one_liner, narrative,
|
|
575
|
+
verification_result, duration, completed_at, blocker_discovered,
|
|
576
|
+
deviations, known_issues, key_files, key_decisions, full_summary_md,
|
|
577
|
+
sequence
|
|
578
|
+
) VALUES (
|
|
579
|
+
:milestone_id, :slice_id, :id, :title, 'complete', :one_liner, :narrative,
|
|
580
|
+
:verification_result, :duration, :completed_at, :blocker_discovered,
|
|
581
|
+
:deviations, :known_issues, :key_files, :key_decisions, :full_summary_md,
|
|
582
|
+
:sequence
|
|
583
|
+
)
|
|
584
|
+
ON CONFLICT(milestone_id, slice_id, id) DO UPDATE SET
|
|
585
|
+
title = CASE WHEN NULLIF(:title, '') IS NOT NULL THEN :title ELSE tasks.title END,
|
|
586
|
+
status = 'complete',
|
|
587
|
+
one_liner = CASE WHEN NULLIF(:one_liner, '') IS NOT NULL THEN :one_liner ELSE tasks.one_liner END,
|
|
588
|
+
narrative = CASE WHEN NULLIF(:narrative, '') IS NOT NULL THEN :narrative ELSE tasks.narrative END,
|
|
589
|
+
verification_result = :verification_result,
|
|
590
|
+
duration = CASE WHEN NULLIF(:duration, '') IS NOT NULL THEN :duration ELSE tasks.duration END,
|
|
591
|
+
completed_at = :completed_at,
|
|
592
|
+
blocker_discovered = :blocker_discovered,
|
|
593
|
+
deviations = CASE WHEN NULLIF(:deviations, '') IS NOT NULL THEN :deviations ELSE tasks.deviations END,
|
|
594
|
+
known_issues = CASE WHEN NULLIF(:known_issues, '') IS NOT NULL THEN :known_issues ELSE tasks.known_issues END,
|
|
595
|
+
key_files = :key_files,
|
|
596
|
+
key_decisions = :key_decisions,
|
|
597
|
+
full_summary_md = :full_summary_md`,
|
|
598
|
+
).run({
|
|
599
|
+
":milestone_id": t.milestoneId,
|
|
600
|
+
":slice_id": t.sliceId,
|
|
601
|
+
":id": t.taskId,
|
|
602
|
+
":title": t.title ?? "",
|
|
603
|
+
":one_liner": t.oneLiner ?? "",
|
|
604
|
+
":narrative": t.narrative ?? "",
|
|
605
|
+
":verification_result": t.verificationResult,
|
|
606
|
+
":duration": t.duration ?? "",
|
|
607
|
+
":completed_at": t.completedAt,
|
|
608
|
+
":blocker_discovered": t.blockerDiscovered ? 1 : 0,
|
|
609
|
+
":deviations": t.deviations ?? "",
|
|
610
|
+
":known_issues": t.knownIssues ?? "",
|
|
611
|
+
":key_files": JSON.stringify(t.keyFiles ?? []),
|
|
612
|
+
":key_decisions": JSON.stringify(t.keyDecisions ?? []),
|
|
613
|
+
":full_summary_md": t.fullSummaryMd,
|
|
614
|
+
":sequence": seq?.next_sequence ?? 1,
|
|
615
|
+
});
|
|
616
|
+
});
|
|
617
|
+
}
|
|
618
|
+
|
|
538
619
|
export function setTaskBlockerDiscovered(milestoneId: string, sliceId: string, taskId: string, discovered: boolean): void {
|
|
539
620
|
if (!getDbOrNull()!) return;
|
|
540
621
|
getDbOrNull()!.prepare(
|
|
@@ -1325,6 +1406,19 @@ export function deleteArtifactByPath(path: string): void {
|
|
|
1325
1406
|
getDbOrNull()!.prepare("DELETE FROM artifacts WHERE path = :path").run({ ":path": path });
|
|
1326
1407
|
}
|
|
1327
1408
|
|
|
1409
|
+
/** Delete artifact rows whose paths share a DB-relative prefix. */
|
|
1410
|
+
export function deleteArtifactsByPathPrefix(prefix: string): number {
|
|
1411
|
+
if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
1412
|
+
return transaction(() => {
|
|
1413
|
+
const likePrefix = `${prefix}%`;
|
|
1414
|
+
const countRow = getDbOrNull()!.prepare(
|
|
1415
|
+
"SELECT COUNT(*) AS count FROM artifacts WHERE path LIKE :prefix",
|
|
1416
|
+
).get({ ":prefix": likePrefix });
|
|
1417
|
+
getDbOrNull()!.prepare("DELETE FROM artifacts WHERE path LIKE :prefix").run({ ":prefix": likePrefix });
|
|
1418
|
+
return Number(countRow?.["count"] ?? 0);
|
|
1419
|
+
});
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1328
1422
|
/**
|
|
1329
1423
|
* Drop hierarchy rows in dependency order inside a transaction. Used by
|
|
1330
1424
|
* `gsd recover --confirm` to rebuild engine state from markdown.
|
|
@@ -209,6 +209,8 @@ const DOCTOR_FIX_HINTS: Partial<Record<DoctorIssueCode, string>> = {
|
|
|
209
209
|
state_file_stale: "Run `/gsd doctor fix` to rebuild the projection from the database.",
|
|
210
210
|
state_file_missing: "Run `/gsd doctor fix` to rebuild the projection from the database.",
|
|
211
211
|
projection_drift: "Run `/gsd doctor fix` to rebuild markdown projections from the database (DB is the source of truth).",
|
|
212
|
+
artifact_user_content_missing:
|
|
213
|
+
"Doctor cannot recreate user-authored content from the database. Re-run `/gsd discuss` for CONTEXT artifacts or `/gsd auto` for RESEARCH artifacts in that milestone.",
|
|
212
214
|
uat_retry_exhausted: "Review the failing UAT criteria via `/gsd status`, fix the issue, then re-run `/gsd auto`.",
|
|
213
215
|
};
|
|
214
216
|
|
|
@@ -42,7 +42,7 @@ import { gsdHome } from "./gsd-home.js";
|
|
|
42
42
|
import {
|
|
43
43
|
gsdRoot, milestonesDir, legacyMilestonesDir, resolveMilestoneFile,
|
|
44
44
|
resolveSliceFile, resolveSlicePath, resolveGsdRootFile, relGsdRootFile,
|
|
45
|
-
relMilestoneFile, relSliceFile,
|
|
45
|
+
relMilestoneFile, relSliceFile, clearPathCache,
|
|
46
46
|
} from "./paths.js";
|
|
47
47
|
import { join } from "node:path";
|
|
48
48
|
import { readFileSync, existsSync, mkdirSync, readdirSync, rmSync } from "node:fs";
|
|
@@ -50,8 +50,8 @@ import { readSessionLockData, isSessionLockProcessAlive } from "./session-lock.j
|
|
|
50
50
|
import { nativeAddAll, nativeCommit, nativeHasCommittedHead, nativeIsRepo, nativeInit } from "./native-git-bridge.js";
|
|
51
51
|
import { isInheritedRepo } from "./repo-identity.js";
|
|
52
52
|
import { ensureGitignore, ensurePreferences, untrackRuntimeFiles } from "./gitignore.js";
|
|
53
|
-
import { getIsolationMode, loadEffectiveGSDPreferences } from "./preferences.js";
|
|
54
|
-
import { getAutoWorktreePath } from "./auto-worktree.js";
|
|
53
|
+
import { getIsolationMode, loadEffectiveGSDPreferences, renderLanguageDirectiveForPrompt } from "./preferences.js";
|
|
54
|
+
import { getAutoWorktreePath } from "./auto-worktree-path-resolution.js";
|
|
55
55
|
import { resolveUokFlags } from "./uok/flags.js";
|
|
56
56
|
import { ensurePlanV2Graph, isMissingFinalizedContextResult } from "./uok/plan-v2.js";
|
|
57
57
|
import { detectProjectState, hasGsdBootstrapArtifacts } from "./detection.js";
|
|
@@ -94,13 +94,14 @@ import {
|
|
|
94
94
|
import { probeCoversRequiredWorkflowTools } from "./tool-surface-readiness.js";
|
|
95
95
|
import { getRequiredWorkflowToolsForUnit } from "./unit-tool-contracts.js";
|
|
96
96
|
import { isWorkflowToolSurfaceName } from "./workflow-tool-surface.js";
|
|
97
|
-
import {
|
|
97
|
+
import { getUnitWorkflowDispatchReadinessErrorForModel } from "./tool-contract.js";
|
|
98
98
|
import {
|
|
99
99
|
runPreparation,
|
|
100
100
|
formatCodebaseBrief,
|
|
101
101
|
formatPriorContextBrief,
|
|
102
102
|
} from "./preparation.js";
|
|
103
103
|
import { verifyExpectedArtifact } from "./auto-recovery.js";
|
|
104
|
+
import { countPlanMilestoneRoadmapSlices } from "./artifact-verification.js";
|
|
104
105
|
import type { MilestoneScope } from "./workspace.js";
|
|
105
106
|
import { clearPendingGate, extractDepthVerificationMilestoneId, getPendingGate } from "./bootstrap/write-gate.js";
|
|
106
107
|
import {
|
|
@@ -164,7 +165,7 @@ export const _scheduleAutoStartAfterIdleForTest = scheduleAutoStartAfterIdle;
|
|
|
164
165
|
// These thin wrappers accept a MilestoneScope so callers that already hold a
|
|
165
166
|
// pinned scope never have to re-derive (basePath, milestoneId) separately.
|
|
166
167
|
// The underlying implementations in auto-recovery.ts / auto-artifact-paths.ts /
|
|
167
|
-
// state.ts
|
|
168
|
+
// state.ts remain the default for non-scope-specific units.
|
|
168
169
|
|
|
169
170
|
/**
|
|
170
171
|
* Scope-based overload of verifyExpectedArtifact.
|
|
@@ -176,9 +177,47 @@ export function verifyExpectedArtifactForScope(
|
|
|
176
177
|
unitType: string,
|
|
177
178
|
unitId: string,
|
|
178
179
|
): boolean {
|
|
180
|
+
if (
|
|
181
|
+
unitId === scope.milestoneId &&
|
|
182
|
+
(unitType === "discuss-milestone" || unitType === "plan-milestone")
|
|
183
|
+
) {
|
|
184
|
+
// Layout-aware scope paths use resolveMilestoneFile; clear stale dir listings
|
|
185
|
+
// primed before discuss/plan wrote CONTEXT.md or ROADMAP.md (see checkAutoStartAfterDiscuss).
|
|
186
|
+
clearPathCache();
|
|
187
|
+
}
|
|
188
|
+
if (
|
|
189
|
+
unitId === scope.milestoneId &&
|
|
190
|
+
unitType === "discuss-milestone"
|
|
191
|
+
) {
|
|
192
|
+
const path = resolveExpectedArtifactPathForScope(scope, unitType, unitId);
|
|
193
|
+
return path ? existsSync(path) : false;
|
|
194
|
+
}
|
|
195
|
+
if (unitId === scope.milestoneId && unitType === "plan-milestone") {
|
|
196
|
+
const path = resolveExpectedArtifactPathForScope(scope, unitType, unitId);
|
|
197
|
+
return verifyScopedPlanMilestoneArtifact(path, unitType, unitId);
|
|
198
|
+
}
|
|
179
199
|
return verifyExpectedArtifact(unitType, unitId, scope.workspace.projectRoot);
|
|
180
200
|
}
|
|
181
201
|
|
|
202
|
+
function verifyScopedPlanMilestoneArtifact(
|
|
203
|
+
path: string | null,
|
|
204
|
+
unitType: string,
|
|
205
|
+
unitId: string,
|
|
206
|
+
): boolean {
|
|
207
|
+
if (!path || !existsSync(path)) return false;
|
|
208
|
+
try {
|
|
209
|
+
const roadmapContent = readFileSync(path, "utf-8");
|
|
210
|
+
if (countPlanMilestoneRoadmapSlices(roadmapContent) === 0) {
|
|
211
|
+
logWarning("recovery", `verify-fail ${unitType} ${unitId}: roadmap has zero slices at ${path}`);
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
214
|
+
return true;
|
|
215
|
+
} catch (err) {
|
|
216
|
+
logWarning("recovery", `plan-milestone roadmap verification failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
182
221
|
/**
|
|
183
222
|
* Scope-based overload of resolveExpectedArtifactPath.
|
|
184
223
|
* Returns the canonical absolute path (or null) using the scope's projectRoot.
|
|
@@ -188,6 +227,10 @@ export function resolveExpectedArtifactPathForScope(
|
|
|
188
227
|
unitType: string,
|
|
189
228
|
unitId: string,
|
|
190
229
|
): string | null {
|
|
230
|
+
if (unitId === scope.milestoneId) {
|
|
231
|
+
if (unitType === "discuss-milestone") return scope.contextFile();
|
|
232
|
+
if (unitType === "plan-milestone") return scope.roadmapFile();
|
|
233
|
+
}
|
|
191
234
|
return resolveExpectedArtifactPath(unitType, unitId, scope.workspace.projectRoot);
|
|
192
235
|
}
|
|
193
236
|
|
|
@@ -570,7 +613,7 @@ interface DispatchWorkflowOptions {
|
|
|
570
613
|
deps?: {
|
|
571
614
|
loadPreferences?: typeof loadEffectiveGSDPreferences;
|
|
572
615
|
selectModel?: typeof selectAndApplyModel;
|
|
573
|
-
getDispatchReadinessError?: typeof
|
|
616
|
+
getDispatchReadinessError?: typeof getUnitWorkflowDispatchReadinessErrorForModel;
|
|
574
617
|
};
|
|
575
618
|
}
|
|
576
619
|
|
|
@@ -687,7 +730,7 @@ async function dispatchWorkflow(
|
|
|
687
730
|
const loadPreferences = resolvedOptions.deps?.loadPreferences ?? loadEffectiveGSDPreferences;
|
|
688
731
|
const selectModel = resolvedOptions.deps?.selectModel ?? selectAndApplyModel;
|
|
689
732
|
const getDispatchReadinessError = resolvedOptions.deps?.getDispatchReadinessError
|
|
690
|
-
??
|
|
733
|
+
?? getUnitWorkflowDispatchReadinessErrorForModel;
|
|
691
734
|
|
|
692
735
|
// Route through the dynamic routing pipeline (complexity classification,
|
|
693
736
|
// tier downgrade, fallback chains) — same path as auto-mode dispatches (#2958).
|
|
@@ -707,16 +750,12 @@ async function dispatchWorkflow(
|
|
|
707
750
|
}
|
|
708
751
|
|
|
709
752
|
const compatibilityError = getDispatchReadinessError({
|
|
710
|
-
|
|
753
|
+
model: result.appliedModel,
|
|
754
|
+
fallbackModel: ctx.model,
|
|
755
|
+
getProviderAuthMode: (provider) => ctx.modelRegistry.getProviderAuthMode(provider),
|
|
711
756
|
projectRoot,
|
|
712
757
|
surface: "guided flow",
|
|
713
758
|
unitType,
|
|
714
|
-
authMode: result.appliedModel?.provider
|
|
715
|
-
? ctx.modelRegistry.getProviderAuthMode(result.appliedModel.provider)
|
|
716
|
-
: ctx.model?.provider
|
|
717
|
-
? ctx.modelRegistry.getProviderAuthMode(ctx.model.provider)
|
|
718
|
-
: undefined,
|
|
719
|
-
baseUrl: result.appliedModel?.baseUrl ?? ctx.model?.baseUrl,
|
|
720
759
|
// Guided flow starts the MCP workflow server as part of dispatch, so the
|
|
721
760
|
// parent session's activeTools doesn't include MCP tools yet. The MCP
|
|
722
761
|
// launch config check (detectWorkflowMcpLaunchConfig) is the right gate
|
|
@@ -882,7 +921,7 @@ function resolveAvailableModel<T extends { id: string; provider: string }>(
|
|
|
882
921
|
* Build the discuss-and-plan prompt for a new milestone.
|
|
883
922
|
* Used by all three "new milestone" paths (first ever, no active, all complete).
|
|
884
923
|
*/
|
|
885
|
-
function buildDiscussPrompt(nextId: string, preamble: string,
|
|
924
|
+
function buildDiscussPrompt(nextId: string, preamble: string, basePath: string, pi: ExtensionAPI, ctx: ExtensionCommandContext, preparationContext?: string): string {
|
|
886
925
|
const milestoneRel = `.gsd/milestones/${nextId}`;
|
|
887
926
|
const structuredQuestionsAvailable = getStructuredQuestionsAvailability(pi, ctx);
|
|
888
927
|
const inlinedTemplates = [
|
|
@@ -892,7 +931,7 @@ function buildDiscussPrompt(nextId: string, preamble: string, _basePath: string,
|
|
|
892
931
|
inlineTemplate("roadmap", "Roadmap"),
|
|
893
932
|
inlineTemplate("decisions", "Decisions"),
|
|
894
933
|
].join("\n\n---\n\n");
|
|
895
|
-
return loadPrompt("discuss", {
|
|
934
|
+
return prependLanguageDirective(basePath, loadPrompt("discuss", {
|
|
896
935
|
milestoneId: nextId,
|
|
897
936
|
preamble,
|
|
898
937
|
preparationContext: preparationContext ?? "",
|
|
@@ -902,14 +941,26 @@ function buildDiscussPrompt(nextId: string, preamble: string, _basePath: string,
|
|
|
902
941
|
inlinedTemplates,
|
|
903
942
|
commitInstruction: buildDocsCommitInstruction(`docs(${nextId}): context, requirements, and roadmap`),
|
|
904
943
|
multiMilestoneCommitInstruction: buildDocsCommitInstruction("docs: project plan — N milestones"),
|
|
905
|
-
});
|
|
944
|
+
}));
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
/**
|
|
948
|
+
* Prepend the configured response-language directive to a dispatched discuss
|
|
949
|
+
* prompt so the discuss/QA conversation is held in the language set in
|
|
950
|
+
* PREFERENCES.md (#1210). No-op when no language is configured.
|
|
951
|
+
*/
|
|
952
|
+
function prependLanguageDirective(basePath: string, prompt: string): string {
|
|
953
|
+
const directive = renderLanguageDirectiveForPrompt(
|
|
954
|
+
loadEffectiveGSDPreferences(basePath)?.preferences,
|
|
955
|
+
);
|
|
956
|
+
return directive ? `${directive}\n\n${prompt}` : prompt;
|
|
906
957
|
}
|
|
907
958
|
|
|
908
959
|
/**
|
|
909
960
|
* Build the discuss prompt for headless milestone creation.
|
|
910
961
|
* Uses the discuss-headless prompt template with seed context injected.
|
|
911
962
|
*/
|
|
912
|
-
function buildHeadlessDiscussPrompt(nextId: string, seedContext: string,
|
|
963
|
+
function buildHeadlessDiscussPrompt(nextId: string, seedContext: string, basePath: string): string {
|
|
913
964
|
const milestoneRel = `.gsd/milestones/${nextId}`;
|
|
914
965
|
const inlinedTemplates = [
|
|
915
966
|
inlineTemplate("project", "Project"),
|
|
@@ -918,7 +969,7 @@ function buildHeadlessDiscussPrompt(nextId: string, seedContext: string, _basePa
|
|
|
918
969
|
inlineTemplate("roadmap", "Roadmap"),
|
|
919
970
|
inlineTemplate("decisions", "Decisions"),
|
|
920
971
|
].join("\n\n---\n\n");
|
|
921
|
-
return loadPrompt("discuss-headless", {
|
|
972
|
+
return prependLanguageDirective(basePath, loadPrompt("discuss-headless", {
|
|
922
973
|
milestoneId: nextId,
|
|
923
974
|
seedContext,
|
|
924
975
|
contextPath: `${milestoneRel}/${nextId}-CONTEXT.md`,
|
|
@@ -926,7 +977,7 @@ function buildHeadlessDiscussPrompt(nextId: string, seedContext: string, _basePa
|
|
|
926
977
|
inlinedTemplates,
|
|
927
978
|
commitInstruction: buildDocsCommitInstruction(`docs(${nextId}): context, requirements, and roadmap`),
|
|
928
979
|
multiMilestoneCommitInstruction: buildDocsCommitInstruction("docs: project plan — N milestones"),
|
|
929
|
-
});
|
|
980
|
+
}));
|
|
930
981
|
}
|
|
931
982
|
|
|
932
983
|
/**
|
|
@@ -43,6 +43,7 @@ export const PROVIDER_REGISTRY: ProviderInfo[] = [
|
|
|
43
43
|
// must be in the canonical registry so all consumers see the same catalog.
|
|
44
44
|
// See: https://github.com/open-gsd/gsd-pi/issues/4541
|
|
45
45
|
{ id: "claude-code", label: "Claude Code CLI", category: "llm", authMode: "externalCli" },
|
|
46
|
+
{ id: "cursor-agent", label: "Cursor Agent", category: "llm", envVar: "CURSOR_API_KEY", authMode: "externalCli" },
|
|
46
47
|
{ id: "openai", label: "OpenAI", category: "llm", envVar: "OPENAI_API_KEY", prefixes: ["sk-"], dashboardUrl: "platform.openai.com/api-keys" },
|
|
47
48
|
{ id: "github-copilot", label: "GitHub Copilot", category: "llm", envVar: "GITHUB_TOKEN", authMode: "browserOAuth" },
|
|
48
49
|
{ id: "openai-codex", label: "ChatGPT Plus/Pro (Codex)",category: "llm", authMode: "browserOAuth" },
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
getSliceScopedArtifacts,
|
|
21
21
|
getMilestoneSlices,
|
|
22
22
|
getSliceTasks,
|
|
23
|
+
getTasksBySliceIds,
|
|
23
24
|
getTask,
|
|
24
25
|
getSlice,
|
|
25
26
|
insertArtifact,
|
|
@@ -136,6 +137,12 @@ function meaningfulSection(value: string | null | undefined): string {
|
|
|
136
137
|
return trimmed;
|
|
137
138
|
}
|
|
138
139
|
|
|
140
|
+
function renderGateFindings(gate: GateRow): string {
|
|
141
|
+
const findings = gate.findings.trim() || `- **Verdict:** ${gate.verdict}\n- **Rationale:** ${gate.rationale}`;
|
|
142
|
+
if (gate.verdict !== "flag") return findings;
|
|
143
|
+
return `> **Warning:** Verdict: flag - concerns recorded below\n\n${findings}`;
|
|
144
|
+
}
|
|
145
|
+
|
|
139
146
|
function pushIndented(lines: string[], value: string, indent = " "): void {
|
|
140
147
|
for (const line of value.split("\n")) {
|
|
141
148
|
lines.push(`${indent}${line}`);
|
|
@@ -356,7 +363,7 @@ function renderTaskPlanMarkdown(task: TaskRow, taskGates: GateRow[] = []): strin
|
|
|
356
363
|
if (gate && gate.verdict !== "omitted") {
|
|
357
364
|
lines.push(`## ${label}`);
|
|
358
365
|
lines.push("");
|
|
359
|
-
lines.push(
|
|
366
|
+
lines.push(renderGateFindings(gate));
|
|
360
367
|
lines.push("");
|
|
361
368
|
}
|
|
362
369
|
}
|
|
@@ -390,7 +397,7 @@ function renderSlicePlanMarkdown(slice: SliceRow, tasks: TaskRow[], gates: GateR
|
|
|
390
397
|
if (q3 && q3.verdict !== "omitted") {
|
|
391
398
|
lines.push("## Threat Surface");
|
|
392
399
|
lines.push("");
|
|
393
|
-
lines.push(
|
|
400
|
+
lines.push(renderGateFindings(q3));
|
|
394
401
|
lines.push("");
|
|
395
402
|
}
|
|
396
403
|
|
|
@@ -398,7 +405,7 @@ function renderSlicePlanMarkdown(slice: SliceRow, tasks: TaskRow[], gates: GateR
|
|
|
398
405
|
if (q4 && q4.verdict !== "omitted") {
|
|
399
406
|
lines.push("## Requirement Impact");
|
|
400
407
|
lines.push("");
|
|
401
|
-
lines.push(
|
|
408
|
+
lines.push(renderGateFindings(q4));
|
|
402
409
|
lines.push("");
|
|
403
410
|
}
|
|
404
411
|
|
|
@@ -876,6 +883,17 @@ export async function renderAllFromDb(basePath: string): Promise<RenderAllResult
|
|
|
876
883
|
const result: RenderAllResult = { rendered: 0, skipped: 0, errors: [] };
|
|
877
884
|
const milestones = getAllMilestones();
|
|
878
885
|
|
|
886
|
+
// Pre-fetch slices once per milestone and batch-load all tasks in one query
|
|
887
|
+
// family, avoiding an N+1 (previously one task query per slice).
|
|
888
|
+
const slicesByMilestone = new Map<string, SliceRow[]>();
|
|
889
|
+
const slicePairs: Array<{ milestoneId: string; sliceId: string }> = [];
|
|
890
|
+
for (const milestone of milestones) {
|
|
891
|
+
const slices = getMilestoneSlices(milestone.id);
|
|
892
|
+
slicesByMilestone.set(milestone.id, slices);
|
|
893
|
+
for (const slice of slices) slicePairs.push({ milestoneId: milestone.id, sliceId: slice.id });
|
|
894
|
+
}
|
|
895
|
+
const tasksBySlice = getTasksBySliceIds(slicePairs);
|
|
896
|
+
|
|
879
897
|
for (const milestone of milestones) {
|
|
880
898
|
// Render roadmap checkboxes
|
|
881
899
|
try {
|
|
@@ -894,8 +912,8 @@ export async function renderAllFromDb(basePath: string): Promise<RenderAllResult
|
|
|
894
912
|
result.errors.push(`milestone artifacts ${milestone.id}: ${(err as Error).message}`);
|
|
895
913
|
}
|
|
896
914
|
|
|
897
|
-
// Iterate slices
|
|
898
|
-
const slices =
|
|
915
|
+
// Iterate slices (pre-fetched above)
|
|
916
|
+
const slices = slicesByMilestone.get(milestone.id) ?? [];
|
|
899
917
|
for (const slice of slices) {
|
|
900
918
|
// Preserve slice-scoped artifacts imported from disk, including real PLAN
|
|
901
919
|
// fallback content when task rows cannot regenerate it.
|
|
@@ -931,8 +949,8 @@ export async function renderAllFromDb(basePath: string): Promise<RenderAllResult
|
|
|
931
949
|
);
|
|
932
950
|
}
|
|
933
951
|
|
|
934
|
-
// Iterate tasks
|
|
935
|
-
const tasks =
|
|
952
|
+
// Iterate tasks (batched above)
|
|
953
|
+
const tasks = tasksBySlice.get(`${milestone.id}\0${slice.id}`) ?? [];
|
|
936
954
|
for (const task of tasks) {
|
|
937
955
|
try {
|
|
938
956
|
const ok = await renderTaskSummary(
|
|
@@ -1281,9 +1299,21 @@ export async function renderAssessmentFromDb(
|
|
|
1281
1299
|
sliceId: string,
|
|
1282
1300
|
assessmentData: AssessmentData,
|
|
1283
1301
|
): Promise<{ assessmentPath: string; content: string }> {
|
|
1284
|
-
// Flat-phase: assessment file lives in the phase dir
|
|
1285
|
-
|
|
1286
|
-
|
|
1302
|
+
// Flat-phase: the assessment file lives in the phase dir, NOT in a slices/SID/
|
|
1303
|
+
// subdir. resolveSlicePath() detects a slices/SID/ dir unconditionally, so a
|
|
1304
|
+
// stray slices/SID/ created by an earlier planning step would send this write
|
|
1305
|
+
// to a hybrid path (wrong dir, flat filename) that verification cannot find.
|
|
1306
|
+
// Guard with the same legacy-base check relSlicePath() uses so flat-phase
|
|
1307
|
+
// milestones always target the phase dir.
|
|
1308
|
+
const mDir = resolveMilestonePath(basePath, milestoneId);
|
|
1309
|
+
const legacyBase = legacyMilestonesDir(basePath);
|
|
1310
|
+
const isLegacyLayout = mDir
|
|
1311
|
+
? mDir.startsWith(legacyBase + "/") || mDir.startsWith(legacyBase + "\\")
|
|
1312
|
+
: false;
|
|
1313
|
+
const fallbackDir = join(milestonesDir(basePath), canonicalPhaseDirName(milestoneId, getMilestone(milestoneId)?.title));
|
|
1314
|
+
const slicePath = isLegacyLayout
|
|
1315
|
+
? (resolveSlicePath(basePath, milestoneId, sliceId) ?? fallbackDir)
|
|
1316
|
+
: (mDir ?? fallbackDir);
|
|
1287
1317
|
const phaseNum = milestoneIdToPhaseNum(milestoneId);
|
|
1288
1318
|
const planNum = sliceIdToPlanNum(sliceId);
|
|
1289
1319
|
const absPath = join(slicePath, planFileName(phaseNum, planNum, "ASSESSMENT"));
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// Exports: parseDecisionsTable, parseRequirementsSections, migrateFromMarkdown
|
|
6
6
|
|
|
7
7
|
import { readFileSync, readdirSync, existsSync, statSync } from 'node:fs';
|
|
8
|
-
import { join, relative, basename } from 'node:path';
|
|
8
|
+
import { join, relative, basename, dirname } from 'node:path';
|
|
9
9
|
import type { Decision, Requirement } from './types.js';
|
|
10
10
|
import {
|
|
11
11
|
upsertDecision,
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
resolveGsdRootFile,
|
|
25
25
|
resolveMilestoneFile,
|
|
26
26
|
resolveSliceFile,
|
|
27
|
+
resolveSlicePath,
|
|
27
28
|
resolveTasksDir,
|
|
28
29
|
legacyMilestonesDir,
|
|
29
30
|
gsdRoot,
|
|
@@ -33,7 +34,7 @@ import {
|
|
|
33
34
|
import { findMilestoneIds } from './guided-flow.js';
|
|
34
35
|
import { milestoneIdToPhaseNum } from './layout-policy.js';
|
|
35
36
|
import { parseRoadmap, parsePlan } from './parsers-legacy.js';
|
|
36
|
-
import { parseContextDependsOn } from './files.js';
|
|
37
|
+
import { parseContextDependsOn, parseSummary } from './files.js';
|
|
37
38
|
import { logWarning } from './workflow-logger.js';
|
|
38
39
|
|
|
39
40
|
// ─── DECISIONS.md Parser ───────────────────────────────────────────────────
|
|
@@ -816,23 +817,68 @@ export function migrateHierarchyToDb(basePath: string): {
|
|
|
816
817
|
// Per K002: use 'complete' not 'done'
|
|
817
818
|
let taskStatus: string = taskEntry.done ? 'complete' : 'pending';
|
|
818
819
|
|
|
819
|
-
//
|
|
820
|
-
//
|
|
821
|
-
//
|
|
822
|
-
//
|
|
823
|
-
//
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
820
|
+
// Resolve the per-task SUMMARY.md. Legacy layout keeps summaries under
|
|
821
|
+
// a tasks/ subdir; flat-phase writes TID-SUMMARY.md directly in the
|
|
822
|
+
// phase dir (execute-task's gsd_task_complete writes it there). A tasks/
|
|
823
|
+
// subdir may still exist in flat-phase for auxiliary artifacts — its
|
|
824
|
+
// mere existence must NOT redirect summary resolution into tasks/ (#1208).
|
|
825
|
+
const slicePath = resolveSlicePath(basePath, milestoneId, sliceEntry.id);
|
|
826
|
+
let taskSummaryFile: string | null = null;
|
|
827
|
+
let isLegacySlice = false;
|
|
828
|
+
// Legacy layout keeps per-task summaries under a tasks/ subdir. Its
|
|
829
|
+
// presence — not merely "is this a legacy slice" — is what makes a
|
|
830
|
+
// missing summary a downgrade signal. resolveTasksDir returns null when
|
|
831
|
+
// no such dir exists, so a legacy slice whose checkbox is the only
|
|
832
|
+
// completion signal (no tasks/ dir at all) is left complete on import.
|
|
833
|
+
let legacyTasksDir: string | null = null;
|
|
834
|
+
if (slicePath) {
|
|
835
|
+
isLegacySlice = basename(dirname(slicePath)) === 'slices';
|
|
836
|
+
legacyTasksDir = isLegacySlice
|
|
837
|
+
? resolveTasksDir(basePath, milestoneId, sliceEntry.id)
|
|
838
|
+
: null;
|
|
839
|
+
const summaryDir = legacyTasksDir ?? slicePath;
|
|
840
|
+
taskSummaryFile = join(summaryDir, `${taskEntry.id}-SUMMARY.md`);
|
|
841
|
+
}
|
|
842
|
+
const hasTaskSummary = taskSummaryFile !== null && existsSync(taskSummaryFile);
|
|
843
|
+
|
|
844
|
+
// Pre-migration consistency (legacy tasks/ layout only): if a task is
|
|
845
|
+
// marked done but its tasks/ dir has no per-task SUMMARY.md, import it
|
|
846
|
+
// as pending so it gets re-executed rather than silently entering the DB
|
|
847
|
+
// as complete. A legacy slice with no tasks/ dir (checkbox-only
|
|
848
|
+
// completion) and flat-phase layout are both left as-is here.
|
|
849
|
+
if (taskStatus === 'complete' && legacyTasksDir !== null && !hasTaskSummary) {
|
|
850
|
+
taskStatus = 'pending';
|
|
851
|
+
process.stderr.write(
|
|
852
|
+
`gsd-migrate: ${milestoneId}/${sliceEntry.id}/${taskEntry.id} marked done but missing summary — importing as pending\n`,
|
|
853
|
+
);
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
// Lost-update guard (#1222): a per-task SUMMARY.md is the durable
|
|
857
|
+
// completion attestation written by gsd_task_complete. When the plan
|
|
858
|
+
// checkbox is stale-unchecked but the SUMMARY exists on disk, a
|
|
859
|
+
// re-import must NOT downgrade the completed task back to pending — that
|
|
860
|
+
// silent revert is the lost-update that hard-stopped auto-mode after the
|
|
861
|
+
// first execute-task. The surviving SUMMARY wins over a stale checkbox.
|
|
862
|
+
// reopen-task removes the SUMMARY, so this never re-completes an
|
|
863
|
+
// intentionally reopened task.
|
|
864
|
+
// Flat-phase summaries are phase-scoped (T01-SUMMARY.md); when a milestone
|
|
865
|
+
// has multiple slices, require the summary parent frontmatter to match so
|
|
866
|
+
// one slice's completion does not attest a sibling's same-named task.
|
|
867
|
+
let summaryAttestsCompletion = hasTaskSummary;
|
|
868
|
+
if (summaryAttestsCompletion && !isLegacySlice && roadmap.slices.length > 1 && taskSummaryFile) {
|
|
869
|
+
try {
|
|
870
|
+
const summaryContent = readFileSync(taskSummaryFile, 'utf-8');
|
|
871
|
+
summaryAttestsCompletion = parseSummary(summaryContent).frontmatter.parent === sliceEntry.id;
|
|
872
|
+
} catch {
|
|
873
|
+
summaryAttestsCompletion = false;
|
|
834
874
|
}
|
|
835
875
|
}
|
|
876
|
+
if (taskStatus === 'pending' && summaryAttestsCompletion) {
|
|
877
|
+
taskStatus = 'complete';
|
|
878
|
+
process.stderr.write(
|
|
879
|
+
`gsd-migrate: ${milestoneId}/${sliceEntry.id}/${taskEntry.id} unchecked in plan but SUMMARY.md present — importing as complete (#1222)\n`,
|
|
880
|
+
);
|
|
881
|
+
}
|
|
836
882
|
|
|
837
883
|
insertTask({
|
|
838
884
|
id: taskEntry.id,
|
|
@@ -844,6 +890,12 @@ export function migrateHierarchyToDb(basePath: string): {
|
|
|
844
890
|
files: taskEntry.files ?? [],
|
|
845
891
|
verify: taskEntry.verify ?? '',
|
|
846
892
|
},
|
|
893
|
+
// #1222 (metadata half): re-import derives status from the plan/summary
|
|
894
|
+
// but has none of the execution prose gsd_task_complete wrote to the DB.
|
|
895
|
+
// Preserve the existing row's execution columns and completed_at so a
|
|
896
|
+
// re-import cannot blank a completed task's summary metadata or refresh
|
|
897
|
+
// its completion timestamp — the DB row is strictly richer than the plan.
|
|
898
|
+
preserveCompletionMetadata: true,
|
|
847
899
|
});
|
|
848
900
|
counts.tasks++;
|
|
849
901
|
}
|
|
@@ -857,12 +909,31 @@ export function migrateHierarchyToDb(basePath: string): {
|
|
|
857
909
|
if (!sliceEntry.done) {
|
|
858
910
|
const sliceSummaryPath = resolveSliceFile(basePath, milestoneId, sliceEntry.id, 'SUMMARY');
|
|
859
911
|
const hasSliceSummary = sliceSummaryPath !== null && existsSync(sliceSummaryPath);
|
|
912
|
+
const slicePathForTasks = resolveSlicePath(basePath, milestoneId, sliceEntry.id);
|
|
913
|
+
const isLegacySliceLayout = slicePathForTasks !== null
|
|
914
|
+
&& basename(dirname(slicePathForTasks)) === 'slices';
|
|
915
|
+
const taskSummaryDir = slicePathForTasks
|
|
916
|
+
? (isLegacySliceLayout
|
|
917
|
+
? (resolveTasksDir(basePath, milestoneId, sliceEntry.id) ?? slicePathForTasks)
|
|
918
|
+
: slicePathForTasks)
|
|
919
|
+
: null;
|
|
860
920
|
const allTasksDone = plan.tasks.length > 0 && plan.tasks.every(t => {
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
921
|
+
const taskSummaryFile = taskSummaryDir !== null
|
|
922
|
+
? join(taskSummaryDir, `${t.id}-SUMMARY.md`)
|
|
923
|
+
: null;
|
|
924
|
+
const hasTaskSummary = taskSummaryFile !== null && existsSync(taskSummaryFile);
|
|
925
|
+
let summaryAttestsCompletion = hasTaskSummary;
|
|
926
|
+
if (summaryAttestsCompletion && !isLegacySliceLayout && roadmap.slices.length > 1 && taskSummaryFile) {
|
|
927
|
+
try {
|
|
928
|
+
const summaryContent = readFileSync(taskSummaryFile, 'utf-8');
|
|
929
|
+
summaryAttestsCompletion = parseSummary(summaryContent).frontmatter.parent === sliceEntry.id;
|
|
930
|
+
} catch {
|
|
931
|
+
summaryAttestsCompletion = false;
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
// Match per-task import rules above: SUMMARY attestation wins over a stale
|
|
935
|
+
// checkbox (#1222); flat-phase checkboxes are authoritative without summary.
|
|
936
|
+
return summaryAttestsCompletion || (t.done && !isLegacySliceLayout);
|
|
866
937
|
});
|
|
867
938
|
if (allTasksDone && hasSliceSummary) {
|
|
868
939
|
if (_getAdapter()) {
|