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
@@ -85,7 +85,11 @@ function makeMockDeps(
85
85
  resolveMilestoneFile: () => null,
86
86
  reconcileMergeState: () => "clean",
87
87
  preflightCleanRoot: () => ({ stashPushed: false, summary: "" }),
88
- postflightPopStash: () => {},
88
+ postflightPopStash: () => ({
89
+ restored: true,
90
+ needsManualRecovery: false,
91
+ message: "restored",
92
+ }),
89
93
  getLedger: () => ({ units: [] }),
90
94
  getProjectTotals: () => ({ cost: 0 }),
91
95
  formatCost: (c: number) => `$${c.toFixed(2)}`,
@@ -399,6 +403,240 @@ test("runDispatch pauses when complete-milestone summary exists on disk but the
399
403
  assert.equal(stopCalls, 0, "mismatch pause should not hard-stop the loop");
400
404
  });
401
405
 
406
+ test("runDispatch pauses when execute-task artifacts exist but DB status is still open", async (t) => {
407
+ const capture = createEventCapture();
408
+ let pauseCalls = 0;
409
+ let stopCalls = 0;
410
+ let invalidateCalls = 0;
411
+ const base = join(tmpdir(), `gsd-stuck-execute-task-${randomUUID()}`);
412
+ t.after(() => {
413
+ closeDatabase();
414
+ rmSync(base, { recursive: true, force: true });
415
+ });
416
+
417
+ const sliceDir = join(base, ".gsd", "milestones", "M001", "slices", "S01");
418
+ const tasksDir = join(sliceDir, "tasks");
419
+ mkdirSync(tasksDir, { recursive: true });
420
+ openDatabase(join(base, ".gsd", "gsd.db"));
421
+ insertMilestone({ id: "M001", title: "Test", status: "active" });
422
+ insertSlice({ id: "S01", milestoneId: "M001", title: "Slice", status: "in_progress" });
423
+ insertTask({ id: "T01", milestoneId: "M001", sliceId: "S01", title: "First task", status: "pending" });
424
+ writeFileSync(
425
+ join(sliceDir, "S01-PLAN.md"),
426
+ [
427
+ "# S01",
428
+ "",
429
+ "## Tasks",
430
+ "",
431
+ "- [x] **T01: First task** `est:1h`",
432
+ "",
433
+ ].join("\n"),
434
+ );
435
+ writeFileSync(join(tasksDir, "T01-PLAN.md"), "# T01 Plan\n");
436
+ writeFileSync(join(tasksDir, "T01-SUMMARY.md"), "# T01 Summary\n\nDone on disk.\n");
437
+
438
+ const deps = makeMockDeps(capture, {
439
+ pauseAuto: async () => { pauseCalls++; },
440
+ stopAuto: async () => { stopCalls++; },
441
+ invalidateAllCaches: () => { invalidateCalls++; },
442
+ resolveDispatch: async () => ({
443
+ action: "dispatch" as const,
444
+ unitType: "execute-task",
445
+ unitId: "M001/S01/T01",
446
+ prompt: "execute the task",
447
+ matchedRule: "executing → execute-task",
448
+ }),
449
+ });
450
+ const ic = makeIC(deps, {
451
+ s: {
452
+ ...makeSession(),
453
+ basePath: base,
454
+ originalBasePath: base,
455
+ } as any,
456
+ });
457
+ const preData: PreDispatchData = {
458
+ state: {
459
+ phase: "executing",
460
+ activeMilestone: { id: "M001", title: "Test", status: "active" },
461
+ activeSlice: { id: "S01", title: "Slice" },
462
+ activeTask: { id: "T01", title: "First task" },
463
+ registry: [{ id: "M001", status: "active" }],
464
+ blockers: [],
465
+ } as any,
466
+ mid: "M001",
467
+ midTitle: "Test Milestone",
468
+ };
469
+ const loopState: LoopState = {
470
+ recentUnits: [
471
+ { key: "execute-task/M001/S01/T01" },
472
+ { key: "execute-task/M001/S01/T01" },
473
+ ],
474
+ stuckRecoveryAttempts: 0,
475
+ consecutiveFinalizeTimeouts: 0,
476
+ };
477
+
478
+ const result = await runDispatch(ic, preData, loopState);
479
+
480
+ assert.equal(result.action, "break");
481
+ assert.equal((result as any).reason, "execute-task-artifact-db-mismatch");
482
+ assert.equal(pauseCalls, 1, "execute-task disk/db mismatch should pause auto-mode");
483
+ assert.equal(stopCalls, 0, "execute-task disk/db mismatch should not hard-stop the loop");
484
+ assert.equal(invalidateCalls, 0, "mismatch should not clear caches and continue toward redispatch");
485
+ assert.equal(loopState.recentUnits.length, 3, "mismatch should keep the stuck window intact");
486
+ assert.equal(loopState.stuckRecoveryAttempts, 1, "mismatch should not reset the recovery counter");
487
+ });
488
+
489
+ test("runDispatch pauses at Level 2 when execute-task artifacts exist but DB status is still open", async (t) => {
490
+ const capture = createEventCapture();
491
+ let pauseCalls = 0;
492
+ let stopCalls = 0;
493
+ let invalidateCalls = 0;
494
+ const base = join(tmpdir(), `gsd-stuck-execute-task-l2-${randomUUID()}`);
495
+ t.after(() => {
496
+ closeDatabase();
497
+ rmSync(base, { recursive: true, force: true });
498
+ });
499
+
500
+ const sliceDir = join(base, ".gsd", "milestones", "M001", "slices", "S01");
501
+ const tasksDir = join(sliceDir, "tasks");
502
+ mkdirSync(tasksDir, { recursive: true });
503
+ openDatabase(join(base, ".gsd", "gsd.db"));
504
+ insertMilestone({ id: "M001", title: "Test", status: "active" });
505
+ insertSlice({ id: "S01", milestoneId: "M001", title: "Slice", status: "in_progress" });
506
+ insertTask({ id: "T01", milestoneId: "M001", sliceId: "S01", title: "First task", status: "pending" });
507
+ writeFileSync(
508
+ join(sliceDir, "S01-PLAN.md"),
509
+ "# S01\n\n## Tasks\n\n- [x] **T01: First task** `est:1h`\n",
510
+ );
511
+ writeFileSync(join(tasksDir, "T01-PLAN.md"), "# T01 Plan\n");
512
+ writeFileSync(join(tasksDir, "T01-SUMMARY.md"), "# T01 Summary\n\nDone on disk.\n");
513
+
514
+ const deps = makeMockDeps(capture, {
515
+ pauseAuto: async () => { pauseCalls++; },
516
+ stopAuto: async () => { stopCalls++; },
517
+ invalidateAllCaches: () => { invalidateCalls++; },
518
+ resolveDispatch: async () => ({
519
+ action: "dispatch" as const,
520
+ unitType: "execute-task",
521
+ unitId: "M001/S01/T01",
522
+ prompt: "execute the task",
523
+ matchedRule: "executing execute-task",
524
+ }),
525
+ });
526
+ const ic = makeIC(deps, {
527
+ s: {
528
+ ...makeSession(),
529
+ basePath: base,
530
+ originalBasePath: base,
531
+ } as any,
532
+ });
533
+ const preData: PreDispatchData = {
534
+ state: {
535
+ phase: "executing",
536
+ activeMilestone: { id: "M001", title: "Test", status: "active" },
537
+ activeSlice: { id: "S01", title: "Slice" },
538
+ activeTask: { id: "T01", title: "First task" },
539
+ registry: [{ id: "M001", status: "active" }],
540
+ blockers: [],
541
+ } as any,
542
+ mid: "M001",
543
+ midTitle: "Test Milestone",
544
+ };
545
+ const loopState: LoopState = {
546
+ recentUnits: [
547
+ { key: "execute-task/M001/S01/T01" },
548
+ { key: "execute-task/M001/S01/T01" },
549
+ ],
550
+ stuckRecoveryAttempts: 1,
551
+ consecutiveFinalizeTimeouts: 0,
552
+ };
553
+
554
+ const result = await runDispatch(ic, preData, loopState);
555
+
556
+ assert.equal(result.action, "break");
557
+ assert.equal((result as any).reason, "execute-task-artifact-db-mismatch");
558
+ assert.equal(pauseCalls, 1, "Level 2 execute-task disk/db mismatch should pause auto-mode");
559
+ assert.equal(stopCalls, 0, "Level 2 execute-task disk/db mismatch should not hard-stop the loop");
560
+ assert.equal(invalidateCalls, 1, "Level 2 should invalidate caches before the final artifact recheck");
561
+ assert.equal(loopState.recentUnits.length, 3, "Level 2 mismatch should keep the stuck window intact");
562
+ assert.equal(loopState.stuckRecoveryAttempts, 1, "Level 2 mismatch should not reset the recovery counter");
563
+ });
564
+
565
+ test("runDispatch clears execute-task stuck state when artifacts and DB status are complete", async (t) => {
566
+ const capture = createEventCapture();
567
+ let pauseCalls = 0;
568
+ let stopCalls = 0;
569
+ let invalidateCalls = 0;
570
+ const base = join(tmpdir(), `gsd-stuck-execute-task-complete-${randomUUID()}`);
571
+ t.after(() => {
572
+ closeDatabase();
573
+ rmSync(base, { recursive: true, force: true });
574
+ });
575
+
576
+ const sliceDir = join(base, ".gsd", "milestones", "M001", "slices", "S01");
577
+ const tasksDir = join(sliceDir, "tasks");
578
+ mkdirSync(tasksDir, { recursive: true });
579
+ openDatabase(join(base, ".gsd", "gsd.db"));
580
+ insertMilestone({ id: "M001", title: "Test", status: "active" });
581
+ insertSlice({ id: "S01", milestoneId: "M001", title: "Slice", status: "in_progress" });
582
+ insertTask({ id: "T01", milestoneId: "M001", sliceId: "S01", title: "First task", status: "complete" });
583
+ writeFileSync(
584
+ join(sliceDir, "S01-PLAN.md"),
585
+ "# S01\n\n## Tasks\n\n- [x] **T01: First task** `est:1h`\n",
586
+ );
587
+ writeFileSync(join(tasksDir, "T01-PLAN.md"), "# T01 Plan\n");
588
+ writeFileSync(join(tasksDir, "T01-SUMMARY.md"), "# T01 Summary\n\nDone on disk.\n");
589
+
590
+ const deps = makeMockDeps(capture, {
591
+ pauseAuto: async () => { pauseCalls++; },
592
+ stopAuto: async () => { stopCalls++; },
593
+ invalidateAllCaches: () => { invalidateCalls++; },
594
+ resolveDispatch: async () => ({
595
+ action: "dispatch" as const,
596
+ unitType: "execute-task",
597
+ unitId: "M001/S01/T01",
598
+ prompt: "execute the task",
599
+ matchedRule: "executing execute-task",
600
+ }),
601
+ });
602
+ const ic = makeIC(deps, {
603
+ s: {
604
+ ...makeSession(),
605
+ basePath: base,
606
+ originalBasePath: base,
607
+ } as any,
608
+ });
609
+ const preData: PreDispatchData = {
610
+ state: {
611
+ phase: "executing",
612
+ activeMilestone: { id: "M001", title: "Test", status: "active" },
613
+ activeSlice: { id: "S01", title: "Slice" },
614
+ activeTask: { id: "T01", title: "First task" },
615
+ registry: [{ id: "M001", status: "active" }],
616
+ blockers: [],
617
+ } as any,
618
+ mid: "M001",
619
+ midTitle: "Test Milestone",
620
+ };
621
+ const loopState: LoopState = {
622
+ recentUnits: [
623
+ { key: "execute-task/M001/S01/T01" },
624
+ { key: "execute-task/M001/S01/T01" },
625
+ ],
626
+ stuckRecoveryAttempts: 0,
627
+ consecutiveFinalizeTimeouts: 0,
628
+ };
629
+
630
+ const result = await runDispatch(ic, preData, loopState);
631
+
632
+ assert.equal(result.action, "continue");
633
+ assert.equal(pauseCalls, 0, "closed DB task should not pause auto-mode");
634
+ assert.equal(stopCalls, 0, "closed DB task should not hard-stop the loop");
635
+ assert.equal(invalidateCalls, 1, "closed DB task recovery should invalidate caches once");
636
+ assert.deepEqual(loopState.recentUnits, [], "closed DB task recovery should clear the stuck window");
637
+ assert.equal(loopState.stuckRecoveryAttempts, 0, "closed DB task recovery should reset the recovery counter");
638
+ });
639
+
402
640
  test("runDispatch clears stuck state after Level 1 artifact recovery", async (t) => {
403
641
  const capture = createEventCapture();
404
642
  let invalidateCalls = 0;
@@ -52,6 +52,16 @@ async function executeToolInDir(tool: any, params: Record<string, unknown>, dir:
52
52
  }
53
53
  }
54
54
 
55
+ async function executeToolWithContextRoot(tool: any, params: Record<string, unknown>, processDir: string, contextRoot: string) {
56
+ const originalCwd = process.cwd();
57
+ try {
58
+ process.chdir(processDir);
59
+ return await tool.execute("test-call-id", params, undefined, undefined, { cwd: contextRoot });
60
+ } finally {
61
+ process.chdir(originalCwd);
62
+ }
63
+ }
64
+
55
65
  // ─── Registration ─────────────────────────────────────────────────────────────
56
66
 
57
67
  test("registerJournalTools registers gsd_journal_query tool", () => {
@@ -126,6 +136,28 @@ test("gsd_journal_query respects limit parameter", async () => {
126
136
  }
127
137
  });
128
138
 
139
+ test("gsd_journal_query uses context cwd instead of process cwd", async () => {
140
+ const processBase = makeTmpBase();
141
+ const contextBase = makeTmpBase();
142
+ try {
143
+ emitJournalEvent(processBase, makeEntry({ seq: 0, flowId: "process-flow" }));
144
+ emitJournalEvent(contextBase, makeEntry({ seq: 0, flowId: "context-flow" }));
145
+
146
+ const pi = makeMockPi();
147
+ registerJournalTools(pi);
148
+ const tool = pi.tools[0];
149
+
150
+ const result = await executeToolWithContextRoot(tool, { limit: 5 }, processBase, contextBase);
151
+ const entries = JSON.parse(result.content[0].text) as JournalEntry[];
152
+
153
+ assert.equal(entries.length, 1);
154
+ assert.equal(entries[0].flowId, "context-flow");
155
+ } finally {
156
+ cleanup(processBase);
157
+ cleanup(contextBase);
158
+ }
159
+ });
160
+
129
161
  // ─── Error Handling ───────────────────────────────────────────────────────────
130
162
 
131
163
  test("gsd_journal_query handles errors gracefully", async () => {
@@ -249,6 +249,28 @@ test('loadKnowledgeBlock: reports globalSizeKb above 4KB threshold', () => {
249
249
  rmSync(tmp, { recursive: true, force: true });
250
250
  });
251
251
 
252
+ test('loadKnowledgeBlock: caps repeated system prompt knowledge by default with source path', () => {
253
+ const tmp = realpathSync(mkdtempSync(join(tmpdir(), 'gsd-kb-')));
254
+ const gsdHome = join(tmp, 'home');
255
+ const cwd = join(tmp, 'project');
256
+ mkdirSync(join(cwd, '.gsd'), { recursive: true });
257
+ mkdirSync(join(gsdHome, 'agent'), { recursive: true });
258
+ writeFileSync(join(cwd, '.gsd', 'KNOWLEDGE.md'), `K001: ${'large project knowledge '.repeat(1200)}`);
259
+
260
+ const original = process.env.PI_GSD_KNOWLEDGE_MAX_CHARS;
261
+ delete process.env.PI_GSD_KNOWLEDGE_MAX_CHARS;
262
+ try {
263
+ const result = loadKnowledgeBlock(gsdHome, cwd);
264
+ assert.ok(result.block.includes('Source: `'));
265
+ assert.ok(result.block.length <= 12_500, `knowledge block ${result.block.length} should stay near default cap`);
266
+ assert.ok(result.block.includes('[Knowledge Truncated]'));
267
+ } finally {
268
+ if (original === undefined) delete process.env.PI_GSD_KNOWLEDGE_MAX_CHARS;
269
+ else process.env.PI_GSD_KNOWLEDGE_MAX_CHARS = original;
270
+ rmSync(tmp, { recursive: true, force: true });
271
+ }
272
+ });
273
+
252
274
  // ─── inlineKnowledgeBudgeted — issue #4719 ─────────────────────────────────
253
275
  // Milestone-phase prompts must not inject the full KNOWLEDGE.md. The budgeted
254
276
  // helper scopes by milestone-level keywords and caps the injected size.
@@ -315,6 +337,31 @@ test('inlineKnowledgeBudgeted: caps payload below budget for large files', async
315
337
  rmSync(tmp, { recursive: true, force: true });
316
338
  });
317
339
 
340
+ test('inlineKnowledgeBudgeted: default budget keeps auto prompt knowledge compact', async () => {
341
+ const tmp = realpathSync(mkdtempSync(join(tmpdir(), 'gsd-knowledge-')));
342
+ const gsdDir = join(tmp, '.gsd');
343
+ mkdirSync(gsdDir, { recursive: true });
344
+
345
+ const entries = Array.from({ length: 300 }, (_, i) =>
346
+ `### Entry ${i}: shared topic\n${'default budget filler '.repeat(25)}\n`,
347
+ ).join('\n');
348
+ writeFileSync(join(gsdDir, 'KNOWLEDGE.md'), `# Project Knowledge\n\n## Patterns\n\n${entries}`);
349
+
350
+ const result = await inlineKnowledgeBudgeted(tmp, ['shared']);
351
+ assert.ok(result !== null, 'should return content');
352
+ assert.ok(
353
+ result!.length <= 12_500,
354
+ `default payload ${result!.length} chars should stay near the 12k budget`,
355
+ );
356
+ assert.match(
357
+ result!,
358
+ /\[\.\.\.truncated \d+ chars; rerun with narrower scope if needed\]/,
359
+ 'should include truncation note when default budget is exceeded',
360
+ );
361
+
362
+ rmSync(tmp, { recursive: true, force: true });
363
+ });
364
+
318
365
  test('inlineKnowledgeBudgeted: returns null when no KNOWLEDGE.md exists', async () => {
319
366
  const tmp = realpathSync(mkdtempSync(join(tmpdir(), 'gsd-knowledge-')));
320
367
  const gsdDir = join(tmp, '.gsd');
@@ -0,0 +1,90 @@
1
+ // gsd-2 / memoryDecayFactor unit tests
2
+ //
3
+ // Pure-function boundary tests for the V28 time-decay scoring helper.
4
+ // The function maps last_hit_at → multiplier in [0.7, 1.0] used by
5
+ // queryMemoriesRanked to down-weight stale memories without fully suppressing
6
+ // them. These tests pin the contract:
7
+ //
8
+ // - null / invalid / future timestamps → 1.0 (no decay penalty)
9
+ // - 0 days ago → 1.0
10
+ // - linear decay between 0 and 90 days
11
+ // - 90+ days ago → 0.7 floor
12
+
13
+ import test from "node:test";
14
+ import assert from "node:assert/strict";
15
+
16
+ import { memoryDecayFactor } from "../memory-store.ts";
17
+
18
+ const DAY_MS = 86_400_000;
19
+
20
+ function isoDaysAgo(days: number): string {
21
+ return new Date(Date.now() - days * DAY_MS).toISOString();
22
+ }
23
+
24
+ test("memoryDecayFactor: null lastHitAt returns 1.0 (never-hit = no decay)", () => {
25
+ assert.equal(memoryDecayFactor(null), 1.0);
26
+ });
27
+
28
+ test("memoryDecayFactor: invalid timestamp string returns 1.0 (defensive)", () => {
29
+ assert.equal(memoryDecayFactor("not-a-date"), 1.0);
30
+ assert.equal(memoryDecayFactor(""), 1.0);
31
+ });
32
+
33
+ test("memoryDecayFactor: future timestamp clamps to daysAgo=0 → 1.0", () => {
34
+ // Clock skew or manual DB edits can yield future last_hit_at values.
35
+ // The factor must stay within [0.7, 1.0] regardless.
36
+ const future = new Date(Date.now() + 30 * DAY_MS).toISOString();
37
+ const factor = memoryDecayFactor(future);
38
+ assert.ok(factor <= 1.0, `factor must not exceed 1.0, got ${factor}`);
39
+ assert.ok(factor >= 0.7, `factor must not fall below 0.7, got ${factor}`);
40
+ assert.equal(factor, 1.0);
41
+ });
42
+
43
+ test("memoryDecayFactor: 0 days ago returns 1.0", () => {
44
+ const factor = memoryDecayFactor(new Date().toISOString());
45
+ // Tiny clock drift between now-string and Date.now() inside the function;
46
+ // assert it's effectively 1.0 within float tolerance.
47
+ assert.ok(Math.abs(factor - 1.0) < 1e-6, `expected ≈1.0, got ${factor}`);
48
+ });
49
+
50
+ test("memoryDecayFactor: 30 days ago returns ~0.90 (linear midpoint)", () => {
51
+ // Formula: 1.0 - 0.3 * (30/90) = 1.0 - 0.1 = 0.90
52
+ const factor = memoryDecayFactor(isoDaysAgo(30));
53
+ assert.ok(Math.abs(factor - 0.90) < 1e-3, `expected ≈0.90, got ${factor}`);
54
+ });
55
+
56
+ test("memoryDecayFactor: 60 days ago returns ~0.80", () => {
57
+ // Formula: 1.0 - 0.3 * (60/90) = 1.0 - 0.2 = 0.80
58
+ const factor = memoryDecayFactor(isoDaysAgo(60));
59
+ assert.ok(Math.abs(factor - 0.80) < 1e-3, `expected ≈0.80, got ${factor}`);
60
+ });
61
+
62
+ test("memoryDecayFactor: 90 days ago returns 0.70 (floor)", () => {
63
+ const factor = memoryDecayFactor(isoDaysAgo(90));
64
+ assert.ok(Math.abs(factor - 0.70) < 1e-3, `expected ≈0.70, got ${factor}`);
65
+ });
66
+
67
+ test("memoryDecayFactor: 180 days ago stays at 0.70 floor", () => {
68
+ const factor = memoryDecayFactor(isoDaysAgo(180));
69
+ assert.equal(factor, 0.70);
70
+ });
71
+
72
+ test("memoryDecayFactor: result always in [0.7, 1.0] for any input", () => {
73
+ const samples: (string | null)[] = [
74
+ null,
75
+ "",
76
+ "garbage",
77
+ new Date(0).toISOString(),
78
+ isoDaysAgo(0),
79
+ isoDaysAgo(15),
80
+ isoDaysAgo(45),
81
+ isoDaysAgo(89),
82
+ isoDaysAgo(91),
83
+ isoDaysAgo(365),
84
+ new Date(Date.now() + 365 * DAY_MS).toISOString(),
85
+ ];
86
+ for (const s of samples) {
87
+ const f = memoryDecayFactor(s);
88
+ assert.ok(f >= 0.7 && f <= 1.0, `factor out of [0.7, 1.0] for ${s}: ${f}`);
89
+ }
90
+ });
@@ -70,6 +70,7 @@ function makeDeps(
70
70
  getAutoWorktreePath: () => null,
71
71
  autoCommitCurrentBranch: () => undefined,
72
72
  getCurrentBranch: () => "worktree/M001",
73
+ checkoutBranch: () => undefined,
73
74
  autoWorktreeBranch: (mid: string) => `worktree/${mid}`,
74
75
  resolveMilestoneFile: () => null, // no roadmap → early return path
75
76
  readFileSync: () => "",
@@ -13,6 +13,9 @@ import { parseRoadmap, parsePlan } from '../parsers-legacy.ts';
13
13
  import { parseSummary } from '../files.ts';
14
14
  import { deriveState } from '../state.ts';
15
15
  import { invalidateAllCaches } from '../cache.ts';
16
+ import { ensureDbOpen } from '../bootstrap/dynamic-tools.ts';
17
+ import { closeDatabase, getAllMilestones } from '../gsd-db.ts';
18
+ import { importWrittenMigrationToDb } from '../migrate/command.ts';
16
19
  import type {
17
20
  GSDProject,
18
21
  GSDMilestone,
@@ -250,6 +253,51 @@ test('Scenario 1: Incomplete project — write, parse, deriveState', async () =>
250
253
  }
251
254
  });
252
255
 
256
+ test('Scenario 1b: written migration imports into authoritative DB state', async () => {
257
+ const base = mkdtempSync(join(tmpdir(), 'gsd-writer-db-import-'));
258
+ try {
259
+ const project = buildIncompleteProject();
260
+ await writeGSDDirectory(project, base);
261
+
262
+ assert.equal(await ensureDbOpen(base), true, 'db import: ensureDbOpen creates authoritative DB');
263
+
264
+ invalidateAllCaches();
265
+ const before = await deriveState(base);
266
+ assert.equal(before.activeMilestone, null, 'db import: markdown-only migration is invisible before DB import');
267
+
268
+ const imported = await importWrittenMigrationToDb(base);
269
+ assert.deepStrictEqual(imported.hierarchy, { milestones: 1, slices: 2, tasks: 3 }, 'db import: hierarchy counts');
270
+
271
+ invalidateAllCaches();
272
+ const after = await deriveState(base);
273
+ assert.deepStrictEqual(after.phase, 'executing', 'db import: deriveState sees imported DB hierarchy');
274
+ assert.deepStrictEqual(after.activeMilestone?.id, 'M001', 'db import: active milestone');
275
+ assert.deepStrictEqual(after.activeSlice?.id, 'S02', 'db import: active slice');
276
+ assert.deepStrictEqual(after.activeTask?.id, 'T03', 'db import: active task');
277
+ } finally {
278
+ closeDatabase();
279
+ rmSync(base, { recursive: true, force: true });
280
+ }
281
+ });
282
+
283
+ test('Scenario 1c: DB import verification fails when preview counts do not match', async () => {
284
+ const base = mkdtempSync(join(tmpdir(), 'gsd-writer-db-check-'));
285
+ try {
286
+ const project = buildIncompleteProject();
287
+ await writeGSDDirectory(project, base);
288
+
289
+ const preview = generatePreview(project);
290
+ await assert.rejects(
291
+ () => importWrittenMigrationToDb(base, { ...preview, totalTasks: preview.totalTasks + 1 }),
292
+ /migration DB import verification failed: tasks 3\/4/,
293
+ );
294
+ assert.deepStrictEqual(getAllMilestones(), [], 'db import: failed verification rolls back hierarchy rewrite');
295
+ } finally {
296
+ closeDatabase();
297
+ rmSync(base, { recursive: true, force: true });
298
+ }
299
+ });
300
+
253
301
  // ─── Scenario 2: Fully complete project ────────────────────────────────
254
302
 
255
303
  test('Scenario 2: Fully complete project — deriveState phase', async () => {
@@ -0,0 +1,127 @@
1
+ import assert from "node:assert/strict";
2
+ import { mkdtempSync, rmSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { tmpdir } from "node:os";
5
+ import test from "node:test";
6
+
7
+ import { ensureDbOpen } from "../bootstrap/dynamic-tools.ts";
8
+ import {
9
+ _getAdapter,
10
+ closeDatabase,
11
+ getAllMilestones,
12
+ getSliceTasks,
13
+ } from "../gsd-db.ts";
14
+ import {
15
+ autoImportMarkdownHierarchyIfDbMismatch,
16
+ countMarkdownHierarchy,
17
+ } from "../migration-auto-check.ts";
18
+ import { writeGSDDirectory } from "../migrate/writer.ts";
19
+ import type { GSDProject } from "../migrate/types.ts";
20
+
21
+ function makeBase(): string {
22
+ return mkdtempSync(join(tmpdir(), "gsd-migration-auto-check-"));
23
+ }
24
+
25
+ function cleanup(base: string): void {
26
+ closeDatabase();
27
+ rmSync(base, { recursive: true, force: true });
28
+ }
29
+
30
+ function projectFixture(): GSDProject {
31
+ return {
32
+ projectContent: "# Legacy Project\n",
33
+ decisionsContent: "",
34
+ requirements: [],
35
+ milestones: [
36
+ {
37
+ id: "M001",
38
+ title: "Legacy Milestone",
39
+ vision: "Carry forward previous work",
40
+ successCriteria: ["Existing task is visible"],
41
+ research: null,
42
+ boundaryMap: [],
43
+ slices: [
44
+ {
45
+ id: "S01",
46
+ title: "Legacy Slice",
47
+ risk: "medium",
48
+ depends: [],
49
+ done: false,
50
+ demo: "Legacy slice demo",
51
+ goal: "Legacy slice demo",
52
+ research: null,
53
+ summary: null,
54
+ tasks: [
55
+ {
56
+ id: "T01",
57
+ title: "Legacy Task",
58
+ description: "Task carried from markdown",
59
+ done: false,
60
+ estimate: "",
61
+ files: ["src/index.ts"],
62
+ mustHaves: [],
63
+ summary: null,
64
+ },
65
+ ],
66
+ },
67
+ ],
68
+ },
69
+ ],
70
+ };
71
+ }
72
+
73
+ test("migration auto-check imports markdown hierarchy when DB is empty", async () => {
74
+ const base = makeBase();
75
+ try {
76
+ await writeGSDDirectory(projectFixture(), base);
77
+ assert.deepEqual(countMarkdownHierarchy(base), { milestones: 1, slices: 1, tasks: 1 });
78
+
79
+ assert.equal(await ensureDbOpen(base), true);
80
+ assert.equal(getAllMilestones().length, 0, "fresh authoritative DB starts empty");
81
+
82
+ const result = await autoImportMarkdownHierarchyIfDbMismatch(base);
83
+ assert.equal(result.action, "imported");
84
+ assert.equal(result.reason, "db-empty");
85
+ assert.deepEqual(result.afterDb, { milestones: 1, slices: 1, tasks: 1 });
86
+ assert.equal(getAllMilestones().length, 1);
87
+ assert.equal(getSliceTasks("M001", "S01").length, 1);
88
+ } finally {
89
+ cleanup(base);
90
+ }
91
+ });
92
+
93
+ test("migration auto-check repairs DB hierarchy count mismatch", async () => {
94
+ const base = makeBase();
95
+ try {
96
+ await writeGSDDirectory(projectFixture(), base);
97
+ await autoImportMarkdownHierarchyIfDbMismatch(base);
98
+
99
+ _getAdapter()!.prepare("DELETE FROM tasks WHERE milestone_id = ? AND slice_id = ? AND id = ?").run("M001", "S01", "T01");
100
+ assert.equal(getSliceTasks("M001", "S01").length, 0, "test fixture simulates stale DB task count");
101
+
102
+ const result = await autoImportMarkdownHierarchyIfDbMismatch(base);
103
+ assert.equal(result.action, "imported");
104
+ assert.equal(result.reason, "count-mismatch");
105
+ assert.deepEqual(result.beforeDb, { milestones: 1, slices: 1, tasks: 0 });
106
+ assert.deepEqual(result.afterDb, { milestones: 1, slices: 1, tasks: 1 });
107
+ assert.equal(getSliceTasks("M001", "S01").length, 1);
108
+ } finally {
109
+ cleanup(base);
110
+ }
111
+ });
112
+
113
+ test("migration auto-check leaves matching DB hierarchy alone", async () => {
114
+ const base = makeBase();
115
+ try {
116
+ await writeGSDDirectory(projectFixture(), base);
117
+ await autoImportMarkdownHierarchyIfDbMismatch(base);
118
+
119
+ const result = await autoImportMarkdownHierarchyIfDbMismatch(base);
120
+ assert.equal(result.action, "none");
121
+ assert.equal(result.reason, "in-sync");
122
+ assert.deepEqual(result.markdown, { milestones: 1, slices: 1, tasks: 1 });
123
+ assert.deepEqual(result.afterDb, { milestones: 1, slices: 1, tasks: 1 });
124
+ } finally {
125
+ cleanup(base);
126
+ }
127
+ });