gsd-pi 2.78.1-dev.b0759e59b → 2.78.1-dev.e9d88a536

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 (203) hide show
  1. package/README.md +8 -5
  2. package/dist/headless-recover.d.ts +23 -0
  3. package/dist/headless-recover.js +93 -0
  4. package/dist/headless.js +9 -0
  5. package/dist/help-text.js +1 -0
  6. package/dist/resources/.managed-resources-content-hash +1 -1
  7. package/dist/resources/extensions/browser-tools/tools/intent.js +8 -1
  8. package/dist/resources/extensions/gsd/auto-dispatch.js +4 -56
  9. package/dist/resources/extensions/gsd/auto-post-unit.js +7 -27
  10. package/dist/resources/extensions/gsd/auto-start.js +1 -8
  11. package/dist/resources/extensions/gsd/auto-worktree.js +59 -176
  12. package/dist/resources/extensions/gsd/auto.js +24 -6
  13. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +9 -77
  14. package/dist/resources/extensions/gsd/commands-codebase.js +2 -2
  15. package/dist/resources/extensions/gsd/commands-handlers.js +5 -5
  16. package/dist/resources/extensions/gsd/commands-logs.js +2 -2
  17. package/dist/resources/extensions/gsd/commands-scan.js +2 -2
  18. package/dist/resources/extensions/gsd/commands-ship.js +2 -2
  19. package/dist/resources/extensions/gsd/commands-workflow-templates.js +5 -5
  20. package/dist/resources/extensions/gsd/db-writer.js +16 -85
  21. package/dist/resources/extensions/gsd/dispatch-guard.js +6 -10
  22. package/dist/resources/extensions/gsd/doctor-engine-checks.js +2 -2
  23. package/dist/resources/extensions/gsd/gsd-db.js +74 -8
  24. package/dist/resources/extensions/gsd/guided-flow.js +31 -8
  25. package/dist/resources/extensions/gsd/markdown-renderer.js +14 -51
  26. package/dist/resources/extensions/gsd/parallel-merge.js +14 -13
  27. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +5 -2
  28. package/dist/resources/extensions/gsd/paths.js +35 -1
  29. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +6 -0
  30. package/dist/resources/extensions/gsd/queue-order.js +6 -1
  31. package/dist/resources/extensions/gsd/rethink.js +2 -2
  32. package/dist/resources/extensions/gsd/state.js +91 -372
  33. package/dist/resources/extensions/gsd/tools/complete-milestone.js +6 -5
  34. package/dist/resources/extensions/gsd/tools/complete-slice.js +7 -12
  35. package/dist/resources/extensions/gsd/tools/complete-task.js +19 -31
  36. package/dist/resources/extensions/gsd/tools/validate-milestone.js +7 -5
  37. package/dist/resources/extensions/gsd/workflow-manifest.js +2 -1
  38. package/dist/resources/extensions/gsd/workflow-mcp-auto-prep.js +3 -21
  39. package/dist/resources/extensions/gsd/workflow-reconcile.js +3 -3
  40. package/dist/resources/extensions/gsd/worktree-command.js +4 -3
  41. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  42. package/dist/web/standalone/.next/BUILD_ID +1 -1
  43. package/dist/web/standalone/.next/app-path-routes-manifest.json +12 -12
  44. package/dist/web/standalone/.next/build-manifest.json +2 -2
  45. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  46. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  47. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  48. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  49. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  50. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  51. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  52. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  53. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  54. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  55. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  56. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  57. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  58. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  59. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  60. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  61. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  62. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  63. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  64. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  65. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  66. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  67. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  68. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  69. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  70. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  71. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  72. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  73. package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
  74. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  75. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  76. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  77. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  78. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  79. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  80. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  81. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  82. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  83. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  84. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  85. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  86. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  87. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  88. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  89. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  90. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  91. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  92. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  93. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  94. package/dist/web/standalone/.next/server/app/index.html +1 -1
  95. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  100. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  101. package/dist/web/standalone/.next/server/app-paths-manifest.json +12 -12
  102. package/dist/web/standalone/.next/server/chunks/6336.js +1 -0
  103. package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
  104. package/dist/web/standalone/.next/server/middleware-build-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 +1 -1
  107. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  108. package/package.json +1 -1
  109. package/packages/mcp-server/dist/workflow-tools.d.ts +6 -0
  110. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  111. package/packages/mcp-server/dist/workflow-tools.js +56 -2
  112. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  113. package/packages/mcp-server/src/parse-workflow-args.test.ts +80 -0
  114. package/packages/mcp-server/src/workflow-tools.ts +61 -2
  115. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  116. package/src/resources/extensions/browser-tools/tools/intent.ts +13 -2
  117. package/src/resources/extensions/gsd/auto-dispatch.ts +4 -60
  118. package/src/resources/extensions/gsd/auto-post-unit.ts +7 -26
  119. package/src/resources/extensions/gsd/auto-start.ts +1 -8
  120. package/src/resources/extensions/gsd/auto-worktree.ts +61 -204
  121. package/src/resources/extensions/gsd/auto.ts +23 -6
  122. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +9 -84
  123. package/src/resources/extensions/gsd/commands-codebase.ts +2 -2
  124. package/src/resources/extensions/gsd/commands-handlers.ts +5 -5
  125. package/src/resources/extensions/gsd/commands-logs.ts +2 -2
  126. package/src/resources/extensions/gsd/commands-scan.ts +2 -2
  127. package/src/resources/extensions/gsd/commands-ship.ts +2 -2
  128. package/src/resources/extensions/gsd/commands-workflow-templates.ts +5 -5
  129. package/src/resources/extensions/gsd/db-writer.ts +16 -83
  130. package/src/resources/extensions/gsd/dispatch-guard.ts +6 -11
  131. package/src/resources/extensions/gsd/doctor-engine-checks.ts +2 -2
  132. package/src/resources/extensions/gsd/gsd-db.ts +85 -8
  133. package/src/resources/extensions/gsd/guided-flow.ts +35 -8
  134. package/src/resources/extensions/gsd/markdown-renderer.ts +13 -64
  135. package/src/resources/extensions/gsd/parallel-merge.ts +14 -13
  136. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +5 -2
  137. package/src/resources/extensions/gsd/paths.ts +55 -1
  138. package/src/resources/extensions/gsd/prompts/plan-milestone.md +6 -0
  139. package/src/resources/extensions/gsd/queue-order.ts +6 -1
  140. package/src/resources/extensions/gsd/rethink.ts +2 -2
  141. package/src/resources/extensions/gsd/state.ts +91 -389
  142. package/src/resources/extensions/gsd/tests/artifact-corruption-2630.test.ts +1 -0
  143. package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +6 -0
  144. package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +21 -34
  145. package/src/resources/extensions/gsd/tests/complete-task-rollback-evidence.test.ts +6 -7
  146. package/src/resources/extensions/gsd/tests/complete-task.test.ts +8 -6
  147. package/src/resources/extensions/gsd/tests/completed-at-reconcile.test.ts +12 -27
  148. package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +18 -5
  149. package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +4 -4
  150. package/src/resources/extensions/gsd/tests/db-writer.test.ts +14 -16
  151. package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +6 -5
  152. package/src/resources/extensions/gsd/tests/derive-state-db-disk-reconcile.test.ts +10 -38
  153. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +136 -56
  154. package/src/resources/extensions/gsd/tests/derive-state-draft.test.ts +3 -0
  155. package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +119 -61
  156. package/src/resources/extensions/gsd/tests/derive-state.test.ts +4 -0
  157. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +6 -20
  158. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +4 -5
  159. package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +14 -15
  160. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +11 -16
  161. package/src/resources/extensions/gsd/tests/escalation.test.ts +2 -1
  162. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +2 -1
  163. package/src/resources/extensions/gsd/tests/gsdroot-worktree-detection.test.ts +15 -36
  164. package/src/resources/extensions/gsd/tests/handler-worktree-write-isolation.test.ts +57 -0
  165. package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +15 -15
  166. package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +15 -5
  167. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +14 -8
  168. package/src/resources/extensions/gsd/tests/md-importer.test.ts +2 -1
  169. package/src/resources/extensions/gsd/tests/memory-store.test.ts +3 -2
  170. package/src/resources/extensions/gsd/tests/park-milestone.test.ts +2 -0
  171. package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +25 -16
  172. package/src/resources/extensions/gsd/tests/projection-regression.test.ts +1 -0
  173. package/src/resources/extensions/gsd/tests/ready-phrase-no-files-4573.test.ts +184 -0
  174. package/src/resources/extensions/gsd/tests/register-hooks-compaction-checkpoint.test.ts +6 -1
  175. package/src/resources/extensions/gsd/tests/replan-slice.test.ts +3 -0
  176. package/src/resources/extensions/gsd/tests/resolve-ts.mjs +4 -0
  177. package/src/resources/extensions/gsd/tests/rogue-file-detection.test.ts +3 -4
  178. package/src/resources/extensions/gsd/tests/slice-disk-reconcile.test.ts +10 -56
  179. package/src/resources/extensions/gsd/tests/stale-slice-rows.test.ts +15 -16
  180. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +1 -0
  181. package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +23 -27
  182. package/src/resources/extensions/gsd/tests/steer-worktree-path.test.ts +13 -14
  183. package/src/resources/extensions/gsd/tests/stop-auto-remote.test.ts +4 -3
  184. package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +10 -33
  185. package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +7 -8
  186. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +9 -15
  187. package/src/resources/extensions/gsd/tests/workflow-logger-wiring.test.ts +12 -7
  188. package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +4 -4
  189. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +24 -1
  190. package/src/resources/extensions/gsd/tests/worktree-db-same-file.test.ts +13 -0
  191. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +65 -71
  192. package/src/resources/extensions/gsd/tests/worktree-sync-tasks.test.ts +26 -151
  193. package/src/resources/extensions/gsd/tools/complete-milestone.ts +7 -5
  194. package/src/resources/extensions/gsd/tools/complete-slice.ts +7 -14
  195. package/src/resources/extensions/gsd/tools/complete-task.ts +19 -34
  196. package/src/resources/extensions/gsd/tools/validate-milestone.ts +7 -5
  197. package/src/resources/extensions/gsd/workflow-manifest.ts +4 -1
  198. package/src/resources/extensions/gsd/workflow-mcp-auto-prep.ts +2 -18
  199. package/src/resources/extensions/gsd/workflow-reconcile.ts +3 -3
  200. package/src/resources/extensions/gsd/worktree-command.ts +4 -3
  201. package/dist/web/standalone/.next/server/chunks/8527.js +0 -1
  202. /package/dist/web/standalone/.next/static/{rk1EN3FQTE6Z1yalkW_GE → oZGTPvJBQX_IDKKnuV8Bt}/_buildManifest.js +0 -0
  203. /package/dist/web/standalone/.next/static/{rk1EN3FQTE6Z1yalkW_GE → oZGTPvJBQX_IDKKnuV8Bt}/_ssgManifest.js +0 -0
@@ -8,7 +8,7 @@ import { existsSync, readdirSync } from "node:fs";
8
8
  import { join } from "node:path";
9
9
  import { spawnSync } from "node:child_process";
10
10
  import { loadFile } from "./files.js";
11
- import { resolveMilestoneFile } from "./paths.js";
11
+ import { resolveGsdPathContract, resolveMilestoneFile } from "./paths.js";
12
12
  import { mergeMilestoneToMain } from "./auto-worktree.js";
13
13
  import { MergeConflictError } from "./git-service.js";
14
14
  import { removeSessionStatus } from "./session-status-io.js";
@@ -16,12 +16,13 @@ import { getErrorMessage } from "./error-utils.js";
16
16
  import { logWarning } from "./workflow-logger.js";
17
17
  // ─── Merge Queue ───────────────────────────────────────────────────────────
18
18
  /**
19
- * Check whether a milestone is complete by querying its worktree SQLite DB.
19
+ * Check whether a milestone is complete by querying the canonical project DB.
20
20
  * Uses a subprocess to avoid disrupting the global DB singleton.
21
- * Returns true when milestones.status = 'complete' in the worktree's gsd.db.
21
+ * Returns true when milestones.status = 'complete' in project gsd.db.
22
22
  */
23
- export function isMilestoneCompleteInWorktreeDb(basePath, mid) {
24
- const dbPath = join(basePath, ".gsd", "worktrees", mid, ".gsd", "gsd.db");
23
+ export function isMilestoneCompleteInProjectDb(basePath, mid) {
24
+ const workRoot = join(basePath, ".gsd", "worktrees", mid);
25
+ const dbPath = resolveGsdPathContract(workRoot, basePath).projectDb;
25
26
  if (!existsSync(dbPath))
26
27
  return false;
27
28
  try {
@@ -34,15 +35,15 @@ export function isMilestoneCompleteInWorktreeDb(basePath, mid) {
34
35
  }
35
36
  }
36
37
  /**
37
- * Discover milestone IDs with status='complete' in their worktree DB,
38
- * scanning .gsd/worktrees/<MID>/.gsd/gsd.db for each worktree directory.
38
+ * Discover milestone IDs with status='complete' in the canonical DB,
39
+ * using worktree directories only to enumerate active parallel workers.
39
40
  */
40
41
  function discoverDbCompletedMilestones(basePath) {
41
42
  const completed = new Set();
42
43
  const worktreeDir = join(basePath, ".gsd", "worktrees");
43
44
  try {
44
45
  for (const entry of readdirSync(worktreeDir)) {
45
- if (entry.startsWith("M") && isMilestoneCompleteInWorktreeDb(basePath, entry)) {
46
+ if (entry.startsWith("M") && isMilestoneCompleteInProjectDb(basePath, entry)) {
46
47
  completed.add(entry);
47
48
  }
48
49
  }
@@ -57,15 +58,15 @@ function discoverDbCompletedMilestones(basePath) {
57
58
  * Sequential: merge in milestone ID order (M001 before M002).
58
59
  * By-completion: merge in the order milestones finished.
59
60
  *
60
- * When basePath is provided, also checks worktree SQLite DBs as the
61
- * source of truth workers with stale orchestrator state (e.g. "error")
62
- * are included if their worktree DB shows status='complete'.
61
+ * When basePath is provided, also checks the canonical project DB as the
62
+ * source of truth. Workers with stale orchestrator state (e.g. "error")
63
+ * are included if their project DB row shows status='complete'.
63
64
  * See: https://github.com/gsd-build/gsd-2/issues/2812
64
65
  */
65
66
  export function determineMergeOrder(workers, order = "sequential", basePath) {
66
67
  // Start with workers the orchestrator already knows are stopped
67
68
  const stoppedIds = new Set(workers.filter(w => w.state === "stopped").map(w => w.milestoneId));
68
- // When basePath is available, also check worktree DBs for milestones
69
+ // When basePath is available, also check the project DB for milestones
69
70
  // whose orchestrator state is stale but are actually complete (#2812)
70
71
  const dbCompleted = basePath ? discoverDbCompletedMilestones(basePath) : new Set();
71
72
  // Union: milestone is mergeable if stopped OR DB-complete
@@ -80,7 +81,7 @@ export function determineMergeOrder(workers, order = "sequential", basePath) {
80
81
  allMergeable.push(w);
81
82
  }
82
83
  else {
83
- // Milestone discovered from worktree DB but not in workers list
84
+ // Milestone discovered from project DB but not in workers list
84
85
  allMergeable.push({
85
86
  milestoneId: mid,
86
87
  title: mid,
@@ -13,6 +13,7 @@ import { spawnSync } from "node:child_process";
13
13
  import { matchesKey, Key } from "@gsd/pi-tui";
14
14
  import { formatDuration } from "../shared/mod.js";
15
15
  import { formattedShortcutPair } from "./shortcut-defs.js";
16
+ import { resolveGsdPathContract } from "./paths.js";
16
17
  // ─── Data Helpers ─────────────────────────────────────────────────────────
17
18
  function readJsonSafe(filePath) {
18
19
  try {
@@ -74,7 +75,8 @@ function discoverWorkers(basePath) {
74
75
  return [...mids].sort();
75
76
  }
76
77
  function querySliceProgress(basePath, mid) {
77
- const dbPath = join(basePath, ".gsd", "worktrees", mid, ".gsd", "gsd.db");
78
+ const workRoot = join(basePath, ".gsd", "worktrees", mid);
79
+ const dbPath = resolveGsdPathContract(workRoot, basePath).projectDb;
78
80
  if (!existsSync(dbPath))
79
81
  return [];
80
82
  try {
@@ -119,7 +121,8 @@ function extractCostFromNdjson(basePath, mid) {
119
121
  }
120
122
  }
121
123
  function queryRecentCompletions(basePath, mid) {
122
- const dbPath = join(basePath, ".gsd", "worktrees", mid, ".gsd", "gsd.db");
124
+ const workRoot = join(basePath, ".gsd", "worktrees", mid);
125
+ const dbPath = resolveGsdPathContract(workRoot, basePath).projectDb;
123
126
  if (!existsSync(dbPath))
124
127
  return [];
125
128
  try {
@@ -9,12 +9,13 @@
9
9
  * via prefix matching, so existing projects work without migration.
10
10
  */
11
11
  import { readdirSync, existsSync, realpathSync, Dirent } from "node:fs";
12
- import { join, dirname, normalize } from "node:path";
12
+ import { join, dirname, normalize, resolve } from "node:path";
13
13
  import { homedir } from "node:os";
14
14
  import { spawnSync } from "node:child_process";
15
15
  import { nativeScanGsdTree } from "./native-parser-bridge.js";
16
16
  import { DIR_CACHE_MAX } from "./constants.js";
17
17
  import { gsdHome } from "./gsd-home.js";
18
+ import { isGsdWorktreePath, resolveWorktreeProjectRoot } from "./worktree-root.js";
18
19
  // ─── Directory Listing Cache ──────────────────────────────────────────────────
19
20
  const dirEntryCache = new Map();
20
21
  const dirListCache = new Map();
@@ -270,6 +271,36 @@ const LEGACY_GSD_ROOT_FILES = {
270
271
  };
271
272
  // ─── GSD Root Discovery ───────────────────────────────────────────────────────
272
273
  const gsdRootCache = new Map();
274
+ export function resolveGsdPathContract(workRoot, originalProjectRoot) {
275
+ const resolvedWorkRoot = resolve(workRoot || process.cwd());
276
+ const isWorktree = isGsdWorktreePath(resolvedWorkRoot);
277
+ if (isWorktree && !originalProjectRoot?.trim()) {
278
+ const externalMatch = /[/\\]\.gsd[/\\]projects[/\\][^/\\]+[/\\]worktrees(?:[/\\]|$)/.exec(resolvedWorkRoot);
279
+ if (externalMatch) {
280
+ const worktreesIdx = externalMatch[0].search(/[/\\]worktrees(?:[/\\]|$)/);
281
+ const projectGsd = resolvedWorkRoot.slice(0, externalMatch.index + worktreesIdx);
282
+ return {
283
+ projectRoot: dirname(dirname(projectGsd)),
284
+ workRoot: resolvedWorkRoot,
285
+ projectGsd,
286
+ worktreeGsd: join(resolvedWorkRoot, ".gsd"),
287
+ projectDb: join(projectGsd, "gsd.db"),
288
+ isWorktree,
289
+ };
290
+ }
291
+ }
292
+ const projectRoot = resolve(resolveWorktreeProjectRoot(resolvedWorkRoot, originalProjectRoot));
293
+ const projectGsd = join(projectRoot, ".gsd");
294
+ const worktreeGsd = isWorktree ? join(resolvedWorkRoot, ".gsd") : null;
295
+ return {
296
+ projectRoot,
297
+ workRoot: resolvedWorkRoot,
298
+ projectGsd,
299
+ worktreeGsd,
300
+ projectDb: join(projectGsd, "gsd.db"),
301
+ isWorktree,
302
+ };
303
+ }
273
304
  /** Exported for tests only — do not call in production code. */
274
305
  export function _clearGsdRootCache() {
275
306
  gsdRootCache.clear();
@@ -362,6 +393,9 @@ function isInsideGsdWorktree(p) {
362
393
  return false;
363
394
  }
364
395
  function probeGsdRoot(rawBasePath) {
396
+ const contract = resolveGsdPathContract(rawBasePath);
397
+ if (contract.isWorktree)
398
+ return contract.projectGsd;
365
399
  // 1. Fast path — check the input path directly
366
400
  const local = join(rawBasePath, ".gsd");
367
401
  if (existsSync(local))
@@ -10,6 +10,12 @@ All relevant context has been preloaded below — start working immediately with
10
10
 
11
11
  {{inlinedContext}}
12
12
 
13
+ ## Already Planned? Soft Brake
14
+
15
+ If `{{outputPath}}` already exists on disk with at least one slice line (e.g. `- [ ] **S01:`) AND `gsd_query` reports slice rows for this milestone, a prior `gsd_plan_milestone` call already persisted the plan. Do **not** re-call `gsd_plan_milestone` — its UPSERT would overwrite the existing plan with whatever you reconstruct, which is unsafe when you don't have the original decomposition reasoning. Skip directly to the ready phrase at the end of this prompt.
16
+
17
+ If only the file exists (no DB rows) or only DB rows exist (no file), the prior write was incomplete — proceed with planning as normal so the tool reconciles both.
18
+
13
19
  ## Your Role in the Pipeline
14
20
 
15
21
  You are the first deep look at this milestone. You have full tool access — explore the codebase, look up docs, investigate technology choices. Your job is to understand the landscape and then strategically decompose the work into demoable slices.
@@ -12,6 +12,7 @@ import { join } from "node:path";
12
12
  import { gsdRoot } from "./paths.js";
13
13
  import { milestoneIdSort } from "./milestone-ids.js";
14
14
  import { loadJsonFileOrNull, saveJsonFile } from "./json-persistence.js";
15
+ import { isDbAvailable, setMilestoneQueueOrder } from "./gsd-db.js";
15
16
  // ─── Path ────────────────────────────────────────────────────────────────────
16
17
  function queueOrderPath(basePath) {
17
18
  return join(gsdRoot(basePath), "QUEUE-ORDER.json");
@@ -30,9 +31,13 @@ export function loadQueueOrder(basePath) {
30
31
  return data?.order ?? null;
31
32
  }
32
33
  /**
33
- * Save a custom queue order to disk.
34
+ * Save a custom queue order. The DB sequence is canonical when a DB
35
+ * connection is open; QUEUE-ORDER.json remains a compatibility projection.
34
36
  */
35
37
  export function saveQueueOrder(basePath, order) {
38
+ if (isDbAvailable()) {
39
+ setMilestoneQueueOrder(order);
40
+ }
36
41
  const data = {
37
42
  order,
38
43
  updatedAt: new Date().toISOString(),
@@ -17,14 +17,14 @@ import { getMilestoneSlices, isDbAvailable } from "./gsd-db.js";
17
17
  import { buildExistingMilestonesContext } from "./guided-flow-queue.js";
18
18
  import { loadPrompt } from "./prompt-loader.js";
19
19
  import { isGsdGitignored } from "./gitignore.js";
20
- import { projectRoot } from "./commands/context.js";
20
+ import { currentDirectoryRoot } from "./commands/context.js";
21
21
  // ─── Entry Point ──────────────────────────────────────────────────────────────
22
22
  export async function handleRethink(_args, ctx, pi) {
23
23
  if (isAutoActive()) {
24
24
  ctx.ui.notify("Cannot rethink while auto-mode is active. Stop auto-mode first.", "error");
25
25
  return;
26
26
  }
27
- const basePath = projectRoot();
27
+ const basePath = currentDirectoryRoot();
28
28
  const root = gsdRoot(basePath);
29
29
  if (!existsSync(root)) {
30
30
  ctx.ui.notify("No GSD project found. Run /gsd init first.", "warning");