gsd-pi 2.80.0-dev.c5f2443b3 → 2.80.0-dev.d4fc28e6b

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 (580) hide show
  1. package/README.md +4 -2
  2. package/dist/cli.js +0 -19
  3. package/dist/resources/.managed-resources-content-hash +1 -1
  4. package/dist/resources/GSD-WORKFLOW.md +2 -2
  5. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +29 -0
  6. package/dist/resources/extensions/github-sync/templates.js +39 -8
  7. package/dist/resources/extensions/gsd/auto/loop.js +119 -18
  8. package/dist/resources/extensions/gsd/auto/phases.js +212 -135
  9. package/dist/resources/extensions/gsd/auto/resolve.js +29 -0
  10. package/dist/resources/extensions/gsd/auto/run-unit.js +41 -45
  11. package/dist/resources/extensions/gsd/auto/session.js +8 -0
  12. package/dist/resources/extensions/gsd/auto/workflow-dispatch-claim.js +33 -1
  13. package/dist/resources/extensions/gsd/auto/workflow-worker-heartbeat.js +9 -1
  14. package/dist/resources/extensions/gsd/auto-dashboard.js +51 -15
  15. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +5 -32
  16. package/dist/resources/extensions/gsd/auto-dispatch.js +26 -0
  17. package/dist/resources/extensions/gsd/auto-post-unit.js +27 -14
  18. package/dist/resources/extensions/gsd/auto-prompts.js +214 -17
  19. package/dist/resources/extensions/gsd/auto-recovery.js +197 -9
  20. package/dist/resources/extensions/gsd/auto-start.js +199 -9
  21. package/dist/resources/extensions/gsd/auto-supervisor.js +8 -1
  22. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +2 -2
  23. package/dist/resources/extensions/gsd/auto-worktree.js +111 -1
  24. package/dist/resources/extensions/gsd/auto.js +95 -27
  25. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +103 -3
  26. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +49 -36
  27. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +15 -5
  28. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +33 -20
  29. package/dist/resources/extensions/gsd/bootstrap/journal-tools.js +7 -1
  30. package/dist/resources/extensions/gsd/bootstrap/memory-tools.js +9 -3
  31. package/dist/resources/extensions/gsd/bootstrap/query-tools.js +8 -2
  32. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +330 -55
  33. package/dist/resources/extensions/gsd/bootstrap/system-context.js +82 -23
  34. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +129 -1
  35. package/dist/resources/extensions/gsd/clean-root-preflight.js +65 -9
  36. package/dist/resources/extensions/gsd/commands/dispatcher.js +5 -0
  37. package/dist/resources/extensions/gsd/commands-extract-learnings.js +17 -12
  38. package/dist/resources/extensions/gsd/commands-handlers.js +23 -9
  39. package/dist/resources/extensions/gsd/context-budget.js +37 -2
  40. package/dist/resources/extensions/gsd/crash-recovery.js +56 -10
  41. package/dist/resources/extensions/gsd/custom-workflow-engine.js +22 -2
  42. package/dist/resources/extensions/gsd/db/unit-dispatches.js +92 -0
  43. package/dist/resources/extensions/gsd/db-base-schema.js +18 -2
  44. package/dist/resources/extensions/gsd/db-migration-steps.js +22 -0
  45. package/dist/resources/extensions/gsd/detection.js +106 -0
  46. package/dist/resources/extensions/gsd/ecosystem/gsd-extension-api.js +2 -0
  47. package/dist/resources/extensions/gsd/git-service.js +36 -4
  48. package/dist/resources/extensions/gsd/graph.js +9 -3
  49. package/dist/resources/extensions/gsd/gsd-db.js +146 -13
  50. package/dist/resources/extensions/gsd/guided-flow.js +129 -44
  51. package/dist/resources/extensions/gsd/memory-store.js +69 -12
  52. package/dist/resources/extensions/gsd/migrate/command.js +40 -1
  53. package/dist/resources/extensions/gsd/migration-auto-check.js +87 -0
  54. package/dist/resources/extensions/gsd/native-git-bridge.js +32 -8
  55. package/dist/resources/extensions/gsd/orphan-stash-audit.js +101 -0
  56. package/dist/resources/extensions/gsd/parallel-orchestrator.js +13 -3
  57. package/dist/resources/extensions/gsd/planning-path-scope.js +26 -0
  58. package/dist/resources/extensions/gsd/pr-evidence.js +57 -16
  59. package/dist/resources/extensions/gsd/pre-execution-checks.js +22 -0
  60. package/dist/resources/extensions/gsd/prompt-loader.js +28 -2
  61. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +21 -19
  62. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  63. package/dist/resources/extensions/gsd/prompts/execute-task.md +4 -2
  64. package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +1 -1
  65. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +3 -1
  66. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  67. package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -5
  68. package/dist/resources/extensions/gsd/prompts/replan-slice.md +2 -2
  69. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
  70. package/dist/resources/extensions/gsd/quick.js +34 -2
  71. package/dist/resources/extensions/gsd/safety/evidence-collector.js +10 -2
  72. package/dist/resources/extensions/gsd/tools/context-mode-tool-result.js +15 -0
  73. package/dist/resources/extensions/gsd/tools/exec-search-tool.js +5 -0
  74. package/dist/resources/extensions/gsd/tools/exec-tool.js +3 -15
  75. package/dist/resources/extensions/gsd/tools/memory-tools.js +1 -0
  76. package/dist/resources/extensions/gsd/tools/plan-slice.js +9 -0
  77. package/dist/resources/extensions/gsd/tools/plan-task.js +9 -0
  78. package/dist/resources/extensions/gsd/tools/resume-tool.js +5 -0
  79. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +1 -1
  80. package/dist/resources/extensions/gsd/unit-context-composer.js +12 -3
  81. package/dist/resources/extensions/gsd/unit-runtime.js +22 -0
  82. package/dist/resources/extensions/gsd/workflow-protocol.js +131 -0
  83. package/dist/resources/extensions/gsd/working-output-messages.js +64 -0
  84. package/dist/resources/extensions/gsd/worktree-manager.js +16 -14
  85. package/dist/resources/extensions/gsd/worktree-resolver.js +68 -21
  86. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  87. package/dist/web/standalone/.next/BUILD_ID +1 -1
  88. package/dist/web/standalone/.next/app-path-routes-manifest.json +11 -11
  89. package/dist/web/standalone/.next/build-manifest.json +3 -3
  90. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  91. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  92. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  93. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  100. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  101. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  102. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  103. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  104. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  106. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  108. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  109. package/dist/web/standalone/.next/server/app/index.html +1 -1
  110. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app-paths-manifest.json +11 -11
  117. package/dist/web/standalone/.next/server/chunks/6897.js +3 -3
  118. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  120. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  121. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  122. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  123. package/dist/web/standalone/.next/static/chunks/{8336.6f6f30e410419aff.js → 8336.631939fb583761fa.js} +1 -1
  124. package/dist/web/standalone/.next/static/chunks/{webpack-d82dbee6356c1733.js → webpack-0481f1221120a7c6.js} +1 -1
  125. package/dist/welcome-screen.d.ts +2 -0
  126. package/dist/welcome-screen.js +9 -7
  127. package/package.json +12 -8
  128. package/packages/contracts/package.json +1 -1
  129. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  130. package/packages/mcp-server/dist/workflow-tools.js +22 -17
  131. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  132. package/packages/mcp-server/src/workflow-tools.test.ts +75 -2
  133. package/packages/mcp-server/src/workflow-tools.ts +30 -16
  134. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  135. package/packages/native/tsconfig.tsbuildinfo +1 -1
  136. package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  137. package/packages/pi-agent-core/dist/agent-loop.js +4 -1
  138. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  139. package/packages/pi-agent-core/dist/agent.d.ts +5 -0
  140. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  141. package/packages/pi-agent-core/dist/agent.js +2 -0
  142. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  143. package/packages/pi-agent-core/dist/index.d.ts +1 -0
  144. package/packages/pi-agent-core/dist/index.d.ts.map +1 -1
  145. package/packages/pi-agent-core/dist/index.js +2 -0
  146. package/packages/pi-agent-core/dist/index.js.map +1 -1
  147. package/packages/pi-agent-core/dist/token-audit.d.ts +47 -0
  148. package/packages/pi-agent-core/dist/token-audit.d.ts.map +1 -0
  149. package/packages/pi-agent-core/dist/token-audit.js +221 -0
  150. package/packages/pi-agent-core/dist/token-audit.js.map +1 -0
  151. package/packages/pi-agent-core/dist/types.d.ts +9 -0
  152. package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
  153. package/packages/pi-agent-core/dist/types.js.map +1 -1
  154. package/packages/pi-agent-core/src/agent-loop.test.ts +128 -0
  155. package/packages/pi-agent-core/src/agent-loop.ts +4 -1
  156. package/packages/pi-agent-core/src/agent.ts +8 -0
  157. package/packages/pi-agent-core/src/index.ts +2 -0
  158. package/packages/pi-agent-core/src/token-audit.test.ts +189 -0
  159. package/packages/pi-agent-core/src/token-audit.ts +287 -0
  160. package/packages/pi-agent-core/src/types.ts +14 -0
  161. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  162. package/packages/pi-ai/dist/models/fake-model.d.ts +12 -0
  163. package/packages/pi-ai/dist/models/fake-model.d.ts.map +1 -0
  164. package/packages/pi-ai/dist/models/fake-model.js +27 -0
  165. package/packages/pi-ai/dist/models/fake-model.js.map +1 -0
  166. package/packages/pi-ai/dist/models/index.d.ts.map +1 -1
  167. package/packages/pi-ai/dist/models/index.js +8 -0
  168. package/packages/pi-ai/dist/models/index.js.map +1 -1
  169. package/packages/pi-ai/dist/providers/fake.d.ts +42 -0
  170. package/packages/pi-ai/dist/providers/fake.d.ts.map +1 -0
  171. package/packages/pi-ai/dist/providers/fake.js +319 -0
  172. package/packages/pi-ai/dist/providers/fake.js.map +1 -0
  173. package/packages/pi-ai/dist/providers/register-builtins.d.ts.map +1 -1
  174. package/packages/pi-ai/dist/providers/register-builtins.js +24 -0
  175. package/packages/pi-ai/dist/providers/register-builtins.js.map +1 -1
  176. package/packages/pi-ai/src/models/fake-model.ts +30 -0
  177. package/packages/pi-ai/src/models/index.ts +9 -0
  178. package/packages/pi-ai/src/providers/fake.ts +376 -0
  179. package/packages/pi-ai/src/providers/register-builtins.ts +23 -0
  180. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  181. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +32 -0
  182. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
  183. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +18 -0
  184. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -1
  185. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +12 -0
  186. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  187. package/packages/pi-coding-agent/dist/core/agent-session.js +44 -7
  188. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  189. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +76 -0
  190. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
  191. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +11 -0
  192. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  193. package/packages/pi-coding-agent/dist/core/compaction/compaction.js +9 -0
  194. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  195. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.d.ts +2 -0
  196. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.d.ts.map +1 -0
  197. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.js +103 -0
  198. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.js.map +1 -0
  199. package/packages/pi-coding-agent/dist/core/db-snapshot.d.ts +15 -0
  200. package/packages/pi-coding-agent/dist/core/db-snapshot.d.ts.map +1 -0
  201. package/packages/pi-coding-agent/dist/core/db-snapshot.js +66 -0
  202. package/packages/pi-coding-agent/dist/core/db-snapshot.js.map +1 -0
  203. package/packages/pi-coding-agent/dist/core/db-snapshot.test.d.ts +2 -0
  204. package/packages/pi-coding-agent/dist/core/db-snapshot.test.d.ts.map +1 -0
  205. package/packages/pi-coding-agent/dist/core/db-snapshot.test.js +24 -0
  206. package/packages/pi-coding-agent/dist/core/db-snapshot.test.js.map +1 -0
  207. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  208. package/packages/pi-coding-agent/dist/core/extensions/loader.js +8 -0
  209. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  210. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +5 -0
  211. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  212. package/packages/pi-coding-agent/dist/core/extensions/runner.js +20 -7
  213. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  214. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +102 -3
  215. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
  216. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +39 -1
  217. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  218. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  219. package/packages/pi-coding-agent/dist/core/hooks-runner.test.js +2 -0
  220. package/packages/pi-coding-agent/dist/core/hooks-runner.test.js.map +1 -1
  221. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  222. package/packages/pi-coding-agent/dist/core/model-registry.js +5 -0
  223. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  224. package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.d.ts +2 -0
  225. package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.d.ts.map +1 -0
  226. package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.js +46 -0
  227. package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.js.map +1 -0
  228. package/packages/pi-coding-agent/dist/core/sdk.d.ts +10 -2
  229. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  230. package/packages/pi-coding-agent/dist/core/sdk.js +74 -2
  231. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  232. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +24 -0
  233. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  234. package/packages/pi-coding-agent/dist/core/settings-manager.js +33 -0
  235. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  236. package/packages/pi-coding-agent/dist/core/skill-tool.test.js +22 -0
  237. package/packages/pi-coding-agent/dist/core/skill-tool.test.js.map +1 -1
  238. package/packages/pi-coding-agent/dist/core/slash-commands.d.ts.map +1 -1
  239. package/packages/pi-coding-agent/dist/core/slash-commands.js +1 -0
  240. package/packages/pi-coding-agent/dist/core/slash-commands.js.map +1 -1
  241. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +6 -7
  242. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  243. package/packages/pi-coding-agent/dist/core/system-prompt.js +2 -3
  244. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  245. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.js +6 -4
  246. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.js.map +1 -1
  247. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +54 -15
  248. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  249. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts +26 -0
  250. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts.map +1 -0
  251. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js +112 -0
  252. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js.map +1 -0
  253. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.d.ts +2 -0
  254. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.d.ts.map +1 -0
  255. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js +51 -0
  256. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js.map +1 -0
  257. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  258. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
  259. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts.map +1 -1
  260. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js +10 -9
  261. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js.map +1 -1
  262. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +3 -0
  263. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  264. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +11 -0
  265. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
  266. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +7 -6
  267. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +1 -1
  268. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +17 -0
  269. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  270. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +109 -17
  271. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  272. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  273. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +69 -2
  274. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  275. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js +93 -1
  276. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js.map +1 -1
  277. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +1 -0
  278. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  279. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +1 -0
  280. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  281. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  282. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +3 -0
  283. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  284. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +26 -0
  285. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  286. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.d.ts.map +1 -1
  287. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +20 -0
  288. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -1
  289. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.d.ts +2 -0
  290. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.d.ts.map +1 -0
  291. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.js +79 -0
  292. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.js.map +1 -0
  293. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.d.ts +12 -0
  294. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.d.ts.map +1 -1
  295. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.js +13 -0
  296. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.js.map +1 -1
  297. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts +1 -1
  298. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  299. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js +18 -1
  300. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
  301. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.d.ts.map +1 -1
  302. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +36 -27
  303. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -1
  304. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.d.ts +11 -0
  305. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.d.ts.map +1 -0
  306. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.js +18 -0
  307. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.js.map +1 -0
  308. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.d.ts +2 -0
  309. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.d.ts.map +1 -0
  310. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js +48 -0
  311. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js.map +1 -0
  312. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.d.ts +2 -0
  313. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.d.ts.map +1 -0
  314. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js +10 -0
  315. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js.map +1 -0
  316. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.d.ts.map +1 -1
  317. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js +3 -2
  318. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js.map +1 -1
  319. package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +36 -0
  320. package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +25 -0
  321. package/packages/pi-coding-agent/src/core/agent-session.ts +48 -7
  322. package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +89 -0
  323. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +18 -0
  324. package/packages/pi-coding-agent/src/core/compaction-threshold.test.ts +121 -0
  325. package/packages/pi-coding-agent/src/core/db-snapshot.test.ts +32 -0
  326. package/packages/pi-coding-agent/src/core/db-snapshot.ts +66 -0
  327. package/packages/pi-coding-agent/src/core/extensions/loader.ts +10 -0
  328. package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +113 -3
  329. package/packages/pi-coding-agent/src/core/extensions/runner.ts +24 -6
  330. package/packages/pi-coding-agent/src/core/extensions/types.ts +42 -1
  331. package/packages/pi-coding-agent/src/core/hooks-runner.test.ts +2 -0
  332. package/packages/pi-coding-agent/src/core/model-registry.ts +4 -0
  333. package/packages/pi-coding-agent/src/core/sdk-tool-filter.test.ts +60 -0
  334. package/packages/pi-coding-agent/src/core/sdk.ts +85 -3
  335. package/packages/pi-coding-agent/src/core/settings-manager.ts +51 -1
  336. package/packages/pi-coding-agent/src/core/skill-tool.test.ts +28 -0
  337. package/packages/pi-coding-agent/src/core/slash-commands.ts +1 -0
  338. package/packages/pi-coding-agent/src/core/system-prompt.ts +8 -10
  339. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.ts +7 -5
  340. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +78 -15
  341. package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.test.ts +59 -0
  342. package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.ts +160 -0
  343. package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +1 -0
  344. package/packages/pi-coding-agent/src/modes/interactive/components/chat-frame.ts +10 -9
  345. package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +15 -0
  346. package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +10 -9
  347. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +122 -17
  348. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.test.ts +99 -1
  349. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +92 -3
  350. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +1 -0
  351. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +1 -1
  352. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +28 -0
  353. package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.test.ts +95 -0
  354. package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +24 -1
  355. package/packages/pi-coding-agent/src/modes/interactive/theme/theme-schema.ts +13 -0
  356. package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +32 -2
  357. package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +36 -27
  358. package/packages/pi-coding-agent/src/modes/interactive/tui-mode.test.ts +65 -0
  359. package/packages/pi-coding-agent/src/modes/interactive/tui-mode.ts +29 -0
  360. package/packages/pi-coding-agent/src/resources/extensions/memory/storage-safety-guard.test.ts +14 -0
  361. package/packages/pi-coding-agent/src/resources/extensions/memory/storage.ts +3 -2
  362. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  363. package/packages/pi-tui/dist/__tests__/style.test.d.ts +2 -0
  364. package/packages/pi-tui/dist/__tests__/style.test.d.ts.map +1 -0
  365. package/packages/pi-tui/dist/__tests__/style.test.js +63 -0
  366. package/packages/pi-tui/dist/__tests__/style.test.js.map +1 -0
  367. package/packages/pi-tui/dist/__tests__/tui.test.js +24 -3
  368. package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
  369. package/packages/pi-tui/dist/index.d.ts +1 -0
  370. package/packages/pi-tui/dist/index.d.ts.map +1 -1
  371. package/packages/pi-tui/dist/index.js +2 -0
  372. package/packages/pi-tui/dist/index.js.map +1 -1
  373. package/packages/pi-tui/dist/style.d.ts +41 -0
  374. package/packages/pi-tui/dist/style.d.ts.map +1 -0
  375. package/packages/pi-tui/dist/style.js +158 -0
  376. package/packages/pi-tui/dist/style.js.map +1 -0
  377. package/packages/pi-tui/dist/tui.d.ts +0 -1
  378. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  379. package/packages/pi-tui/dist/tui.js +21 -16
  380. package/packages/pi-tui/dist/tui.js.map +1 -1
  381. package/packages/pi-tui/src/__tests__/style.test.ts +76 -0
  382. package/packages/pi-tui/src/__tests__/tui.test.ts +29 -3
  383. package/packages/pi-tui/src/index.ts +9 -0
  384. package/packages/pi-tui/src/style.ts +225 -0
  385. package/packages/pi-tui/src/tui.ts +23 -16
  386. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  387. package/pkg/dist/modes/interactive/theme/theme-schema.d.ts +12 -0
  388. package/pkg/dist/modes/interactive/theme/theme-schema.d.ts.map +1 -1
  389. package/pkg/dist/modes/interactive/theme/theme-schema.js +13 -0
  390. package/pkg/dist/modes/interactive/theme/theme-schema.js.map +1 -1
  391. package/pkg/dist/modes/interactive/theme/theme.d.ts +1 -1
  392. package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  393. package/pkg/dist/modes/interactive/theme/theme.js +18 -1
  394. package/pkg/dist/modes/interactive/theme/theme.js.map +1 -1
  395. package/pkg/dist/modes/interactive/theme/themes.d.ts.map +1 -1
  396. package/pkg/dist/modes/interactive/theme/themes.js +36 -27
  397. package/pkg/dist/modes/interactive/theme/themes.js.map +1 -1
  398. package/src/resources/GSD-WORKFLOW.md +2 -2
  399. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +30 -0
  400. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +26 -0
  401. package/src/resources/extensions/github-sync/templates.ts +38 -8
  402. package/src/resources/extensions/github-sync/tests/inline-code.test.ts +66 -0
  403. package/src/resources/extensions/gsd/auto/loop-deps.ts +3 -2
  404. package/src/resources/extensions/gsd/auto/loop.ts +151 -26
  405. package/src/resources/extensions/gsd/auto/phases.ts +289 -196
  406. package/src/resources/extensions/gsd/auto/resolve.ts +42 -1
  407. package/src/resources/extensions/gsd/auto/run-unit.ts +52 -44
  408. package/src/resources/extensions/gsd/auto/session.ts +8 -0
  409. package/src/resources/extensions/gsd/auto/workflow-dispatch-claim.ts +63 -1
  410. package/src/resources/extensions/gsd/auto/workflow-worker-heartbeat.ts +14 -1
  411. package/src/resources/extensions/gsd/auto-dashboard.ts +57 -8
  412. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +8 -34
  413. package/src/resources/extensions/gsd/auto-dispatch.ts +33 -0
  414. package/src/resources/extensions/gsd/auto-post-unit.ts +28 -14
  415. package/src/resources/extensions/gsd/auto-prompts.ts +228 -16
  416. package/src/resources/extensions/gsd/auto-recovery.ts +207 -7
  417. package/src/resources/extensions/gsd/auto-start.ts +237 -15
  418. package/src/resources/extensions/gsd/auto-supervisor.ts +7 -0
  419. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +2 -2
  420. package/src/resources/extensions/gsd/auto-worktree.ts +123 -0
  421. package/src/resources/extensions/gsd/auto.ts +110 -22
  422. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +119 -2
  423. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +50 -36
  424. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +16 -5
  425. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +34 -19
  426. package/src/resources/extensions/gsd/bootstrap/journal-tools.ts +8 -1
  427. package/src/resources/extensions/gsd/bootstrap/memory-tools.ts +10 -3
  428. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +9 -2
  429. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +386 -55
  430. package/src/resources/extensions/gsd/bootstrap/system-context.ts +90 -22
  431. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +135 -1
  432. package/src/resources/extensions/gsd/clean-root-preflight.ts +72 -9
  433. package/src/resources/extensions/gsd/commands/dispatcher.ts +6 -0
  434. package/src/resources/extensions/gsd/commands-extract-learnings.ts +17 -12
  435. package/src/resources/extensions/gsd/commands-handlers.ts +34 -15
  436. package/src/resources/extensions/gsd/context-budget.ts +44 -2
  437. package/src/resources/extensions/gsd/crash-recovery.ts +67 -10
  438. package/src/resources/extensions/gsd/custom-workflow-engine.ts +24 -1
  439. package/src/resources/extensions/gsd/db/unit-dispatches.ts +107 -0
  440. package/src/resources/extensions/gsd/db-base-schema.ts +19 -2
  441. package/src/resources/extensions/gsd/db-migration-steps.ts +25 -0
  442. package/src/resources/extensions/gsd/detection.ts +128 -0
  443. package/src/resources/extensions/gsd/ecosystem/gsd-extension-api.ts +3 -0
  444. package/src/resources/extensions/gsd/git-service.ts +46 -8
  445. package/src/resources/extensions/gsd/graph.ts +12 -5
  446. package/src/resources/extensions/gsd/gsd-db.ts +168 -13
  447. package/src/resources/extensions/gsd/guided-flow.ts +150 -51
  448. package/src/resources/extensions/gsd/memory-store.ts +77 -12
  449. package/src/resources/extensions/gsd/migrate/command.ts +47 -1
  450. package/src/resources/extensions/gsd/migration-auto-check.ts +129 -0
  451. package/src/resources/extensions/gsd/native-git-bridge.ts +39 -6
  452. package/src/resources/extensions/gsd/orphan-stash-audit.ts +117 -0
  453. package/src/resources/extensions/gsd/parallel-orchestrator.ts +13 -3
  454. package/src/resources/extensions/gsd/planning-path-scope.ts +35 -0
  455. package/src/resources/extensions/gsd/pr-evidence.ts +63 -5
  456. package/src/resources/extensions/gsd/pre-execution-checks.ts +23 -0
  457. package/src/resources/extensions/gsd/preferences-types.ts +1 -1
  458. package/src/resources/extensions/gsd/prompt-loader.ts +27 -2
  459. package/src/resources/extensions/gsd/prompts/complete-milestone.md +21 -19
  460. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  461. package/src/resources/extensions/gsd/prompts/execute-task.md +4 -2
  462. package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +1 -1
  463. package/src/resources/extensions/gsd/prompts/plan-milestone.md +3 -1
  464. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  465. package/src/resources/extensions/gsd/prompts/quick-task.md +1 -5
  466. package/src/resources/extensions/gsd/prompts/replan-slice.md +2 -2
  467. package/src/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
  468. package/src/resources/extensions/gsd/quick.ts +37 -2
  469. package/src/resources/extensions/gsd/safety/evidence-collector.ts +11 -2
  470. package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +2 -2
  471. package/src/resources/extensions/gsd/tests/auto-abort-pause-regression.test.ts +7 -1
  472. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +33 -0
  473. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +516 -15
  474. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +56 -13
  475. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +184 -2
  476. package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +168 -6
  477. package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +97 -2
  478. package/src/resources/extensions/gsd/tests/commands-extract-learnings.test.ts +9 -0
  479. package/src/resources/extensions/gsd/tests/compaction-snapshot.test.ts +14 -1
  480. package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +31 -0
  481. package/src/resources/extensions/gsd/tests/complete-slice-composer.test.ts +3 -2
  482. package/src/resources/extensions/gsd/tests/context-budget.test.ts +10 -1
  483. package/src/resources/extensions/gsd/tests/context-store.test.ts +7 -1
  484. package/src/resources/extensions/gsd/tests/crash-handler-secondary.test.ts +55 -0
  485. package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +22 -0
  486. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +117 -7
  487. package/src/resources/extensions/gsd/tests/custom-workflow-engine.test.ts +40 -2
  488. package/src/resources/extensions/gsd/tests/db-migration-steps.integration.test.ts +428 -0
  489. package/src/resources/extensions/gsd/tests/db-schema-metadata.test.ts +2 -2
  490. package/src/resources/extensions/gsd/tests/detection.test.ts +140 -0
  491. package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +313 -0
  492. package/src/resources/extensions/gsd/tests/exec-history.test.ts +15 -0
  493. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +65 -0
  494. package/src/resources/extensions/gsd/tests/execute-task-rendering.test.ts +5 -2
  495. package/src/resources/extensions/gsd/tests/fast-forward-reused-milestone-branch.test.ts +219 -0
  496. package/src/resources/extensions/gsd/tests/finalize-survivor-branch.test.ts +132 -0
  497. package/src/resources/extensions/gsd/tests/fixtures/pr-body/commands-ship-basic.md +52 -0
  498. package/src/resources/extensions/gsd/tests/fixtures/pr-body/commands-ship-empty-optionals.md +42 -0
  499. package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-no-blockers.md +55 -0
  500. package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-with-blockers.md +60 -0
  501. package/src/resources/extensions/gsd/tests/graph-operations.test.ts +10 -0
  502. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +44 -0
  503. package/src/resources/extensions/gsd/tests/has-pending-deep-stage.test.ts +33 -1
  504. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +54 -0
  505. package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +6 -3
  506. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +239 -1
  507. package/src/resources/extensions/gsd/tests/journal-query-tool.test.ts +32 -0
  508. package/src/resources/extensions/gsd/tests/knowledge.test.ts +47 -0
  509. package/src/resources/extensions/gsd/tests/memory-decay-factor.test.ts +90 -0
  510. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +1 -0
  511. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +48 -0
  512. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +127 -0
  513. package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +242 -0
  514. package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +34 -2
  515. package/src/resources/extensions/gsd/tests/originalbase-path-comparison.test.ts +3 -0
  516. package/src/resources/extensions/gsd/tests/orphan-merge-bootstrap.test.ts +133 -0
  517. package/src/resources/extensions/gsd/tests/orphan-stash-audit.test.ts +201 -0
  518. package/src/resources/extensions/gsd/tests/parallel-orchestrator-fast-forward.test.ts +113 -0
  519. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +50 -0
  520. package/src/resources/extensions/gsd/tests/plan-task.test.ts +21 -0
  521. package/src/resources/extensions/gsd/tests/pr-evidence-equivalence.test.ts +102 -0
  522. package/src/resources/extensions/gsd/tests/pr-evidence-hardening.test.ts +165 -0
  523. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +45 -5
  524. package/src/resources/extensions/gsd/tests/prompt-duplication-cuts.test.ts +230 -0
  525. package/src/resources/extensions/gsd/tests/prompt-path-audit.test.ts +40 -0
  526. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +19 -0
  527. package/src/resources/extensions/gsd/tests/query-tools-db-open.test.ts +3 -3
  528. package/src/resources/extensions/gsd/tests/quick-external-gsd.test.ts +40 -0
  529. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +38 -17
  530. package/src/resources/extensions/gsd/tests/right-sized-workflow-prompts.test.ts +192 -0
  531. package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +29 -0
  532. package/src/resources/extensions/gsd/tests/schema-v27-v28-sequence.test.ts +156 -0
  533. package/src/resources/extensions/gsd/tests/select-resumable-milestone.test.ts +96 -0
  534. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +77 -0
  535. package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +166 -0
  536. package/src/resources/extensions/gsd/tests/signal-handlers.test.ts +27 -0
  537. package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +38 -0
  538. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +49 -1
  539. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +101 -2
  540. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +1 -0
  541. package/src/resources/extensions/gsd/tests/status-db-open.test.ts +9 -0
  542. package/src/resources/extensions/gsd/tests/system-context-memory.test.ts +112 -0
  543. package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +7 -9
  544. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +291 -0
  545. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +136 -4
  546. package/src/resources/extensions/gsd/tests/unit-dispatches.test.ts +80 -1
  547. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +37 -0
  548. package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +5 -4
  549. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +1 -1
  550. package/src/resources/extensions/gsd/tests/workflow-dispatch-claim.test.ts +142 -0
  551. package/src/resources/extensions/gsd/tests/workflow-protocol-excerpt.test.ts +99 -0
  552. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +3 -0
  553. package/src/resources/extensions/gsd/tests/workflow-worker-heartbeat.test.ts +32 -1
  554. package/src/resources/extensions/gsd/tests/working-output-messages.test.ts +93 -0
  555. package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +37 -6
  556. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +1 -0
  557. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +7 -0
  558. package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +9 -2
  559. package/src/resources/extensions/gsd/tests/worktree-path-injection.test.ts +22 -19
  560. package/src/resources/extensions/gsd/tests/worktree-project-root-degrade.test.ts +66 -0
  561. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +167 -4
  562. package/src/resources/extensions/gsd/tests/worktree-write-gate.test.ts +179 -0
  563. package/src/resources/extensions/gsd/tools/context-mode-tool-result.ts +25 -0
  564. package/src/resources/extensions/gsd/tools/exec-search-tool.ts +7 -7
  565. package/src/resources/extensions/gsd/tools/exec-tool.ts +4 -23
  566. package/src/resources/extensions/gsd/tools/memory-tools.ts +1 -0
  567. package/src/resources/extensions/gsd/tools/plan-slice.ts +13 -0
  568. package/src/resources/extensions/gsd/tools/plan-task.ts +10 -0
  569. package/src/resources/extensions/gsd/tools/resume-tool.ts +7 -7
  570. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +1 -1
  571. package/src/resources/extensions/gsd/unit-context-composer.ts +19 -4
  572. package/src/resources/extensions/gsd/unit-runtime.ts +25 -0
  573. package/src/resources/extensions/gsd/workflow-protocol.ts +160 -0
  574. package/src/resources/extensions/gsd/working-output-messages.ts +120 -0
  575. package/src/resources/extensions/gsd/worktree-manager.ts +15 -4
  576. package/src/resources/extensions/gsd/worktree-resolver.ts +85 -19
  577. package/packages/contracts/tsconfig.tsbuildinfo +0 -1
  578. package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +0 -97
  579. /package/dist/web/standalone/.next/static/{bQDK5_LtkGVS64AirQgQG → cWaxzf-sdbSSbbwYu8q7a}/_buildManifest.js +0 -0
  580. /package/dist/web/standalone/.next/static/{bQDK5_LtkGVS64AirQgQG → cWaxzf-sdbSSbbwYu8q7a}/_ssgManifest.js +0 -0
@@ -144,6 +144,18 @@ test("safety-harness-bug2-race: bash evidence survives mid-unit reset between to
144
144
  assert.ok(bash[0].outputSnippet.includes("found"), "output snippet captured");
145
145
  });
146
146
 
147
+ test("safety-harness: gsd_exec counts as execution evidence", () => {
148
+ resetEvidence();
149
+
150
+ recordToolCall("tc-exec-1", "gsd_exec", { command: "grep -n render index.html" });
151
+ recordToolResult("tc-exec-1", "gsd_exec", "Command exited with code 0\n1:render\n", false);
152
+
153
+ const bash = getEvidence().filter((e): e is BashEvidence => e.kind === "bash");
154
+ assert.equal(bash.length, 1, "gsd_exec must be tracked as execution evidence");
155
+ assert.equal(bash[0].command, "grep -n render index.html");
156
+ assert.equal(bash[0].exitCode, 0);
157
+ });
158
+
147
159
  // ─── Bug 3: git diff HEAD~1 scope check ─────────────────────────────────────
148
160
 
149
161
  test("safety-harness-bug3: validateFileChanges works on initial commit (no HEAD~1)", (t) => {
@@ -237,3 +249,20 @@ test("safety-harness-bug3: validateFileChanges works on merge commit", (t) => {
237
249
  // Must produce a valid result without throwing
238
250
  assert.ok(audit !== null, "audit must be produced for merge commit repo");
239
251
  });
252
+
253
+ test("safety-harness: planned changed file avoids unexpected-file warning", (t) => {
254
+ const base = mkdtempSync(join(tmpdir(), "gsd-planned-file-"));
255
+ t.after(() => rmSync(base, { recursive: true, force: true }));
256
+
257
+ execFileSync("git", ["init"], { cwd: base });
258
+ execFileSync("git", ["config", "user.email", "test@example.com"], { cwd: base });
259
+ execFileSync("git", ["config", "user.name", "Test User"], { cwd: base });
260
+ writeFileSync(join(base, "index.html"), "<main></main>\n");
261
+ execFileSync("git", ["add", "index.html"], { cwd: base });
262
+ execFileSync("git", ["commit", "-m", "add static app"], { cwd: base });
263
+
264
+ const audit = validateFileChanges(base, [], ["index.html"]);
265
+ assert.ok(audit !== null, "audit must be produced");
266
+ assert.deepEqual(audit!.unexpectedFiles, [], "planned index.html must not be unexpected");
267
+ assert.deepEqual(audit!.missingFiles, [], "planned index.html must not be missing");
268
+ });
@@ -0,0 +1,156 @@
1
+ // gsd-2 / V27 + V28 schema migration regression tests
2
+ //
3
+ // Same bug class as #4591 (schema-v21-sequence): a migration block can be
4
+ // added but the SCHEMA_VERSION constant left unchanged, causing fresh-install
5
+ // + upgrade paths to silently skip the column add. This file pins both V27
6
+ // (artifacts.content_hash) and V28 (memories.last_hit_at) at the schema and
7
+ // write-path level on fresh-install DBs.
8
+
9
+ import test from "node:test";
10
+ import assert from "node:assert/strict";
11
+ import * as fs from "node:fs";
12
+ import * as path from "node:path";
13
+ import * as os from "node:os";
14
+
15
+ import {
16
+ openDatabase,
17
+ closeDatabase,
18
+ _getAdapter,
19
+ insertArtifact,
20
+ insertMemoryRow,
21
+ incrementMemoryHitCount,
22
+ SCHEMA_VERSION,
23
+ } from "../gsd-db.ts";
24
+
25
+ function makeTmp(): string {
26
+ return fs.mkdtempSync(path.join(os.tmpdir(), "gsd-v27v28-"));
27
+ }
28
+
29
+ function cleanup(base: string): void {
30
+ try { closeDatabase(); } catch { /* noop */ }
31
+ try { fs.rmSync(base, { recursive: true, force: true }); } catch { /* noop */ }
32
+ }
33
+
34
+ test("SCHEMA_VERSION constant is at least 28 (V28 migration committed)", () => {
35
+ assert.ok(
36
+ SCHEMA_VERSION >= 28,
37
+ `SCHEMA_VERSION must be ≥ 28 after V28 migration; got ${SCHEMA_VERSION}`,
38
+ );
39
+ });
40
+
41
+ test("fresh-install DB has artifacts.content_hash column (V27)", () => {
42
+ const base = makeTmp();
43
+ const dbPath = path.join(base, "gsd.db");
44
+ try {
45
+ openDatabase(dbPath);
46
+ const db = _getAdapter()!;
47
+ const cols = db.prepare("PRAGMA table_info(artifacts)").all() as Array<Record<string, unknown>>;
48
+ const colNames = new Set(cols.map((c) => c["name"] as string));
49
+ assert.ok(
50
+ colNames.has("content_hash"),
51
+ "V27 must add content_hash column to artifacts on fresh install",
52
+ );
53
+ } finally {
54
+ cleanup(base);
55
+ }
56
+ });
57
+
58
+ test("fresh-install DB has memories.last_hit_at column (V28)", () => {
59
+ const base = makeTmp();
60
+ const dbPath = path.join(base, "gsd.db");
61
+ try {
62
+ openDatabase(dbPath);
63
+ const db = _getAdapter()!;
64
+ const cols = db.prepare("PRAGMA table_info(memories)").all() as Array<Record<string, unknown>>;
65
+ const colNames = new Set(cols.map((c) => c["name"] as string));
66
+ assert.ok(
67
+ colNames.has("last_hit_at"),
68
+ "V28 must add last_hit_at column to memories on fresh install",
69
+ );
70
+ } finally {
71
+ cleanup(base);
72
+ }
73
+ });
74
+
75
+ test("fresh-install DB stamps SCHEMA_VERSION (≥28) in schema_version table", () => {
76
+ const base = makeTmp();
77
+ const dbPath = path.join(base, "gsd.db");
78
+ try {
79
+ openDatabase(dbPath);
80
+ const db = _getAdapter()!;
81
+ const row = db.prepare("SELECT MAX(version) as v FROM schema_version").get() as Record<string, unknown> | undefined;
82
+ const max = (row?.["v"] as number) ?? 0;
83
+ assert.ok(max >= 28, `fresh install must record schema_version ≥ 28; got ${max}`);
84
+ } finally {
85
+ cleanup(base);
86
+ }
87
+ });
88
+
89
+ test("insertArtifact populates content_hash with SHA-256 of full_content (V27 write-path)", () => {
90
+ const base = makeTmp();
91
+ const dbPath = path.join(base, "gsd.db");
92
+ try {
93
+ openDatabase(dbPath);
94
+ insertArtifact({
95
+ path: "M001/PROJECT.md",
96
+ artifact_type: "PROJECT",
97
+ milestone_id: "M001",
98
+ slice_id: null,
99
+ task_id: null,
100
+ full_content: "hello world",
101
+ });
102
+
103
+ const db = _getAdapter()!;
104
+ const row = db
105
+ .prepare("SELECT content_hash FROM artifacts WHERE path = :p")
106
+ .get({ ":p": "M001/PROJECT.md" }) as Record<string, unknown> | undefined;
107
+ const hash = row?.["content_hash"] as string | null | undefined;
108
+
109
+ // SHA-256 of "hello world" hex-encoded:
110
+ const expected = "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9";
111
+ assert.equal(hash, expected, "content_hash must be SHA-256 hex of full_content");
112
+ } finally {
113
+ cleanup(base);
114
+ }
115
+ });
116
+
117
+ test("incrementMemoryHitCount sets last_hit_at alongside hit_count (V28 write-path)", () => {
118
+ const base = makeTmp();
119
+ const dbPath = path.join(base, "gsd.db");
120
+ try {
121
+ openDatabase(dbPath);
122
+
123
+ const created = "2026-01-01T00:00:00.000Z";
124
+ insertMemoryRow({
125
+ id: "MEM001",
126
+ category: "gotcha",
127
+ content: "test memory",
128
+ confidence: 0.9,
129
+ sourceUnitType: null,
130
+ sourceUnitId: null,
131
+ createdAt: created,
132
+ updatedAt: created,
133
+ scope: "project",
134
+ tags: [],
135
+ structuredFields: null,
136
+ });
137
+
138
+ // Before increment: last_hit_at should be NULL
139
+ const db = _getAdapter()!;
140
+ const before = db
141
+ .prepare("SELECT last_hit_at FROM memories WHERE id = :id")
142
+ .get({ ":id": "MEM001" }) as Record<string, unknown>;
143
+ assert.equal(before["last_hit_at"], null, "last_hit_at starts NULL on fresh insert");
144
+
145
+ const hitTime = "2026-02-01T00:00:00.000Z";
146
+ incrementMemoryHitCount("MEM001", hitTime);
147
+
148
+ const after = db
149
+ .prepare("SELECT hit_count, last_hit_at FROM memories WHERE id = :id")
150
+ .get({ ":id": "MEM001" }) as Record<string, unknown>;
151
+ assert.equal(after["hit_count"], 1, "hit_count increments");
152
+ assert.equal(after["last_hit_at"], hitTime, "last_hit_at set to provided timestamp");
153
+ } finally {
154
+ cleanup(base);
155
+ }
156
+ });
@@ -0,0 +1,96 @@
1
+ // GSD-2 + src/resources/extensions/gsd/tests/select-resumable-milestone.test.ts
2
+ // Regression: bootstrap must rederive `currentMilestoneId` from an unmerged
3
+ // completed milestone branch when in-memory state was lost across a process
4
+ // restart (#5538-followup).
5
+
6
+ import test from "node:test";
7
+ import assert from "node:assert/strict";
8
+
9
+ import { _selectResumableMilestone } from "../auto-start.js";
10
+
11
+ const ALL_COMPLETE = (_id: string) => true;
12
+ const NEVER_COMPLETE = (_id: string) => false;
13
+ const HAS_COMMITS = (_branch: string) => 1;
14
+ const NO_COMMITS = (_branch: string) => 0;
15
+
16
+ test("returns null when no branches exist", () => {
17
+ const result = _selectResumableMilestone([], new Set(), ALL_COMPLETE, HAS_COMMITS);
18
+ assert.equal(result, null);
19
+ });
20
+
21
+ test("returns null when every milestone branch is already merged", () => {
22
+ const branches = ["milestone/M001", "milestone/M002"];
23
+ const merged = new Set(branches);
24
+ const result = _selectResumableMilestone(branches, merged, ALL_COMPLETE, HAS_COMMITS);
25
+ assert.equal(result, null);
26
+ });
27
+
28
+ test("returns null when no candidate milestones are complete", () => {
29
+ const branches = ["milestone/M002"];
30
+ const result = _selectResumableMilestone(branches, new Set(), NEVER_COMPLETE, HAS_COMMITS);
31
+ assert.equal(result, null);
32
+ });
33
+
34
+ test("returns null when no branch has commits ahead", () => {
35
+ const branches = ["milestone/M002"];
36
+ const result = _selectResumableMilestone(branches, new Set(), ALL_COMPLETE, NO_COMMITS);
37
+ assert.equal(result, null);
38
+ });
39
+
40
+ test("returns the unmerged completed milestone (regression: M002 stranded after restart)", () => {
41
+ // Repro of test12345 state: M001 ✅ merged, M002 ✅ unmerged, M003 🔄.
42
+ // Bootstrap must seed currentMilestoneId = "M002" so the loop's transition
43
+ // guard fires when the next iteration sees mid="M003".
44
+ const branches = ["milestone/M002", "milestone/M003"];
45
+ const merged = new Set<string>(); // none merged from this list
46
+ const isComplete = (id: string) => id === "M002"; // M003 still in progress
47
+ const result = _selectResumableMilestone(branches, merged, isComplete, HAS_COMMITS);
48
+ assert.equal(result, "M002");
49
+ });
50
+
51
+ test("picks the lex-greatest milestone when multiple candidates exist", () => {
52
+ // M001, M002 both unmerged complete -> pick M002 (the most recent).
53
+ const branches = ["milestone/M001", "milestone/M002"];
54
+ const result = _selectResumableMilestone(
55
+ branches,
56
+ new Set(),
57
+ ALL_COMPLETE,
58
+ HAS_COMMITS,
59
+ );
60
+ assert.equal(result, "M002");
61
+ });
62
+
63
+ test("ignores branch names that don't follow the milestone/ prefix", () => {
64
+ const branches = ["feature/something", "milestone/M002", "fix/bug-1"];
65
+ const result = _selectResumableMilestone(
66
+ branches,
67
+ new Set(),
68
+ ALL_COMPLETE,
69
+ HAS_COMMITS,
70
+ );
71
+ assert.equal(result, "M002");
72
+ });
73
+
74
+ test("isComplete callback throwing skips that milestone but does not crash", () => {
75
+ const branches = ["milestone/M001", "milestone/M002"];
76
+ const isComplete = (id: string) => {
77
+ if (id === "M001") throw new Error("db unavailable for M001");
78
+ return true;
79
+ };
80
+ // Implementation choice: a thrown isComplete is propagated. Wrapping in
81
+ // try/catch happens at the production wrapper level (findUnmergedCompletedMilestone).
82
+ // Verify the helper itself surfaces the error so callers see real failures.
83
+ assert.throws(() => _selectResumableMilestone(branches, new Set(), isComplete, HAS_COMMITS));
84
+ });
85
+
86
+ test("commitsAhead callback throwing for one branch falls through to others", () => {
87
+ // Production wrapper: commits-ahead failures should not abort the search.
88
+ // The helper catches throws from commitsAhead per-branch and treats as 0.
89
+ const branches = ["milestone/M001", "milestone/M002"];
90
+ const commitsAhead = (branch: string) => {
91
+ if (branch === "milestone/M001") throw new Error("rev-walk failed");
92
+ return 5;
93
+ };
94
+ const result = _selectResumableMilestone(branches, new Set(), ALL_COMPLETE, commitsAhead);
95
+ assert.equal(result, "M002");
96
+ });
@@ -206,6 +206,83 @@ test("session_start does NOT call setFooter or suppress gsd-health when isAutoAc
206
206
  assert.equal(healthWidgetHideCount, 0, "gsd-health must NOT be hidden when isAutoActive() is false");
207
207
  });
208
208
 
209
+ test("session_start installs the welcome screen as the TUI header", async (t) => {
210
+ const dir = join(
211
+ tmpdir(),
212
+ `gsd-welcome-header-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
213
+ );
214
+ mkdirSync(join(dir, "bin"), { recursive: true });
215
+ mkdirSync(join(dir, "dist"), { recursive: true });
216
+ writeFileSync(join(dir, "bin", "welcome-screen.js"), "export const stale = true;\n", "utf-8");
217
+ writeFileSync(
218
+ join(dir, "dist", "welcome-screen.js"),
219
+ [
220
+ "export function buildWelcomeScreenLines(opts) {",
221
+ " return [`welcome ${opts.version} ${opts.remoteChannel ?? 'none'} ${opts.width}`];",
222
+ "}",
223
+ "",
224
+ ].join("\n"),
225
+ "utf-8",
226
+ );
227
+
228
+ const originalCwd = process.cwd();
229
+ const originalGsdPkgRoot = process.env.GSD_PKG_ROOT;
230
+ const originalGsdBinPath = process.env.GSD_BIN_PATH;
231
+ const originalGsdVersion = process.env.GSD_VERSION;
232
+ const originalFirstRunBanner = process.env.GSD_FIRST_RUN_BANNER;
233
+ process.chdir(dir);
234
+ process.env.GSD_PKG_ROOT = dir;
235
+ process.env.GSD_BIN_PATH = join(dir, "bin", "loader.js");
236
+ process.env.GSD_VERSION = "9.9.9-test";
237
+ delete process.env.GSD_FIRST_RUN_BANNER;
238
+ t.after(() => {
239
+ process.chdir(originalCwd);
240
+ if (originalGsdPkgRoot === undefined) delete process.env.GSD_PKG_ROOT;
241
+ else process.env.GSD_PKG_ROOT = originalGsdPkgRoot;
242
+ if (originalGsdBinPath === undefined) delete process.env.GSD_BIN_PATH;
243
+ else process.env.GSD_BIN_PATH = originalGsdBinPath;
244
+ if (originalGsdVersion === undefined) delete process.env.GSD_VERSION;
245
+ else process.env.GSD_VERSION = originalGsdVersion;
246
+ if (originalFirstRunBanner === undefined) delete process.env.GSD_FIRST_RUN_BANNER;
247
+ else process.env.GSD_FIRST_RUN_BANNER = originalFirstRunBanner;
248
+ try { rmSync(dir, { recursive: true, force: true }); } catch { /* best-effort */ }
249
+ });
250
+
251
+ const handlers = new Map<string, (event: unknown, ctx: any) => Promise<void> | void>();
252
+ const pi = {
253
+ on(event: string, handler: (event: unknown, ctx: any) => Promise<void> | void) {
254
+ handlers.set(event, handler);
255
+ },
256
+ } as any;
257
+
258
+ registerHooks(pi, []);
259
+
260
+ const sessionStart = handlers.get("session_start");
261
+ assert.ok(sessionStart, "session_start handler must be registered");
262
+
263
+ let headerFactory: ((tui: unknown, theme: unknown) => { render(width: number): string[] }) | undefined;
264
+ await sessionStart!({}, {
265
+ hasUI: true,
266
+ ui: {
267
+ notify: () => {},
268
+ setStatus: () => {},
269
+ setFooter: () => {},
270
+ setHeader: (factory: typeof headerFactory) => {
271
+ headerFactory = factory;
272
+ },
273
+ setWorkingMessage: () => {},
274
+ onTerminalInput: () => () => {},
275
+ setWidget: () => {},
276
+ },
277
+ sessionManager: { getSessionId: () => null },
278
+ model: null,
279
+ } as any);
280
+
281
+ assert.equal(typeof headerFactory, "function", "session_start should install a header factory");
282
+ const header = headerFactory!({}, {});
283
+ assert.deepEqual(header.render(123), ["welcome 9.9.9-test none 123"]);
284
+ });
285
+
209
286
  test("session_start and session_switch apply disabled model provider policy from current preferences", async (t) => {
210
287
  const dir = join(
211
288
  tmpdir(),
@@ -0,0 +1,166 @@
1
+ // GSD-2 + src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts
2
+ // Regression: session-transition aborts must not be classified as user cancellations.
3
+
4
+ import test from "node:test";
5
+ import assert from "node:assert/strict";
6
+
7
+ import {
8
+ _handleSessionSwitchAgentEnd,
9
+ isClaudeCodeSessionSwitchAbortMessage,
10
+ } from "../bootstrap/agent-end-recovery.js";
11
+ import type { ErrorContext } from "../auto/types.js";
12
+
13
+ test("user-abort message during session-switch is dropped (not propagated as cancellation)", () => {
14
+ // The Anthropic SDK emits this exact string when newSession() aborts an
15
+ // in-flight stream during a unit-to-unit session transition. Before the fix
16
+ // this was misclassified as a user cancellation and killed auto-mode with
17
+ // "Auto-mode stopped — Unit aborted: Claude Code process aborted by user".
18
+ let cancelledWith: ErrorContext | null = null;
19
+ const resolveCancelled = (ctx: ErrorContext) => {
20
+ cancelledWith = ctx;
21
+ return true;
22
+ };
23
+
24
+ _handleSessionSwitchAgentEnd(
25
+ { stopReason: "error", errorMessage: "Claude Code process aborted by user" },
26
+ resolveCancelled,
27
+ );
28
+ assert.equal(cancelledWith, null, "SDK user-abort during session-switch must not propagate cancellation");
29
+
30
+ _handleSessionSwitchAgentEnd(
31
+ { stopReason: "error", errorMessage: "Request aborted by user" },
32
+ resolveCancelled,
33
+ );
34
+ assert.equal(cancelledWith, null, "proxy user-abort during session-switch must not propagate cancellation");
35
+ });
36
+
37
+ test("genuine stopReason='aborted' with errorMessage during session-switch still propagates", () => {
38
+ // Regression guard for prior behavior: genuine aborts with diagnostic content
39
+ // continue to surface as cancellations so transient-pause recovery can run.
40
+ let cancelledWith: { message: string; category: string; isTransient?: boolean } | null = null;
41
+ const resolveCancelled = (ctx: ErrorContext) => {
42
+ cancelledWith = ctx;
43
+ return true;
44
+ };
45
+
46
+ _handleSessionSwitchAgentEnd(
47
+ {
48
+ stopReason: "aborted",
49
+ errorMessage: "stream torn down mid-flight",
50
+ content: [{ type: "text", text: "partial output" }],
51
+ },
52
+ resolveCancelled,
53
+ );
54
+
55
+ assert.deepEqual(cancelledWith, {
56
+ message: "stream torn down mid-flight",
57
+ category: "aborted",
58
+ isTransient: true,
59
+ });
60
+ });
61
+
62
+ test("Claude Code stream-aborted placeholder during session-switch is dropped", () => {
63
+ let cancelledWith: unknown = null;
64
+ const resolveCancelled = (ctx: ErrorContext) => {
65
+ cancelledWith = ctx;
66
+ return true;
67
+ };
68
+
69
+ _handleSessionSwitchAgentEnd(
70
+ {
71
+ stopReason: "aborted",
72
+ content: [{ type: "text", text: "Claude Code stream aborted by caller" }],
73
+ },
74
+ resolveCancelled,
75
+ );
76
+
77
+ assert.equal(cancelledWith, null);
78
+ });
79
+
80
+ test("Claude Code session-switch abort detection is narrow", () => {
81
+ assert.equal(
82
+ isClaudeCodeSessionSwitchAbortMessage({
83
+ stopReason: "error",
84
+ content: [{ type: "text", text: "Claude Code error: Claude Code process aborted by user" }],
85
+ }),
86
+ false,
87
+ );
88
+ assert.equal(
89
+ isClaudeCodeSessionSwitchAbortMessage({
90
+ stopReason: "aborted",
91
+ content: [{ type: "text", text: "Claude Code stream aborted by caller" }],
92
+ }),
93
+ true,
94
+ );
95
+ assert.equal(
96
+ isClaudeCodeSessionSwitchAbortMessage({
97
+ stopReason: "aborted",
98
+ content: [{ type: "text", text: "partial output before network failure" }],
99
+ }),
100
+ false,
101
+ );
102
+ assert.equal(
103
+ isClaudeCodeSessionSwitchAbortMessage({
104
+ stopReason: "aborted",
105
+ content: [{ type: "text", text: "Request aborted by user\nAPI Error: 529 overloaded" }],
106
+ }),
107
+ false,
108
+ );
109
+ assert.equal(
110
+ isClaudeCodeSessionSwitchAbortMessage({
111
+ stopReason: "error",
112
+ errorMessage: "Request aborted by user",
113
+ content: [{ type: "text", text: "Claude Code process aborted by user" }],
114
+ }),
115
+ true,
116
+ );
117
+ });
118
+
119
+ test("empty-content aborted during session-switch is silently ignored", () => {
120
+ // Empty-content aborted is a non-fatal LLM stop; we must not pause/cancel.
121
+ let cancelledWith: unknown = null;
122
+ const resolveCancelled = (ctx: ErrorContext) => {
123
+ cancelledWith = ctx;
124
+ return true;
125
+ };
126
+
127
+ _handleSessionSwitchAgentEnd(
128
+ { stopReason: "aborted", content: [] },
129
+ resolveCancelled,
130
+ );
131
+
132
+ assert.equal(cancelledWith, null);
133
+ });
134
+
135
+ test("non-abort errors during session-switch are not propagated through this helper", () => {
136
+ // Real provider errors (rate-limit, network, unsupported-model) are handled
137
+ // by the post-switch retry pipeline — not by the in-flight switch handler.
138
+ let cancelledWith: unknown = null;
139
+ const resolveCancelled = (ctx: ErrorContext) => {
140
+ cancelledWith = ctx;
141
+ return true;
142
+ };
143
+
144
+ _handleSessionSwitchAgentEnd(
145
+ { stopReason: "error", errorMessage: "rate limit exceeded" },
146
+ resolveCancelled,
147
+ );
148
+
149
+ assert.equal(cancelledWith, null);
150
+ });
151
+
152
+ test("malformed lastMsg is rejected gracefully", () => {
153
+ let calls = 0;
154
+ const resolveCancelled = (_ctx: unknown) => {
155
+ calls += 1;
156
+ return true;
157
+ };
158
+
159
+ _handleSessionSwitchAgentEnd(undefined, resolveCancelled as never);
160
+ _handleSessionSwitchAgentEnd(null, resolveCancelled as never);
161
+ _handleSessionSwitchAgentEnd("not an object", resolveCancelled as never);
162
+ _handleSessionSwitchAgentEnd({}, resolveCancelled as never);
163
+ _handleSessionSwitchAgentEnd({ stopReason: "completed" }, resolveCancelled as never);
164
+
165
+ assert.equal(calls, 0, "malformed or non-abort lastMsg must not invoke cancellation");
166
+ });
@@ -101,3 +101,30 @@ test("registerSigtermHandler deregisters previous handler from all signals", ()
101
101
  // Clean up
102
102
  deregisterSigtermHandler(handler2);
103
103
  });
104
+
105
+ test("registered signal handler runs best-effort cleanup before exiting", () => {
106
+ let cleanupCalled = false;
107
+ let exitCode: number | string | null | undefined;
108
+ const originalExit = process.exit;
109
+ const handler = registerSigtermHandler(
110
+ "/tmp/test-signal-cleanup",
111
+ null,
112
+ () => {
113
+ cleanupCalled = true;
114
+ },
115
+ );
116
+
117
+ (process as any).exit = ((code?: number | string | null) => {
118
+ exitCode = code;
119
+ throw new Error("process.exit intercepted");
120
+ }) as never;
121
+
122
+ try {
123
+ assert.throws(() => handler(), /process\.exit intercepted/);
124
+ assert.equal(cleanupCalled, true);
125
+ assert.equal(exitCode, 0);
126
+ } finally {
127
+ (process as any).exit = originalExit;
128
+ deregisterSigtermHandler(handler);
129
+ }
130
+ });
@@ -47,6 +47,9 @@ test("guided-flow complete branch offers a chooser for next milestone or status"
47
47
  const branchChunk = guidedFlowSource.slice(branchIdx, nextBranchIdx === -1 ? branchIdx + 1600 : nextBranchIdx);
48
48
 
49
49
  assert.match(branchChunk, /showNextAction\(/, "complete branch should present a chooser");
50
+ assert.match(branchChunk, /id:\s*"quick_task"/, "complete branch should offer quick task before milestone planning");
51
+ assert.match(branchChunk, /Do a small bounded task without opening a milestone/, "quick task action should explain that it avoids milestones");
52
+ assert.match(branchChunk, /recommended:\s*true/, "quick task action should be the recommended complete-state action");
50
53
  assert.match(branchChunk, /findMilestoneIds\(basePath\)/, "complete branch should compute the next milestone id");
51
54
  assert.match(
52
55
  branchChunk,
@@ -56,6 +59,41 @@ test("guided-flow complete branch offers a chooser for next milestone or status"
56
59
  assert.match(branchChunk, /dispatchWorkflow\(pi, await prepareAndBuildDiscussPrompt\(/, "complete branch should dispatch the prepared discuss prompt");
57
60
  });
58
61
 
62
+ test("guided-flow quick task choices prompt for text and route through /gsd quick", () => {
63
+ const guidedFlowSource = readFileSync(join(import.meta.dirname, "..", "guided-flow.ts"), "utf-8");
64
+
65
+ assert.match(
66
+ guidedFlowSource,
67
+ /async function runQuickTaskChoice\([\s\S]*ctx\.ui\.input\("Quick task"[\s\S]*await import\("\.\/quick\.js"\)[\s\S]*await handleQuick\(task,\s*ctx,\s*pi\)/,
68
+ "quick task chooser should prompt for task text and route through handleQuick",
69
+ );
70
+
71
+ const notifyOnlyPattern = /if \(choice === "quick_task"\) \{\s*ctx\.ui\.notify\("Run \/gsd quick <task>/;
72
+ assert.doesNotMatch(
73
+ guidedFlowSource,
74
+ notifyOnlyPattern,
75
+ "quick task chooser must not merely print instructions after selection",
76
+ );
77
+
78
+ const quickChoiceCalls = guidedFlowSource.match(/if \(choice === "quick_task"\) \{\s*await runQuickTaskChoice\(ctx,\s*pi\);/g) ?? [];
79
+ assert.equal(quickChoiceCalls.length, 3, "all guided-flow quick task choices should dispatch the helper");
80
+ });
81
+
82
+ test("dispatcher routes multi-word freeform /gsd input through /gsd do", () => {
83
+ const dispatcherSource = readFileSync(join(import.meta.dirname, "..", "commands", "dispatcher.ts"), "utf-8");
84
+
85
+ assert.match(
86
+ dispatcherSource,
87
+ /if\s*\(trimmed\.includes\(" "\)\)\s*\{[\s\S]*handleDo\(trimmed,\s*ctx,\s*pi\)/,
88
+ "dispatcher should treat multi-word unknown input as natural-language /gsd do work",
89
+ );
90
+ assert.match(
91
+ dispatcherSource,
92
+ /Unknown: \/gsd/,
93
+ "single-token unknown commands should still report the normal unknown-command warning",
94
+ );
95
+ });
96
+
59
97
  test("guided-flow needs-discussion skip branch opens the project DB before reserving a new milestone", () => {
60
98
  const guidedFlowSource = readFileSync(join(import.meta.dirname, "..", "guided-flow.ts"), "utf-8");
61
99
  const laterDbOpenIdx = guidedFlowSource.indexOf("// Ensure DB is open before querying slices (#2560).");