gsd-pi 2.29.0-dev.953d788 → 2.29.0-dev.f08b4fe
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 +24 -17
- package/dist/extension-registry.d.ts +63 -0
- package/dist/extension-registry.js +166 -0
- package/dist/headless.js +4 -0
- package/dist/loader.js +10 -1
- package/dist/resource-loader.js +11 -1
- package/dist/resources/extensions/async-jobs/extension-manifest.json +13 -0
- package/dist/resources/extensions/bg-shell/extension-manifest.json +14 -0
- package/dist/resources/extensions/bg-shell/process-manager.ts +13 -0
- package/dist/resources/extensions/browser-tools/extension-manifest.json +37 -0
- package/dist/resources/extensions/context7/extension-manifest.json +12 -0
- package/dist/resources/extensions/google-search/extension-manifest.json +12 -0
- package/dist/resources/extensions/gsd/auto-dashboard.ts +217 -65
- package/dist/resources/extensions/gsd/auto-dispatch.ts +32 -3
- package/dist/resources/extensions/gsd/auto-post-unit.ts +45 -13
- package/dist/resources/extensions/gsd/auto-prompts.ts +40 -17
- package/dist/resources/extensions/gsd/auto-recovery.ts +18 -23
- package/dist/resources/extensions/gsd/auto-start.ts +18 -32
- package/dist/resources/extensions/gsd/auto-worktree.ts +21 -182
- package/dist/resources/extensions/gsd/auto.ts +2 -24
- package/dist/resources/extensions/gsd/captures.ts +4 -10
- package/dist/resources/extensions/gsd/commands-extensions.ts +328 -0
- package/dist/resources/extensions/gsd/commands-handlers.ts +22 -2
- package/dist/resources/extensions/gsd/commands-logs.ts +13 -14
- package/dist/resources/extensions/gsd/commands-prefs-wizard.ts +44 -14
- package/dist/resources/extensions/gsd/commands-workflow-templates.ts +544 -0
- package/dist/resources/extensions/gsd/commands.ts +108 -24
- package/dist/resources/extensions/gsd/dashboard-overlay.ts +2 -1
- package/dist/resources/extensions/gsd/detection.ts +2 -1
- package/dist/resources/extensions/gsd/doctor-checks.ts +49 -1
- package/dist/resources/extensions/gsd/doctor-types.ts +3 -1
- package/dist/resources/extensions/gsd/extension-manifest.json +18 -0
- package/dist/resources/extensions/gsd/forensics.ts +2 -2
- package/dist/resources/extensions/gsd/git-service.ts +3 -2
- package/dist/resources/extensions/gsd/gitignore.ts +9 -63
- package/dist/resources/extensions/gsd/gsd-db.ts +1 -165
- package/dist/resources/extensions/gsd/guided-flow.ts +8 -5
- package/dist/resources/extensions/gsd/index.ts +3 -3
- package/dist/resources/extensions/gsd/json-persistence.ts +16 -1
- package/dist/resources/extensions/gsd/md-importer.ts +3 -2
- package/dist/resources/extensions/gsd/mechanical-completion.ts +430 -0
- package/dist/resources/extensions/gsd/migrate/command.ts +3 -2
- package/dist/resources/extensions/gsd/migrate/writer.ts +2 -1
- package/dist/resources/extensions/gsd/migrate-external.ts +123 -0
- package/dist/resources/extensions/gsd/paths.ts +24 -2
- package/dist/resources/extensions/gsd/post-unit-hooks.ts +6 -5
- package/dist/resources/extensions/gsd/preferences-models.ts +7 -1
- package/dist/resources/extensions/gsd/preferences-validation.ts +2 -1
- package/dist/resources/extensions/gsd/preferences.ts +10 -5
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +4 -2
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +26 -2
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +15 -1
- package/dist/resources/extensions/gsd/prompts/workflow-start.md +28 -0
- package/dist/resources/extensions/gsd/queue-order.ts +10 -11
- package/dist/resources/extensions/gsd/repo-identity.ts +148 -0
- package/dist/resources/extensions/gsd/resource-version.ts +99 -0
- package/dist/resources/extensions/gsd/session-forensics.ts +4 -3
- package/dist/resources/extensions/gsd/session-status-io.ts +23 -41
- package/dist/resources/extensions/gsd/tests/activity-log.test.ts +2 -2
- package/dist/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +1 -1
- package/dist/resources/extensions/gsd/tests/auto-recovery.test.ts +3 -3
- package/dist/resources/extensions/gsd/tests/auto-skip-loop.test.ts +1 -1
- package/dist/resources/extensions/gsd/tests/auto-worktree.test.ts +0 -58
- package/dist/resources/extensions/gsd/tests/doctor-runtime.test.ts +3 -4
- package/dist/resources/extensions/gsd/tests/extension-selector-separator.test.ts +60 -38
- package/dist/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +5 -18
- package/dist/resources/extensions/gsd/tests/git-service.test.ts +10 -37
- package/dist/resources/extensions/gsd/tests/knowledge.test.ts +4 -4
- package/dist/resources/extensions/gsd/tests/mechanical-completion.test.ts +356 -0
- package/dist/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +1 -1
- package/dist/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +1 -0
- package/dist/resources/extensions/gsd/tests/token-profile.test.ts +14 -16
- package/dist/resources/extensions/gsd/tests/workflow-templates.test.ts +173 -0
- package/dist/resources/extensions/gsd/triage-resolution.ts +2 -1
- package/dist/resources/extensions/gsd/types.ts +2 -0
- package/dist/resources/extensions/gsd/workflow-templates/bugfix.md +87 -0
- package/dist/resources/extensions/gsd/workflow-templates/dep-upgrade.md +74 -0
- package/dist/resources/extensions/gsd/workflow-templates/full-project.md +41 -0
- package/dist/resources/extensions/gsd/workflow-templates/hotfix.md +45 -0
- package/dist/resources/extensions/gsd/workflow-templates/refactor.md +83 -0
- package/dist/resources/extensions/gsd/workflow-templates/registry.json +85 -0
- package/dist/resources/extensions/gsd/workflow-templates/security-audit.md +73 -0
- package/dist/resources/extensions/gsd/workflow-templates/small-feature.md +81 -0
- package/dist/resources/extensions/gsd/workflow-templates/spike.md +69 -0
- package/dist/resources/extensions/gsd/workflow-templates.ts +241 -0
- package/dist/resources/extensions/gsd/worktree-command.ts +1 -11
- package/dist/resources/extensions/gsd/worktree-manager.ts +3 -2
- package/dist/resources/extensions/gsd/worktree.ts +42 -5
- package/dist/resources/extensions/mac-tools/extension-manifest.json +16 -0
- package/dist/resources/extensions/mcp-client/index.ts +459 -0
- package/dist/resources/extensions/mcporter/extension-manifest.json +12 -0
- package/dist/resources/extensions/remote-questions/discord-adapter.ts +8 -19
- package/dist/resources/extensions/remote-questions/extension-manifest.json +11 -0
- package/dist/resources/extensions/remote-questions/http-client.ts +76 -0
- package/dist/resources/extensions/remote-questions/slack-adapter.ts +11 -17
- package/dist/resources/extensions/remote-questions/telegram-adapter.ts +8 -19
- package/dist/resources/extensions/search-the-web/extension-manifest.json +13 -0
- package/dist/resources/extensions/slash-commands/extension-manifest.json +11 -0
- package/dist/resources/extensions/subagent/extension-manifest.json +13 -0
- package/dist/resources/extensions/ttsr/extension-manifest.json +11 -0
- package/dist/resources/extensions/universal-config/extension-manifest.json +13 -0
- package/dist/resources/extensions/voice/extension-manifest.json +12 -0
- package/dist/resources/skills/create-gsd-extension/SKILL.md +87 -0
- package/dist/resources/skills/create-gsd-extension/references/compaction-session-control.md +77 -0
- package/dist/resources/skills/create-gsd-extension/references/custom-commands.md +139 -0
- package/dist/resources/skills/create-gsd-extension/references/custom-rendering.md +108 -0
- package/dist/resources/skills/create-gsd-extension/references/custom-tools.md +183 -0
- package/dist/resources/skills/create-gsd-extension/references/custom-ui.md +490 -0
- package/dist/resources/skills/create-gsd-extension/references/events-reference.md +126 -0
- package/dist/resources/skills/create-gsd-extension/references/extension-lifecycle.md +64 -0
- package/dist/resources/skills/create-gsd-extension/references/extensionapi-reference.md +75 -0
- package/dist/resources/skills/create-gsd-extension/references/extensioncontext-reference.md +53 -0
- package/dist/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +36 -0
- package/dist/resources/skills/create-gsd-extension/references/mode-behavior.md +32 -0
- package/dist/resources/skills/create-gsd-extension/references/model-provider-management.md +89 -0
- package/dist/resources/skills/create-gsd-extension/references/packaging-distribution.md +55 -0
- package/dist/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +90 -0
- package/dist/resources/skills/create-gsd-extension/references/state-management.md +70 -0
- package/dist/resources/skills/create-gsd-extension/references/system-prompt-modification.md +52 -0
- package/dist/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +51 -0
- package/dist/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +143 -0
- package/dist/resources/skills/create-gsd-extension/workflows/add-capability.md +57 -0
- package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +156 -0
- package/dist/resources/skills/create-gsd-extension/workflows/debug-extension.md +74 -0
- package/dist/resources/skills/create-skill/SKILL.md +184 -0
- package/dist/resources/skills/create-skill/references/api-security.md +226 -0
- package/dist/resources/skills/create-skill/references/be-clear-and-direct.md +531 -0
- package/dist/resources/skills/create-skill/references/common-patterns.md +595 -0
- package/dist/resources/skills/create-skill/references/core-principles.md +437 -0
- package/dist/resources/skills/create-skill/references/executable-code.md +175 -0
- package/dist/resources/skills/create-skill/references/gsd-skill-ecosystem.md +68 -0
- package/dist/resources/skills/create-skill/references/iteration-and-testing.md +474 -0
- package/dist/resources/skills/create-skill/references/recommended-structure.md +168 -0
- package/dist/resources/skills/create-skill/references/skill-structure.md +372 -0
- package/dist/resources/skills/create-skill/references/use-xml-tags.md +466 -0
- package/dist/resources/skills/create-skill/references/using-scripts.md +113 -0
- package/dist/resources/skills/create-skill/references/using-templates.md +112 -0
- package/dist/resources/skills/create-skill/references/workflows-and-validation.md +510 -0
- package/dist/resources/skills/create-skill/templates/router-skill.md +73 -0
- package/dist/resources/skills/create-skill/templates/simple-skill.md +33 -0
- package/dist/resources/skills/create-skill/workflows/add-reference.md +96 -0
- package/dist/resources/skills/create-skill/workflows/add-script.md +93 -0
- package/dist/resources/skills/create-skill/workflows/add-template.md +74 -0
- package/dist/resources/skills/create-skill/workflows/add-workflow.md +120 -0
- package/dist/resources/skills/create-skill/workflows/audit-skill.md +148 -0
- package/dist/resources/skills/create-skill/workflows/create-new-skill.md +196 -0
- package/dist/resources/skills/create-skill/workflows/get-guidance.md +121 -0
- package/dist/resources/skills/create-skill/workflows/upgrade-to-router.md +161 -0
- package/dist/resources/skills/create-skill/workflows/verify-skill.md +204 -0
- package/dist/resources/skills/react-best-practices/SKILL.md +1 -1
- package/package.json +1 -1
- package/packages/native/dist/native.d.ts +2 -0
- package/packages/native/dist/native.js +19 -5
- package/packages/native/src/native.ts +23 -9
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +13 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/client.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/client.js +3 -0
- package/packages/pi-coding-agent/dist/core/lsp/client.js.map +1 -1
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +13 -0
- package/packages/pi-coding-agent/src/core/lsp/client.ts +3 -0
- package/src/resources/extensions/async-jobs/extension-manifest.json +13 -0
- package/src/resources/extensions/bg-shell/extension-manifest.json +14 -0
- package/src/resources/extensions/bg-shell/process-manager.ts +13 -0
- package/src/resources/extensions/browser-tools/extension-manifest.json +37 -0
- package/src/resources/extensions/context7/extension-manifest.json +12 -0
- package/src/resources/extensions/google-search/extension-manifest.json +12 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +217 -65
- package/src/resources/extensions/gsd/auto-dispatch.ts +32 -3
- package/src/resources/extensions/gsd/auto-post-unit.ts +45 -13
- package/src/resources/extensions/gsd/auto-prompts.ts +40 -17
- package/src/resources/extensions/gsd/auto-recovery.ts +18 -23
- package/src/resources/extensions/gsd/auto-start.ts +18 -32
- package/src/resources/extensions/gsd/auto-worktree.ts +21 -182
- package/src/resources/extensions/gsd/auto.ts +2 -24
- package/src/resources/extensions/gsd/captures.ts +4 -10
- package/src/resources/extensions/gsd/commands-extensions.ts +328 -0
- package/src/resources/extensions/gsd/commands-handlers.ts +22 -2
- package/src/resources/extensions/gsd/commands-logs.ts +13 -14
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +44 -14
- package/src/resources/extensions/gsd/commands-workflow-templates.ts +544 -0
- package/src/resources/extensions/gsd/commands.ts +108 -24
- package/src/resources/extensions/gsd/dashboard-overlay.ts +2 -1
- package/src/resources/extensions/gsd/detection.ts +2 -1
- package/src/resources/extensions/gsd/doctor-checks.ts +49 -1
- package/src/resources/extensions/gsd/doctor-types.ts +3 -1
- package/src/resources/extensions/gsd/extension-manifest.json +18 -0
- package/src/resources/extensions/gsd/forensics.ts +2 -2
- package/src/resources/extensions/gsd/git-service.ts +3 -2
- package/src/resources/extensions/gsd/gitignore.ts +9 -63
- package/src/resources/extensions/gsd/gsd-db.ts +1 -165
- package/src/resources/extensions/gsd/guided-flow.ts +8 -5
- package/src/resources/extensions/gsd/index.ts +3 -3
- package/src/resources/extensions/gsd/json-persistence.ts +16 -1
- package/src/resources/extensions/gsd/md-importer.ts +3 -2
- package/src/resources/extensions/gsd/mechanical-completion.ts +430 -0
- package/src/resources/extensions/gsd/migrate/command.ts +3 -2
- package/src/resources/extensions/gsd/migrate/writer.ts +2 -1
- package/src/resources/extensions/gsd/migrate-external.ts +123 -0
- package/src/resources/extensions/gsd/paths.ts +24 -2
- package/src/resources/extensions/gsd/post-unit-hooks.ts +6 -5
- package/src/resources/extensions/gsd/preferences-models.ts +7 -1
- package/src/resources/extensions/gsd/preferences-validation.ts +2 -1
- package/src/resources/extensions/gsd/preferences.ts +10 -5
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +4 -2
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +26 -2
- package/src/resources/extensions/gsd/prompts/plan-slice.md +15 -1
- package/src/resources/extensions/gsd/prompts/workflow-start.md +28 -0
- package/src/resources/extensions/gsd/queue-order.ts +10 -11
- package/src/resources/extensions/gsd/repo-identity.ts +148 -0
- package/src/resources/extensions/gsd/resource-version.ts +99 -0
- package/src/resources/extensions/gsd/session-forensics.ts +4 -3
- package/src/resources/extensions/gsd/session-status-io.ts +23 -41
- package/src/resources/extensions/gsd/tests/activity-log.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/auto-skip-loop.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +0 -58
- package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +3 -4
- package/src/resources/extensions/gsd/tests/extension-selector-separator.test.ts +60 -38
- package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +5 -18
- package/src/resources/extensions/gsd/tests/git-service.test.ts +10 -37
- package/src/resources/extensions/gsd/tests/knowledge.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/mechanical-completion.test.ts +356 -0
- package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/token-profile.test.ts +14 -16
- package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +173 -0
- package/src/resources/extensions/gsd/triage-resolution.ts +2 -1
- package/src/resources/extensions/gsd/types.ts +2 -0
- package/src/resources/extensions/gsd/workflow-templates/bugfix.md +87 -0
- package/src/resources/extensions/gsd/workflow-templates/dep-upgrade.md +74 -0
- package/src/resources/extensions/gsd/workflow-templates/full-project.md +41 -0
- package/src/resources/extensions/gsd/workflow-templates/hotfix.md +45 -0
- package/src/resources/extensions/gsd/workflow-templates/refactor.md +83 -0
- package/src/resources/extensions/gsd/workflow-templates/registry.json +85 -0
- package/src/resources/extensions/gsd/workflow-templates/security-audit.md +73 -0
- package/src/resources/extensions/gsd/workflow-templates/small-feature.md +81 -0
- package/src/resources/extensions/gsd/workflow-templates/spike.md +69 -0
- package/src/resources/extensions/gsd/workflow-templates.ts +241 -0
- package/src/resources/extensions/gsd/worktree-command.ts +1 -11
- package/src/resources/extensions/gsd/worktree-manager.ts +3 -2
- package/src/resources/extensions/gsd/worktree.ts +42 -5
- package/src/resources/extensions/mac-tools/extension-manifest.json +16 -0
- package/src/resources/extensions/mcp-client/index.ts +459 -0
- package/src/resources/extensions/mcporter/extension-manifest.json +12 -0
- package/src/resources/extensions/remote-questions/discord-adapter.ts +8 -19
- package/src/resources/extensions/remote-questions/extension-manifest.json +11 -0
- package/src/resources/extensions/remote-questions/http-client.ts +76 -0
- package/src/resources/extensions/remote-questions/slack-adapter.ts +11 -17
- package/src/resources/extensions/remote-questions/telegram-adapter.ts +8 -19
- package/src/resources/extensions/search-the-web/extension-manifest.json +13 -0
- package/src/resources/extensions/slash-commands/extension-manifest.json +11 -0
- package/src/resources/extensions/subagent/extension-manifest.json +13 -0
- package/src/resources/extensions/ttsr/extension-manifest.json +11 -0
- package/src/resources/extensions/universal-config/extension-manifest.json +13 -0
- package/src/resources/extensions/voice/extension-manifest.json +12 -0
- package/src/resources/skills/create-gsd-extension/SKILL.md +87 -0
- package/src/resources/skills/create-gsd-extension/references/compaction-session-control.md +77 -0
- package/src/resources/skills/create-gsd-extension/references/custom-commands.md +139 -0
- package/src/resources/skills/create-gsd-extension/references/custom-rendering.md +108 -0
- package/src/resources/skills/create-gsd-extension/references/custom-tools.md +183 -0
- package/src/resources/skills/create-gsd-extension/references/custom-ui.md +490 -0
- package/src/resources/skills/create-gsd-extension/references/events-reference.md +126 -0
- package/src/resources/skills/create-gsd-extension/references/extension-lifecycle.md +64 -0
- package/src/resources/skills/create-gsd-extension/references/extensionapi-reference.md +75 -0
- package/src/resources/skills/create-gsd-extension/references/extensioncontext-reference.md +53 -0
- package/src/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +36 -0
- package/src/resources/skills/create-gsd-extension/references/mode-behavior.md +32 -0
- package/src/resources/skills/create-gsd-extension/references/model-provider-management.md +89 -0
- package/src/resources/skills/create-gsd-extension/references/packaging-distribution.md +55 -0
- package/src/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +90 -0
- package/src/resources/skills/create-gsd-extension/references/state-management.md +70 -0
- package/src/resources/skills/create-gsd-extension/references/system-prompt-modification.md +52 -0
- package/src/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +51 -0
- package/src/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +143 -0
- package/src/resources/skills/create-gsd-extension/workflows/add-capability.md +57 -0
- package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +156 -0
- package/src/resources/skills/create-gsd-extension/workflows/debug-extension.md +74 -0
- package/src/resources/skills/create-skill/SKILL.md +184 -0
- package/src/resources/skills/create-skill/references/api-security.md +226 -0
- package/src/resources/skills/create-skill/references/be-clear-and-direct.md +531 -0
- package/src/resources/skills/create-skill/references/common-patterns.md +595 -0
- package/src/resources/skills/create-skill/references/core-principles.md +437 -0
- package/src/resources/skills/create-skill/references/executable-code.md +175 -0
- package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +68 -0
- package/src/resources/skills/create-skill/references/iteration-and-testing.md +474 -0
- package/src/resources/skills/create-skill/references/recommended-structure.md +168 -0
- package/src/resources/skills/create-skill/references/skill-structure.md +372 -0
- package/src/resources/skills/create-skill/references/use-xml-tags.md +466 -0
- package/src/resources/skills/create-skill/references/using-scripts.md +113 -0
- package/src/resources/skills/create-skill/references/using-templates.md +112 -0
- package/src/resources/skills/create-skill/references/workflows-and-validation.md +510 -0
- package/src/resources/skills/create-skill/templates/router-skill.md +73 -0
- package/src/resources/skills/create-skill/templates/simple-skill.md +33 -0
- package/src/resources/skills/create-skill/workflows/add-reference.md +96 -0
- package/src/resources/skills/create-skill/workflows/add-script.md +93 -0
- package/src/resources/skills/create-skill/workflows/add-template.md +74 -0
- package/src/resources/skills/create-skill/workflows/add-workflow.md +120 -0
- package/src/resources/skills/create-skill/workflows/audit-skill.md +148 -0
- package/src/resources/skills/create-skill/workflows/create-new-skill.md +196 -0
- package/src/resources/skills/create-skill/workflows/get-guidance.md +121 -0
- package/src/resources/skills/create-skill/workflows/upgrade-to-router.md +161 -0
- package/src/resources/skills/create-skill/workflows/verify-skill.md +204 -0
- package/src/resources/skills/react-best-practices/SKILL.md +1 -1
- package/dist/resources/extensions/gsd/auto-worktree-sync.ts +0 -198
- package/dist/resources/extensions/gsd/tests/worktree-db-integration.test.ts +0 -205
- package/dist/resources/extensions/gsd/tests/worktree-db.test.ts +0 -442
- package/dist/resources/extensions/mcporter/index.ts +0 -525
- package/src/resources/extensions/gsd/auto-worktree-sync.ts +0 -198
- package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +0 -205
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +0 -442
- package/src/resources/extensions/mcporter/index.ts +0 -525
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* worktree-db-integration.test.ts
|
|
3
|
-
*
|
|
4
|
-
* Integration tests for the worktree DB copy and reconcile hooks.
|
|
5
|
-
* Uses real temp git repos and real SQLite databases.
|
|
6
|
-
*
|
|
7
|
-
* Test cases:
|
|
8
|
-
* 1. Copy: createAutoWorktree seeds .gsd/gsd.db into the worktree when main has one
|
|
9
|
-
* 2. Copy-skip: createAutoWorktree silently skips when main has no gsd.db
|
|
10
|
-
* 3. Reconcile: reconcileWorktreeDb merges worktree rows into main DB
|
|
11
|
-
* 4. Reconcile-skip: reconcileWorktreeDb is non-fatal when both paths are nonexistent
|
|
12
|
-
* 5. Failure path: reconcileWorktreeDb emits to stderr on open failure (observable)
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
import { mkdtempSync, mkdirSync, writeFileSync, rmSync, existsSync, realpathSync } from "node:fs";
|
|
16
|
-
import { join } from "node:path";
|
|
17
|
-
import { tmpdir } from "node:os";
|
|
18
|
-
import { execSync } from "node:child_process";
|
|
19
|
-
|
|
20
|
-
import { createAutoWorktree } from "../auto-worktree.ts";
|
|
21
|
-
import { worktreePath } from "../worktree-manager.ts";
|
|
22
|
-
import {
|
|
23
|
-
copyWorktreeDb,
|
|
24
|
-
reconcileWorktreeDb,
|
|
25
|
-
openDatabase,
|
|
26
|
-
closeDatabase,
|
|
27
|
-
upsertDecision,
|
|
28
|
-
getActiveDecisions,
|
|
29
|
-
isDbAvailable,
|
|
30
|
-
} from "../gsd-db.ts";
|
|
31
|
-
|
|
32
|
-
import { createTestContext } from "./test-helpers.ts";
|
|
33
|
-
|
|
34
|
-
const { assertEq, assertTrue, report } = createTestContext();
|
|
35
|
-
|
|
36
|
-
function run(command: string, cwd: string): string {
|
|
37
|
-
return execSync(command, { cwd, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }).trim();
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function createTempRepo(): string {
|
|
41
|
-
const dir = realpathSync(mkdtempSync(join(tmpdir(), "wt-db-int-test-")));
|
|
42
|
-
run("git init", dir);
|
|
43
|
-
run("git config user.email test@test.com", dir);
|
|
44
|
-
run("git config user.name Test", dir);
|
|
45
|
-
writeFileSync(join(dir, "README.md"), "# test\n");
|
|
46
|
-
run("git add .", dir);
|
|
47
|
-
run("git commit -m init", dir);
|
|
48
|
-
run("git branch -M main", dir);
|
|
49
|
-
return dir;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
async function main(): Promise<void> {
|
|
53
|
-
const savedCwd = process.cwd();
|
|
54
|
-
const tempDirs: string[] = [];
|
|
55
|
-
|
|
56
|
-
function makeTempDir(): string {
|
|
57
|
-
const dir = realpathSync(mkdtempSync(join(tmpdir(), "wt-db-int-")));
|
|
58
|
-
tempDirs.push(dir);
|
|
59
|
-
return dir;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
try {
|
|
63
|
-
|
|
64
|
-
// ─── Test 1: copy on worktree creation ───────────────────────────
|
|
65
|
-
console.log("\n=== Test 1: copy on worktree creation ===");
|
|
66
|
-
{
|
|
67
|
-
const tempDir = createTempRepo();
|
|
68
|
-
tempDirs.push(tempDir);
|
|
69
|
-
|
|
70
|
-
// Seed a gsd.db in the main repo
|
|
71
|
-
const gsdDir = join(tempDir, ".gsd");
|
|
72
|
-
mkdirSync(gsdDir, { recursive: true });
|
|
73
|
-
const mainDbPath = join(gsdDir, "gsd.db");
|
|
74
|
-
openDatabase(mainDbPath);
|
|
75
|
-
closeDatabase();
|
|
76
|
-
|
|
77
|
-
// Commit so createAutoWorktree can copy planning artifacts
|
|
78
|
-
run("git add .", tempDir);
|
|
79
|
-
run('git commit -m "add gsd dir"', tempDir);
|
|
80
|
-
|
|
81
|
-
// createAutoWorktree should copy the DB into the worktree
|
|
82
|
-
const wtPath = createAutoWorktree(tempDir, "M004");
|
|
83
|
-
|
|
84
|
-
const worktreeDbPath = join(worktreePath(tempDir, "M004"), ".gsd", "gsd.db");
|
|
85
|
-
assertTrue(
|
|
86
|
-
existsSync(worktreeDbPath),
|
|
87
|
-
"gsd.db exists in worktree .gsd after createAutoWorktree",
|
|
88
|
-
);
|
|
89
|
-
|
|
90
|
-
// Restore cwd for next test
|
|
91
|
-
process.chdir(savedCwd);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// ─── Test 2: copy skip when no source DB ─────────────────────────
|
|
95
|
-
console.log("\n=== Test 2: copy skip when no source DB ===");
|
|
96
|
-
{
|
|
97
|
-
const tempDir = createTempRepo();
|
|
98
|
-
tempDirs.push(tempDir);
|
|
99
|
-
|
|
100
|
-
// No gsd.db — just a bare repo
|
|
101
|
-
let threw = false;
|
|
102
|
-
let wtPath: string | null = null;
|
|
103
|
-
try {
|
|
104
|
-
wtPath = createAutoWorktree(tempDir, "M004");
|
|
105
|
-
} catch (err) {
|
|
106
|
-
threw = true;
|
|
107
|
-
console.error(" Unexpected throw:", err);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
assertTrue(!threw, "createAutoWorktree does not throw when no source DB");
|
|
111
|
-
|
|
112
|
-
const worktreeDbPath = join(worktreePath(tempDir, "M004"), ".gsd", "gsd.db");
|
|
113
|
-
assertTrue(
|
|
114
|
-
!existsSync(worktreeDbPath),
|
|
115
|
-
"gsd.db is absent in worktree when source had none",
|
|
116
|
-
);
|
|
117
|
-
|
|
118
|
-
process.chdir(savedCwd);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// ─── Test 3: reconcile inserts worktree rows into main ───────────
|
|
122
|
-
console.log("\n=== Test 3: reconcile merges worktree rows into main ===");
|
|
123
|
-
{
|
|
124
|
-
const mainDbPath = join(makeTempDir(), "main.db");
|
|
125
|
-
const worktreeDbPath = join(makeTempDir(), "wt.db");
|
|
126
|
-
|
|
127
|
-
// Seed main DB (empty schema)
|
|
128
|
-
openDatabase(mainDbPath);
|
|
129
|
-
closeDatabase();
|
|
130
|
-
|
|
131
|
-
// Seed worktree DB with one decision
|
|
132
|
-
openDatabase(worktreeDbPath);
|
|
133
|
-
upsertDecision({
|
|
134
|
-
id: "D-WT-001",
|
|
135
|
-
when_context: "integration test",
|
|
136
|
-
scope: "test",
|
|
137
|
-
decision: "use reconcile",
|
|
138
|
-
choice: "reconcile on merge",
|
|
139
|
-
rationale: "test coverage",
|
|
140
|
-
revisable: "no",
|
|
141
|
-
superseded_by: null,
|
|
142
|
-
});
|
|
143
|
-
closeDatabase();
|
|
144
|
-
|
|
145
|
-
// Reconcile worktree → main
|
|
146
|
-
const result = reconcileWorktreeDb(mainDbPath, worktreeDbPath);
|
|
147
|
-
assertTrue(result.decisions >= 1, "reconcile reports at least 1 decision merged");
|
|
148
|
-
|
|
149
|
-
// Open main DB and verify the row is present
|
|
150
|
-
openDatabase(mainDbPath);
|
|
151
|
-
const decisions = getActiveDecisions();
|
|
152
|
-
closeDatabase();
|
|
153
|
-
|
|
154
|
-
const found = decisions.some((d) => d.id === "D-WT-001");
|
|
155
|
-
assertTrue(found, "worktree decision D-WT-001 present in main DB after reconcile");
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// ─── Test 4: reconcile non-fatal when both paths nonexistent ─────
|
|
159
|
-
console.log("\n=== Test 4: reconcile non-fatal on nonexistent paths ===");
|
|
160
|
-
{
|
|
161
|
-
let threw = false;
|
|
162
|
-
try {
|
|
163
|
-
reconcileWorktreeDb("/nonexistent/path/gsd.db", "/also/nonexistent/gsd.db");
|
|
164
|
-
} catch {
|
|
165
|
-
threw = true;
|
|
166
|
-
}
|
|
167
|
-
assertTrue(!threw, "reconcileWorktreeDb does not throw when worktree DB is absent");
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// ─── Test 5: failure path observable via stderr (diagnostic) ─────
|
|
171
|
-
// reconcileWorktreeDb emits to stderr on reconciliation failures.
|
|
172
|
-
// We can't easily intercept stderr in this test harness, but we verify
|
|
173
|
-
// that the function returns the zero-result shape (not undefined/throws)
|
|
174
|
-
// when the worktree DB is missing — confirming the failure path is non-fatal
|
|
175
|
-
// and returns a structured result.
|
|
176
|
-
console.log("\n=== Test 5: reconcile returns zero-shape when worktree DB absent ===");
|
|
177
|
-
{
|
|
178
|
-
const mainDbPath = join(makeTempDir(), "main2.db");
|
|
179
|
-
openDatabase(mainDbPath);
|
|
180
|
-
closeDatabase();
|
|
181
|
-
|
|
182
|
-
const result = reconcileWorktreeDb(mainDbPath, "/definitely/does/not/exist.db");
|
|
183
|
-
assertEq(result.decisions, 0, "decisions is 0 when worktree DB absent");
|
|
184
|
-
assertEq(result.requirements, 0, "requirements is 0 when worktree DB absent");
|
|
185
|
-
assertEq(result.artifacts, 0, "artifacts is 0 when worktree DB absent");
|
|
186
|
-
assertEq(result.conflicts.length, 0, "conflicts is empty when worktree DB absent");
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
} finally {
|
|
190
|
-
// Always restore cwd
|
|
191
|
-
process.chdir(savedCwd);
|
|
192
|
-
// Ensure DB is closed
|
|
193
|
-
if (isDbAvailable()) closeDatabase();
|
|
194
|
-
// Remove all temp dirs
|
|
195
|
-
for (const dir of tempDirs) {
|
|
196
|
-
if (existsSync(dir)) {
|
|
197
|
-
rmSync(dir, { recursive: true, force: true });
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
report();
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
main();
|
|
@@ -1,442 +0,0 @@
|
|
|
1
|
-
import { createTestContext } from './test-helpers.ts';
|
|
2
|
-
import * as fs from 'node:fs';
|
|
3
|
-
import * as path from 'node:path';
|
|
4
|
-
import * as os from 'node:os';
|
|
5
|
-
import {
|
|
6
|
-
openDatabase,
|
|
7
|
-
closeDatabase,
|
|
8
|
-
isDbAvailable,
|
|
9
|
-
insertDecision,
|
|
10
|
-
insertRequirement,
|
|
11
|
-
insertArtifact,
|
|
12
|
-
getDecisionById,
|
|
13
|
-
getRequirementById,
|
|
14
|
-
_getAdapter,
|
|
15
|
-
copyWorktreeDb,
|
|
16
|
-
reconcileWorktreeDb,
|
|
17
|
-
} from '../gsd-db.ts';
|
|
18
|
-
|
|
19
|
-
const { assertEq, assertTrue, report } = createTestContext();
|
|
20
|
-
|
|
21
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
22
|
-
// Helpers
|
|
23
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
24
|
-
|
|
25
|
-
function tempDir(): string {
|
|
26
|
-
return fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-wt-test-'));
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function cleanup(...dirs: string[]): void {
|
|
30
|
-
closeDatabase();
|
|
31
|
-
for (const dir of dirs) {
|
|
32
|
-
try {
|
|
33
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
34
|
-
} catch {
|
|
35
|
-
// best effort
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function seedMainDb(dbPath: string): void {
|
|
41
|
-
openDatabase(dbPath);
|
|
42
|
-
insertDecision({
|
|
43
|
-
id: 'D001',
|
|
44
|
-
when_context: '2025-01-01',
|
|
45
|
-
scope: 'M001/S01',
|
|
46
|
-
decision: 'Use SQLite',
|
|
47
|
-
choice: 'node:sqlite',
|
|
48
|
-
rationale: 'Built-in',
|
|
49
|
-
revisable: 'yes',
|
|
50
|
-
superseded_by: null,
|
|
51
|
-
});
|
|
52
|
-
insertRequirement({
|
|
53
|
-
id: 'R001',
|
|
54
|
-
class: 'functional',
|
|
55
|
-
status: 'active',
|
|
56
|
-
description: 'Must store decisions',
|
|
57
|
-
why: 'Core feature',
|
|
58
|
-
source: 'design',
|
|
59
|
-
primary_owner: 'S01',
|
|
60
|
-
supporting_slices: '',
|
|
61
|
-
validation: 'test',
|
|
62
|
-
notes: '',
|
|
63
|
-
full_content: 'Full requirement text',
|
|
64
|
-
superseded_by: null,
|
|
65
|
-
});
|
|
66
|
-
insertArtifact({
|
|
67
|
-
path: 'docs/arch.md',
|
|
68
|
-
artifact_type: 'plan',
|
|
69
|
-
milestone_id: 'M001',
|
|
70
|
-
slice_id: null,
|
|
71
|
-
task_id: null,
|
|
72
|
-
full_content: 'Architecture document',
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
77
|
-
// copyWorktreeDb tests
|
|
78
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
79
|
-
|
|
80
|
-
console.log('\n=== worktree-db: copyWorktreeDb ===');
|
|
81
|
-
|
|
82
|
-
// Test: copies DB file and data is queryable
|
|
83
|
-
{
|
|
84
|
-
const srcDir = tempDir();
|
|
85
|
-
const destDir = tempDir();
|
|
86
|
-
const srcDb = path.join(srcDir, 'gsd.db');
|
|
87
|
-
const destDb = path.join(destDir, 'nested', 'gsd.db');
|
|
88
|
-
|
|
89
|
-
seedMainDb(srcDb);
|
|
90
|
-
closeDatabase();
|
|
91
|
-
|
|
92
|
-
const result = copyWorktreeDb(srcDb, destDb);
|
|
93
|
-
assertTrue(result === true, 'copyWorktreeDb returns true on success');
|
|
94
|
-
assertTrue(fs.existsSync(destDb), 'dest DB file exists after copy');
|
|
95
|
-
|
|
96
|
-
// Open the copy and verify data is queryable
|
|
97
|
-
openDatabase(destDb);
|
|
98
|
-
const d = getDecisionById('D001');
|
|
99
|
-
assertTrue(d !== null, 'decision queryable in copied DB');
|
|
100
|
-
assertEq(d?.choice, 'node:sqlite', 'decision data preserved in copy');
|
|
101
|
-
|
|
102
|
-
const r = getRequirementById('R001');
|
|
103
|
-
assertTrue(r !== null, 'requirement queryable in copied DB');
|
|
104
|
-
assertEq(r?.description, 'Must store decisions', 'requirement data preserved in copy');
|
|
105
|
-
|
|
106
|
-
cleanup(srcDir, destDir);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Test: skips -wal and -shm files
|
|
110
|
-
{
|
|
111
|
-
const srcDir = tempDir();
|
|
112
|
-
const destDir = tempDir();
|
|
113
|
-
const srcDb = path.join(srcDir, 'gsd.db');
|
|
114
|
-
const destDb = path.join(destDir, 'gsd.db');
|
|
115
|
-
|
|
116
|
-
seedMainDb(srcDb);
|
|
117
|
-
closeDatabase();
|
|
118
|
-
|
|
119
|
-
// Create fake WAL/SHM files
|
|
120
|
-
fs.writeFileSync(srcDb + '-wal', 'fake wal data');
|
|
121
|
-
fs.writeFileSync(srcDb + '-shm', 'fake shm data');
|
|
122
|
-
|
|
123
|
-
copyWorktreeDb(srcDb, destDb);
|
|
124
|
-
|
|
125
|
-
assertTrue(fs.existsSync(destDb), 'DB file copied');
|
|
126
|
-
assertTrue(!fs.existsSync(destDb + '-wal'), 'WAL file NOT copied');
|
|
127
|
-
assertTrue(!fs.existsSync(destDb + '-shm'), 'SHM file NOT copied');
|
|
128
|
-
|
|
129
|
-
cleanup(srcDir, destDir);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// Test: returns false when source doesn't exist (no throw)
|
|
133
|
-
{
|
|
134
|
-
const destDir = tempDir();
|
|
135
|
-
const result = copyWorktreeDb('/nonexistent/path/gsd.db', path.join(destDir, 'gsd.db'));
|
|
136
|
-
assertEq(result, false, 'returns false for missing source');
|
|
137
|
-
cleanup(destDir);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// Test: creates dest directory if needed
|
|
141
|
-
{
|
|
142
|
-
const srcDir = tempDir();
|
|
143
|
-
const destDir = tempDir();
|
|
144
|
-
const srcDb = path.join(srcDir, 'gsd.db');
|
|
145
|
-
const deepDest = path.join(destDir, 'a', 'b', 'c', 'gsd.db');
|
|
146
|
-
|
|
147
|
-
seedMainDb(srcDb);
|
|
148
|
-
closeDatabase();
|
|
149
|
-
|
|
150
|
-
const result = copyWorktreeDb(srcDb, deepDest);
|
|
151
|
-
assertTrue(result === true, 'copyWorktreeDb succeeds with nested dest');
|
|
152
|
-
assertTrue(fs.existsSync(deepDest), 'DB file created at deeply nested path');
|
|
153
|
-
|
|
154
|
-
cleanup(srcDir, destDir);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
158
|
-
// reconcileWorktreeDb tests
|
|
159
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
160
|
-
|
|
161
|
-
console.log('\n=== worktree-db: reconcileWorktreeDb ===');
|
|
162
|
-
|
|
163
|
-
// Test: merges new decisions from worktree into main
|
|
164
|
-
{
|
|
165
|
-
const mainDir = tempDir();
|
|
166
|
-
const wtDir = tempDir();
|
|
167
|
-
const mainDb = path.join(mainDir, 'gsd.db');
|
|
168
|
-
const wtDb = path.join(wtDir, 'gsd.db');
|
|
169
|
-
|
|
170
|
-
// Seed main with D001
|
|
171
|
-
seedMainDb(mainDb);
|
|
172
|
-
closeDatabase();
|
|
173
|
-
|
|
174
|
-
// Copy to worktree, add D002 in worktree
|
|
175
|
-
copyWorktreeDb(mainDb, wtDb);
|
|
176
|
-
openDatabase(wtDb);
|
|
177
|
-
insertDecision({
|
|
178
|
-
id: 'D002',
|
|
179
|
-
when_context: '2025-02-01',
|
|
180
|
-
scope: 'M001/S02',
|
|
181
|
-
decision: 'Use WAL mode',
|
|
182
|
-
choice: 'WAL',
|
|
183
|
-
rationale: 'Performance',
|
|
184
|
-
revisable: 'yes',
|
|
185
|
-
superseded_by: null,
|
|
186
|
-
});
|
|
187
|
-
closeDatabase();
|
|
188
|
-
|
|
189
|
-
// Re-open main and reconcile
|
|
190
|
-
openDatabase(mainDb);
|
|
191
|
-
const result = reconcileWorktreeDb(mainDb, wtDb);
|
|
192
|
-
|
|
193
|
-
assertTrue(result.decisions > 0, 'decisions merged count > 0');
|
|
194
|
-
const d2 = getDecisionById('D002');
|
|
195
|
-
assertTrue(d2 !== null, 'D002 from worktree now in main');
|
|
196
|
-
assertEq(d2?.choice, 'WAL', 'D002 data correct after merge');
|
|
197
|
-
|
|
198
|
-
cleanup(mainDir, wtDir);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// Test: merges new requirements from worktree into main
|
|
202
|
-
{
|
|
203
|
-
const mainDir = tempDir();
|
|
204
|
-
const wtDir = tempDir();
|
|
205
|
-
const mainDb = path.join(mainDir, 'gsd.db');
|
|
206
|
-
const wtDb = path.join(wtDir, 'gsd.db');
|
|
207
|
-
|
|
208
|
-
seedMainDb(mainDb);
|
|
209
|
-
closeDatabase();
|
|
210
|
-
copyWorktreeDb(mainDb, wtDb);
|
|
211
|
-
|
|
212
|
-
openDatabase(wtDb);
|
|
213
|
-
insertRequirement({
|
|
214
|
-
id: 'R002',
|
|
215
|
-
class: 'non-functional',
|
|
216
|
-
status: 'active',
|
|
217
|
-
description: 'Must be fast',
|
|
218
|
-
why: 'UX',
|
|
219
|
-
source: 'design',
|
|
220
|
-
primary_owner: 'S02',
|
|
221
|
-
supporting_slices: '',
|
|
222
|
-
validation: 'benchmark',
|
|
223
|
-
notes: '',
|
|
224
|
-
full_content: 'Performance requirement',
|
|
225
|
-
superseded_by: null,
|
|
226
|
-
});
|
|
227
|
-
closeDatabase();
|
|
228
|
-
|
|
229
|
-
openDatabase(mainDb);
|
|
230
|
-
const result = reconcileWorktreeDb(mainDb, wtDb);
|
|
231
|
-
|
|
232
|
-
assertTrue(result.requirements > 0, 'requirements merged count > 0');
|
|
233
|
-
const r2 = getRequirementById('R002');
|
|
234
|
-
assertTrue(r2 !== null, 'R002 from worktree now in main');
|
|
235
|
-
assertEq(r2?.description, 'Must be fast', 'R002 data correct after merge');
|
|
236
|
-
|
|
237
|
-
cleanup(mainDir, wtDir);
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
// Test: merges new artifacts from worktree into main
|
|
241
|
-
{
|
|
242
|
-
const mainDir = tempDir();
|
|
243
|
-
const wtDir = tempDir();
|
|
244
|
-
const mainDb = path.join(mainDir, 'gsd.db');
|
|
245
|
-
const wtDb = path.join(wtDir, 'gsd.db');
|
|
246
|
-
|
|
247
|
-
seedMainDb(mainDb);
|
|
248
|
-
closeDatabase();
|
|
249
|
-
copyWorktreeDb(mainDb, wtDb);
|
|
250
|
-
|
|
251
|
-
openDatabase(wtDb);
|
|
252
|
-
insertArtifact({
|
|
253
|
-
path: 'docs/api.md',
|
|
254
|
-
artifact_type: 'reference',
|
|
255
|
-
milestone_id: 'M001',
|
|
256
|
-
slice_id: 'S01',
|
|
257
|
-
task_id: 'T01',
|
|
258
|
-
full_content: 'API documentation',
|
|
259
|
-
});
|
|
260
|
-
closeDatabase();
|
|
261
|
-
|
|
262
|
-
openDatabase(mainDb);
|
|
263
|
-
const result = reconcileWorktreeDb(mainDb, wtDb);
|
|
264
|
-
|
|
265
|
-
assertTrue(result.artifacts > 0, 'artifacts merged count > 0');
|
|
266
|
-
const adapter = _getAdapter()!;
|
|
267
|
-
const row = adapter.prepare('SELECT * FROM artifacts WHERE path = ?').get('docs/api.md');
|
|
268
|
-
assertTrue(row !== null, 'artifact from worktree now in main');
|
|
269
|
-
assertEq(row?.['artifact_type'], 'reference', 'artifact data correct after merge');
|
|
270
|
-
|
|
271
|
-
cleanup(mainDir, wtDir);
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
// Test: detects conflicts (same PK, different content in both DBs)
|
|
275
|
-
{
|
|
276
|
-
const mainDir = tempDir();
|
|
277
|
-
const wtDir = tempDir();
|
|
278
|
-
const mainDb = path.join(mainDir, 'gsd.db');
|
|
279
|
-
const wtDb = path.join(wtDir, 'gsd.db');
|
|
280
|
-
|
|
281
|
-
// Seed main with D001
|
|
282
|
-
seedMainDb(mainDb);
|
|
283
|
-
closeDatabase();
|
|
284
|
-
copyWorktreeDb(mainDb, wtDb);
|
|
285
|
-
|
|
286
|
-
// Modify D001 in main
|
|
287
|
-
openDatabase(mainDb);
|
|
288
|
-
const mainAdapter = _getAdapter()!;
|
|
289
|
-
mainAdapter.prepare(
|
|
290
|
-
`UPDATE decisions SET choice = 'better-sqlite3' WHERE id = 'D001'`,
|
|
291
|
-
).run();
|
|
292
|
-
closeDatabase();
|
|
293
|
-
|
|
294
|
-
// Modify D001 in worktree differently
|
|
295
|
-
openDatabase(wtDb);
|
|
296
|
-
const wtAdapter = _getAdapter()!;
|
|
297
|
-
wtAdapter.prepare(
|
|
298
|
-
`UPDATE decisions SET choice = 'sql.js' WHERE id = 'D001'`,
|
|
299
|
-
).run();
|
|
300
|
-
closeDatabase();
|
|
301
|
-
|
|
302
|
-
// Reconcile
|
|
303
|
-
openDatabase(mainDb);
|
|
304
|
-
const result = reconcileWorktreeDb(mainDb, wtDb);
|
|
305
|
-
|
|
306
|
-
assertTrue(result.conflicts.length > 0, 'conflicts detected');
|
|
307
|
-
assertTrue(
|
|
308
|
-
result.conflicts.some(c => c.includes('D001')),
|
|
309
|
-
'conflict mentions D001',
|
|
310
|
-
);
|
|
311
|
-
|
|
312
|
-
// Worktree-wins: D001 should now have worktree's value
|
|
313
|
-
const d1 = getDecisionById('D001');
|
|
314
|
-
assertEq(d1?.choice, 'sql.js', 'worktree wins on conflict (INSERT OR REPLACE)');
|
|
315
|
-
|
|
316
|
-
cleanup(mainDir, wtDir);
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
// Test: handles missing worktree DB gracefully
|
|
320
|
-
{
|
|
321
|
-
const mainDir = tempDir();
|
|
322
|
-
const mainDb = path.join(mainDir, 'gsd.db');
|
|
323
|
-
|
|
324
|
-
seedMainDb(mainDb);
|
|
325
|
-
|
|
326
|
-
const result = reconcileWorktreeDb(mainDb, '/nonexistent/worktree.db');
|
|
327
|
-
assertEq(result.decisions, 0, 'no decisions merged for missing worktree DB');
|
|
328
|
-
assertEq(result.requirements, 0, 'no requirements merged for missing worktree DB');
|
|
329
|
-
assertEq(result.artifacts, 0, 'no artifacts merged for missing worktree DB');
|
|
330
|
-
assertEq(result.conflicts.length, 0, 'no conflicts for missing worktree DB');
|
|
331
|
-
|
|
332
|
-
cleanup(mainDir);
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
// Test: path with spaces works
|
|
336
|
-
{
|
|
337
|
-
const baseDir = tempDir();
|
|
338
|
-
const mainDir = path.join(baseDir, 'main dir');
|
|
339
|
-
const wtDir = path.join(baseDir, 'worktree dir');
|
|
340
|
-
fs.mkdirSync(mainDir, { recursive: true });
|
|
341
|
-
fs.mkdirSync(wtDir, { recursive: true });
|
|
342
|
-
|
|
343
|
-
const mainDb = path.join(mainDir, 'gsd.db');
|
|
344
|
-
const wtDb = path.join(wtDir, 'gsd.db');
|
|
345
|
-
|
|
346
|
-
seedMainDb(mainDb);
|
|
347
|
-
closeDatabase();
|
|
348
|
-
copyWorktreeDb(mainDb, wtDb);
|
|
349
|
-
|
|
350
|
-
// Add a decision in worktree
|
|
351
|
-
openDatabase(wtDb);
|
|
352
|
-
insertDecision({
|
|
353
|
-
id: 'D003',
|
|
354
|
-
when_context: '2025-03-01',
|
|
355
|
-
scope: 'M001/S03',
|
|
356
|
-
decision: 'Path spaces test',
|
|
357
|
-
choice: 'yes',
|
|
358
|
-
rationale: 'Robustness',
|
|
359
|
-
revisable: 'no',
|
|
360
|
-
superseded_by: null,
|
|
361
|
-
});
|
|
362
|
-
closeDatabase();
|
|
363
|
-
|
|
364
|
-
openDatabase(mainDb);
|
|
365
|
-
const result = reconcileWorktreeDb(mainDb, wtDb);
|
|
366
|
-
assertTrue(result.decisions > 0, 'reconciliation works with spaces in path');
|
|
367
|
-
const d3 = getDecisionById('D003');
|
|
368
|
-
assertTrue(d3 !== null, 'D003 merged from worktree with spaces in path');
|
|
369
|
-
|
|
370
|
-
cleanup(baseDir);
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
// Test: main DB is usable after reconciliation (DETACH cleanup verified)
|
|
374
|
-
{
|
|
375
|
-
const mainDir = tempDir();
|
|
376
|
-
const wtDir = tempDir();
|
|
377
|
-
const mainDb = path.join(mainDir, 'gsd.db');
|
|
378
|
-
const wtDb = path.join(wtDir, 'gsd.db');
|
|
379
|
-
|
|
380
|
-
seedMainDb(mainDb);
|
|
381
|
-
closeDatabase();
|
|
382
|
-
copyWorktreeDb(mainDb, wtDb);
|
|
383
|
-
|
|
384
|
-
openDatabase(mainDb);
|
|
385
|
-
reconcileWorktreeDb(mainDb, wtDb);
|
|
386
|
-
|
|
387
|
-
// Verify main DB is still fully usable after DETACH
|
|
388
|
-
assertTrue(isDbAvailable(), 'DB still available after reconciliation');
|
|
389
|
-
|
|
390
|
-
insertDecision({
|
|
391
|
-
id: 'D099',
|
|
392
|
-
when_context: '2025-12-01',
|
|
393
|
-
scope: 'test',
|
|
394
|
-
decision: 'Post-reconcile insert',
|
|
395
|
-
choice: 'works',
|
|
396
|
-
rationale: 'Verify DETACH cleanup',
|
|
397
|
-
revisable: 'no',
|
|
398
|
-
superseded_by: null,
|
|
399
|
-
});
|
|
400
|
-
|
|
401
|
-
const d99 = getDecisionById('D099');
|
|
402
|
-
assertTrue(d99 !== null, 'can insert and query after reconciliation');
|
|
403
|
-
assertEq(d99?.choice, 'works', 'post-reconcile data correct');
|
|
404
|
-
|
|
405
|
-
// Verify no "wt" database still attached
|
|
406
|
-
const adapter = _getAdapter()!;
|
|
407
|
-
let wtAccessible = false;
|
|
408
|
-
try {
|
|
409
|
-
adapter.prepare('SELECT count(*) FROM wt.decisions').get();
|
|
410
|
-
wtAccessible = true;
|
|
411
|
-
} catch {
|
|
412
|
-
// Expected — wt should be detached
|
|
413
|
-
}
|
|
414
|
-
assertTrue(!wtAccessible, 'wt database is detached after reconciliation');
|
|
415
|
-
|
|
416
|
-
cleanup(mainDir, wtDir);
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
// Test: reconcile with empty worktree DB (no new rows, no conflicts)
|
|
420
|
-
{
|
|
421
|
-
const mainDir = tempDir();
|
|
422
|
-
const wtDir = tempDir();
|
|
423
|
-
const mainDb = path.join(mainDir, 'gsd.db');
|
|
424
|
-
const wtDb = path.join(wtDir, 'gsd.db');
|
|
425
|
-
|
|
426
|
-
seedMainDb(mainDb);
|
|
427
|
-
closeDatabase();
|
|
428
|
-
copyWorktreeDb(mainDb, wtDb);
|
|
429
|
-
|
|
430
|
-
// Don't modify the worktree DB at all — reconcile the identical copy
|
|
431
|
-
openDatabase(mainDb);
|
|
432
|
-
const result = reconcileWorktreeDb(mainDb, wtDb);
|
|
433
|
-
|
|
434
|
-
// Should still report counts for the existing rows (INSERT OR REPLACE touches them)
|
|
435
|
-
assertTrue(result.conflicts.length === 0, 'no conflicts when DBs are identical');
|
|
436
|
-
assertTrue(isDbAvailable(), 'DB usable after no-change reconciliation');
|
|
437
|
-
|
|
438
|
-
cleanup(mainDir, wtDir);
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
// ─── Final Report ──────────────────────────────────────────────────────────
|
|
442
|
-
report();
|