gsd-pi 2.44.0 → 2.45.0-dev.e0ee972

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 (505) hide show
  1. package/README.md +30 -12
  2. package/dist/help-text.js +1 -1
  3. package/dist/loader.js +34 -0
  4. package/dist/resources/extensions/gsd/activity-log.js +7 -0
  5. package/dist/resources/extensions/gsd/auto/infra-errors.js +3 -0
  6. package/dist/resources/extensions/gsd/auto/phases.js +52 -45
  7. package/dist/resources/extensions/gsd/auto/run-unit.js +6 -3
  8. package/dist/resources/extensions/gsd/auto-prompts.js +24 -1
  9. package/dist/resources/extensions/gsd/auto-start.js +31 -2
  10. package/dist/resources/extensions/gsd/auto-timers.js +57 -3
  11. package/dist/resources/extensions/gsd/auto-worktree-sync.js +4 -0
  12. package/dist/resources/extensions/gsd/auto-worktree.js +14 -10
  13. package/dist/resources/extensions/gsd/auto.js +34 -8
  14. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +168 -11
  15. package/dist/resources/extensions/gsd/bootstrap/system-context.js +46 -12
  16. package/dist/resources/extensions/gsd/commands/catalog.js +7 -1
  17. package/dist/resources/extensions/gsd/commands/handlers/core.js +2 -0
  18. package/dist/resources/extensions/gsd/commands/handlers/ops.js +10 -0
  19. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +5 -0
  20. package/dist/resources/extensions/gsd/commands-mcp-status.js +187 -0
  21. package/dist/resources/extensions/gsd/db-writer.js +40 -22
  22. package/dist/resources/extensions/gsd/doctor-checks.js +1 -1
  23. package/dist/resources/extensions/gsd/doctor.js +10 -2
  24. package/dist/resources/extensions/gsd/git-service.js +8 -3
  25. package/dist/resources/extensions/gsd/gsd-db.js +17 -2
  26. package/dist/resources/extensions/gsd/markdown-renderer.js +1 -1
  27. package/dist/resources/extensions/gsd/preferences-types.js +2 -2
  28. package/dist/resources/extensions/gsd/preferences.js +17 -5
  29. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +2 -4
  30. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  31. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -6
  32. package/dist/resources/extensions/gsd/prompts/replan-slice.md +3 -14
  33. package/dist/resources/extensions/gsd/prompts/rethink.md +78 -0
  34. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +7 -37
  35. package/dist/resources/extensions/gsd/provider-error-pause.js +7 -0
  36. package/dist/resources/extensions/gsd/repo-identity.js +45 -7
  37. package/dist/resources/extensions/gsd/rethink.js +115 -0
  38. package/dist/resources/extensions/gsd/state.js +41 -3
  39. package/dist/resources/extensions/gsd/tools/plan-slice.js +1 -0
  40. package/dist/resources/extensions/gsd/tools/plan-task.js +1 -0
  41. package/dist/resources/extensions/gsd/tools/replan-slice.js +2 -0
  42. package/dist/resources/extensions/gsd/tools/validate-milestone.js +88 -0
  43. package/dist/resources/extensions/gsd/workflow-logger.js +138 -0
  44. package/dist/resources/extensions/gsd/worktree-manager.js +34 -3
  45. package/dist/resources/extensions/gsd/worktree-resolver.js +43 -0
  46. package/dist/resources/extensions/mcp-client/index.js +14 -0
  47. package/dist/resources/extensions/voice/index.js +11 -16
  48. package/dist/resources/extensions/voice/linux-ready.js +67 -0
  49. package/dist/web/standalone/.next/BUILD_ID +1 -1
  50. package/dist/web/standalone/.next/app-path-routes-manifest.json +15 -15
  51. package/dist/web/standalone/.next/build-manifest.json +4 -4
  52. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  53. package/dist/web/standalone/.next/react-loadable-manifest.json +2 -2
  54. package/dist/web/standalone/.next/required-server-files.json +3 -3
  55. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  56. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  57. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  58. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  59. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  60. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  61. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  62. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  63. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  64. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  65. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  66. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  67. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  68. package/dist/web/standalone/.next/server/app/_not-found.rsc +5 -5
  69. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +5 -5
  70. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  71. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -4
  72. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  73. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  74. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  75. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  76. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  77. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  78. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  79. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  80. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  81. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  82. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  83. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  84. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  85. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  86. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  87. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  88. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  89. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  90. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  91. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  92. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  93. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  94. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  95. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  96. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  97. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  98. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  99. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  100. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  101. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  102. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  103. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  104. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  105. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  106. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  107. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  108. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  109. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  110. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  111. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  113. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +5 -5
  120. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  126. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
  140. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  142. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  144. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  146. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/index.html +1 -1
  156. package/dist/web/standalone/.next/server/app/index.rsc +6 -6
  157. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  158. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +6 -6
  159. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  160. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -4
  161. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  162. package/dist/web/standalone/.next/server/app/page.js +2 -2
  163. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  164. package/dist/web/standalone/.next/server/app-paths-manifest.json +15 -15
  165. package/dist/web/standalone/.next/server/chunks/229.js +1 -1
  166. package/dist/web/standalone/.next/server/chunks/471.js +3 -3
  167. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  168. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/middleware.js +2 -2
  170. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  172. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  173. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  174. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  175. package/dist/web/standalone/.next/static/chunks/4024.11ca5c01938e5948.js +9 -0
  176. package/dist/web/standalone/.next/static/chunks/{3721.bf31263de6d5fa46.js → 485.243af25f0cdf50d6.js} +2 -2
  177. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  178. package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
  179. package/dist/web/standalone/.next/static/chunks/app/page-6654a8cca61a3d1c.js +1 -0
  180. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  181. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  182. package/dist/web/standalone/.next/static/chunks/webpack-0a4cd455ec4197d2.js +1 -0
  183. package/dist/web/standalone/.next/static/css/dd4ae3f58ac9b600.css +1 -0
  184. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  185. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  186. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  187. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  188. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  189. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  190. package/dist/web/standalone/server.js +1 -1
  191. package/package.json +1 -1
  192. package/packages/native/dist/stream-process/index.js +2 -2
  193. package/packages/native/src/__tests__/stream-process.test.mjs +34 -0
  194. package/packages/native/src/stream-process/index.ts +2 -2
  195. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +3 -1
  196. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  197. package/packages/pi-coding-agent/dist/core/auth-storage.js +15 -1
  198. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  199. package/packages/pi-coding-agent/dist/core/auth-storage.test.js +6 -8
  200. package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
  201. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts.map +1 -1
  202. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js +2 -0
  203. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js.map +1 -1
  204. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +24 -26
  205. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
  206. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +2 -1
  207. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  208. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  209. package/packages/pi-coding-agent/dist/core/fs-utils.test.js +29 -48
  210. package/packages/pi-coding-agent/dist/core/fs-utils.test.js.map +1 -1
  211. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts +4 -0
  212. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts.map +1 -1
  213. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js +10 -5
  214. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js.map +1 -1
  215. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.test.d.ts +2 -0
  216. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.test.d.ts.map +1 -0
  217. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.test.js +185 -0
  218. package/packages/pi-coding-agent/dist/core/lifecycle-hooks.test.js.map +1 -0
  219. package/packages/pi-coding-agent/dist/core/local-model-check.d.ts +15 -0
  220. package/packages/pi-coding-agent/dist/core/local-model-check.d.ts.map +1 -0
  221. package/packages/pi-coding-agent/dist/core/local-model-check.js +41 -0
  222. package/packages/pi-coding-agent/dist/core/local-model-check.js.map +1 -0
  223. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +239 -10
  224. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
  225. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +13 -1
  226. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  227. package/packages/pi-coding-agent/dist/core/model-registry.js +40 -3
  228. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  229. package/packages/pi-coding-agent/dist/core/package-commands.test.js +206 -195
  230. package/packages/pi-coding-agent/dist/core/package-commands.test.js.map +1 -1
  231. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js +34 -44
  232. package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js.map +1 -1
  233. package/packages/pi-coding-agent/dist/core/session-manager.test.js +30 -34
  234. package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
  235. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
  236. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  237. package/packages/pi-coding-agent/dist/core/settings-manager.js +6 -0
  238. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  239. package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js +10 -12
  240. package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js.map +1 -1
  241. package/packages/pi-coding-agent/dist/main.d.ts.map +1 -1
  242. package/packages/pi-coding-agent/dist/main.js +17 -0
  243. package/packages/pi-coding-agent/dist/main.js.map +1 -1
  244. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.d.ts +2 -0
  245. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.d.ts.map +1 -0
  246. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.js +32 -0
  247. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.js.map +1 -0
  248. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts +3 -1
  249. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  250. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +8 -1
  251. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
  252. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  253. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  254. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +12 -0
  255. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
  256. package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.d.ts +15 -0
  257. package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.d.ts.map +1 -0
  258. package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.js +40 -0
  259. package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.js.map +1 -0
  260. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  261. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +4 -1
  262. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  263. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts +5 -2
  264. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  265. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js +13 -2
  266. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js.map +1 -1
  267. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  268. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +17 -8
  269. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  270. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  271. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +7 -3
  272. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  273. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js +43 -47
  274. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js.map +1 -1
  275. package/packages/pi-coding-agent/package.json +1 -1
  276. package/packages/pi-coding-agent/src/core/auth-storage.test.ts +7 -7
  277. package/packages/pi-coding-agent/src/core/auth-storage.ts +15 -1
  278. package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +2 -0
  279. package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +26 -26
  280. package/packages/pi-coding-agent/src/core/extensions/types.ts +2 -1
  281. package/packages/pi-coding-agent/src/core/fs-utils.test.ts +31 -43
  282. package/packages/pi-coding-agent/src/core/lifecycle-hooks.test.ts +227 -0
  283. package/packages/pi-coding-agent/src/core/lifecycle-hooks.ts +11 -5
  284. package/packages/pi-coding-agent/src/core/local-model-check.ts +45 -0
  285. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +297 -11
  286. package/packages/pi-coding-agent/src/core/model-registry.ts +51 -4
  287. package/packages/pi-coding-agent/src/core/package-commands.test.ts +227 -205
  288. package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +40 -45
  289. package/packages/pi-coding-agent/src/core/session-manager.test.ts +33 -33
  290. package/packages/pi-coding-agent/src/core/settings-manager.ts +9 -0
  291. package/packages/pi-coding-agent/src/core/tools/edit-diff.test.ts +17 -17
  292. package/packages/pi-coding-agent/src/main.ts +19 -0
  293. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/timestamp.test.ts +38 -0
  294. package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +10 -0
  295. package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +15 -0
  296. package/packages/pi-coding-agent/src/modes/interactive/components/timestamp.ts +48 -0
  297. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +3 -1
  298. package/packages/pi-coding-agent/src/modes/interactive/components/user-message.ts +18 -3
  299. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +16 -7
  300. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +8 -1
  301. package/packages/pi-coding-agent/src/resources/extensions/memory/storage.test.ts +74 -74
  302. package/pkg/package.json +1 -1
  303. package/src/resources/extensions/gsd/activity-log.ts +1 -0
  304. package/src/resources/extensions/gsd/auto/infra-errors.ts +3 -0
  305. package/src/resources/extensions/gsd/auto/phases.ts +61 -59
  306. package/src/resources/extensions/gsd/auto/run-unit.ts +6 -3
  307. package/src/resources/extensions/gsd/auto-prompts.ts +24 -1
  308. package/src/resources/extensions/gsd/auto-start.ts +39 -2
  309. package/src/resources/extensions/gsd/auto-timers.ts +64 -3
  310. package/src/resources/extensions/gsd/auto-worktree-sync.ts +5 -0
  311. package/src/resources/extensions/gsd/auto-worktree.ts +17 -11
  312. package/src/resources/extensions/gsd/auto.ts +40 -6
  313. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +160 -11
  314. package/src/resources/extensions/gsd/bootstrap/system-context.ts +48 -11
  315. package/src/resources/extensions/gsd/commands/catalog.ts +7 -1
  316. package/src/resources/extensions/gsd/commands/handlers/core.ts +2 -0
  317. package/src/resources/extensions/gsd/commands/handlers/ops.ts +10 -0
  318. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +8 -0
  319. package/src/resources/extensions/gsd/commands-mcp-status.ts +247 -0
  320. package/src/resources/extensions/gsd/db-writer.ts +41 -27
  321. package/src/resources/extensions/gsd/doctor-checks.ts +1 -1
  322. package/src/resources/extensions/gsd/doctor.ts +9 -3
  323. package/src/resources/extensions/gsd/git-service.ts +6 -2
  324. package/src/resources/extensions/gsd/gsd-db.ts +21 -2
  325. package/src/resources/extensions/gsd/journal.ts +6 -1
  326. package/src/resources/extensions/gsd/markdown-renderer.ts +1 -1
  327. package/src/resources/extensions/gsd/preferences-types.ts +2 -2
  328. package/src/resources/extensions/gsd/preferences.ts +18 -4
  329. package/src/resources/extensions/gsd/prompts/complete-milestone.md +2 -4
  330. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  331. package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -6
  332. package/src/resources/extensions/gsd/prompts/replan-slice.md +3 -14
  333. package/src/resources/extensions/gsd/prompts/rethink.md +78 -0
  334. package/src/resources/extensions/gsd/prompts/validate-milestone.md +7 -37
  335. package/src/resources/extensions/gsd/provider-error-pause.ts +9 -0
  336. package/src/resources/extensions/gsd/repo-identity.ts +46 -7
  337. package/src/resources/extensions/gsd/rethink.ts +154 -0
  338. package/src/resources/extensions/gsd/state.ts +41 -1
  339. package/src/resources/extensions/gsd/tests/all-milestones-complete-merge.test.ts +99 -99
  340. package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +14 -16
  341. package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +43 -57
  342. package/src/resources/extensions/gsd/tests/auto-pr-bugs.test.ts +88 -0
  343. package/src/resources/extensions/gsd/tests/auto-preflight.test.ts +11 -13
  344. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +465 -523
  345. package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +73 -75
  346. package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +34 -56
  347. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +533 -656
  348. package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +165 -143
  349. package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +29 -52
  350. package/src/resources/extensions/gsd/tests/captures.test.ts +148 -176
  351. package/src/resources/extensions/gsd/tests/claude-import-tui.test.ts +32 -33
  352. package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +141 -143
  353. package/src/resources/extensions/gsd/tests/commands-inspect-open-db.test.ts +25 -25
  354. package/src/resources/extensions/gsd/tests/commands-logs.test.ts +81 -81
  355. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +38 -59
  356. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +228 -263
  357. package/src/resources/extensions/gsd/tests/complete-task.test.ts +250 -302
  358. package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +114 -0
  359. package/src/resources/extensions/gsd/tests/context-store.test.ts +354 -367
  360. package/src/resources/extensions/gsd/tests/continue-here.test.ts +68 -72
  361. package/src/resources/extensions/gsd/tests/cost-projection.test.ts +92 -106
  362. package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +27 -35
  363. package/src/resources/extensions/gsd/tests/dashboard-budget.test.ts +220 -237
  364. package/src/resources/extensions/gsd/tests/db-writer.test.ts +465 -416
  365. package/src/resources/extensions/gsd/tests/definition-loader.test.ts +76 -92
  366. package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +68 -83
  367. package/src/resources/extensions/gsd/tests/derive-state-db-disk-reconcile.test.ts +121 -0
  368. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +210 -181
  369. package/src/resources/extensions/gsd/tests/derive-state-deps.test.ts +78 -101
  370. package/src/resources/extensions/gsd/tests/derive-state.test.ts +192 -227
  371. package/src/resources/extensions/gsd/tests/detection.test.ts +232 -278
  372. package/src/resources/extensions/gsd/tests/dev-engine-wrapper.test.ts +30 -34
  373. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +164 -180
  374. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +43 -49
  375. package/src/resources/extensions/gsd/tests/dispatch-uat-last-completed.test.ts +28 -32
  376. package/src/resources/extensions/gsd/tests/doctor-completion-deferral.test.ts +27 -29
  377. package/src/resources/extensions/gsd/tests/doctor-delimiter-fix.test.ts +34 -38
  378. package/src/resources/extensions/gsd/tests/doctor-enhancements.test.ts +54 -75
  379. package/src/resources/extensions/gsd/tests/doctor-environment-worktree.test.ts +21 -32
  380. package/src/resources/extensions/gsd/tests/doctor-environment.test.ts +72 -97
  381. package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +38 -44
  382. package/src/resources/extensions/gsd/tests/doctor-git.test.ts +104 -145
  383. package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +84 -106
  384. package/src/resources/extensions/gsd/tests/doctor-roadmap-summary-atomicity.test.ts +54 -60
  385. package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +72 -93
  386. package/src/resources/extensions/gsd/tests/doctor.test.ts +104 -134
  387. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +123 -131
  388. package/src/resources/extensions/gsd/tests/est-annotation-timeout.test.ts +120 -0
  389. package/src/resources/extensions/gsd/tests/exit-command.test.ts +20 -24
  390. package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +48 -57
  391. package/src/resources/extensions/gsd/tests/files-loadfile-eisdir.test.ts +5 -7
  392. package/src/resources/extensions/gsd/tests/flag-file-db.test.ts +30 -42
  393. package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +198 -206
  394. package/src/resources/extensions/gsd/tests/git-locale.test.ts +13 -27
  395. package/src/resources/extensions/gsd/tests/git-service.test.ts +285 -388
  396. package/src/resources/extensions/gsd/tests/gitignore-tracked-gsd.test.ts +31 -39
  397. package/src/resources/extensions/gsd/tests/graph-operations.test.ts +63 -69
  398. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +255 -264
  399. package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +108 -119
  400. package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +81 -103
  401. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +229 -262
  402. package/src/resources/extensions/gsd/tests/headless-answers.test.ts +13 -13
  403. package/src/resources/extensions/gsd/tests/health-widget.test.ts +29 -37
  404. package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +81 -102
  405. package/src/resources/extensions/gsd/tests/infra-error.test.ts +20 -2
  406. package/src/resources/extensions/gsd/tests/inherited-repo-home-dir.test.ts +121 -0
  407. package/src/resources/extensions/gsd/tests/init-wizard.test.ts +16 -18
  408. package/src/resources/extensions/gsd/tests/integration-edge.test.ts +41 -46
  409. package/src/resources/extensions/gsd/tests/integration-lifecycle.test.ts +42 -53
  410. package/src/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +75 -91
  411. package/src/resources/extensions/gsd/tests/integration-proof.test.ts +18 -18
  412. package/src/resources/extensions/gsd/tests/knowledge.test.ts +89 -0
  413. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +150 -194
  414. package/src/resources/extensions/gsd/tests/mcp-status.test.ts +103 -0
  415. package/src/resources/extensions/gsd/tests/md-importer.test.ts +101 -125
  416. package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +45 -54
  417. package/src/resources/extensions/gsd/tests/memory-store.test.ts +80 -93
  418. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +66 -0
  419. package/src/resources/extensions/gsd/tests/migrate-command.test.ts +57 -66
  420. package/src/resources/extensions/gsd/tests/migrate-hierarchy.test.ts +83 -93
  421. package/src/resources/extensions/gsd/tests/migrate-parser.test.ts +161 -170
  422. package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +125 -141
  423. package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +107 -131
  424. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +87 -96
  425. package/src/resources/extensions/gsd/tests/migrate-writer.test.ts +125 -164
  426. package/src/resources/extensions/gsd/tests/must-have-parser.test.ts +81 -94
  427. package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +75 -37
  428. package/src/resources/extensions/gsd/tests/overrides.test.ts +99 -106
  429. package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +40 -47
  430. package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +25 -28
  431. package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +66 -83
  432. package/src/resources/extensions/gsd/tests/park-edge-cases.test.ts +54 -77
  433. package/src/resources/extensions/gsd/tests/park-milestone.test.ts +68 -115
  434. package/src/resources/extensions/gsd/tests/parsers.test.ts +546 -611
  435. package/src/resources/extensions/gsd/tests/paths.test.ts +72 -87
  436. package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +77 -117
  437. package/src/resources/extensions/gsd/tests/preferences.test.ts +34 -9
  438. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +11 -7
  439. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +56 -56
  440. package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +93 -119
  441. package/src/resources/extensions/gsd/tests/queue-order.test.ts +70 -82
  442. package/src/resources/extensions/gsd/tests/queue-reorder-e2e.test.ts +42 -55
  443. package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +100 -0
  444. package/src/resources/extensions/gsd/tests/quick-branch-lifecycle.test.ts +45 -73
  445. package/src/resources/extensions/gsd/tests/reassess-prompt.test.ts +28 -38
  446. package/src/resources/extensions/gsd/tests/recovery-attempts-reset.test.ts +176 -0
  447. package/src/resources/extensions/gsd/tests/replan-slice.test.ts +73 -80
  448. package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +71 -74
  449. package/src/resources/extensions/gsd/tests/requirements.test.ts +70 -75
  450. package/src/resources/extensions/gsd/tests/retry-state-reset.test.ts +44 -66
  451. package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +114 -181
  452. package/src/resources/extensions/gsd/tests/rule-registry.test.ts +63 -65
  453. package/src/resources/extensions/gsd/tests/run-uat.test.ts +66 -128
  454. package/src/resources/extensions/gsd/tests/session-lock-multipath.test.ts +18 -25
  455. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +37 -44
  456. package/src/resources/extensions/gsd/tests/shared-wal.test.ts +19 -26
  457. package/src/resources/extensions/gsd/tests/sqlite-unavailable-gate.test.ts +63 -0
  458. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +6 -8
  459. package/src/resources/extensions/gsd/tests/stop-auto-merge-back.test.ts +67 -0
  460. package/src/resources/extensions/gsd/tests/survivor-branch-complete.test.ts +108 -0
  461. package/src/resources/extensions/gsd/tests/symlink-numbered-variants.test.ts +22 -28
  462. package/src/resources/extensions/gsd/tests/terminated-transient.test.ts +49 -0
  463. package/src/resources/extensions/gsd/tests/token-savings.test.ts +54 -56
  464. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +23 -25
  465. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +10 -11
  466. package/src/resources/extensions/gsd/tests/unique-milestone-ids.test.ts +66 -82
  467. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +46 -47
  468. package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +20 -22
  469. package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +84 -86
  470. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +41 -43
  471. package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +94 -96
  472. package/src/resources/extensions/gsd/tests/windows-path-normalization.test.ts +11 -13
  473. package/src/resources/extensions/gsd/tests/worker-registry.test.ts +27 -29
  474. package/src/resources/extensions/gsd/tests/workflow-logger.test.ts +275 -0
  475. package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +50 -52
  476. package/src/resources/extensions/gsd/tests/worktree-bugfix.test.ts +10 -13
  477. package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +14 -18
  478. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +38 -39
  479. package/src/resources/extensions/gsd/tests/worktree-e2e.test.ts +17 -21
  480. package/src/resources/extensions/gsd/tests/worktree-health.test.ts +25 -30
  481. package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +30 -37
  482. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +220 -0
  483. package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +65 -0
  484. package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +15 -22
  485. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +59 -66
  486. package/src/resources/extensions/gsd/tests/worktree.test.ts +44 -50
  487. package/src/resources/extensions/gsd/tools/plan-slice.ts +2 -0
  488. package/src/resources/extensions/gsd/tools/plan-task.ts +2 -0
  489. package/src/resources/extensions/gsd/tools/replan-slice.ts +3 -0
  490. package/src/resources/extensions/gsd/tools/validate-milestone.ts +127 -0
  491. package/src/resources/extensions/gsd/workflow-logger.ts +193 -0
  492. package/src/resources/extensions/gsd/worktree-manager.ts +41 -5
  493. package/src/resources/extensions/gsd/worktree-resolver.ts +44 -0
  494. package/src/resources/extensions/mcp-client/index.ts +20 -0
  495. package/src/resources/extensions/voice/index.ts +11 -21
  496. package/src/resources/extensions/voice/linux-ready.ts +87 -0
  497. package/src/resources/extensions/voice/tests/linux-ready.test.ts +124 -0
  498. package/dist/web/standalone/.next/static/chunks/4024.0de81b543b28b9fe.js +0 -9
  499. package/dist/web/standalone/.next/static/chunks/app/page-7e9530a7122506c5.js +0 -1
  500. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  501. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  502. package/dist/web/standalone/.next/static/chunks/webpack-9014b5adb127a98a.js +0 -1
  503. package/dist/web/standalone/.next/static/css/8a727f372cf53002.css +0 -1
  504. /package/dist/web/standalone/.next/static/{mgkxN0mGP6gSUmGPEzbk_ → dFMji9G1LZ-Tv36el9pRT}/_buildManifest.js +0 -0
  505. /package/dist/web/standalone/.next/static/{mgkxN0mGP6gSUmGPEzbk_ → dFMji9G1LZ-Tv36el9pRT}/_ssgManifest.js +0 -0
@@ -1,3 +1,5 @@
1
+ import { describe, test } from 'node:test';
2
+ import assert from 'node:assert/strict';
1
3
  /**
2
4
  * Tests for dashboard budget indicator rendering.
3
5
  *
@@ -18,10 +20,6 @@ import {
18
20
  getProjectTotals,
19
21
  formatTokenCount,
20
22
  } from "../metrics.js";
21
- import { createTestContext } from './test-helpers.ts';
22
-
23
- const { assertEq, assertTrue, assertMatch, assertNoMatch, report } = createTestContext();
24
-
25
23
  // ─── Test helpers ─────────────────────────────────────────────────────────────
26
24
 
27
25
  function makeUnit(overrides: Partial<UnitMetrics> = {}): UnitMetrics {
@@ -102,245 +100,230 @@ function renderModelContextWindow(units: UnitMetrics[], modelName: string): stri
102
100
 
103
101
  // ─── Completed section: budget indicators ─────────────────────────────────────
104
102
 
105
- console.log("\n=== Completed section: truncation + continue-here markers ===");
106
-
107
- {
108
- // Unit with truncation and continue-here — both markers appear
109
- const ledgerUnits = [
110
- makeUnit({ type: "execute-task", id: "M001/S01/T01", truncationSections: 3, continueHereFired: true }),
111
- ];
112
- const markers = renderCompletedBudgetMarkers(
113
- { type: "execute-task", id: "M001/S01/T01" },
114
- ledgerUnits,
115
- );
116
- assertMatch(markers, /▼3/, "completed: shows ▼3 for 3 truncation sections");
117
- assertMatch(markers, /→ wrap-up/, "completed: shows → wrap-up when continueHereFired");
118
- }
119
-
120
- {
121
- // Unit with truncation only — no wrap-up marker
122
- const ledgerUnits = [
123
- makeUnit({ type: "execute-task", id: "M001/S01/T01", truncationSections: 5, continueHereFired: false }),
124
- ];
125
- const markers = renderCompletedBudgetMarkers(
126
- { type: "execute-task", id: "M001/S01/T01" },
127
- ledgerUnits,
128
- );
129
- assertMatch(markers, /▼5/, "completed: shows ▼5 truncation only");
130
- assertNoMatch(markers, /wrap-up/, "completed: no wrap-up when continueHereFired=false");
131
- }
132
-
133
- {
134
- // Unit with continue-here only — no truncation marker
135
- const ledgerUnits = [
136
- makeUnit({ type: "execute-task", id: "M001/S01/T01", truncationSections: 0, continueHereFired: true }),
137
- ];
138
- const markers = renderCompletedBudgetMarkers(
139
- { type: "execute-task", id: "M001/S01/T01" },
140
- ledgerUnits,
141
- );
142
- assertNoMatch(markers, /▼/, "completed: no ▼ when truncationSections=0");
143
- assertMatch(markers, /→ wrap-up/, "completed: shows → wrap-up");
144
- }
145
-
146
- // ─── Completed section: missing ledger match ──────────────────────────────────
147
-
148
- console.log("\n=== Completed section: missing ledger match ===");
149
-
150
- {
151
- // Completed unit with no matching ledger entry — no crash, no markers
152
- const ledgerUnits = [
153
- makeUnit({ type: "execute-task", id: "M001/S01/T99", truncationSections: 3 }),
154
- ];
155
- const markers = renderCompletedBudgetMarkers(
156
- { type: "execute-task", id: "M001/S01/T01" },
157
- ledgerUnits,
158
- );
159
- assertEq(markers, "", "missing match: empty markers when no ledger entry matches");
160
- }
161
-
162
- {
163
- // Empty ledger — no crash, no markers
164
- const markers = renderCompletedBudgetMarkers(
165
- { type: "execute-task", id: "M001/S01/T01" },
166
- [],
167
- );
168
- assertEq(markers, "", "empty ledger: empty markers");
169
- }
170
-
171
- // ─── Completed section: retry handling (last entry wins) ──────────────────────
172
-
173
- console.log("\n=== Completed section: retry handling ===");
174
-
175
- {
176
- // Two ledger entries for same unit (retry) — last entry wins
177
- const ledgerUnits = [
178
- makeUnit({ type: "execute-task", id: "M001/S01/T01", truncationSections: 1 }),
179
- makeUnit({ type: "execute-task", id: "M001/S01/T01", truncationSections: 7 }),
180
- ];
181
- const markers = renderCompletedBudgetMarkers(
182
- { type: "execute-task", id: "M001/S01/T01" },
183
- ledgerUnits,
184
- );
185
- assertMatch(markers, /▼7/, "retry: last entry's truncation count (7) wins over first (1)");
186
- assertNoMatch(markers, /▼1/, "retry: first entry's count (1) is not shown");
187
- }
188
-
189
- // ─── By Model section: context window display ─────────────────────────────────
190
-
191
- console.log("\n=== By Model section: context window ===");
192
-
193
- {
194
- // Model with context window — shows formatted token count
195
- const units = [
196
- makeUnit({ model: "claude-sonnet-4-20250514", contextWindowTokens: 200000 }),
197
- ];
198
- const label = renderModelContextWindow(units, "claude-sonnet-4-20250514");
199
- assertEq(label, "[200.0k]", "by model: shows [200.0k] for 200000 context window");
200
- }
201
-
202
- {
203
- // Model without context window — no label
204
- const units = [
205
- makeUnit({ model: "claude-sonnet-4-20250514" }),
206
- ];
207
- const label = renderModelContextWindow(units, "claude-sonnet-4-20250514");
208
- assertEq(label, null, "by model: null when no contextWindowTokens");
209
- }
210
-
211
- {
212
- // Multiple models — each gets its own context window
213
- const units = [
214
- makeUnit({ model: "claude-sonnet-4-20250514", contextWindowTokens: 200000, cost: 0.05 }),
215
- makeUnit({ model: "claude-opus-4-20250514", contextWindowTokens: 200000, cost: 0.30 }),
216
- ];
217
- const sonnetLabel = renderModelContextWindow(units, "claude-sonnet-4-20250514");
218
- const opusLabel = renderModelContextWindow(units, "claude-opus-4-20250514");
219
- assertEq(sonnetLabel, "[200.0k]", "by model multi: sonnet has context window");
220
- assertEq(opusLabel, "[200.0k]", "by model multi: opus has context window");
221
- }
222
-
223
- // ─── By Model section: single model visibility ───────────────────────────────
224
-
225
- console.log("\n=== By Model section: single model visibility ===");
226
-
227
- {
228
- // With guard changed to >= 1, single model aggregation should produce results
229
- const units = [
230
- makeUnit({ model: "claude-sonnet-4-20250514" }),
231
- ];
232
- const models = aggregateByModel(units);
233
- assertTrue(models.length >= 1, "single model: aggregateByModel returns >= 1 entry");
234
- assertEq(models.length, 1, "single model: exactly 1 model aggregate");
235
- assertEq(models[0].model, "claude-sonnet-4-20250514", "single model: correct model name");
236
- // The guard `models.length >= 1` (changed from > 1) means this section now renders
237
- assertTrue(models.length >= 1, "single model: passes >= 1 guard (section will render)");
238
- }
239
-
240
- // ─── Cost & Usage: aggregate budget line ──────────────────────────────────────
241
-
242
- console.log("\n=== Cost & Usage: aggregate budget line ===");
243
-
244
- {
245
- // Units with truncation and continue-here — both stats appear
246
- const units = [
247
- makeUnit({ truncationSections: 3, continueHereFired: true }),
248
- makeUnit({ truncationSections: 2, continueHereFired: false }),
249
- makeUnit({ truncationSections: 1, continueHereFired: true }),
250
- ];
251
- const line = renderCostBudgetLine(units);
252
- assertTrue(line !== null, "cost budget: line rendered when budget data exists");
253
- assertMatch(line!, /6 sections truncated/, "cost budget: shows total truncation count (3+2+1=6)");
254
- assertMatch(line!, /2 continue-here fired/, "cost budget: shows continue-here count");
255
- }
103
+ describe('dashboard-budget', () => {
104
+ test('Completed section: truncation + continue-here markers', () => {
105
+ // Unit with truncation and continue-here — both markers appear
106
+ const ledgerUnits = [
107
+ makeUnit({ type: "execute-task", id: "M001/S01/T01", truncationSections: 3, continueHereFired: true }),
108
+ ];
109
+ const markers = renderCompletedBudgetMarkers(
110
+ { type: "execute-task", id: "M001/S01/T01" },
111
+ ledgerUnits,
112
+ );
113
+ assert.match(markers, /▼3/, "completed: shows ▼3 for 3 truncation sections");
114
+ assert.match(markers, /→ wrap-up/, "completed: shows wrap-up when continueHereFired");
115
+ });
116
+
117
+ {
118
+ // Unit with truncation only — no wrap-up marker
119
+ const ledgerUnits = [
120
+ makeUnit({ type: "execute-task", id: "M001/S01/T01", truncationSections: 5, continueHereFired: false }),
121
+ ];
122
+ const markers = renderCompletedBudgetMarkers(
123
+ { type: "execute-task", id: "M001/S01/T01" },
124
+ ledgerUnits,
125
+ );
126
+ assert.match(markers, /▼5/, "completed: shows ▼5 truncation only");
127
+ assert.doesNotMatch(markers, /wrap-up/, "completed: no wrap-up when continueHereFired=false");
128
+ }
256
129
 
257
- {
258
- // Only truncation, no continue-here
259
- const units = [
260
- makeUnit({ truncationSections: 4, continueHereFired: false }),
261
- ];
262
- const line = renderCostBudgetLine(units);
263
- assertTrue(line !== null, "cost budget truncation-only: line rendered");
264
- assertMatch(line!, /4 sections truncated/, "cost budget truncation-only: shows count");
265
- assertNoMatch(line!, /continue-here/, "cost budget truncation-only: no continue-here text");
266
- }
130
+ {
131
+ // Unit with continue-here only — no truncation marker
132
+ const ledgerUnits = [
133
+ makeUnit({ type: "execute-task", id: "M001/S01/T01", truncationSections: 0, continueHereFired: true }),
134
+ ];
135
+ const markers = renderCompletedBudgetMarkers(
136
+ { type: "execute-task", id: "M001/S01/T01" },
137
+ ledgerUnits,
138
+ );
139
+ assert.doesNotMatch(markers, /▼/, "completed: no ▼ when truncationSections=0");
140
+ assert.match(markers, /→ wrap-up/, "completed: shows → wrap-up");
141
+ }
267
142
 
268
- {
269
- // Only continue-here, no truncation
270
- const units = [
271
- makeUnit({ truncationSections: 0, continueHereFired: true }),
272
- ];
273
- const line = renderCostBudgetLine(units);
274
- assertTrue(line !== null, "cost budget continue-only: line rendered");
275
- assertNoMatch(line!, /truncated/, "cost budget continue-only: no truncation text");
276
- assertMatch(line!, /1 continue-here fired/, "cost budget continue-only: shows count");
277
- }
143
+ // ─── Completed section: missing ledger match ──────────────────────────────────
144
+
145
+ test('Completed section: missing ledger match', () => {
146
+ // Completed unit with no matching ledger entry — no crash, no markers
147
+ const ledgerUnits = [
148
+ makeUnit({ type: "execute-task", id: "M001/S01/T99", truncationSections: 3 }),
149
+ ];
150
+ const markers = renderCompletedBudgetMarkers(
151
+ { type: "execute-task", id: "M001/S01/T01" },
152
+ ledgerUnits,
153
+ );
154
+ assert.deepStrictEqual(markers, "", "missing match: empty markers when no ledger entry matches");
155
+ });
156
+
157
+ {
158
+ // Empty ledger — no crash, no markers
159
+ const markers = renderCompletedBudgetMarkers(
160
+ { type: "execute-task", id: "M001/S01/T01" },
161
+ [],
162
+ );
163
+ assert.deepStrictEqual(markers, "", "empty ledger: empty markers");
164
+ }
278
165
 
279
- // ─── Backward compat: no budget fields ────────────────────────────────────────
280
-
281
- console.log("\n=== Backward compat: no budget data ===");
282
-
283
- {
284
- // Old-format units without budget fields — no indicators anywhere
285
- const oldUnits = [
286
- makeUnit(), // no budget fields
287
- makeUnit({ id: "M001/S01/T02" }),
288
- ];
289
-
290
- // Completed section: no markers
291
- const markers = renderCompletedBudgetMarkers(
292
- { type: "execute-task", id: "M001/S01/T01" },
293
- oldUnits,
294
- );
295
- assertNoMatch(markers, /▼/, "backward compat completed: no truncation marker");
296
- assertNoMatch(markers, /wrap-up/, "backward compat completed: no wrap-up marker");
297
- assertEq(markers, "", "backward compat completed: empty markers string");
298
-
299
- // By Model section: no context window label
300
- const label = renderModelContextWindow(oldUnits, "claude-sonnet-4-20250514");
301
- assertEq(label, null, "backward compat by-model: no context window label");
302
-
303
- // Cost & Usage: no budget line
304
- const line = renderCostBudgetLine(oldUnits);
305
- assertEq(line, null, "backward compat cost: no budget summary line");
306
-
307
- // Aggregation still works
308
- const totals = getProjectTotals(oldUnits);
309
- assertEq(totals.totalTruncationSections, 0, "backward compat: truncation total = 0");
310
- assertEq(totals.continueHereFiredCount, 0, "backward compat: continueHere count = 0");
311
- assertEq(totals.units, 2, "backward compat: unit count correct");
312
- }
166
+ // ─── Completed section: retry handling (last entry wins) ──────────────────────
167
+
168
+ test('Completed section: retry handling', () => {
169
+ // Two ledger entries for same unit (retry) — last entry wins
170
+ const ledgerUnits = [
171
+ makeUnit({ type: "execute-task", id: "M001/S01/T01", truncationSections: 1 }),
172
+ makeUnit({ type: "execute-task", id: "M001/S01/T01", truncationSections: 7 }),
173
+ ];
174
+ const markers = renderCompletedBudgetMarkers(
175
+ { type: "execute-task", id: "M001/S01/T01" },
176
+ ledgerUnits,
177
+ );
178
+ assert.match(markers, /▼7/, "retry: last entry's truncation count (7) wins over first (1)");
179
+ assert.doesNotMatch(markers, /▼1/, "retry: first entry's count (1) is not shown");
180
+ });
181
+
182
+ // ─── By Model section: context window display ─────────────────────────────────
183
+
184
+ test('By Model section: context window', () => {
185
+ // Model with context window — shows formatted token count
186
+ const units = [
187
+ makeUnit({ model: "claude-sonnet-4-20250514", contextWindowTokens: 200000 }),
188
+ ];
189
+ const label = renderModelContextWindow(units, "claude-sonnet-4-20250514");
190
+ assert.deepStrictEqual(label, "[200.0k]", "by model: shows [200.0k] for 200000 context window");
191
+ });
192
+
193
+ {
194
+ // Model without context window — no label
195
+ const units = [
196
+ makeUnit({ model: "claude-sonnet-4-20250514" }),
197
+ ];
198
+ const label = renderModelContextWindow(units, "claude-sonnet-4-20250514");
199
+ assert.deepStrictEqual(label, null, "by model: null when no contextWindowTokens");
200
+ }
313
201
 
314
- // ─── Edge cases ───────────────────────────────────────────────────────────────
202
+ {
203
+ // Multiple models — each gets its own context window
204
+ const units = [
205
+ makeUnit({ model: "claude-sonnet-4-20250514", contextWindowTokens: 200000, cost: 0.05 }),
206
+ makeUnit({ model: "claude-opus-4-20250514", contextWindowTokens: 200000, cost: 0.30 }),
207
+ ];
208
+ const sonnetLabel = renderModelContextWindow(units, "claude-sonnet-4-20250514");
209
+ const opusLabel = renderModelContextWindow(units, "claude-opus-4-20250514");
210
+ assert.deepStrictEqual(sonnetLabel, "[200.0k]", "by model multi: sonnet has context window");
211
+ assert.deepStrictEqual(opusLabel, "[200.0k]", "by model multi: opus has context window");
212
+ }
315
213
 
316
- console.log("\n=== Edge cases ===");
214
+ // ─── By Model section: single model visibility ───────────────────────────────
215
+
216
+ test('By Model section: single model visibility', () => {
217
+ // With guard changed to >= 1, single model aggregation should produce results
218
+ const units = [
219
+ makeUnit({ model: "claude-sonnet-4-20250514" }),
220
+ ];
221
+ const models = aggregateByModel(units);
222
+ assert.ok(models.length >= 1, "single model: aggregateByModel returns >= 1 entry");
223
+ assert.deepStrictEqual(models.length, 1, "single model: exactly 1 model aggregate");
224
+ assert.deepStrictEqual(models[0].model, "claude-sonnet-4-20250514", "single model: correct model name");
225
+ // The guard `models.length >= 1` (changed from > 1) means this section now renders
226
+ assert.ok(models.length >= 1, "single model: passes >= 1 guard (section will render)");
227
+ });
228
+
229
+ // ─── Cost & Usage: aggregate budget line ──────────────────────────────────────
230
+
231
+ test('Cost & Usage: aggregate budget line', () => {
232
+ // Units with truncation and continue-here — both stats appear
233
+ const units = [
234
+ makeUnit({ truncationSections: 3, continueHereFired: true }),
235
+ makeUnit({ truncationSections: 2, continueHereFired: false }),
236
+ makeUnit({ truncationSections: 1, continueHereFired: true }),
237
+ ];
238
+ const line = renderCostBudgetLine(units);
239
+ assert.ok(line !== null, "cost budget: line rendered when budget data exists");
240
+ assert.match(line!, /6 sections truncated/, "cost budget: shows total truncation count (3+2+1=6)");
241
+ assert.match(line!, /2 continue-here fired/, "cost budget: shows continue-here count");
242
+ });
243
+
244
+ {
245
+ // Only truncation, no continue-here
246
+ const units = [
247
+ makeUnit({ truncationSections: 4, continueHereFired: false }),
248
+ ];
249
+ const line = renderCostBudgetLine(units);
250
+ assert.ok(line !== null, "cost budget truncation-only: line rendered");
251
+ assert.match(line!, /4 sections truncated/, "cost budget truncation-only: shows count");
252
+ assert.doesNotMatch(line!, /continue-here/, "cost budget truncation-only: no continue-here text");
253
+ }
317
254
 
318
- {
319
- // formatTokenCount for context window values
320
- assertEq(formatTokenCount(200000), "200.0k", "format: 200000 → 200.0k");
321
- assertEq(formatTokenCount(128000), "128.0k", "format: 128000 → 128.0k");
322
- assertEq(formatTokenCount(1000000), "1.00M", "format: 1000000 → 1.00M");
323
- assertEq(formatTokenCount(32000), "32.0k", "format: 32000 → 32.0k");
324
- }
255
+ {
256
+ // Only continue-here, no truncation
257
+ const units = [
258
+ makeUnit({ truncationSections: 0, continueHereFired: true }),
259
+ ];
260
+ const line = renderCostBudgetLine(units);
261
+ assert.ok(line !== null, "cost budget continue-only: line rendered");
262
+ assert.doesNotMatch(line!, /truncated/, "cost budget continue-only: no truncation text");
263
+ assert.match(line!, /1 continue-here fired/, "cost budget continue-only: shows count");
264
+ }
325
265
 
326
- {
327
- // Completed unit key includes type — different types don't collide
328
- const ledgerUnits = [
329
- makeUnit({ type: "research-slice", id: "M001/S01", truncationSections: 2 }),
330
- makeUnit({ type: "plan-slice", id: "M001/S01", truncationSections: 5 }),
331
- ];
332
- const researchMarkers = renderCompletedBudgetMarkers(
333
- { type: "research-slice", id: "M001/S01" },
334
- ledgerUnits,
335
- );
336
- const planMarkers = renderCompletedBudgetMarkers(
337
- { type: "plan-slice", id: "M001/S01" },
338
- ledgerUnits,
339
- );
340
- assertMatch(researchMarkers, /▼2/, "type-keying: research unit gets its own truncation count");
341
- assertMatch(planMarkers, /▼5/, "type-keying: plan unit gets its own truncation count");
342
- }
266
+ // ─── Backward compat: no budget fields ────────────────────────────────────────
267
+
268
+ test('Backward compat: no budget data', () => {
269
+ // Old-format units without budget fields — no indicators anywhere
270
+ const oldUnits = [
271
+ makeUnit(), // no budget fields
272
+ makeUnit({ id: "M001/S01/T02" }),
273
+ ];
274
+
275
+ // Completed section: no markers
276
+ const markers = renderCompletedBudgetMarkers(
277
+ { type: "execute-task", id: "M001/S01/T01" },
278
+ oldUnits,
279
+ );
280
+ assert.doesNotMatch(markers, /▼/, "backward compat completed: no truncation marker");
281
+ assert.doesNotMatch(markers, /wrap-up/, "backward compat completed: no wrap-up marker");
282
+ assert.deepStrictEqual(markers, "", "backward compat completed: empty markers string");
283
+
284
+ // By Model section: no context window label
285
+ const label = renderModelContextWindow(oldUnits, "claude-sonnet-4-20250514");
286
+ assert.deepStrictEqual(label, null, "backward compat by-model: no context window label");
287
+
288
+ // Cost & Usage: no budget line
289
+ const line = renderCostBudgetLine(oldUnits);
290
+ assert.deepStrictEqual(line, null, "backward compat cost: no budget summary line");
291
+
292
+ // Aggregation still works
293
+ const totals = getProjectTotals(oldUnits);
294
+ assert.deepStrictEqual(totals.totalTruncationSections, 0, "backward compat: truncation total = 0");
295
+ assert.deepStrictEqual(totals.continueHereFiredCount, 0, "backward compat: continueHere count = 0");
296
+ assert.deepStrictEqual(totals.units, 2, "backward compat: unit count correct");
297
+ });
298
+
299
+ // ─── Edge cases ───────────────────────────────────────────────────────────────
300
+
301
+ test('Edge cases', () => {
302
+ // formatTokenCount for context window values
303
+ assert.deepStrictEqual(formatTokenCount(200000), "200.0k", "format: 200000 → 200.0k");
304
+ assert.deepStrictEqual(formatTokenCount(128000), "128.0k", "format: 128000 → 128.0k");
305
+ assert.deepStrictEqual(formatTokenCount(1000000), "1.00M", "format: 1000000 → 1.00M");
306
+ assert.deepStrictEqual(formatTokenCount(32000), "32.0k", "format: 32000 → 32.0k");
307
+ });
308
+
309
+ {
310
+ // Completed unit key includes type — different types don't collide
311
+ const ledgerUnits = [
312
+ makeUnit({ type: "research-slice", id: "M001/S01", truncationSections: 2 }),
313
+ makeUnit({ type: "plan-slice", id: "M001/S01", truncationSections: 5 }),
314
+ ];
315
+ const researchMarkers = renderCompletedBudgetMarkers(
316
+ { type: "research-slice", id: "M001/S01" },
317
+ ledgerUnits,
318
+ );
319
+ const planMarkers = renderCompletedBudgetMarkers(
320
+ { type: "plan-slice", id: "M001/S01" },
321
+ ledgerUnits,
322
+ );
323
+ assert.match(researchMarkers, /▼2/, "type-keying: research unit gets its own truncation count");
324
+ assert.match(planMarkers, /▼5/, "type-keying: plan unit gets its own truncation count");
325
+ }
343
326
 
344
- // ─── Summary ──────────────────────────────────────────────────────────────────
327
+ // ─── Summary ──────────────────────────────────────────────────────────────────
345
328
 
346
- report();
329
+ });