gsd-pi 2.80.0-dev.2848d9009 → 2.80.0-dev.42bd34838

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 (241) hide show
  1. package/README.md +4 -2
  2. package/dist/resources/.managed-resources-content-hash +1 -1
  3. package/dist/resources/extensions/gsd/auto/loop.js +32 -1
  4. package/dist/resources/extensions/gsd/auto/phases.js +29 -15
  5. package/dist/resources/extensions/gsd/auto/resolve.js +17 -0
  6. package/dist/resources/extensions/gsd/auto/run-unit.js +13 -1
  7. package/dist/resources/extensions/gsd/auto-prompts.js +13 -1
  8. package/dist/resources/extensions/gsd/auto-recovery.js +43 -1
  9. package/dist/resources/extensions/gsd/auto-supervisor.js +8 -1
  10. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +2 -2
  11. package/dist/resources/extensions/gsd/auto.js +68 -4
  12. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +21 -2
  13. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +27 -20
  14. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +21 -0
  15. package/dist/resources/extensions/gsd/context-budget.js +37 -2
  16. package/dist/resources/extensions/gsd/crash-recovery.js +56 -10
  17. package/dist/resources/extensions/gsd/db/unit-dispatches.js +39 -0
  18. package/dist/resources/extensions/gsd/db-base-schema.js +4 -2
  19. package/dist/resources/extensions/gsd/db-migration-steps.js +6 -0
  20. package/dist/resources/extensions/gsd/git-service.js +36 -4
  21. package/dist/resources/extensions/gsd/gsd-db.js +46 -13
  22. package/dist/resources/extensions/gsd/guided-flow.js +52 -10
  23. package/dist/resources/extensions/gsd/memory-store.js +69 -12
  24. package/dist/resources/extensions/gsd/migrate/command.js +40 -1
  25. package/dist/resources/extensions/gsd/migration-auto-check.js +87 -0
  26. package/dist/resources/extensions/gsd/planning-path-scope.js +26 -0
  27. package/dist/resources/extensions/gsd/prompt-loader.js +28 -2
  28. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +14 -13
  29. package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +1 -1
  30. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  31. package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -5
  32. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
  33. package/dist/resources/extensions/gsd/quick.js +34 -2
  34. package/dist/resources/extensions/gsd/tools/context-mode-tool-result.js +15 -0
  35. package/dist/resources/extensions/gsd/tools/exec-search-tool.js +5 -0
  36. package/dist/resources/extensions/gsd/tools/exec-tool.js +3 -15
  37. package/dist/resources/extensions/gsd/tools/memory-tools.js +1 -0
  38. package/dist/resources/extensions/gsd/tools/plan-slice.js +9 -0
  39. package/dist/resources/extensions/gsd/tools/plan-task.js +9 -0
  40. package/dist/resources/extensions/gsd/tools/resume-tool.js +5 -0
  41. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +1 -1
  42. package/dist/resources/extensions/gsd/unit-context-composer.js +12 -3
  43. package/dist/resources/extensions/gsd/unit-runtime.js +22 -0
  44. package/dist/resources/extensions/gsd/worktree-resolver.js +33 -17
  45. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  46. package/dist/web/standalone/.next/BUILD_ID +1 -1
  47. package/dist/web/standalone/.next/app-path-routes-manifest.json +11 -11
  48. package/dist/web/standalone/.next/build-manifest.json +2 -2
  49. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  50. package/dist/web/standalone/.next/required-server-files.json +1 -1
  51. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  52. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  53. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  54. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  55. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  56. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  57. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  58. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  59. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  60. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  61. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  62. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  63. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  64. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  65. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  66. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  67. package/dist/web/standalone/.next/server/app/index.html +1 -1
  68. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  69. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  70. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  71. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  72. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  73. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  74. package/dist/web/standalone/.next/server/app-paths-manifest.json +11 -11
  75. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  76. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  77. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  78. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  79. package/dist/web/standalone/server.js +1 -1
  80. package/package.json +3 -3
  81. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  82. package/packages/mcp-server/dist/workflow-tools.js +22 -17
  83. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  84. package/packages/mcp-server/src/workflow-tools.test.ts +75 -2
  85. package/packages/mcp-server/src/workflow-tools.ts +30 -16
  86. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  87. package/packages/native/tsconfig.tsbuildinfo +1 -1
  88. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +32 -0
  89. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
  90. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  91. package/packages/pi-coding-agent/dist/core/agent-session.js +8 -0
  92. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  93. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +3 -1
  94. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
  95. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +11 -0
  96. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  97. package/packages/pi-coding-agent/dist/core/compaction/compaction.js +9 -0
  98. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  99. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.d.ts +2 -0
  100. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.d.ts.map +1 -0
  101. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.js +103 -0
  102. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.js.map +1 -0
  103. package/packages/pi-coding-agent/dist/core/db-snapshot.d.ts +15 -0
  104. package/packages/pi-coding-agent/dist/core/db-snapshot.d.ts.map +1 -0
  105. package/packages/pi-coding-agent/dist/core/db-snapshot.js +66 -0
  106. package/packages/pi-coding-agent/dist/core/db-snapshot.js.map +1 -0
  107. package/packages/pi-coding-agent/dist/core/db-snapshot.test.d.ts +2 -0
  108. package/packages/pi-coding-agent/dist/core/db-snapshot.test.d.ts.map +1 -0
  109. package/packages/pi-coding-agent/dist/core/db-snapshot.test.js +24 -0
  110. package/packages/pi-coding-agent/dist/core/db-snapshot.test.js.map +1 -0
  111. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +1 -0
  112. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  113. package/packages/pi-coding-agent/dist/core/extensions/runner.js +3 -0
  114. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  115. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +2 -0
  116. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
  117. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +7 -0
  118. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  119. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  120. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +20 -0
  121. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  122. package/packages/pi-coding-agent/dist/core/settings-manager.js +25 -0
  123. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  124. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +1 -0
  125. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  126. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +3 -0
  127. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  128. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  129. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +13 -5
  130. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  131. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js +53 -0
  132. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js.map +1 -1
  133. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  134. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +3 -0
  135. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  136. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.d.ts +2 -0
  137. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.d.ts.map +1 -0
  138. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js +10 -0
  139. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js.map +1 -0
  140. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.d.ts.map +1 -1
  141. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js +3 -2
  142. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js.map +1 -1
  143. package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +36 -0
  144. package/packages/pi-coding-agent/src/core/agent-session.ts +8 -0
  145. package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +3 -1
  146. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +18 -0
  147. package/packages/pi-coding-agent/src/core/compaction-threshold.test.ts +121 -0
  148. package/packages/pi-coding-agent/src/core/db-snapshot.test.ts +32 -0
  149. package/packages/pi-coding-agent/src/core/db-snapshot.ts +66 -0
  150. package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +2 -0
  151. package/packages/pi-coding-agent/src/core/extensions/runner.ts +3 -0
  152. package/packages/pi-coding-agent/src/core/extensions/types.ts +7 -0
  153. package/packages/pi-coding-agent/src/core/settings-manager.ts +39 -1
  154. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +4 -0
  155. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.test.ts +56 -0
  156. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +22 -7
  157. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +3 -0
  158. package/packages/pi-coding-agent/src/resources/extensions/memory/storage-safety-guard.test.ts +14 -0
  159. package/packages/pi-coding-agent/src/resources/extensions/memory/storage.ts +3 -2
  160. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  161. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  162. package/packages/pi-tui/dist/tui.js +18 -8
  163. package/packages/pi-tui/dist/tui.js.map +1 -1
  164. package/packages/pi-tui/src/tui.ts +20 -8
  165. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  166. package/src/resources/extensions/gsd/auto/loop.ts +50 -8
  167. package/src/resources/extensions/gsd/auto/phases.ts +35 -20
  168. package/src/resources/extensions/gsd/auto/resolve.ts +23 -1
  169. package/src/resources/extensions/gsd/auto/run-unit.ts +18 -1
  170. package/src/resources/extensions/gsd/auto-prompts.ts +17 -1
  171. package/src/resources/extensions/gsd/auto-recovery.ts +54 -0
  172. package/src/resources/extensions/gsd/auto-supervisor.ts +7 -0
  173. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +2 -2
  174. package/src/resources/extensions/gsd/auto.ts +80 -3
  175. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +21 -1
  176. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +27 -19
  177. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +22 -0
  178. package/src/resources/extensions/gsd/context-budget.ts +44 -2
  179. package/src/resources/extensions/gsd/crash-recovery.ts +67 -10
  180. package/src/resources/extensions/gsd/db/unit-dispatches.ts +41 -0
  181. package/src/resources/extensions/gsd/db-base-schema.ts +4 -2
  182. package/src/resources/extensions/gsd/db-migration-steps.ts +8 -0
  183. package/src/resources/extensions/gsd/git-service.ts +46 -8
  184. package/src/resources/extensions/gsd/gsd-db.ts +50 -13
  185. package/src/resources/extensions/gsd/guided-flow.ts +71 -10
  186. package/src/resources/extensions/gsd/memory-store.ts +77 -12
  187. package/src/resources/extensions/gsd/migrate/command.ts +47 -1
  188. package/src/resources/extensions/gsd/migration-auto-check.ts +129 -0
  189. package/src/resources/extensions/gsd/planning-path-scope.ts +35 -0
  190. package/src/resources/extensions/gsd/preferences-types.ts +1 -1
  191. package/src/resources/extensions/gsd/prompt-loader.ts +27 -2
  192. package/src/resources/extensions/gsd/prompts/complete-milestone.md +14 -13
  193. package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +1 -1
  194. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  195. package/src/resources/extensions/gsd/prompts/quick-task.md +1 -5
  196. package/src/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
  197. package/src/resources/extensions/gsd/quick.ts +37 -2
  198. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +71 -0
  199. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +56 -13
  200. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +14 -1
  201. package/src/resources/extensions/gsd/tests/compaction-snapshot.test.ts +14 -1
  202. package/src/resources/extensions/gsd/tests/context-budget.test.ts +10 -1
  203. package/src/resources/extensions/gsd/tests/crash-handler-secondary.test.ts +55 -0
  204. package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +22 -0
  205. package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +313 -0
  206. package/src/resources/extensions/gsd/tests/exec-history.test.ts +15 -0
  207. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +65 -0
  208. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +54 -0
  209. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +234 -0
  210. package/src/resources/extensions/gsd/tests/memory-decay-factor.test.ts +90 -0
  211. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +48 -0
  212. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +127 -0
  213. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +50 -0
  214. package/src/resources/extensions/gsd/tests/plan-task.test.ts +21 -0
  215. package/src/resources/extensions/gsd/tests/prompt-path-audit.test.ts +40 -0
  216. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +19 -0
  217. package/src/resources/extensions/gsd/tests/quick-external-gsd.test.ts +40 -0
  218. package/src/resources/extensions/gsd/tests/schema-v27-v28-sequence.test.ts +156 -0
  219. package/src/resources/extensions/gsd/tests/signal-handlers.test.ts +27 -0
  220. package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +20 -0
  221. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +49 -1
  222. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +55 -0
  223. package/src/resources/extensions/gsd/tests/status-db-open.test.ts +9 -0
  224. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +136 -4
  225. package/src/resources/extensions/gsd/tests/unit-dispatches.test.ts +30 -0
  226. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +37 -0
  227. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +3 -0
  228. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +63 -1
  229. package/src/resources/extensions/gsd/tools/context-mode-tool-result.ts +25 -0
  230. package/src/resources/extensions/gsd/tools/exec-search-tool.ts +7 -7
  231. package/src/resources/extensions/gsd/tools/exec-tool.ts +4 -23
  232. package/src/resources/extensions/gsd/tools/memory-tools.ts +1 -0
  233. package/src/resources/extensions/gsd/tools/plan-slice.ts +13 -0
  234. package/src/resources/extensions/gsd/tools/plan-task.ts +10 -0
  235. package/src/resources/extensions/gsd/tools/resume-tool.ts +7 -7
  236. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +1 -1
  237. package/src/resources/extensions/gsd/unit-context-composer.ts +19 -4
  238. package/src/resources/extensions/gsd/unit-runtime.ts +25 -0
  239. package/src/resources/extensions/gsd/worktree-resolver.ts +36 -15
  240. /package/dist/web/standalone/.next/static/{vaQ47E8aNlbbNEDoeME6G → tht0ltP8EIjsohPOA_WZf}/_buildManifest.js +0 -0
  241. /package/dist/web/standalone/.next/static/{vaQ47E8aNlbbNEDoeME6G → tht0ltP8EIjsohPOA_WZf}/_ssgManifest.js +0 -0
@@ -8,8 +8,8 @@
8
8
  * Quick tasks live in `.gsd/quick/` and are tracked in STATE.md's
9
9
  * "Quick Tasks Completed" table.
10
10
  */
11
- import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
12
- import { join } from "node:path";
11
+ import { existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, rmSync, writeFileSync } from "node:fs";
12
+ import { isAbsolute, join, relative } from "node:path";
13
13
  import { loadPrompt } from "./prompt-loader.js";
14
14
  import { gsdRoot } from "./paths.js";
15
15
  import { GitServiceImpl, runGit } from "./git-service.js";
@@ -64,6 +64,37 @@ function ensureQuickDir(basePath, taskNum, slug) {
64
64
  mkdirSync(taskDir, { recursive: true });
65
65
  return taskDir;
66
66
  }
67
+ function isPathInside(parent, child) {
68
+ const rel = relative(parent, child);
69
+ return rel === "" || (!!rel && !rel.startsWith("..") && !isAbsolute(rel));
70
+ }
71
+ function isExternalGsdRoot(basePath, root) {
72
+ try {
73
+ return !isPathInside(realpathSync(basePath), realpathSync(root));
74
+ }
75
+ catch {
76
+ return !isPathInside(basePath, root);
77
+ }
78
+ }
79
+ export function buildQuickCommitInstruction(basePath, root) {
80
+ const externalState = isExternalGsdRoot(basePath, root);
81
+ if (externalState) {
82
+ return [
83
+ "Commit repo changes atomically, but do not stage or commit `.gsd/quick/...`:",
84
+ " - `.gsd/` resolves outside this git repository, so Git cannot stage quick-task summary files from the project repo.",
85
+ " - Write the quick summary file directly at the requested path; that file is persisted by GSD external state.",
86
+ " - Stage and commit only implementation/test/docs files that live inside the repository.",
87
+ " - If the task only writes quick-task research/summary files and no repository files changed, do not run `git commit`; report that there was nothing in the project repo to commit.",
88
+ ].join("\n");
89
+ }
90
+ return [
91
+ "Commit your changes atomically:",
92
+ " - Use conventional commit messages (feat:, fix:, refactor:, etc.)",
93
+ " - Stage only relevant files — never commit secrets or runtime files.",
94
+ " - Commit logical units separately if the task involves distinct changes.",
95
+ " - Quick tasks run outside the auto-mode lifecycle — there is no system auto-commit, so commit directly here.",
96
+ ].join("\n");
97
+ }
67
98
  function quickReturnStatePath(basePath) {
68
99
  return join(gsdRoot(basePath), "runtime", "quick-return.json");
69
100
  }
@@ -198,6 +229,7 @@ export async function handleQuick(args, ctx, pi) {
198
229
  taskDir: taskDirRel,
199
230
  branch: actualBranch,
200
231
  summaryPath,
232
+ commitInstruction: buildQuickCommitInstruction(basePath, root),
201
233
  date,
202
234
  taskNum: String(taskNum),
203
235
  slug,
@@ -0,0 +1,15 @@
1
+ // Project/App: GSD-2
2
+ // File Purpose: Shared Context Mode tool result helpers.
3
+ export function contextModeDisabledResult(operation) {
4
+ return {
5
+ content: [
6
+ {
7
+ type: "text",
8
+ text: `${operation} is disabled by \`context_mode.enabled: false\` in preferences. ` +
9
+ "Remove that override or set it to true to re-enable Context Mode tools.",
10
+ },
11
+ ],
12
+ details: { operation, error: "context_mode_disabled" },
13
+ isError: true,
14
+ };
15
+ }
@@ -3,7 +3,12 @@
3
3
  // Scans .gsd/exec/*.meta.json and returns a ranked summary so agents can
4
4
  // re-discover past runs without re-executing. Read-only; no DB writes.
5
5
  import { searchExecHistory } from "../exec-history.js";
6
+ import { isContextModeEnabled } from "../preferences-types.js";
7
+ import { contextModeDisabledResult } from "./context-mode-tool-result.js";
6
8
  export function executeExecSearch(params, opts) {
9
+ if (!isContextModeEnabled(opts.preferences)) {
10
+ return contextModeDisabledResult("gsd_exec_search");
11
+ }
7
12
  const searchOpts = {
8
13
  query: typeof params.query === "string" ? params.query : undefined,
9
14
  runtime: params.runtime,
@@ -5,6 +5,7 @@
5
5
  // for MCP return.
6
6
  import { EXEC_DEFAULTS, runExecSandbox, } from "../exec-sandbox.js";
7
7
  import { isContextModeEnabled } from "../preferences-types.js";
8
+ import { contextModeDisabledResult } from "./context-mode-tool-result.js";
8
9
  export function buildExecOptions(baseDir, cfg, extras) {
9
10
  const allowlist = Array.isArray(cfg?.exec_env_allowlist) ? cfg.exec_env_allowlist : EXEC_DEFAULTS.envAllowlist;
10
11
  const stdoutCap = clampNumber(cfg?.exec_stdout_cap_bytes, EXEC_DEFAULTS.stdoutCapBytes, 4_096, 16_777_216);
@@ -33,19 +34,6 @@ function clampNumber(value, fallback, min, max) {
33
34
  function isEnabled(prefs) {
34
35
  return isContextModeEnabled(prefs);
35
36
  }
36
- function disabledResult() {
37
- return {
38
- content: [
39
- {
40
- type: "text",
41
- text: "gsd_exec is disabled by `context_mode.enabled: false` in preferences. Remove that " +
42
- "override (or set it to true) to re-enable sandboxed tool-output execution.",
43
- },
44
- ],
45
- details: { operation: "gsd_exec", error: "context_mode_disabled" },
46
- isError: true,
47
- };
48
- }
49
37
  function paramError(message) {
50
38
  return {
51
39
  content: [{ type: "text", text: `Error: ${message}` }],
@@ -55,7 +43,7 @@ function paramError(message) {
55
43
  }
56
44
  export async function executeGsdExec(params, deps) {
57
45
  if (!isEnabled(deps.preferences))
58
- return disabledResult();
46
+ return contextModeDisabledResult("gsd_exec");
59
47
  const runtime = params.runtime;
60
48
  if (runtime !== "bash" && runtime !== "node" && runtime !== "python") {
61
49
  return paramError(`invalid runtime "${String(runtime)}" — must be bash | node | python`);
@@ -67,7 +55,7 @@ export async function executeGsdExec(params, deps) {
67
55
  if (Buffer.byteLength(script, "utf8") > 200_000) {
68
56
  return paramError("script exceeds the 200 KB length limit");
69
57
  }
70
- const opts = buildExecOptions(deps.baseDir, deps.preferences?.context_mode, { now: deps.now, generateId: deps.generateId });
58
+ const opts = buildExecOptions(deps.baseDir, deps.preferences?.context_mode, { env: deps.env, now: deps.now, generateId: deps.generateId });
71
59
  const run = deps.run ?? runExecSandbox;
72
60
  try {
73
61
  const result = await run({
@@ -256,6 +256,7 @@ function includeSupersededMemories(rankedActive) {
256
256
  scope: row["scope"] ?? "project",
257
257
  tags,
258
258
  structured_fields: structuredFields,
259
+ last_hit_at: row["last_hit_at"] ?? null,
259
260
  };
260
261
  });
261
262
  }
@@ -8,6 +8,7 @@ import { renderAllProjections } from "../workflow-projections.js";
8
8
  import { writeManifest } from "../workflow-manifest.js";
9
9
  import { appendEvent } from "../workflow-events.js";
10
10
  import { logWarning } from "../workflow-logger.js";
11
+ import { validatePlanningPathScope } from "../planning-path-scope.js";
11
12
  function validateTasks(value) {
12
13
  if (!Array.isArray(value) || value.length === 0) {
13
14
  throw new Error("tasks must be a non-empty array");
@@ -91,6 +92,14 @@ export async function handlePlanSlice(rawParams, basePath) {
91
92
  catch (err) {
92
93
  return { error: `validation failed: ${err.message}` };
93
94
  }
95
+ const pathScopeError = validatePlanningPathScope(basePath, params.tasks.flatMap((task, index) => [
96
+ { field: `tasks[${index}].files`, values: task.files },
97
+ { field: `tasks[${index}].inputs`, values: task.inputs },
98
+ { field: `tasks[${index}].expectedOutput`, values: task.expectedOutput },
99
+ ]));
100
+ if (pathScopeError) {
101
+ return { error: `validation failed: ${pathScopeError}` };
102
+ }
94
103
  // ── Guards + DB writes inside a single transaction (prevents TOCTOU) ───
95
104
  // Guards must be inside the transaction so the state they check cannot
96
105
  // change between the read and the write (#2723).
@@ -8,6 +8,7 @@ import { renderAllProjections } from "../workflow-projections.js";
8
8
  import { writeManifest } from "../workflow-manifest.js";
9
9
  import { appendEvent } from "../workflow-events.js";
10
10
  import { logWarning } from "../workflow-logger.js";
11
+ import { validatePlanningPathScope } from "../planning-path-scope.js";
11
12
  function validateParams(params) {
12
13
  if (!isNonEmptyString(params?.milestoneId))
13
14
  throw new Error("milestoneId is required");
@@ -41,6 +42,14 @@ export async function handlePlanTask(rawParams, basePath) {
41
42
  catch (err) {
42
43
  return { error: `validation failed: ${err.message}` };
43
44
  }
45
+ const pathScopeError = validatePlanningPathScope(basePath, [
46
+ { field: "files", values: params.files },
47
+ { field: "inputs", values: params.inputs },
48
+ { field: "expectedOutput", values: params.expectedOutput },
49
+ ]);
50
+ if (pathScopeError) {
51
+ return { error: `validation failed: ${pathScopeError}` };
52
+ }
44
53
  // ── Guards + DB writes inside a single transaction (prevents TOCTOU) ───
45
54
  // Guards must be inside the transaction so the state they check cannot
46
55
  // change between the read and the write (#2723).
@@ -2,7 +2,12 @@
2
2
  // agents can re-orient after compaction or session resume without
3
3
  // re-deriving project memory state.
4
4
  import { readCompactionSnapshot } from "../compaction-snapshot.js";
5
+ import { isContextModeEnabled } from "../preferences-types.js";
6
+ import { contextModeDisabledResult } from "./context-mode-tool-result.js";
5
7
  export function executeResume(_params, opts) {
8
+ if (!isContextModeEnabled(opts.preferences)) {
9
+ return contextModeDisabledResult("gsd_resume");
10
+ }
6
11
  const snapshot = readCompactionSnapshot(opts.baseDir);
7
12
  if (snapshot == null) {
8
13
  return {
@@ -680,7 +680,7 @@ export async function executeMilestoneStatus(params, basePath = process.cwd()) {
680
680
  };
681
681
  return {
682
682
  content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
683
- details: { operation: "milestone_status", milestoneId: milestone.id, sliceCount: slices.length },
683
+ details: { operation: "milestone_status", ...result },
684
684
  };
685
685
  });
686
686
  }
@@ -80,7 +80,15 @@ const CONTEXT_MODE_LANE_LABELS = {
80
80
  orchestration: "orchestration",
81
81
  docs: "documentation",
82
82
  };
83
- const CONTEXT_MODE_GUIDANCE = "Use `gsd_exec` for noisy commands, `gsd_exec_search` before reruns, and `gsd_resume` after compaction or resume.";
83
+ const CONTEXT_MODE_GUIDANCE_BY_LANE = {
84
+ interview: "Use `gsd_resume` to restore prior discussion, `gsd_exec` for noisy discovery, and `gsd_exec_search` before repeating scans.",
85
+ research: "Use `gsd_exec` for noisy research scans, `gsd_exec_search` before reruns, and `gsd_resume` to restore prior findings.",
86
+ planning: "Use `gsd_resume` for planning continuity, `gsd_exec` for noisy checks, and `gsd_exec_search` before rerunning diagnostics.",
87
+ execution: "Use `gsd_exec` for builds, tests, and diagnostics, `gsd_exec_search` before reruns, and `gsd_resume` after compaction or resume.",
88
+ verification: "Use `gsd_exec` for verification commands, `gsd_exec_search` to reuse prior evidence, and `gsd_resume` after compaction or resume.",
89
+ orchestration: "Use `gsd_resume` before resuming orchestration, `gsd_exec_search` to reuse prior runs, and `gsd_exec` for noisy coordination checks.",
90
+ docs: "Use `gsd_resume` for prior context, `gsd_exec_search` for saved evidence, and `gsd_exec` for noisy doc validation commands.",
91
+ };
84
92
  /**
85
93
  * Render the Context Mode instruction lane for a unit type. Unknown unit
86
94
  * types, disabled config, and explicit `contextMode: "none"` all omit the
@@ -93,14 +101,15 @@ export function composeContextModeInstructions(unitType, opts) {
93
101
  if (!manifest || manifest.contextMode === "none")
94
102
  return "";
95
103
  const lane = CONTEXT_MODE_LANE_LABELS[manifest.contextMode];
104
+ const guidance = CONTEXT_MODE_GUIDANCE_BY_LANE[manifest.contextMode];
96
105
  if (opts.renderMode === "nested") {
97
- return `Context Mode (${lane} lane): ${CONTEXT_MODE_GUIDANCE}`;
106
+ return `Context Mode (${lane} lane): ${guidance}`;
98
107
  }
99
108
  return [
100
109
  "## Context Mode",
101
110
  "",
102
111
  `Lane: **${lane} lane**.`,
103
- CONTEXT_MODE_GUIDANCE,
112
+ guidance,
104
113
  ].join("\n");
105
114
  }
106
115
  const SECTION_SEPARATOR = "\n\n---\n\n";
@@ -4,6 +4,8 @@ import { atomicWriteSync } from "./atomic-write.js";
4
4
  import { gsdRoot, relSliceFile, relTaskFile, resolveSliceFile, resolveTaskFile, } from "./paths.js";
5
5
  import { loadFile, parseTaskPlanMustHaves, countMustHavesMentionedInSummary } from "./files.js";
6
6
  import { parseUnitId } from "./unit-id.js";
7
+ import { getTask, isDbAvailable, refreshOpenDatabaseFromDisk } from "./gsd-db.js";
8
+ import { isClosedStatus } from "./status-guards.js";
7
9
  // Per-record advisory lock — prevents read-modify-write races between
8
10
  // concurrent writers updating disjoint fields of the same runtime record.
9
11
  // Within a single Node process this is moot (writeUnitRuntimeRecord is sync),
@@ -67,6 +69,17 @@ function withRecordLock(recordPath, fn) {
67
69
  catch { /* best-effort */ }
68
70
  }
69
71
  }
72
+ export const IN_FLIGHT_RUNTIME_PHASES = new Set([
73
+ "dispatched",
74
+ "wrapup-warning-sent",
75
+ "timeout",
76
+ "finalize-timeout",
77
+ "crashed",
78
+ "paused",
79
+ ]);
80
+ export function isInFlightRuntimePhase(phase) {
81
+ return IN_FLIGHT_RUNTIME_PHASES.has(phase);
82
+ }
70
83
  function runtimeDir(basePath) {
71
84
  return join(gsdRoot(basePath), "runtime", "units");
72
85
  }
@@ -154,6 +167,12 @@ export async function inspectExecuteTaskDurability(basePath, unitId) {
154
167
  const escapedTid = tid.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
155
168
  const taskChecked = !!planContent && new RegExp(`^- \\[[xX]\\] \\*\\*${escapedTid}:`, "m").test(planContent);
156
169
  const nextActionAdvanced = !new RegExp(`Execute ${tid}\\b`).test(stateContent);
170
+ let dbComplete = false;
171
+ if (isDbAvailable()) {
172
+ refreshOpenDatabaseFromDisk();
173
+ const task = getTask(mid, sid, tid);
174
+ dbComplete = !!task && isClosedStatus(task.status);
175
+ }
157
176
  // Must-have coverage: load task plan and count mentions in summary
158
177
  let mustHaveCount = 0;
159
178
  let mustHavesMentionedInSummary = 0;
@@ -177,11 +196,14 @@ export async function inspectExecuteTaskDurability(basePath, unitId) {
177
196
  summaryExists,
178
197
  taskChecked,
179
198
  nextActionAdvanced,
199
+ dbComplete,
180
200
  mustHaveCount,
181
201
  mustHavesMentionedInSummary,
182
202
  };
183
203
  }
184
204
  export function formatExecuteTaskRecoveryStatus(status) {
205
+ if (status.dbComplete)
206
+ return "DB task status is closed";
185
207
  const missing = [];
186
208
  if (!status.summaryExists)
187
209
  missing.push(`summary missing (${status.summaryPath})`);
@@ -22,7 +22,7 @@ import { emitWorktreeCreated, emitWorktreeMerged } from "./worktree-telemetry.js
22
22
  import { getCollapseCadence, getMilestoneResquash, resquashMilestoneOnMain } from "./slice-cadence.js";
23
23
  import { loadEffectiveGSDPreferences } from "./preferences.js";
24
24
  import { resolveWorktreeProjectRoot, normalizeWorktreePathForCompare } from "./worktree-root.js";
25
- import { claimMilestoneLease, releaseMilestoneLease } from "./db/milestone-leases.js";
25
+ import { claimMilestoneLease, refreshMilestoneLease, releaseMilestoneLease } from "./db/milestone-leases.js";
26
26
  // ─── Path Comparison Helper ────────────────────────────────────────────────
27
27
  /**
28
28
  * Compare two paths for physical identity, tolerating trailing slashes,
@@ -119,24 +119,40 @@ export class WorktreeResolver {
119
119
  // milestone (re-entry within the same session).
120
120
  if (this.s.workerId) {
121
121
  if (this.s.currentMilestoneId === milestoneId && this.s.milestoneLeaseToken !== null) {
122
- // Already held no-op, the heartbeat in loop.ts refreshes TTL.
123
- }
124
- else {
125
- // If we held a different milestone, release it first so other
126
- // workers don't have to wait for TTL.
127
- if (this.s.currentMilestoneId && this.s.currentMilestoneId !== milestoneId && this.s.milestoneLeaseToken !== null) {
128
- try {
129
- releaseMilestoneLease(this.s.workerId, this.s.currentMilestoneId, this.s.milestoneLeaseToken);
130
- }
131
- catch (err) {
132
- debugLog("WorktreeResolver", {
133
- action: "enterMilestone",
134
- milestoneId,
135
- releasePriorLeaseError: err instanceof Error ? err.message : String(err),
136
- });
137
- }
122
+ const refreshed = refreshMilestoneLease(this.s.workerId, milestoneId, this.s.milestoneLeaseToken);
123
+ if (refreshed) {
124
+ debugLog("WorktreeResolver", {
125
+ action: "enterMilestone",
126
+ milestoneId,
127
+ leaseRefreshed: true,
128
+ fencingToken: this.s.milestoneLeaseToken,
129
+ });
130
+ }
131
+ else {
132
+ debugLog("WorktreeResolver", {
133
+ action: "enterMilestone",
134
+ milestoneId,
135
+ staleLeaseToken: this.s.milestoneLeaseToken,
136
+ });
138
137
  this.s.milestoneLeaseToken = null;
139
138
  }
139
+ }
140
+ // If we held a different milestone, release it first so other
141
+ // workers don't have to wait for TTL.
142
+ if (this.s.currentMilestoneId && this.s.currentMilestoneId !== milestoneId && this.s.milestoneLeaseToken !== null) {
143
+ try {
144
+ releaseMilestoneLease(this.s.workerId, this.s.currentMilestoneId, this.s.milestoneLeaseToken);
145
+ }
146
+ catch (err) {
147
+ debugLog("WorktreeResolver", {
148
+ action: "enterMilestone",
149
+ milestoneId,
150
+ releasePriorLeaseError: err instanceof Error ? err.message : String(err),
151
+ });
152
+ }
153
+ this.s.milestoneLeaseToken = null;
154
+ }
155
+ if (this.s.milestoneLeaseToken === null) {
140
156
  try {
141
157
  const claim = claimMilestoneLease(this.s.workerId, milestoneId);
142
158
  if (claim.ok) {