gsd-pi 2.54.0-dev.e1efc1a → 2.55.0-dev.9ec7cdf

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.
Files changed (201) hide show
  1. package/dist/cli.js +19 -19
  2. package/dist/headless-ui.d.ts +27 -1
  3. package/dist/headless-ui.js +203 -13
  4. package/dist/headless.js +60 -3
  5. package/dist/resources/extensions/bg-shell/bg-shell-lifecycle.js +2 -2
  6. package/dist/resources/extensions/bg-shell/utilities.js +34 -5
  7. package/dist/resources/extensions/gsd/auto/phases.js +19 -3
  8. package/dist/resources/extensions/gsd/auto-dispatch.js +1 -1
  9. package/dist/resources/extensions/gsd/auto-model-selection.js +17 -1
  10. package/dist/resources/extensions/gsd/auto-prompts.js +9 -0
  11. package/dist/resources/extensions/gsd/auto-start.js +12 -5
  12. package/dist/resources/extensions/gsd/auto-worktree.js +39 -14
  13. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +5 -1
  14. package/dist/resources/extensions/gsd/bootstrap/provider-error-resume.js +18 -0
  15. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +18 -5
  16. package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +20 -0
  17. package/dist/resources/extensions/gsd/commands/catalog.js +2 -1
  18. package/dist/resources/extensions/gsd/commands/handlers/parallel.js +15 -1
  19. package/dist/resources/extensions/gsd/crash-recovery.js +2 -2
  20. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +413 -0
  21. package/dist/resources/extensions/gsd/parallel-orchestrator.js +5 -1
  22. package/dist/resources/extensions/gsd/session-lock.js +46 -12
  23. package/dist/resources/extensions/gsd/skill-health.js +2 -2
  24. package/dist/resources/extensions/gsd/visualizer-overlay.js +3 -3
  25. package/dist/resources/extensions/shared/format-utils.js +1 -1
  26. package/dist/resources/extensions/subagent/worker-registry.js +2 -1
  27. package/dist/web/standalone/.next/BUILD_ID +1 -1
  28. package/dist/web/standalone/.next/app-path-routes-manifest.json +18 -18
  29. package/dist/web/standalone/.next/build-manifest.json +3 -3
  30. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  31. package/dist/web/standalone/.next/react-loadable-manifest.json +2 -2
  32. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  33. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  34. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  35. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  36. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  37. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  38. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  39. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  40. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  41. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  42. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  43. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  44. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  45. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  46. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  47. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  48. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  49. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  50. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  51. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  52. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  53. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  54. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  55. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  56. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  57. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  58. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  59. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  60. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  61. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  62. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  63. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  64. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  65. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  66. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  67. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  68. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  69. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  70. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  71. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  72. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  73. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  74. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  75. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  76. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  77. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  78. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  79. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  80. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  81. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  82. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  83. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  84. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  85. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  86. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  87. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  88. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  89. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  90. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  91. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  92. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  93. package/dist/web/standalone/.next/server/app/index.html +1 -1
  94. package/dist/web/standalone/.next/server/app/index.rsc +2 -2
  95. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  96. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
  97. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  100. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  101. package/dist/web/standalone/.next/server/app-paths-manifest.json +18 -18
  102. package/dist/web/standalone/.next/server/chunks/2229.js +1 -1
  103. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  104. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  105. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  106. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  107. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  108. package/dist/web/standalone/.next/static/chunks/6502.2305d0afd2385711.js +9 -0
  109. package/dist/web/standalone/.next/static/chunks/app/{page-b950e4e384cc62b3.js → page-0c485498795110d6.js} +1 -1
  110. package/dist/web/standalone/.next/static/chunks/{webpack-bca0e732db0dcec3.js → webpack-4332cbd5dd1be584.js} +1 -1
  111. package/package.json +6 -4
  112. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +1 -1
  113. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  114. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  115. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts +2 -0
  116. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts.map +1 -1
  117. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js +14 -2
  118. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js.map +1 -1
  119. package/packages/pi-coding-agent/package.json +1 -1
  120. package/packages/pi-coding-agent/src/core/model-registry.ts +1 -1
  121. package/packages/pi-coding-agent/src/modes/interactive/components/provider-manager.ts +16 -2
  122. package/pkg/package.json +1 -1
  123. package/scripts/ensure-workspace-builds.cjs +45 -41
  124. package/src/resources/extensions/bg-shell/bg-shell-lifecycle.ts +2 -2
  125. package/src/resources/extensions/bg-shell/utilities.ts +39 -4
  126. package/src/resources/extensions/gsd/auto/phases.ts +25 -4
  127. package/src/resources/extensions/gsd/auto-dispatch.ts +1 -1
  128. package/src/resources/extensions/gsd/auto-model-selection.ts +21 -1
  129. package/src/resources/extensions/gsd/auto-prompts.ts +15 -0
  130. package/src/resources/extensions/gsd/auto-start.ts +13 -5
  131. package/src/resources/extensions/gsd/auto-worktree.ts +46 -13
  132. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +5 -4
  133. package/src/resources/extensions/gsd/bootstrap/provider-error-resume.ts +53 -0
  134. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +19 -6
  135. package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +24 -0
  136. package/src/resources/extensions/gsd/commands/catalog.ts +2 -1
  137. package/src/resources/extensions/gsd/commands/handlers/parallel.ts +19 -1
  138. package/src/resources/extensions/gsd/crash-recovery.ts +2 -3
  139. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +497 -0
  140. package/src/resources/extensions/gsd/parallel-orchestrator.ts +6 -1
  141. package/src/resources/extensions/gsd/session-lock.ts +46 -12
  142. package/src/resources/extensions/gsd/skill-health.ts +2 -2
  143. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +139 -0
  144. package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +28 -0
  145. package/src/resources/extensions/gsd/tests/{all-milestones-complete-merge.test.ts → integration/all-milestones-complete-merge.test.ts} +3 -3
  146. package/src/resources/extensions/gsd/tests/{atomic-task-closeout.test.ts → integration/atomic-task-closeout.test.ts} +1 -1
  147. package/src/resources/extensions/gsd/tests/{auto-preflight.test.ts → integration/auto-preflight.test.ts} +1 -1
  148. package/src/resources/extensions/gsd/tests/{auto-recovery.test.ts → integration/auto-recovery.test.ts} +7 -7
  149. package/src/resources/extensions/gsd/tests/{auto-secrets-gate.test.ts → integration/auto-secrets-gate.test.ts} +2 -2
  150. package/src/resources/extensions/gsd/tests/{auto-stash-merge.test.ts → integration/auto-stash-merge.test.ts} +3 -3
  151. package/src/resources/extensions/gsd/tests/{auto-worktree-milestone-merge.test.ts → integration/auto-worktree-milestone-merge.test.ts} +4 -4
  152. package/src/resources/extensions/gsd/tests/{auto-worktree.test.ts → integration/auto-worktree.test.ts} +5 -5
  153. package/src/resources/extensions/gsd/tests/{continue-here.test.ts → integration/continue-here.test.ts} +3 -3
  154. package/src/resources/extensions/gsd/tests/{doctor-completion-deferral.test.ts → integration/doctor-completion-deferral.test.ts} +1 -1
  155. package/src/resources/extensions/gsd/tests/{doctor-delimiter-fix.test.ts → integration/doctor-delimiter-fix.test.ts} +1 -1
  156. package/src/resources/extensions/gsd/tests/{doctor-enhancements.test.ts → integration/doctor-enhancements.test.ts} +3 -3
  157. package/src/resources/extensions/gsd/tests/{doctor-environment-worktree.test.ts → integration/doctor-environment-worktree.test.ts} +1 -1
  158. package/src/resources/extensions/gsd/tests/{doctor-environment.test.ts → integration/doctor-environment.test.ts} +1 -1
  159. package/src/resources/extensions/gsd/tests/{doctor-fixlevel.test.ts → integration/doctor-fixlevel.test.ts} +2 -2
  160. package/src/resources/extensions/gsd/tests/{doctor-git.test.ts → integration/doctor-git.test.ts} +1 -1
  161. package/src/resources/extensions/gsd/tests/{doctor-proactive.test.ts → integration/doctor-proactive.test.ts} +1 -1
  162. package/src/resources/extensions/gsd/tests/{doctor-roadmap-summary-atomicity.test.ts → integration/doctor-roadmap-summary-atomicity.test.ts} +1 -1
  163. package/src/resources/extensions/gsd/tests/{doctor-runtime.test.ts → integration/doctor-runtime.test.ts} +1 -1
  164. package/src/resources/extensions/gsd/tests/{doctor.test.ts → integration/doctor.test.ts} +1 -1
  165. package/src/resources/extensions/gsd/tests/{e2e-workflow-pipeline-integration.test.ts → integration/e2e-workflow-pipeline-integration.test.ts} +5 -5
  166. package/src/resources/extensions/gsd/tests/{feature-branch-lifecycle-integration.test.ts → integration/feature-branch-lifecycle-integration.test.ts} +4 -4
  167. package/src/resources/extensions/gsd/tests/{git-locale.test.ts → integration/git-locale.test.ts} +4 -4
  168. package/src/resources/extensions/gsd/tests/{git-self-heal.test.ts → integration/git-self-heal.test.ts} +1 -1
  169. package/src/resources/extensions/gsd/tests/{git-service.test.ts → integration/git-service.test.ts} +4 -4
  170. package/src/resources/extensions/gsd/tests/{gitignore-tracked-gsd.test.ts → integration/gitignore-tracked-gsd.test.ts} +2 -2
  171. package/src/resources/extensions/gsd/tests/{idle-recovery.test.ts → integration/idle-recovery.test.ts} +3 -3
  172. package/src/resources/extensions/gsd/tests/{inherited-repo-home-dir.test.ts → integration/inherited-repo-home-dir.test.ts} +1 -1
  173. package/src/resources/extensions/gsd/tests/{integration-lifecycle.test.ts → integration/integration-lifecycle.test.ts} +4 -4
  174. package/src/resources/extensions/gsd/tests/{integration-mixed-milestones.test.ts → integration/integration-mixed-milestones.test.ts} +6 -6
  175. package/src/resources/extensions/gsd/tests/{integration-proof.test.ts → integration/integration-proof.test.ts} +12 -12
  176. package/src/resources/extensions/gsd/tests/{migrate-command.test.ts → integration/migrate-command.test.ts} +2 -2
  177. package/src/resources/extensions/gsd/tests/{milestone-transition-worktree.test.ts → integration/milestone-transition-worktree.test.ts} +3 -3
  178. package/src/resources/extensions/gsd/tests/{parallel-merge.test.ts → integration/parallel-merge.test.ts} +3 -3
  179. package/src/resources/extensions/gsd/tests/{parallel-workers-multi-milestone-e2e.test.ts → integration/parallel-workers-multi-milestone-e2e.test.ts} +3 -3
  180. package/src/resources/extensions/gsd/tests/{paths.test.ts → integration/paths.test.ts} +1 -1
  181. package/src/resources/extensions/gsd/tests/{plugin-importer-live.test.ts → integration/plugin-importer-live.test.ts} +2 -2
  182. package/src/resources/extensions/gsd/tests/{queue-completed-milestone-perf.test.ts → integration/queue-completed-milestone-perf.test.ts} +3 -3
  183. package/src/resources/extensions/gsd/tests/{queue-reorder-e2e.test.ts → integration/queue-reorder-e2e.test.ts} +5 -5
  184. package/src/resources/extensions/gsd/tests/{quick-branch-lifecycle.test.ts → integration/quick-branch-lifecycle.test.ts} +5 -5
  185. package/src/resources/extensions/gsd/tests/{run-uat.test.ts → integration/run-uat.test.ts} +4 -4
  186. package/src/resources/extensions/gsd/tests/{token-savings.test.ts → integration/token-savings.test.ts} +3 -3
  187. package/src/resources/extensions/gsd/tests/{worktree-e2e.test.ts → integration/worktree-e2e.test.ts} +4 -4
  188. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +55 -0
  189. package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +60 -0
  190. package/src/resources/extensions/gsd/tests/parallel-worker-lock-contention.test.ts +226 -0
  191. package/src/resources/extensions/gsd/tests/plan-milestone-queue-context.test.ts +48 -0
  192. package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +61 -19
  193. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +98 -0
  194. package/src/resources/extensions/gsd/tests/register-extension-guard.test.ts +59 -0
  195. package/src/resources/extensions/gsd/tests/worktree-preferences-sync.test.ts +49 -24
  196. package/src/resources/extensions/gsd/visualizer-overlay.ts +3 -3
  197. package/src/resources/extensions/shared/format-utils.ts +1 -1
  198. package/src/resources/extensions/subagent/worker-registry.ts +2 -1
  199. package/dist/web/standalone/.next/static/chunks/4024.87fd909ae0110f50.js +0 -9
  200. /package/dist/web/standalone/.next/static/{nISuDzAIpGYC-DVTvs4Po → k92jvAf8IfV4dZE3nnrAr}/_buildManifest.js +0 -0
  201. /package/dist/web/standalone/.next/static/{nISuDzAIpGYC-DVTvs4Po → k92jvAf8IfV4dZE3nnrAr}/_ssgManifest.js +0 -0
@@ -34,11 +34,11 @@ import { join } from "node:path";
34
34
  import { tmpdir } from "node:os";
35
35
  import { stringify, parse } from "yaml";
36
36
 
37
- import { CustomWorkflowEngine } from "../custom-workflow-engine.ts";
38
- import { CustomExecutionPolicy } from "../custom-execution-policy.ts";
39
- import { createRun, listRuns } from "../run-manager.ts";
40
- import { readGraph, writeGraph } from "../graph.ts";
41
- import { validateDefinition } from "../definition-loader.ts";
37
+ import { CustomWorkflowEngine } from "../../custom-workflow-engine.ts";
38
+ import { CustomExecutionPolicy } from "../../custom-execution-policy.ts";
39
+ import { createRun, listRuns } from "../../run-manager.ts";
40
+ import { readGraph, writeGraph } from "../../graph.ts";
41
+ import { validateDefinition } from "../../definition-loader.ts";
42
42
 
43
43
  // ─── Helpers ─────────────────────────────────────────────────────────────
44
44
 
@@ -26,10 +26,10 @@ import {
26
26
  createAutoWorktree,
27
27
  mergeMilestoneToMain,
28
28
  autoWorktreeBranch,
29
- } from "../auto-worktree.ts";
30
- import { captureIntegrationBranch, getSliceBranchName } from "../worktree.ts";
31
- import { writeIntegrationBranch, readIntegrationBranch } from "../git-service.ts";
32
- import { nextMilestoneId, generateMilestoneSuffix } from "../guided-flow.ts";
29
+ } from "../../auto-worktree.ts";
30
+ import { captureIntegrationBranch, getSliceBranchName } from "../../worktree.ts";
31
+ import { writeIntegrationBranch, readIntegrationBranch } from "../../git-service.ts";
32
+ import { nextMilestoneId, generateMilestoneSuffix } from "../../guided-flow.ts";
33
33
 
34
34
  // ─── Helpers ────────────────────────────────────────────────────────────────
35
35
 
@@ -12,9 +12,9 @@ import { join } from "node:path";
12
12
  import { tmpdir } from "node:os";
13
13
  import { execFileSync } from "node:child_process";
14
14
 
15
- import { GIT_NO_PROMPT_ENV } from "../git-constants.ts";
16
- import { nativeAddAllWithExclusions } from "../native-git-bridge.ts";
17
- import { RUNTIME_EXCLUSION_PATHS } from "../git-service.ts";
15
+ import { GIT_NO_PROMPT_ENV } from "../../git-constants.ts";
16
+ import { nativeAddAllWithExclusions } from "../../native-git-bridge.ts";
17
+ import { RUNTIME_EXCLUSION_PATHS } from "../../git-service.ts";
18
18
  function git(cwd: string, ...args: string[]): string {
19
19
  return execFileSync("git", args, { cwd, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }).trim();
20
20
  }
@@ -101,7 +101,7 @@ describe('git-locale', async () => {
101
101
  // We verify indirectly: the source code must pass env: GIT_NO_PROMPT_ENV.
102
102
  // Read the source and check for the pattern. This is a static check.
103
103
  const src = readFileSync(
104
- join(import.meta.dirname, "..", "native-git-bridge.ts"),
104
+ join(import.meta.dirname, "../..", "native-git-bridge.ts"),
105
105
  "utf-8"
106
106
  );
107
107
 
@@ -14,7 +14,7 @@ import assert from "node:assert/strict";
14
14
  import {
15
15
  abortAndReset,
16
16
  formatGitError,
17
- } from "../git-self-heal.js";
17
+ } from "../../git-self-heal.js";
18
18
 
19
19
  // ─── Helpers ─────────────────────────────────────────────────────────
20
20
 
@@ -20,8 +20,8 @@ import {
20
20
  type CommitOptions,
21
21
  type PreMergeCheckResult,
22
22
  type TaskCommitContext,
23
- } from "../git-service.ts";
24
- import { nativeAddAllWithExclusions } from "../native-git-bridge.ts";
23
+ } from "../../git-service.ts";
24
+ import { nativeAddAllWithExclusions } from "../../native-git-bridge.ts";
25
25
  function run(command: string, cwd: string): string {
26
26
  return execSync(command, { cwd, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }).trim();
27
27
  }
@@ -1113,7 +1113,7 @@ describe('git-service', async () => {
1113
1113
  // ─── untrackRuntimeFiles: removes tracked runtime files from index ───
1114
1114
 
1115
1115
  test('untrackRuntimeFiles', async () => {
1116
- const { untrackRuntimeFiles } = await import("../gitignore.ts");
1116
+ const { untrackRuntimeFiles } = await import("../../gitignore.ts");
1117
1117
  const repo = mkdtempSync(join(tmpdir(), "gsd-untrack-"));
1118
1118
  runGit(repo, ["init", "-b", "main"]);
1119
1119
  runGit(repo, ["config", "user.email", "test@test.com"]);
@@ -1222,7 +1222,7 @@ describe('git-service', async () => {
1222
1222
  // ─── ensureGitignore: always adds .gsd to gitignore ──────────────────
1223
1223
 
1224
1224
  test('ensureGitignore: adds .gsd entry', async () => {
1225
- const { ensureGitignore } = await import("../gitignore.ts");
1225
+ const { ensureGitignore } = await import("../../gitignore.ts");
1226
1226
  const repo = mkdtempSync(join(tmpdir(), "gsd-gitignore-external-state-"));
1227
1227
 
1228
1228
  // Should add .gsd to gitignore (external state dir is a symlink)
@@ -22,8 +22,8 @@ import {
22
22
  import { join } from "node:path";
23
23
  import { tmpdir } from "node:os";
24
24
 
25
- import { ensureGitignore, hasGitTrackedGsdFiles } from "../gitignore.ts";
26
- import { migrateToExternalState } from "../migrate-external.ts";
25
+ import { ensureGitignore, hasGitTrackedGsdFiles } from "../../gitignore.ts";
26
+ import { migrateToExternalState } from "../../migrate-external.ts";
27
27
 
28
28
  // ─── Helpers ─────────────────────────────────────────────────────────
29
29
 
@@ -7,7 +7,7 @@ import {
7
7
  writeBlockerPlaceholder,
8
8
  verifyExpectedArtifact,
9
9
  buildLoopRemediationSteps,
10
- } from "../auto-recovery.ts";
10
+ } from "../../auto-recovery.ts";
11
11
  import { describe, test, beforeEach, afterEach } from 'node:test';
12
12
  import assert from 'node:assert/strict';
13
13
 
@@ -299,7 +299,7 @@ test('writeBlockerPlaceholder: updates DB task status for execute-task (#2531)',
299
299
  const base = createFixtureBase();
300
300
  try {
301
301
  const { openDatabase, closeDatabase, insertMilestone, insertSlice, insertTask, getTask, isDbAvailable } =
302
- await import("../gsd-db.ts");
302
+ await import("../../gsd-db.ts");
303
303
 
304
304
  const dbPath = join(base, ".gsd", "gsd.db");
305
305
  // Create the tasks directory (required for artifact path resolution)
@@ -334,7 +334,7 @@ test('writeBlockerPlaceholder: does NOT update DB for non-execute-task types', a
334
334
  const base = createFixtureBase();
335
335
  try {
336
336
  const { openDatabase, closeDatabase, insertMilestone, insertSlice, getSlice, isDbAvailable } =
337
- await import("../gsd-db.ts");
337
+ await import("../../gsd-db.ts");
338
338
 
339
339
  const dbPath = join(base, ".gsd", "gsd.db");
340
340
  mkdirSync(join(base, ".gsd", "milestones", "M001", "slices", "S01"), { recursive: true });
@@ -24,7 +24,7 @@ import { join } from "node:path";
24
24
  import { tmpdir } from "node:os";
25
25
  import { execFileSync } from "node:child_process";
26
26
 
27
- import { isInheritedRepo } from "../repo-identity.ts";
27
+ import { isInheritedRepo } from "../../repo-identity.ts";
28
28
 
29
29
  function run(cmd: string, args: string[], cwd: string): string {
30
30
  return execFileSync(cmd, args, {
@@ -12,15 +12,15 @@ import { mkdtempSync, mkdirSync, rmSync, writeFileSync, readFileSync, appendFile
12
12
  import { join } from 'node:path';
13
13
  import { tmpdir } from 'node:os';
14
14
 
15
- import { openDatabase, closeDatabase, isDbAvailable, _getAdapter } from '../gsd-db.ts';
16
- import { migrateFromMarkdown, parseDecisionsTable } from '../md-importer.ts';
15
+ import { openDatabase, closeDatabase, isDbAvailable, _getAdapter } from '../../gsd-db.ts';
16
+ import { migrateFromMarkdown, parseDecisionsTable } from '../../md-importer.ts';
17
17
  import {
18
18
  queryDecisions,
19
19
  queryRequirements,
20
20
  formatDecisionsForPrompt,
21
21
  formatRequirementsForPrompt,
22
- } from '../context-store.ts';
23
- import { saveDecisionToDb, generateDecisionsMd } from '../db-writer.ts';
22
+ } from '../../context-store.ts';
23
+ import { saveDecisionToDb, generateDecisionsMd } from '../../db-writer.ts';
24
24
  import { describe, test, beforeEach, afterEach } from 'node:test';
25
25
  import assert from 'node:assert/strict';
26
26
 
@@ -11,15 +11,15 @@ import { execSync } from 'node:child_process';
11
11
  import { join } from 'node:path';
12
12
  import { tmpdir } from 'node:os';
13
13
 
14
- import { deriveState } from '../state.ts';
15
- import { indexWorkspace } from '../workspace-index.ts';
16
- import { inlinePriorMilestoneSummary } from '../files.ts';
17
- import { getPriorSliceCompletionBlocker } from '../dispatch-guard.ts';
14
+ import { deriveState } from '../../state.ts';
15
+ import { indexWorkspace } from '../../workspace-index.ts';
16
+ import { inlinePriorMilestoneSummary } from '../../files.ts';
17
+ import { getPriorSliceCompletionBlocker } from '../../dispatch-guard.ts';
18
18
  import {
19
19
  getSliceBranchName,
20
20
  parseSliceBranch,
21
- } from '../worktree.ts';
22
- import { clearPathCache } from '../paths.ts';
21
+ } from '../../worktree.ts';
22
+ import { clearPathCache } from '../../paths.ts';
23
23
  import { describe, test, beforeEach, afterEach } from 'node:test';
24
24
  import assert from 'node:assert/strict';
25
25
 
@@ -50,11 +50,11 @@ import {
50
50
  transaction,
51
51
  isDbAvailable,
52
52
  _getAdapter,
53
- } from "../gsd-db.ts";
53
+ } from "../../gsd-db.ts";
54
54
 
55
55
  // ── Tool handlers ─────────────────────────────────────────────────────────
56
- import { handleCompleteTask } from "../tools/complete-task.ts";
57
- import { handleCompleteSlice } from "../tools/complete-slice.ts";
56
+ import { handleCompleteTask } from "../../tools/complete-task.ts";
57
+ import { handleCompleteSlice } from "../../tools/complete-slice.ts";
58
58
 
59
59
  // ── Markdown renderer ─────────────────────────────────────────────────────
60
60
  import {
@@ -63,32 +63,32 @@ import {
63
63
  renderAllFromDb,
64
64
  detectStaleRenders,
65
65
  repairStaleRenders,
66
- } from "../markdown-renderer.ts";
66
+ } from "../../markdown-renderer.ts";
67
67
 
68
68
  // ── State derivation ──────────────────────────────────────────────────────
69
69
  import {
70
70
  deriveStateFromDb,
71
71
  _deriveStateImpl,
72
72
  invalidateStateCache,
73
- } from "../state.ts";
73
+ } from "../../state.ts";
74
74
 
75
75
  // ── Auto-migration ───────────────────────────────────────────────────────
76
76
  import {
77
77
  migrateHierarchyToDb,
78
78
  migrateFromMarkdown,
79
- } from "../md-importer.ts";
79
+ } from "../../md-importer.ts";
80
80
 
81
81
  // ── Post-unit diagnostics ─────────────────────────────────────────────────
82
- import { detectRogueFileWrites } from "../auto-post-unit.ts";
82
+ import { detectRogueFileWrites } from "../../auto-post-unit.ts";
83
83
 
84
84
  // ── Doctor ────────────────────────────────────────────────────────────────
85
- import { runGSDDoctor } from "../doctor.ts";
85
+ import { runGSDDoctor } from "../../doctor.ts";
86
86
 
87
87
  // ── Undo/reset ────────────────────────────────────────────────────────────
88
- import { handleUndoTask, handleResetSlice } from "../undo.ts";
88
+ import { handleUndoTask, handleResetSlice } from "../../undo.ts";
89
89
 
90
90
  // ── Cache invalidation ───────────────────────────────────────────────────
91
- import { invalidateAllCaches } from "../cache.ts";
91
+ import { invalidateAllCaches } from "../../cache.ts";
92
92
 
93
93
  // ═══════════════════════════════════════════════════════════════════════════
94
94
  // Helpers
@@ -400,7 +400,7 @@ test("full lifecycle: migration through completion through doctor", async (t) =>
400
400
  writeFileSync(join(rogueDir, "T99-SUMMARY.md"), "# Rogue Summary\n", "utf-8");
401
401
 
402
402
  // Clear path cache so resolveTaskFile sees the newly written file
403
- const { clearPathCache } = await import("../paths.ts");
403
+ const { clearPathCache } = await import("../../paths.ts");
404
404
  clearPathCache();
405
405
 
406
406
  const rogues = detectRogueFileWrites("execute-task", "M001/S01/T99", base);
@@ -458,7 +458,7 @@ test("recovery: DB loss → migrateFromMarkdown restores state, stale render det
458
458
  assert.equal(existsSync(dbPath), false, "DB file should be deleted");
459
459
 
460
460
  // Clear path caches so gsdRoot re-probes after DB deletion
461
- const { clearPathCache: clearPaths } = await import("../paths.ts");
461
+ const { clearPathCache: clearPaths } = await import("../../paths.ts");
462
462
  clearPaths();
463
463
  invalidateAllCaches();
464
464
 
@@ -13,8 +13,8 @@ import {
13
13
  transformToGSD,
14
14
  generatePreview,
15
15
  writeGSDDirectory,
16
- } from '../migrate/index.ts';
17
- import { deriveState } from '../state.ts';
16
+ } from '../../migrate/index.ts';
17
+ import { deriveState } from '../../state.ts';
18
18
  import { describe, test, beforeEach, afterEach } from 'node:test';
19
19
  import assert from 'node:assert/strict';
20
20
 
@@ -24,7 +24,7 @@ import {
24
24
  isInAutoWorktree,
25
25
  getAutoWorktreeOriginalBase,
26
26
  mergeMilestoneToMain,
27
- } from "../auto-worktree.ts";
27
+ } from "../../auto-worktree.ts";
28
28
 
29
29
  const __dirname = dirname(fileURLToPath(import.meta.url));
30
30
 
@@ -124,7 +124,7 @@ test("worktree swap on milestone transition: merge old, create new", () => {
124
124
 
125
125
  test("auto/phases.ts milestone transition block contains worktree lifecycle", () => {
126
126
  const phasesSrc = readFileSync(
127
- join(__dirname, "..", "auto", "phases.ts"),
127
+ join(__dirname, "../..", "auto", "phases.ts"),
128
128
  "utf-8",
129
129
  );
130
130
 
@@ -147,7 +147,7 @@ test("auto/phases.ts milestone transition block contains worktree lifecycle", ()
147
147
 
148
148
  test("worktree-resolver mergeAndExit preserves branch when roadmap is missing (#1573)", () => {
149
149
  const resolverSrc = readFileSync(
150
- join(__dirname, "..", "worktree-resolver.ts"),
150
+ join(__dirname, "../..", "worktree-resolver.ts"),
151
151
  "utf-8",
152
152
  );
153
153
 
@@ -32,12 +32,12 @@ import {
32
32
  mergeAllCompleted,
33
33
  formatMergeResults,
34
34
  type MergeResult,
35
- } from "../parallel-merge.ts";
36
- import type { WorkerInfo } from "../parallel-orchestrator.ts";
35
+ } from "../../parallel-merge.ts";
36
+ import type { WorkerInfo } from "../../parallel-orchestrator.ts";
37
37
  import {
38
38
  writeSessionStatus,
39
39
  readSessionStatus,
40
- } from "../session-status-io.ts";
40
+ } from "../../session-status-io.ts";
41
41
 
42
42
  // ─── Helpers ──────────────────────────────────────────────────────────────────
43
43
 
@@ -26,12 +26,12 @@ import {
26
26
  getWorkerBatches,
27
27
  hasActiveWorkers,
28
28
  resetWorkerRegistry,
29
- } from '../../subagent/worker-registry.ts';
29
+ } from '../../../subagent/worker-registry.ts';
30
30
  import {
31
31
  getBudgetAlertLevel,
32
32
  getNewBudgetAlertLevel,
33
33
  getBudgetEnforcementAction,
34
- } from '../auto-budget.ts';
34
+ } from '../../auto-budget.ts';
35
35
  import {
36
36
  type UnitMetrics,
37
37
  type MetricsLedger,
@@ -42,7 +42,7 @@ import {
42
42
  formatCostProjection,
43
43
  getAverageCostPerUnitType,
44
44
  predictRemainingCost,
45
- } from '../metrics.ts';
45
+ } from '../../metrics.ts';
46
46
 
47
47
  // ─── Fixture helpers ──────────────────────────────────────────────────────────
48
48
 
@@ -5,7 +5,7 @@ import { join } from "node:path";
5
5
  import { tmpdir } from "node:os";
6
6
  import { spawnSync } from "node:child_process";
7
7
 
8
- import { gsdRoot, _clearGsdRootCache } from "../paths.ts";
8
+ import { gsdRoot, _clearGsdRootCache } from "../../paths.ts";
9
9
  /** Create a tmp dir and resolve symlinks + 8.3 short names (macOS /var→/private/var, Windows RUNNER~1→runneradmin). */
10
10
  function tmp(): string {
11
11
  const p = mkdtempSync(join(tmpdir(), "gsd-paths-test-"));
@@ -11,8 +11,8 @@
11
11
 
12
12
  import { describe, it, before, after } from 'node:test';
13
13
  import assert from 'node:assert';
14
- import { PluginImporter, type DiscoveryResult, type ImportManifest } from '../plugin-importer.js';
15
- import { getMarketplaceFixtures } from './marketplace-test-fixtures.js';
14
+ import { PluginImporter, type DiscoveryResult, type ImportManifest } from '../../plugin-importer.js';
15
+ import { getMarketplaceFixtures } from '../marketplace-test-fixtures.ts';
16
16
 
17
17
  // ============================================================================
18
18
  // Live Test Configuration
@@ -15,9 +15,9 @@ import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
15
15
  import { join } from "node:path";
16
16
  import { tmpdir } from "node:os";
17
17
 
18
- import { buildExistingMilestonesContext } from "../guided-flow-queue.ts";
19
- import type { GSDState, MilestoneRegistryEntry } from "../types.ts";
20
- import { createTestContext } from "./test-helpers.ts";
18
+ import { buildExistingMilestonesContext } from "../../guided-flow-queue.ts";
19
+ import type { GSDState, MilestoneRegistryEntry } from "../../types.ts";
20
+ import { createTestContext } from "../test-helpers.ts";
21
21
 
22
22
  const { assertTrue, assertEq, report } = createTestContext();
23
23
 
@@ -17,10 +17,10 @@ import { mkdtempSync, mkdirSync, rmSync, writeFileSync, readFileSync, existsSync
17
17
  import { join } from 'node:path';
18
18
  import { tmpdir } from 'node:os';
19
19
 
20
- import { deriveState, invalidateStateCache } from '../state.ts';
21
- import { findMilestoneIds } from '../guided-flow.ts';
22
- import { saveQueueOrder, loadQueueOrder } from '../queue-order.ts';
23
- import { parseContextDependsOn } from '../files.ts';
20
+ import { deriveState, invalidateStateCache } from '../../state.ts';
21
+ import { findMilestoneIds } from '../../guided-flow.ts';
22
+ import { saveQueueOrder, loadQueueOrder } from '../../queue-order.ts';
23
+ import { parseContextDependsOn } from '../../files.ts';
24
24
  // ─── Fixture Helpers ───────────────────────────────────────────────────────
25
25
 
26
26
  function createFixtureBase(): string {
@@ -298,7 +298,7 @@ test('E2E: DB-backed path respects queue order (#2556)', async () => {
298
298
  // the dispatch guard (which respects queue order) blocked completion.
299
299
  const base = createFixtureBase();
300
300
  try {
301
- const { openDatabase, closeDatabase, insertMilestone, isDbAvailable } = await import('../gsd-db.ts');
301
+ const { openDatabase, closeDatabase, insertMilestone, isDbAvailable } = await import('../../gsd-db.ts');
302
302
  const dbPath = join(base, '.gsd', 'gsd.db');
303
303
 
304
304
  // Create milestone directories (required for findMilestoneIds)
@@ -14,8 +14,8 @@ import { join } from "node:path";
14
14
  import { tmpdir } from "node:os";
15
15
  import { execSync } from "node:child_process";
16
16
 
17
- import { captureIntegrationBranch, getCurrentBranch } from "../worktree.ts";
18
- import { readIntegrationBranch, QUICK_BRANCH_RE } from "../git-service.ts";
17
+ import { captureIntegrationBranch, getCurrentBranch } from "../../worktree.ts";
18
+ import { readIntegrationBranch, QUICK_BRANCH_RE } from "../../git-service.ts";
19
19
 
20
20
  function run(command: string, cwd: string): string {
21
21
  return execSync(command, { cwd, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }).trim();
@@ -139,7 +139,7 @@ test('cleanupQuickBranch: merges back and cleans up (same session)', async () =>
139
139
  // Import and call cleanupQuickBranch
140
140
  // Use dynamic import to get a fresh module scope — the in-memory state
141
141
  // won't be set, so it will fall through to disk recovery
142
- const { cleanupQuickBranch } = await import("../quick.ts");
142
+ const { cleanupQuickBranch } = await import("../../quick.ts");
143
143
  const result = cleanupQuickBranch();
144
144
 
145
145
  assert.ok(result, "cleanupQuickBranch returns true");
@@ -187,7 +187,7 @@ test('cleanupQuickBranch: recovers from disk state (cross-session)', async () =>
187
187
 
188
188
  process.chdir(repo);
189
189
 
190
- const { cleanupQuickBranch } = await import("../quick.ts");
190
+ const { cleanupQuickBranch } = await import("../../quick.ts");
191
191
  const result = cleanupQuickBranch();
192
192
 
193
193
  assert.ok(result, "cross-session recovery returns true");
@@ -207,7 +207,7 @@ test('cleanupQuickBranch: no-op without pending state', async () => {
207
207
  const origCwd = process.cwd();
208
208
  process.chdir(repo);
209
209
 
210
- const { cleanupQuickBranch } = await import("../quick.ts");
210
+ const { cleanupQuickBranch } = await import("../../quick.ts");
211
211
  const result = cleanupQuickBranch();
212
212
 
213
213
  assert.ok(!result, "returns false when no pending state");
@@ -5,12 +5,12 @@ import { join, dirname } from 'node:path';
5
5
  import { tmpdir } from 'node:os';
6
6
  import { fileURLToPath } from 'node:url';
7
7
 
8
- import { extractUatType } from '../files.ts';
9
- import { resolveSliceFile } from '../paths.ts';
10
- import { checkNeedsRunUat } from '../auto-prompts.ts';
8
+ import { extractUatType } from '../../files.ts';
9
+ import { resolveSliceFile } from '../../paths.ts';
10
+ import { checkNeedsRunUat } from '../../auto-prompts.ts';
11
11
 
12
12
  const __dirname = dirname(fileURLToPath(import.meta.url));
13
- const worktreePromptsDir = join(__dirname, '..', 'prompts');
13
+ const worktreePromptsDir = join(__dirname, '../..', 'prompts');
14
14
 
15
15
  function loadPromptFromWorktree(name: string, vars: Record<string, string> = {}): string {
16
16
  const path = join(worktreePromptsDir, `${name}.md`);
@@ -10,14 +10,14 @@ import { mkdtempSync, mkdirSync, rmSync, writeFileSync, readFileSync } from 'nod
10
10
  import { join } from 'node:path';
11
11
  import { tmpdir } from 'node:os';
12
12
 
13
- import { openDatabase, closeDatabase } from '../gsd-db.ts';
14
- import { migrateFromMarkdown } from '../md-importer.ts';
13
+ import { openDatabase, closeDatabase } from '../../gsd-db.ts';
14
+ import { migrateFromMarkdown } from '../../md-importer.ts';
15
15
  import {
16
16
  queryDecisions,
17
17
  queryRequirements,
18
18
  formatDecisionsForPrompt,
19
19
  formatRequirementsForPrompt,
20
- } from '../context-store.ts';
20
+ } from '../../context-store.ts';
21
21
  import { test } from 'node:test';
22
22
  import assert from 'node:assert/strict';
23
23
 
@@ -18,10 +18,10 @@ import { execSync } from "node:child_process";
18
18
  import {
19
19
  createAutoWorktree,
20
20
  mergeMilestoneToMain,
21
- } from "../auto-worktree.ts";
22
- import { getSliceBranchName } from "../worktree.ts";
23
- import { abortAndReset } from "../git-self-heal.ts";
24
- import { runGSDDoctor } from "../doctor.ts";
21
+ } from "../../auto-worktree.ts";
22
+ import { getSliceBranchName } from "../../worktree.ts";
23
+ import { abortAndReset } from "../../git-self-heal.ts";
24
+ import { runGSDDoctor } from "../../doctor.ts";
25
25
  import { describe, test } from 'node:test';
26
26
  import assert from 'node:assert/strict';
27
27
 
@@ -260,6 +260,61 @@ test("runDispatch emits dispatch-stop when dispatch returns stop action", async
260
260
  assert.equal(stopEvents[0].flowId, ic.flowId);
261
261
  });
262
262
 
263
+ test("runDispatch checks prior-slice completion against the project root in worktree mode", async () => {
264
+ const capture = createEventCapture();
265
+ const guardCalls: Array<{ fn: string; args: unknown[] }> = [];
266
+ const deps = makeMockDeps(capture, {
267
+ getMainBranch: (basePath: string) => {
268
+ guardCalls.push({ fn: "getMainBranch", args: [basePath] });
269
+ return "main";
270
+ },
271
+ getPriorSliceCompletionBlocker: (
272
+ basePath: string,
273
+ mainBranch: string,
274
+ unitType: string,
275
+ unitId: string,
276
+ ) => {
277
+ guardCalls.push({
278
+ fn: "getPriorSliceCompletionBlocker",
279
+ args: [basePath, mainBranch, unitType, unitId],
280
+ });
281
+ return null;
282
+ },
283
+ });
284
+ const ic = makeIC(deps, {
285
+ s: {
286
+ ...makeSession(),
287
+ basePath: "/tmp/project/.gsd/worktrees/M029-xoklo9",
288
+ originalBasePath: "/tmp/project",
289
+ } as any,
290
+ });
291
+ const preData: PreDispatchData = {
292
+ state: {
293
+ phase: "executing",
294
+ activeMilestone: { id: "M029-xoklo9", title: "Test", status: "active" },
295
+ activeSlice: { id: "S01", title: "Slice 1" },
296
+ registry: [{ id: "M029-xoklo9", status: "active" }],
297
+ blockers: [],
298
+ } as any,
299
+ mid: "M029-xoklo9",
300
+ midTitle: "Test Milestone",
301
+ };
302
+
303
+ const result = await runDispatch(ic, preData, {
304
+ recentUnits: [],
305
+ stuckRecoveryAttempts: 0,
306
+ });
307
+
308
+ assert.equal(result.action, "next");
309
+ assert.deepEqual(guardCalls, [
310
+ { fn: "getMainBranch", args: ["/tmp/project"] },
311
+ {
312
+ fn: "getPriorSliceCompletionBlocker",
313
+ args: ["/tmp/project", "main", "execute-task", "M001/S01/T01"],
314
+ },
315
+ ]);
316
+ });
317
+
263
318
  test("runUnitPhase emits unit-start and unit-end with causedBy reference", async () => {
264
319
  const capture = createEventCapture();
265
320
 
@@ -0,0 +1,60 @@
1
+ import { describe, it } from "node:test";
2
+ import assert from "node:assert";
3
+
4
+ /**
5
+ * Basic tests for the parallel monitor overlay data helpers.
6
+ * The overlay is primarily a rendering component that reads existing
7
+ * status files — these tests verify the helper logic in isolation.
8
+ */
9
+
10
+ describe("parallel-monitor-overlay", () => {
11
+ it("progressBar generates correct width", async () => {
12
+ // Dynamic import to test the module loads cleanly
13
+ const mod = await import("../parallel-monitor-overlay.js");
14
+ // Module should export the class
15
+ assert.ok(mod.ParallelMonitorOverlay, "ParallelMonitorOverlay class should be exported");
16
+ });
17
+
18
+ it("ParallelMonitorOverlay can be instantiated with mock tui", async () => {
19
+ const mod = await import("../parallel-monitor-overlay.js");
20
+
21
+ let renderRequested = false;
22
+ const mockTui = { requestRender: () => { renderRequested = true; } };
23
+ const mockTheme = {
24
+ fg: (_color: string, text: string) => text,
25
+ bold: (text: string) => text,
26
+ };
27
+ let closed = false;
28
+
29
+ const overlay = new mod.ParallelMonitorOverlay(
30
+ mockTui,
31
+ mockTheme as any,
32
+ () => { closed = true; },
33
+ "/nonexistent/path", // basePath — no real data, tests empty state
34
+ );
35
+
36
+ // Should render without throwing
37
+ const lines = overlay.render(80);
38
+ assert.ok(Array.isArray(lines), "render should return an array");
39
+ assert.ok(lines.length > 0, "render should return at least one line");
40
+
41
+ // Should contain header text
42
+ const joined = lines.join("\n");
43
+ assert.ok(joined.includes("Parallel Monitor"), "should include title");
44
+ assert.ok(joined.includes("No parallel workers found"), "should show empty state");
45
+
46
+ // Dispose should not throw
47
+ overlay.dispose();
48
+
49
+ // handleInput with ESC should call onClose
50
+ const overlay2 = new mod.ParallelMonitorOverlay(
51
+ mockTui,
52
+ mockTheme as any,
53
+ () => { closed = true; },
54
+ "/nonexistent/path",
55
+ );
56
+ overlay2.handleInput("q");
57
+ assert.ok(closed, "pressing q should trigger onClose");
58
+ overlay2.dispose();
59
+ });
60
+ });