gsd-pi 2.77.0-dev.eaa4973bc → 2.78.0-dev.aeeb2ca00

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 (545) hide show
  1. package/README.md +53 -17
  2. package/dist/claude-cli-check.js +46 -10
  3. package/dist/headless.js +49 -4
  4. package/dist/resource-loader.d.ts +40 -0
  5. package/dist/resource-loader.js +32 -13
  6. package/dist/resources/extensions/browser-tools/capture.js +9 -0
  7. package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +8 -59
  8. package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +36 -24
  9. package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +69 -71
  10. package/dist/resources/extensions/browser-tools/tools/forms.js +5 -1
  11. package/dist/resources/extensions/browser-tools/tools/intent.js +5 -1
  12. package/dist/resources/extensions/claude-code-cli/readiness.js +72 -16
  13. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +481 -17
  14. package/dist/resources/extensions/github-sync/templates.js +103 -0
  15. package/dist/resources/extensions/google-search/index.js +3 -2
  16. package/dist/resources/extensions/gsd/auto/loop.js +124 -2
  17. package/dist/resources/extensions/gsd/auto/phases.js +57 -39
  18. package/dist/resources/extensions/gsd/auto/session.js +6 -2
  19. package/dist/resources/extensions/gsd/auto-dispatch.js +142 -29
  20. package/dist/resources/extensions/gsd/auto-model-selection.js +124 -4
  21. package/dist/resources/extensions/gsd/auto-post-unit.js +150 -64
  22. package/dist/resources/extensions/gsd/auto-prompts.js +372 -104
  23. package/dist/resources/extensions/gsd/auto-recovery.js +197 -48
  24. package/dist/resources/extensions/gsd/auto-start.js +107 -29
  25. package/dist/resources/extensions/gsd/auto-tool-tracking.js +47 -7
  26. package/dist/resources/extensions/gsd/auto-worktree.js +122 -26
  27. package/dist/resources/extensions/gsd/auto.js +76 -21
  28. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +19 -1
  29. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +209 -0
  30. package/dist/resources/extensions/gsd/bootstrap/provider-error-resume.js +3 -6
  31. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +7 -3
  32. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +127 -9
  33. package/dist/resources/extensions/gsd/component-loader.js +447 -0
  34. package/dist/resources/extensions/gsd/component-types.js +69 -0
  35. package/dist/resources/extensions/gsd/context-store.js +23 -7
  36. package/dist/resources/extensions/gsd/detection.js +49 -1
  37. package/dist/resources/extensions/gsd/dispatch-guard.js +2 -17
  38. package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  39. package/dist/resources/extensions/gsd/forensics.js +106 -0
  40. package/dist/resources/extensions/gsd/gate-registry.js +2 -2
  41. package/dist/resources/extensions/gsd/git-constants.js +28 -1
  42. package/dist/resources/extensions/gsd/git-self-heal.js +27 -0
  43. package/dist/resources/extensions/gsd/git-service.js +126 -2
  44. package/dist/resources/extensions/gsd/gsd-db.js +6 -3
  45. package/dist/resources/extensions/gsd/guided-flow.js +39 -13
  46. package/dist/resources/extensions/gsd/memory-extractor.js +7 -1
  47. package/dist/resources/extensions/gsd/milestone-scope-classifier.js +299 -0
  48. package/dist/resources/extensions/gsd/milestone-summary-classifier.js +37 -0
  49. package/dist/resources/extensions/gsd/model-cost-table.js +3 -0
  50. package/dist/resources/extensions/gsd/model-router.js +6 -0
  51. package/dist/resources/extensions/gsd/native-git-bridge.js +34 -4
  52. package/dist/resources/extensions/gsd/preferences-validation.js +23 -0
  53. package/dist/resources/extensions/gsd/prompt-cache-optimizer.js +4 -0
  54. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +6 -2
  55. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +23 -4
  56. package/dist/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
  57. package/dist/resources/extensions/gsd/prompts/plan-slice.md +15 -2
  58. package/dist/resources/extensions/gsd/safety/git-checkpoint.js +11 -0
  59. package/dist/resources/extensions/gsd/service-tier.js +5 -2
  60. package/dist/resources/extensions/gsd/session-lock.js +19 -10
  61. package/dist/resources/extensions/gsd/skill-manifest.js +168 -0
  62. package/dist/resources/extensions/gsd/slice-cadence.js +238 -0
  63. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +278 -8
  64. package/dist/resources/extensions/gsd/state-transition-matrix.js +118 -0
  65. package/dist/resources/extensions/gsd/state.js +69 -58
  66. package/dist/resources/extensions/gsd/sync-lock.js +98 -42
  67. package/dist/resources/extensions/gsd/tools/validate-milestone.js +7 -2
  68. package/dist/resources/extensions/gsd/unit-context-composer.js +147 -0
  69. package/dist/resources/extensions/gsd/unit-context-manifest.js +370 -0
  70. package/dist/resources/extensions/gsd/uok/dispatch-envelope.js +33 -0
  71. package/dist/resources/extensions/gsd/uok/execution-graph.js +10 -0
  72. package/dist/resources/extensions/gsd/uok/gate-runner.js +53 -5
  73. package/dist/resources/extensions/gsd/uok/gitops.js +2 -1
  74. package/dist/resources/extensions/gsd/uok/loop-adapter.js +37 -10
  75. package/dist/resources/extensions/gsd/uok/parity-report.js +58 -0
  76. package/dist/resources/extensions/gsd/uok/plan-v2.js +10 -4
  77. package/dist/resources/extensions/gsd/uok/writer.js +82 -0
  78. package/dist/resources/extensions/gsd/workflow-mcp.js +6 -0
  79. package/dist/resources/extensions/gsd/worktree-manager.js +85 -8
  80. package/dist/resources/extensions/gsd/worktree-resolver.js +86 -7
  81. package/dist/resources/extensions/gsd/worktree-telemetry.js +198 -0
  82. package/dist/resources/extensions/mcp-client/index.js +3 -1
  83. package/dist/resources/extensions/ollama/index.js +5 -1
  84. package/dist/resources/extensions/remote-questions/manager.js +11 -5
  85. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  86. package/dist/web/standalone/.next/BUILD_ID +1 -1
  87. package/dist/web/standalone/.next/app-path-routes-manifest.json +11 -11
  88. package/dist/web/standalone/.next/build-manifest.json +2 -2
  89. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  90. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  91. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  92. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  99. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  100. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  101. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  102. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  103. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  104. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  106. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  107. package/dist/web/standalone/.next/server/app/index.html +1 -1
  108. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  109. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  110. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app-paths-manifest.json +11 -11
  115. package/dist/web/standalone/.next/server/chunks/1926.js +1 -1
  116. package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
  117. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  118. package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
  119. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  120. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  121. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  122. package/package.json +2 -3
  123. package/packages/daemon/package.json +2 -2
  124. package/packages/daemon/src/logger.ts +4 -3
  125. package/packages/mcp-server/dist/server.d.ts +24 -0
  126. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  127. package/packages/mcp-server/dist/server.js +88 -87
  128. package/packages/mcp-server/dist/server.js.map +1 -1
  129. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  130. package/packages/mcp-server/dist/workflow-tools.js +15 -6
  131. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  132. package/packages/mcp-server/package.json +2 -2
  133. package/packages/mcp-server/src/mcp-server.test.ts +25 -3
  134. package/packages/mcp-server/src/readers/graph.test.ts +87 -15
  135. package/packages/mcp-server/src/secure-env-collect.test.ts +232 -237
  136. package/packages/mcp-server/src/server.ts +131 -105
  137. package/packages/mcp-server/src/workflow-tools.test.ts +85 -0
  138. package/packages/mcp-server/src/workflow-tools.ts +19 -6
  139. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  140. package/packages/native/package.json +2 -2
  141. package/packages/native/src/__tests__/_test-coverage-guard.test.mjs +98 -0
  142. package/packages/native/src/__tests__/module-compat.test.mjs +59 -27
  143. package/packages/native/src/__tests__/ps.test.mjs +14 -8
  144. package/packages/native/src/__tests__/stream-process.test.mjs +23 -2
  145. package/packages/native/src/__tests__/truncate.test.mjs +17 -2
  146. package/packages/pi-agent-core/package.json +1 -1
  147. package/packages/pi-agent-core/src/agent-loop.test.ts +5 -15
  148. package/packages/pi-agent-core/src/agent.test.ts +96 -102
  149. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  150. package/packages/pi-ai/dist/models/capability-patches.d.ts.map +1 -1
  151. package/packages/pi-ai/dist/models/capability-patches.js +9 -2
  152. package/packages/pi-ai/dist/models/capability-patches.js.map +1 -1
  153. package/packages/pi-ai/dist/models/generated/index.d.ts +34 -0
  154. package/packages/pi-ai/dist/models/generated/index.d.ts.map +1 -1
  155. package/packages/pi-ai/dist/models/generated/openai-codex.d.ts +17 -0
  156. package/packages/pi-ai/dist/models/generated/openai-codex.d.ts.map +1 -1
  157. package/packages/pi-ai/dist/models/generated/openai-codex.js +17 -0
  158. package/packages/pi-ai/dist/models/generated/openai-codex.js.map +1 -1
  159. package/packages/pi-ai/dist/models/generated/openai.d.ts +17 -0
  160. package/packages/pi-ai/dist/models/generated/openai.d.ts.map +1 -1
  161. package/packages/pi-ai/dist/models/generated/openai.js +17 -0
  162. package/packages/pi-ai/dist/models/generated/openai.js.map +1 -1
  163. package/packages/pi-ai/dist/models.generated.test.js +43 -70
  164. package/packages/pi-ai/dist/models.generated.test.js.map +1 -1
  165. package/packages/pi-ai/dist/models.test.js +36 -11
  166. package/packages/pi-ai/dist/models.test.js.map +1 -1
  167. package/packages/pi-ai/package.json +1 -1
  168. package/packages/pi-ai/scripts/generate-models.ts +44 -0
  169. package/packages/pi-ai/src/models/capability-patches.ts +10 -2
  170. package/packages/pi-ai/src/models/generated/openai-codex.ts +17 -0
  171. package/packages/pi-ai/src/models/generated/openai.ts +17 -0
  172. package/packages/pi-ai/src/models.generated.test.ts +46 -73
  173. package/packages/pi-ai/src/models.test.ts +48 -11
  174. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  175. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +96 -32
  176. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
  177. package/packages/pi-coding-agent/dist/core/agent-session-model-switch.test.js +75 -12
  178. package/packages/pi-coding-agent/dist/core/agent-session-model-switch.test.js.map +1 -1
  179. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +99 -31
  180. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -1
  181. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +5 -0
  182. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  183. package/packages/pi-coding-agent/dist/core/extensions/loader.js +61 -0
  184. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  185. package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js +30 -4
  186. package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js.map +1 -1
  187. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +17 -0
  188. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
  189. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js +76 -18
  190. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js.map +1 -1
  191. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
  192. package/packages/pi-coding-agent/dist/core/retry-handler.js +2 -6
  193. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
  194. package/packages/pi-coding-agent/dist/core/retry-handler.test.js +5 -1
  195. package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -1
  196. package/packages/pi-coding-agent/dist/core/retryable-error-regex.d.ts +18 -0
  197. package/packages/pi-coding-agent/dist/core/retryable-error-regex.d.ts.map +1 -0
  198. package/packages/pi-coding-agent/dist/core/retryable-error-regex.js +18 -0
  199. package/packages/pi-coding-agent/dist/core/retryable-error-regex.js.map +1 -0
  200. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +20 -0
  201. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  202. package/packages/pi-coding-agent/dist/core/system-prompt.js +16 -2
  203. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  204. package/packages/pi-coding-agent/dist/index.d.ts +1 -0
  205. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  206. package/packages/pi-coding-agent/dist/index.js +1 -0
  207. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  208. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +36 -5
  209. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  210. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js +20 -13
  211. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js.map +1 -1
  212. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  213. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +30 -12
  214. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  215. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  216. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +18 -3
  217. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  218. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +125 -0
  219. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  220. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +2 -0
  221. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  222. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  223. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +4 -0
  224. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  225. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +105 -13
  226. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  227. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.d.ts +2 -0
  228. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.d.ts.map +1 -0
  229. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.js +130 -0
  230. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.js.map +1 -0
  231. package/packages/pi-coding-agent/package.json +1 -1
  232. package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +113 -37
  233. package/packages/pi-coding-agent/src/core/agent-session-model-switch.test.ts +89 -17
  234. package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +112 -43
  235. package/packages/pi-coding-agent/src/core/extensions/loader.ts +58 -0
  236. package/packages/pi-coding-agent/src/core/lsp/lsp-integration.test.ts +35 -4
  237. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +20 -0
  238. package/packages/pi-coding-agent/src/core/resource-loader-cache-reset.test.ts +93 -28
  239. package/packages/pi-coding-agent/src/core/retry-handler.test.ts +5 -1
  240. package/packages/pi-coding-agent/src/core/retry-handler.ts +2 -8
  241. package/packages/pi-coding-agent/src/core/retryable-error-regex.ts +18 -0
  242. package/packages/pi-coding-agent/src/core/system-prompt.ts +35 -1
  243. package/packages/pi-coding-agent/src/index.ts +1 -0
  244. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +49 -3
  245. package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.test.ts +26 -20
  246. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +48 -9
  247. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +146 -1
  248. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +20 -3
  249. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +2 -0
  250. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +119 -13
  251. package/packages/pi-coding-agent/src/tests/system-prompt-skill-filter.test.ts +157 -0
  252. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  253. package/packages/pi-tui/dist/__tests__/autocomplete.test.js +18 -8
  254. package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
  255. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js +128 -17
  256. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js.map +1 -1
  257. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js +37 -11
  258. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js.map +1 -1
  259. package/packages/pi-tui/dist/__tests__/tui.test.js +18 -30
  260. package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
  261. package/packages/pi-tui/dist/components/__tests__/input.test.js +10 -3
  262. package/packages/pi-tui/dist/components/__tests__/input.test.js.map +1 -1
  263. package/packages/pi-tui/dist/components/__tests__/loader.test.js +53 -9
  264. package/packages/pi-tui/dist/components/__tests__/loader.test.js.map +1 -1
  265. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js +6 -2
  266. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js.map +1 -1
  267. package/packages/pi-tui/dist/components/editor.d.ts +14 -0
  268. package/packages/pi-tui/dist/components/editor.d.ts.map +1 -1
  269. package/packages/pi-tui/dist/components/editor.js +19 -0
  270. package/packages/pi-tui/dist/components/editor.js.map +1 -1
  271. package/packages/pi-tui/dist/components/image.test.js +6 -5
  272. package/packages/pi-tui/dist/components/image.test.js.map +1 -1
  273. package/packages/pi-tui/dist/editor-component.d.ts +2 -0
  274. package/packages/pi-tui/dist/editor-component.d.ts.map +1 -1
  275. package/packages/pi-tui/dist/editor-component.js.map +1 -1
  276. package/packages/pi-tui/package.json +1 -1
  277. package/packages/pi-tui/src/__tests__/autocomplete.test.ts +24 -8
  278. package/packages/pi-tui/src/__tests__/overlay-layout.test.ts +140 -17
  279. package/packages/pi-tui/src/__tests__/stdin-buffer.test.ts +42 -11
  280. package/packages/pi-tui/src/__tests__/tui.test.ts +18 -37
  281. package/packages/pi-tui/src/components/__tests__/input.test.ts +19 -3
  282. package/packages/pi-tui/src/components/__tests__/loader.test.ts +112 -35
  283. package/packages/pi-tui/src/components/__tests__/markdown-maxlines.test.ts +9 -2
  284. package/packages/pi-tui/src/components/editor.ts +22 -0
  285. package/packages/pi-tui/src/components/image.test.ts +10 -5
  286. package/packages/pi-tui/src/editor-component.ts +3 -0
  287. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  288. package/packages/rpc-client/dist/rpc-client.test.js +101 -51
  289. package/packages/rpc-client/dist/rpc-client.test.js.map +1 -1
  290. package/packages/rpc-client/package.json +1 -1
  291. package/packages/rpc-client/src/rpc-client.test.ts +109 -52
  292. package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
  293. package/pkg/package.json +1 -1
  294. package/scripts/install.js +15 -1
  295. package/src/resources/extensions/browser-tools/capture.ts +12 -0
  296. package/src/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +8 -59
  297. package/src/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +36 -24
  298. package/src/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +69 -71
  299. package/src/resources/extensions/browser-tools/tools/forms.ts +5 -1
  300. package/src/resources/extensions/browser-tools/tools/intent.ts +5 -1
  301. package/src/resources/extensions/claude-code-cli/readiness.ts +75 -16
  302. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +518 -19
  303. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +919 -75
  304. package/src/resources/extensions/github-sync/templates.ts +151 -0
  305. package/src/resources/extensions/github-sync/tests/cli.test.ts +76 -7
  306. package/src/resources/extensions/github-sync/tests/templates.test.ts +92 -1
  307. package/src/resources/extensions/google-search/index.ts +3 -2
  308. package/src/resources/extensions/gsd/auto/loop.ts +142 -2
  309. package/src/resources/extensions/gsd/auto/phases.ts +62 -38
  310. package/src/resources/extensions/gsd/auto/session.ts +7 -2
  311. package/src/resources/extensions/gsd/auto-dispatch.ts +156 -29
  312. package/src/resources/extensions/gsd/auto-model-selection.ts +131 -4
  313. package/src/resources/extensions/gsd/auto-post-unit.ts +163 -73
  314. package/src/resources/extensions/gsd/auto-prompts.ts +385 -93
  315. package/src/resources/extensions/gsd/auto-recovery.ts +230 -51
  316. package/src/resources/extensions/gsd/auto-start.ts +127 -9
  317. package/src/resources/extensions/gsd/auto-tool-tracking.ts +51 -7
  318. package/src/resources/extensions/gsd/auto-worktree.ts +130 -26
  319. package/src/resources/extensions/gsd/auto.ts +90 -23
  320. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +20 -1
  321. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +221 -0
  322. package/src/resources/extensions/gsd/bootstrap/provider-error-resume.ts +3 -7
  323. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +7 -3
  324. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +158 -9
  325. package/src/resources/extensions/gsd/component-loader.ts +598 -0
  326. package/src/resources/extensions/gsd/component-types.ts +362 -0
  327. package/src/resources/extensions/gsd/context-store.ts +25 -8
  328. package/src/resources/extensions/gsd/detection.ts +58 -1
  329. package/src/resources/extensions/gsd/dispatch-guard.ts +2 -20
  330. package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  331. package/src/resources/extensions/gsd/forensics.ts +118 -1
  332. package/src/resources/extensions/gsd/gate-registry.ts +2 -2
  333. package/src/resources/extensions/gsd/git-constants.ts +30 -1
  334. package/src/resources/extensions/gsd/git-self-heal.ts +31 -0
  335. package/src/resources/extensions/gsd/git-service.ts +149 -2
  336. package/src/resources/extensions/gsd/gsd-db.ts +6 -3
  337. package/src/resources/extensions/gsd/guided-flow.ts +57 -14
  338. package/src/resources/extensions/gsd/journal.ts +11 -1
  339. package/src/resources/extensions/gsd/memory-extractor.ts +11 -3
  340. package/src/resources/extensions/gsd/milestone-scope-classifier.ts +366 -0
  341. package/src/resources/extensions/gsd/milestone-summary-classifier.ts +42 -0
  342. package/src/resources/extensions/gsd/model-cost-table.ts +3 -0
  343. package/src/resources/extensions/gsd/model-router.ts +6 -0
  344. package/src/resources/extensions/gsd/native-git-bridge.ts +34 -4
  345. package/src/resources/extensions/gsd/preferences-validation.ts +21 -0
  346. package/src/resources/extensions/gsd/prompt-cache-optimizer.ts +4 -0
  347. package/src/resources/extensions/gsd/prompts/complete-milestone.md +6 -2
  348. package/src/resources/extensions/gsd/prompts/discuss-headless.md +23 -4
  349. package/src/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
  350. package/src/resources/extensions/gsd/prompts/plan-slice.md +15 -2
  351. package/src/resources/extensions/gsd/safety/git-checkpoint.ts +15 -0
  352. package/src/resources/extensions/gsd/service-tier.ts +5 -2
  353. package/src/resources/extensions/gsd/session-lock.ts +20 -10
  354. package/src/resources/extensions/gsd/skill-manifest.ts +175 -0
  355. package/src/resources/extensions/gsd/slice-cadence.ts +299 -0
  356. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +309 -8
  357. package/src/resources/extensions/gsd/state-transition-matrix.ts +152 -0
  358. package/src/resources/extensions/gsd/state.ts +76 -66
  359. package/src/resources/extensions/gsd/sync-lock.ts +97 -39
  360. package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +270 -0
  361. package/src/resources/extensions/gsd/tests/artifacts-table-preserved-on-cache-invalidate.test.ts +2 -1
  362. package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +341 -0
  363. package/src/resources/extensions/gsd/tests/auto-discuss-milestone-deadlock-4973.test.ts +264 -0
  364. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +133 -292
  365. package/src/resources/extensions/gsd/tests/auto-model-selection-tool-poisoning.test.ts +742 -0
  366. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +78 -0
  367. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +61 -0
  368. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +93 -0
  369. package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +4 -1
  370. package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +8 -194
  371. package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +3 -2
  372. package/src/resources/extensions/gsd/tests/auto-start-cold-db-bootstrap.test.ts +2 -2
  373. package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +15 -58
  374. package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +2 -2
  375. package/src/resources/extensions/gsd/tests/auto-thinking-restore.test.ts +3 -2
  376. package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +3 -2
  377. package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +2 -1
  378. package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +17 -21
  379. package/src/resources/extensions/gsd/tests/canonical-milestone-root.test.ts +108 -0
  380. package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +263 -0
  381. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +25 -0
  382. package/src/resources/extensions/gsd/tests/complete-slice-composer.test.ts +192 -0
  383. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +2 -1
  384. package/src/resources/extensions/gsd/tests/complete-task.test.ts +16 -8
  385. package/src/resources/extensions/gsd/tests/component-loader.test.ts +589 -0
  386. package/src/resources/extensions/gsd/tests/component-types.test.ts +127 -0
  387. package/src/resources/extensions/gsd/tests/context-store.test.ts +79 -0
  388. package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +2 -1
  389. package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +50 -1
  390. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +159 -0
  391. package/src/resources/extensions/gsd/tests/db-access-guardrails.test.ts +1 -0
  392. package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +3 -3
  393. package/src/resources/extensions/gsd/tests/derive-state-db-disk-reconcile.test.ts +40 -0
  394. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +91 -3
  395. package/src/resources/extensions/gsd/tests/derive-state.test.ts +4 -4
  396. package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +2 -1
  397. package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +2 -1
  398. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +5 -0
  399. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +25 -0
  400. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +14 -0
  401. package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +3 -2
  402. package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +4 -3
  403. package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +4 -3
  404. package/src/resources/extensions/gsd/tests/execution-entry-missing-context-4671.test.ts +173 -0
  405. package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +139 -129
  406. package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +8 -104
  407. package/src/resources/extensions/gsd/tests/gate-state-canonicalization.test.ts +102 -0
  408. package/src/resources/extensions/gsd/tests/gate-storage.test.ts +1 -1
  409. package/src/resources/extensions/gsd/tests/google-search-stub.test.ts +14 -4
  410. package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +117 -0
  411. package/src/resources/extensions/gsd/tests/hook-key-parsing.test.ts +4 -55
  412. package/src/resources/extensions/gsd/tests/integration/all-milestones-complete-merge.test.ts +7 -56
  413. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +20 -0
  414. package/src/resources/extensions/gsd/tests/integration/doctor-proactive.test.ts +18 -2
  415. package/src/resources/extensions/gsd/tests/integration/queue-completed-milestone-perf.test.ts +10 -4
  416. package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +144 -7
  417. package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +4 -0
  418. package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +2 -16
  419. package/src/resources/extensions/gsd/tests/interactive-routing-bypass.test.ts +9 -3
  420. package/src/resources/extensions/gsd/tests/interrupted-session-ui.test.ts +6 -9
  421. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +64 -0
  422. package/src/resources/extensions/gsd/tests/knowledge.test.ts +93 -1
  423. package/src/resources/extensions/gsd/tests/mcp-client-security.test.ts +8 -37
  424. package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +5 -15
  425. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +227 -55
  426. package/src/resources/extensions/gsd/tests/milestone-scope-classifier.test.ts +187 -0
  427. package/src/resources/extensions/gsd/tests/milestone-summary-classifier.test.ts +30 -0
  428. package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +9 -1
  429. package/src/resources/extensions/gsd/tests/model-router.test.ts +1 -1
  430. package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +6 -48
  431. package/src/resources/extensions/gsd/tests/notification-widget.test.ts +6 -3
  432. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +59 -2
  433. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +273 -130
  434. package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +301 -0
  435. package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +32 -1
  436. package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +2 -1
  437. package/src/resources/extensions/gsd/tests/prompt-cache-optimizer.test.ts +12 -0
  438. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +15 -4
  439. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +23 -24
  440. package/src/resources/extensions/gsd/tests/queue-auto-guard.test.ts +32 -0
  441. package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +3 -2
  442. package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +4 -5
  443. package/src/resources/extensions/gsd/tests/ready-phrase-no-files-4573.test.ts +75 -2
  444. package/src/resources/extensions/gsd/tests/reassess-default-optin.test.ts +132 -0
  445. package/src/resources/extensions/gsd/tests/recovery-attempts-reset.test.ts +8 -40
  446. package/src/resources/extensions/gsd/tests/regex-hardening.test.ts +136 -256
  447. package/src/resources/extensions/gsd/tests/research-milestone-composer.test.ts +114 -0
  448. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +6 -3
  449. package/src/resources/extensions/gsd/tests/run-uat-composer.test.ts +148 -0
  450. package/src/resources/extensions/gsd/tests/service-tier.test.ts +4 -0
  451. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +29 -0
  452. package/src/resources/extensions/gsd/tests/sidecar-queue.test.ts +3 -2
  453. package/src/resources/extensions/gsd/tests/silent-catch-diagnostics.test.ts +55 -95
  454. package/src/resources/extensions/gsd/tests/single-writer-v3-tool-surface.test.ts +158 -0
  455. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +120 -1
  456. package/src/resources/extensions/gsd/tests/skill-manifest.test.ts +112 -0
  457. package/src/resources/extensions/gsd/tests/slice-cadence.test.ts +242 -0
  458. package/src/resources/extensions/gsd/tests/slice-context-injection.test.ts +3 -2
  459. package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +164 -1
  460. package/src/resources/extensions/gsd/tests/smart-entry-draft.test.ts +2 -1
  461. package/src/resources/extensions/gsd/tests/stale-dirlistcache-4648.test.ts +112 -0
  462. package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +29 -5
  463. package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +44 -0
  464. package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +3 -3
  465. package/src/resources/extensions/gsd/tests/structured-data-formatter.test.ts +11 -92
  466. package/src/resources/extensions/gsd/tests/subagent-model-dispatch.test.ts +7 -6
  467. package/src/resources/extensions/gsd/tests/survivor-branch-complete.test.ts +102 -101
  468. package/src/resources/extensions/gsd/tests/sync-lock.test.ts +31 -0
  469. package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +4 -3
  470. package/src/resources/extensions/gsd/tests/test-helpers.test.ts +98 -0
  471. package/src/resources/extensions/gsd/tests/test-helpers.ts +153 -0
  472. package/src/resources/extensions/gsd/tests/token-profile.test.ts +8 -1
  473. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +61 -1
  474. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +8 -1
  475. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +355 -0
  476. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +258 -0
  477. package/src/resources/extensions/gsd/tests/uok-contracts.test.ts +51 -0
  478. package/src/resources/extensions/gsd/tests/uok-execution-graph.test.ts +16 -0
  479. package/src/resources/extensions/gsd/tests/uok-gate-runner.test.ts +75 -0
  480. package/src/resources/extensions/gsd/tests/uok-gitops-wiring.test.ts +49 -26
  481. package/src/resources/extensions/gsd/tests/uok-loop-adapter-writer.test.ts +65 -0
  482. package/src/resources/extensions/gsd/tests/uok-parity-report.test.ts +42 -0
  483. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +19 -2
  484. package/src/resources/extensions/gsd/tests/uok-writer.test.ts +75 -0
  485. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +12 -0
  486. package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +144 -80
  487. package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +20 -54
  488. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +342 -277
  489. package/src/resources/extensions/gsd/tests/worker-model-override.test.ts +37 -29
  490. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +226 -266
  491. package/src/resources/extensions/gsd/tests/worktree-health-monorepo.test.ts +103 -67
  492. package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +92 -90
  493. package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +238 -59
  494. package/src/resources/extensions/gsd/tests/worktree-sync-overwrite-loop.test.ts +113 -161
  495. package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +210 -0
  496. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +262 -0
  497. package/src/resources/extensions/gsd/tests/write-gate-predicates.test.ts +186 -0
  498. package/src/resources/extensions/gsd/tests/write-gate.test.ts +7 -5
  499. package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +80 -96
  500. package/src/resources/extensions/gsd/tools/validate-milestone.ts +8 -2
  501. package/src/resources/extensions/gsd/types.ts +3 -3
  502. package/src/resources/extensions/gsd/unit-context-composer.ts +218 -0
  503. package/src/resources/extensions/gsd/unit-context-manifest.ts +574 -0
  504. package/src/resources/extensions/gsd/uok/contracts.ts +65 -0
  505. package/src/resources/extensions/gsd/uok/dispatch-envelope.ts +56 -0
  506. package/src/resources/extensions/gsd/uok/execution-graph.ts +22 -0
  507. package/src/resources/extensions/gsd/uok/gate-runner.ts +65 -5
  508. package/src/resources/extensions/gsd/uok/gitops.ts +6 -1
  509. package/src/resources/extensions/gsd/uok/loop-adapter.ts +45 -10
  510. package/src/resources/extensions/gsd/uok/parity-report.ts +84 -0
  511. package/src/resources/extensions/gsd/uok/plan-v2.ts +13 -5
  512. package/src/resources/extensions/gsd/uok/writer.ts +113 -0
  513. package/src/resources/extensions/gsd/workflow-mcp.ts +6 -0
  514. package/src/resources/extensions/gsd/worktree-manager.ts +108 -7
  515. package/src/resources/extensions/gsd/worktree-resolver.ts +96 -9
  516. package/src/resources/extensions/gsd/worktree-telemetry.ts +322 -0
  517. package/src/resources/extensions/mcp-client/index.ts +3 -1
  518. package/src/resources/extensions/mcp-client/tests/server-name-spaces.test.ts +70 -36
  519. package/src/resources/extensions/ollama/index.ts +5 -1
  520. package/src/resources/extensions/ollama/ollama-auth-mode.test.ts +123 -15
  521. package/src/resources/extensions/ollama/ollama-status-indicator.test.ts +206 -19
  522. package/src/resources/extensions/remote-questions/manager.ts +36 -4
  523. package/src/resources/extensions/remote-questions/tests/command-polling.test.ts +200 -190
  524. package/src/resources/extensions/shared/tests/interview-preview.test.ts +11 -3
  525. package/src/resources/extensions/voice/tests/linux-ready.test.ts +129 -113
  526. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts +0 -2
  527. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts.map +0 -1
  528. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js +0 -289
  529. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js.map +0 -1
  530. package/packages/pi-ai/src/utils/oauth/oauth-providers.test.ts +0 -363
  531. package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +0 -143
  532. package/src/resources/extensions/gsd/tests/complete-milestone-false-merge.test.ts +0 -157
  533. package/src/resources/extensions/gsd/tests/dashboard-model-label-ordering.test.ts +0 -107
  534. package/src/resources/extensions/gsd/tests/find-missing-summaries-closed.test.ts +0 -48
  535. package/src/resources/extensions/gsd/tests/forensics-context-persist.test.ts +0 -159
  536. package/src/resources/extensions/gsd/tests/forensics-db-completion.test.ts +0 -96
  537. package/src/resources/extensions/gsd/tests/forensics-dedup.test.ts +0 -79
  538. package/src/resources/extensions/gsd/tests/forensics-hook-key-parse.test.ts +0 -74
  539. package/src/resources/extensions/gsd/tests/forensics-journal.test.ts +0 -162
  540. package/src/resources/extensions/gsd/tests/gitignore-bg-shell.test.ts +0 -38
  541. package/src/resources/extensions/gsd/tests/gsd-no-project-error.test.ts +0 -73
  542. package/src/resources/extensions/gsd/tests/idle-watchdog-stall-override.test.ts +0 -125
  543. package/src/resources/extensions/gsd/tests/import-done-milestones.test.ts +0 -42
  544. /package/dist/web/standalone/.next/static/{5wbu35_C2_MQ3Jj1lEVDx → cAJH99yNS1UPbeSEiNRrV}/_buildManifest.js +0 -0
  545. /package/dist/web/standalone/.next/static/{5wbu35_C2_MQ3Jj1lEVDx → cAJH99yNS1UPbeSEiNRrV}/_ssgManifest.js +0 -0
@@ -1,107 +0,0 @@
1
- /**
2
- * dashboard-model-label-ordering.test.ts — Regression test for #2899.
3
- *
4
- * The dashboard model label was showing the previous unit's model because
5
- * updateProgressWidget was called before selectAndApplyModel in phases.ts.
6
- * This test verifies:
7
- * 1. updateProgressWidget is called AFTER selectAndApplyModel in phases.ts
8
- * 2. session.ts has a currentDispatchedModelId field
9
- * 3. auto.ts exposes getCurrentDispatchedModelId in widgetStateAccessors
10
- * 4. auto-dashboard.ts reads from a dispatched model accessor, not cmdCtx?.model
11
- */
12
-
13
- import { readFileSync } from "node:fs";
14
- import { join } from "node:path";
15
- import { createTestContext } from "./test-helpers.ts";
16
-
17
- const { assertTrue, assertMatch, report } = createTestContext();
18
-
19
- const phasesPath = join(import.meta.dirname, "..", "auto", "phases.ts");
20
- const sessionPath = join(import.meta.dirname, "..", "auto", "session.ts");
21
- const autoPath = join(import.meta.dirname, "..", "auto.ts");
22
- const dashboardPath = join(import.meta.dirname, "..", "auto-dashboard.ts");
23
-
24
- const phasesSrc = readFileSync(phasesPath, "utf-8");
25
- const sessionSrc = readFileSync(sessionPath, "utf-8");
26
- const autoSrc = readFileSync(autoPath, "utf-8");
27
- const dashboardSrc = readFileSync(dashboardPath, "utf-8");
28
-
29
- console.log("\n=== #2899: Dashboard model label shows correct (dispatched) model ===");
30
-
31
- // ── Test 1: updateProgressWidget is called AFTER selectAndApplyModel ──────
32
-
33
- // Find the positions of the calls in the dispatch function body.
34
- // selectAndApplyModel must appear BEFORE updateProgressWidget.
35
- const selectModelPos = phasesSrc.indexOf("deps.selectAndApplyModel(");
36
- const updateWidgetPos = phasesSrc.indexOf("deps.updateProgressWidget(");
37
-
38
- assertTrue(
39
- selectModelPos > 0,
40
- "phases.ts contains deps.selectAndApplyModel call",
41
- );
42
-
43
- assertTrue(
44
- updateWidgetPos > 0,
45
- "phases.ts contains deps.updateProgressWidget call",
46
- );
47
-
48
- assertTrue(
49
- selectModelPos < updateWidgetPos,
50
- `selectAndApplyModel (pos ${selectModelPos}) must be called BEFORE updateProgressWidget (pos ${updateWidgetPos}) — widget needs fresh model`,
51
- );
52
-
53
- // ── Test 2: session.ts declares currentDispatchedModelId ──────────────────
54
-
55
- assertTrue(
56
- sessionSrc.includes("currentDispatchedModelId"),
57
- "session.ts has currentDispatchedModelId field",
58
- );
59
-
60
- // ── Test 3: auto.ts exposes getCurrentDispatchedModelId in widgetStateAccessors ──
61
-
62
- assertTrue(
63
- autoSrc.includes("getCurrentDispatchedModelId"),
64
- "auto.ts exposes getCurrentDispatchedModelId accessor",
65
- );
66
-
67
- // Verify it's in the widgetStateAccessors object
68
- const accessorsBlock = autoSrc.slice(
69
- autoSrc.indexOf("const widgetStateAccessors"),
70
- autoSrc.indexOf("};", autoSrc.indexOf("const widgetStateAccessors")) + 2,
71
- );
72
-
73
- assertTrue(
74
- accessorsBlock.includes("getCurrentDispatchedModelId"),
75
- "getCurrentDispatchedModelId is in the widgetStateAccessors object",
76
- );
77
-
78
- // ── Test 4: WidgetStateAccessors interface has getCurrentDispatchedModelId ──
79
-
80
- assertTrue(
81
- dashboardSrc.includes("getCurrentDispatchedModelId"),
82
- "auto-dashboard.ts references getCurrentDispatchedModelId",
83
- );
84
-
85
- // The dashboard render closure should NOT read model from cmdCtx?.model for display.
86
- // It should use the accessor for the dispatched model ID.
87
- // Check that the "Model display" section uses the accessor, not cmdCtx?.model directly.
88
- const modelDisplaySection = dashboardSrc.slice(
89
- dashboardSrc.indexOf("// Model display"),
90
- dashboardSrc.indexOf("// Model display") + 500,
91
- );
92
-
93
- assertTrue(
94
- modelDisplaySection.includes("getCurrentDispatchedModelId") ||
95
- modelDisplaySection.includes("getDispatchedModelId"),
96
- "Model display section reads from dispatched model accessor, not cmdCtx?.model alone",
97
- );
98
-
99
- // ── Test 5: currentDispatchedModelId is set after selectAndApplyModel in phases.ts ──
100
-
101
- // After selectAndApplyModel returns, phases.ts should store the dispatched model ID
102
- assertTrue(
103
- phasesSrc.includes("currentDispatchedModelId"),
104
- "phases.ts stores currentDispatchedModelId after model selection",
105
- );
106
-
107
- report();
@@ -1,48 +0,0 @@
1
- /**
2
- * Regression test for #3669 — findMissingSummaries skips closed slices
3
- *
4
- * When a slice has status "skipped", "complete", or "done", it should be
5
- * excluded from the missing-summary check because closed slices intentionally
6
- * lack SUMMARY files (or their DB status is authoritative).
7
- *
8
- * This is a structural verification test — it reads the source to confirm the
9
- * CLOSED_STATUSES guard exists at the filter site.
10
- */
11
-
12
- import { describe, test } from 'node:test';
13
- import assert from 'node:assert/strict';
14
- import { readFileSync } from 'node:fs';
15
- import { fileURLToPath } from 'node:url';
16
- import { dirname, join } from 'node:path';
17
-
18
- const __filename = fileURLToPath(import.meta.url);
19
- const __dirname = dirname(__filename);
20
-
21
- const source = readFileSync(join(__dirname, '..', 'auto-dispatch.ts'), 'utf-8');
22
-
23
- describe('findMissingSummaries closed-status exclusion (#3669)', () => {
24
- test('CLOSED_STATUSES set includes skipped, complete, and done', () => {
25
- // The source must define a CLOSED_STATUSES set with all three statuses
26
- assert.match(source, /CLOSED_STATUSES.*=.*new Set\(/,
27
- 'CLOSED_STATUSES set should be defined');
28
- assert.match(source, /"skipped"/, 'CLOSED_STATUSES should include "skipped"');
29
- assert.match(source, /"complete"/, 'CLOSED_STATUSES should include "complete"');
30
- assert.match(source, /"done"/, 'CLOSED_STATUSES should include "done"');
31
- });
32
-
33
- test('filter uses CLOSED_STATUSES.has() to exclude closed slices', () => {
34
- assert.match(source, /CLOSED_STATUSES\.has\(s\.status\)/,
35
- 'filter should call CLOSED_STATUSES.has(s.status)');
36
- });
37
-
38
- test('findMissingSummaries function exists', () => {
39
- assert.match(source, /function findMissingSummaries\(/,
40
- 'findMissingSummaries function should be defined');
41
- });
42
-
43
- test('filter is negated (excludes closed, keeps open)', () => {
44
- // The filter should use !CLOSED_STATUSES.has() to exclude closed slices
45
- assert.match(source, /!CLOSED_STATUSES\.has\(s\.status\)/,
46
- 'filter should negate CLOSED_STATUSES.has() to exclude closed slices');
47
- });
48
- });
@@ -1,159 +0,0 @@
1
- import { describe, it, beforeEach, afterEach } from "node:test";
2
- import assert from "node:assert/strict";
3
- import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
4
- import { join, dirname } from "node:path";
5
- import { fileURLToPath } from "node:url";
6
-
7
- const __dirname = dirname(fileURLToPath(import.meta.url));
8
- const gsdDir = join(__dirname, "..");
9
-
10
- /**
11
- * Test suite for #2941: Forensics report context lost on follow-up turns.
12
- *
13
- * The forensics flow sends a one-shot message via sendMessage() with
14
- * triggerTurn: true. On follow-up turns, the context is gone because
15
- * there's no re-injection mechanism like buildGuidedExecuteContextInjection
16
- * provides for task execution.
17
- *
18
- * Fix: write an active-forensics.json marker when forensics starts, and
19
- * have buildBeforeAgentStartResult() re-inject the forensics prompt on
20
- * subsequent turns.
21
- */
22
-
23
- describe("forensics context persistence (#2941)", () => {
24
- // ─── Source-level invariant tests ──────────────────────────────────────────
25
-
26
- it("forensics.ts writes active-forensics marker after saving report", () => {
27
- const src = readFileSync(join(gsdDir, "forensics.ts"), "utf-8");
28
- assert.ok(
29
- src.includes("active-forensics.json"),
30
- "forensics.ts must reference active-forensics.json marker file",
31
- );
32
- assert.ok(
33
- src.includes("writeForensicsMarker"),
34
- "forensics.ts must call writeForensicsMarker to persist session state",
35
- );
36
- });
37
-
38
- it("system-context.ts checks for active forensics marker in buildBeforeAgentStartResult", () => {
39
- const src = readFileSync(join(gsdDir, "bootstrap", "system-context.ts"), "utf-8");
40
- assert.ok(
41
- src.includes("active-forensics.json"),
42
- "system-context.ts must check for active-forensics.json marker",
43
- );
44
- assert.ok(
45
- src.includes("gsd-forensics"),
46
- "system-context.ts must inject gsd-forensics customType message",
47
- );
48
- });
49
-
50
- it("system-context.ts exports clearForensicsMarker for cleanup", () => {
51
- const src = readFileSync(join(gsdDir, "bootstrap", "system-context.ts"), "utf-8");
52
- assert.ok(
53
- src.includes("clearForensicsMarker"),
54
- "system-context.ts must export clearForensicsMarker function",
55
- );
56
- });
57
-
58
- // ─── Functional tests using temp directories ──────────────────────────────
59
-
60
- const tmpBase = join(__dirname, "__tmp_forensics_persist__");
61
-
62
- beforeEach(() => {
63
- rmSync(tmpBase, { recursive: true, force: true });
64
- mkdirSync(join(tmpBase, ".gsd", "runtime"), { recursive: true });
65
- mkdirSync(join(tmpBase, ".gsd", "forensics"), { recursive: true });
66
- });
67
-
68
- afterEach(() => {
69
- rmSync(tmpBase, { recursive: true, force: true });
70
- });
71
-
72
- it("writeForensicsMarker creates marker with reportPath and promptContent", async () => {
73
- const { writeForensicsMarker } = await import("../forensics.ts");
74
-
75
- const reportPath = join(tmpBase, ".gsd", "forensics", "report-2026-01-01.md");
76
- writeFileSync(reportPath, "# Test Report", "utf-8");
77
-
78
- writeForensicsMarker(tmpBase, reportPath, "Test forensics prompt content");
79
-
80
- const markerPath = join(tmpBase, ".gsd", "runtime", "active-forensics.json");
81
- assert.ok(existsSync(markerPath), "marker file must be created");
82
-
83
- const marker = JSON.parse(readFileSync(markerPath, "utf-8"));
84
- assert.equal(marker.reportPath, reportPath);
85
- assert.equal(marker.promptContent, "Test forensics prompt content");
86
- assert.ok(marker.createdAt, "marker must have createdAt timestamp");
87
- });
88
-
89
- it("readForensicsMarker returns null when no marker exists", async () => {
90
- const { readForensicsMarker } = await import("../forensics.ts");
91
-
92
- const result = readForensicsMarker(join(tmpBase, "nonexistent"));
93
- assert.equal(result, null);
94
- });
95
-
96
- it("readForensicsMarker returns marker data when file exists", async () => {
97
- const { readForensicsMarker } = await import("../forensics.ts");
98
-
99
- const markerPath = join(tmpBase, ".gsd", "runtime", "active-forensics.json");
100
- const markerData = {
101
- reportPath: "/some/report.md",
102
- promptContent: "forensics prompt",
103
- createdAt: new Date().toISOString(),
104
- };
105
- writeFileSync(markerPath, JSON.stringify(markerData), "utf-8");
106
-
107
- const result = readForensicsMarker(tmpBase);
108
- assert.ok(result);
109
- assert.equal(result.reportPath, "/some/report.md");
110
- assert.equal(result.promptContent, "forensics prompt");
111
- });
112
-
113
- it("clearForensicsMarker removes the marker file", async () => {
114
- const { clearForensicsMarker } = await import("../bootstrap/system-context.ts");
115
-
116
- const markerPath = join(tmpBase, ".gsd", "runtime", "active-forensics.json");
117
- writeFileSync(markerPath, JSON.stringify({ reportPath: "/x", promptContent: "y", createdAt: new Date().toISOString() }), "utf-8");
118
- assert.ok(existsSync(markerPath), "precondition: marker must exist");
119
-
120
- clearForensicsMarker(tmpBase);
121
- assert.ok(!existsSync(markerPath), "marker must be removed after clear");
122
- });
123
-
124
- it("clearForensicsMarker is a no-op when no marker exists", async () => {
125
- const { clearForensicsMarker } = await import("../bootstrap/system-context.ts");
126
- // Should not throw
127
- clearForensicsMarker(join(tmpBase, "nonexistent"));
128
- });
129
-
130
- it("buildForensicsContextInjection keeps marker for low-entropy resume prompts", async () => {
131
- const { buildForensicsContextInjection } = await import("../bootstrap/system-context.ts");
132
-
133
- const markerPath = join(tmpBase, ".gsd", "runtime", "active-forensics.json");
134
- writeFileSync(markerPath, JSON.stringify({
135
- reportPath: "/some/report.md",
136
- promptContent: "forensics prompt",
137
- createdAt: new Date().toISOString(),
138
- }), "utf-8");
139
-
140
- const result = buildForensicsContextInjection(tmpBase, "continue");
141
- assert.equal(result, "forensics prompt");
142
- assert.ok(existsSync(markerPath), "resume-like follow-up should keep marker intact");
143
- });
144
-
145
- it("buildForensicsContextInjection clears marker on unrelated user prompts", async () => {
146
- const { buildForensicsContextInjection } = await import("../bootstrap/system-context.ts");
147
-
148
- const markerPath = join(tmpBase, ".gsd", "runtime", "active-forensics.json");
149
- writeFileSync(markerPath, JSON.stringify({
150
- reportPath: "/some/report.md",
151
- promptContent: "forensics prompt",
152
- createdAt: new Date().toISOString(),
153
- }), "utf-8");
154
-
155
- const result = buildForensicsContextInjection(tmpBase, "please summarize the README");
156
- assert.equal(result, null);
157
- assert.ok(!existsSync(markerPath), "unrelated follow-up should clear the stale marker");
158
- });
159
- });
@@ -1,96 +0,0 @@
1
- import { describe, it } from "node:test";
2
- import assert from "node:assert/strict";
3
- import { readFileSync } from "node:fs";
4
- import { join, dirname } from "node:path";
5
- import { fileURLToPath } from "node:url";
6
-
7
- const __dirname = dirname(fileURLToPath(import.meta.url));
8
- const gsdDir = join(__dirname, "..");
9
-
10
- /**
11
- * Tests for #3129: forensics reads DB for completion status instead of legacy file.
12
- *
13
- * The old loadCompletedKeys() reads completed-units.json which is never populated
14
- * during normal auto-mode completion. The DB (milestones/slices/tasks tables) is
15
- * the authoritative source for completion status.
16
- */
17
- describe("forensics DB completion status (#3129)", () => {
18
- const forensicsSrc = readFileSync(join(gsdDir, "forensics.ts"), "utf-8");
19
- const stateSrc = readFileSync(join(gsdDir, "state.ts"), "utf-8");
20
-
21
- // ── Primary fix: forensics queries DB for completion counts ──────────
22
-
23
- it("ForensicReport has dbCompletionCounts field for DB-sourced completion data", () => {
24
- assert.ok(
25
- forensicsSrc.includes("dbCompletionCounts"),
26
- "ForensicReport must include dbCompletionCounts field for DB-sourced completion data",
27
- );
28
- });
29
-
30
- it("buildForensicReport queries DB for completed milestones, slices, and tasks", () => {
31
- assert.ok(
32
- forensicsSrc.includes("getDbCompletionCounts"),
33
- "buildForensicReport must call getDbCompletionCounts to query DB completion status",
34
- );
35
- });
36
-
37
- it("getDbCompletionCounts checks isDbAvailable before querying", () => {
38
- assert.ok(
39
- forensicsSrc.includes("isDbAvailable"),
40
- "getDbCompletionCounts must check isDbAvailable() before querying the DB",
41
- );
42
- });
43
-
44
- it("getDbCompletionCounts queries getAllMilestones for milestone completion", () => {
45
- assert.ok(
46
- forensicsSrc.includes("getAllMilestones"),
47
- "getDbCompletionCounts must use getAllMilestones() to count completed milestones",
48
- );
49
- });
50
-
51
- it("completion counting uses isClosedStatus for consistent status checks", () => {
52
- assert.ok(
53
- forensicsSrc.includes("isClosedStatus"),
54
- "forensics must use isClosedStatus() for consistent status checks",
55
- );
56
- });
57
-
58
- it("report rendering shows DB completion counts instead of just legacy key count", () => {
59
- assert.ok(
60
- forensicsSrc.includes("milestones complete"),
61
- "report must show '__ milestones complete' from DB data",
62
- );
63
- assert.ok(
64
- forensicsSrc.includes("slices complete"),
65
- "report must show '__ slices complete' from DB data",
66
- );
67
- assert.ok(
68
- forensicsSrc.includes("tasks complete"),
69
- "report must show '__ tasks complete' from DB data",
70
- );
71
- });
72
-
73
- it("falls back to completed-units.json only when DB is unavailable", () => {
74
- // loadCompletedKeys should still exist as fallback
75
- assert.ok(
76
- forensicsSrc.includes("loadCompletedKeys"),
77
- "loadCompletedKeys must still exist as fallback for non-DB projects",
78
- );
79
- // But the report should prefer DB counts
80
- assert.ok(
81
- forensicsSrc.includes("dbCompletionCounts"),
82
- "report must prefer dbCompletionCounts over legacy completedKeys",
83
- );
84
- });
85
-
86
- // ── Secondary fix: STATE.md label when all milestones complete ───────
87
-
88
- it("state.ts returns null activeMilestone when all milestones are complete", () => {
89
- // When phase is "complete", activeMilestone should be null, not the last milestone
90
- // The last completed milestone should be in a separate field
91
- assert.ok(
92
- stateSrc.includes("lastCompletedMilestone"),
93
- "GSDState must have lastCompletedMilestone field for the final milestone when phase=complete",
94
- );
95
- });
96
- });
@@ -1,79 +0,0 @@
1
- import { describe, it } from "node:test";
2
- import assert from "node:assert/strict";
3
- import { readFileSync } from "node:fs";
4
- import { join, dirname } from "node:path";
5
- import { fileURLToPath } from "node:url";
6
-
7
- const __dirname = dirname(fileURLToPath(import.meta.url));
8
- const gsdDir = join(__dirname, "..");
9
-
10
- describe("forensics dedup (#2096)", () => {
11
- it("forensics_dedup is in KNOWN_PREFERENCE_KEYS", () => {
12
- const source = readFileSync(join(gsdDir, "preferences-types.ts"), "utf-8");
13
- assert.ok(source.includes('"forensics_dedup"'),
14
- "KNOWN_PREFERENCE_KEYS must contain forensics_dedup");
15
- assert.ok(source.includes("forensics_dedup?: boolean"),
16
- "GSDPreferences must declare forensics_dedup as optional boolean");
17
- });
18
-
19
- it("forensics prompt contains {{dedupSection}} placeholder", () => {
20
- const prompt = readFileSync(join(gsdDir, "prompts", "forensics.md"), "utf-8");
21
- assert.ok(prompt.includes("{{dedupSection}}"),
22
- "forensics.md must contain {{dedupSection}} placeholder");
23
- });
24
-
25
- it("DEDUP_PROMPT_SECTION contains required search commands", async () => {
26
- const source = readFileSync(join(gsdDir, "forensics.ts"), "utf-8");
27
- assert.ok(source.includes("DEDUP_PROMPT_SECTION"), "forensics.ts must define DEDUP_PROMPT_SECTION");
28
- assert.ok(source.includes("gh issue list --repo gsd-build/gsd-2 --state closed"));
29
- assert.ok(source.includes("gh pr list --repo gsd-build/gsd-2 --state open"));
30
- assert.ok(source.includes("gh pr list --repo gsd-build/gsd-2 --state merged"));
31
- });
32
-
33
- it("handleForensics checks forensics_dedup preference", () => {
34
- const source = readFileSync(join(gsdDir, "forensics.ts"), "utf-8");
35
- assert.ok(source.includes("forensics_dedup"),
36
- "handleForensics must reference forensics_dedup preference");
37
- assert.ok(source.includes("dedupSection"),
38
- "handleForensics must pass dedupSection to loadPrompt");
39
- });
40
-
41
- it("first-time opt-in shows when preference is undefined", () => {
42
- const source = readFileSync(join(gsdDir, "forensics.ts"), "utf-8");
43
- assert.ok(source.includes("=== undefined"),
44
- "first-time detection must check for undefined (not false)");
45
- assert.ok(source.includes("Duplicate detection available") || source.includes("duplicate detection"),
46
- "opt-in notice must mention duplicate detection");
47
- });
48
- });
49
-
50
- describe("forensics dedup ordering (#2704)", () => {
51
- it("{{dedupSection}} appears before Investigation Protocol in the prompt template", () => {
52
- const prompt = readFileSync(join(gsdDir, "prompts", "forensics.md"), "utf-8");
53
- const dedupIndex = prompt.indexOf("{{dedupSection}}");
54
- const investigationIndex = prompt.indexOf("## Investigation Protocol");
55
- assert.ok(dedupIndex !== -1, "prompt must contain {{dedupSection}}");
56
- assert.ok(investigationIndex !== -1, "prompt must contain ## Investigation Protocol");
57
- assert.ok(
58
- dedupIndex < investigationIndex,
59
- `{{dedupSection}} (index ${dedupIndex}) must appear before Investigation Protocol (index ${investigationIndex}) — dedup should run before expensive investigation to avoid wasting tokens on already-fixed bugs`,
60
- );
61
- });
62
-
63
- it("DEDUP_PROMPT_SECTION contains a decision gate to skip investigation", () => {
64
- const source = readFileSync(join(gsdDir, "forensics.ts"), "utf-8");
65
- // The dedup section must instruct the agent to skip investigation when a match is found
66
- assert.ok(
67
- source.includes("Skip full investigation") || source.includes("skip full investigation") || source.includes("Skip investigation"),
68
- "DEDUP_PROMPT_SECTION must contain a decision gate telling the agent to skip full investigation when a duplicate is found",
69
- );
70
- });
71
-
72
- it("DEDUP_PROMPT_SECTION heading reflects pre-investigation role", () => {
73
- const source = readFileSync(join(gsdDir, "forensics.ts"), "utf-8");
74
- assert.ok(
75
- source.includes("Pre-Investigation") || source.includes("pre-investigation"),
76
- "DEDUP_PROMPT_SECTION heading must indicate it runs before investigation, not just before issue creation",
77
- );
78
- });
79
- });
@@ -1,74 +0,0 @@
1
- /**
2
- * Regression test for #2826: detectMissingArtifacts must parse hook/
3
- * compound unit types correctly, not just the first slash segment.
4
- *
5
- * Keys like "hook/telegram-progress/M007/S01" must yield:
6
- * unitType = "hook/telegram-progress" (not "hook")
7
- * unitId = "M007/S01" (not "telegram-progress/M007/S01")
8
- *
9
- * The fix extracts a shared splitCompletedKey() helper used by both
10
- * forensics.ts and doctor-runtime-checks.ts.
11
- */
12
- import { describe, it } from "node:test";
13
- import assert from "node:assert/strict";
14
- import { readFileSync } from "node:fs";
15
- import { join, dirname } from "node:path";
16
- import { fileURLToPath } from "node:url";
17
-
18
- const __dirname = dirname(fileURLToPath(import.meta.url));
19
- const gsdDir = join(__dirname, "..");
20
-
21
- describe("forensics hook compound key parsing (#2826)", () => {
22
- const forensicsSrc = readFileSync(join(gsdDir, "forensics.ts"), "utf-8");
23
- const doctorSrc = readFileSync(join(gsdDir, "doctor-runtime-checks.ts"), "utf-8");
24
-
25
- it("forensics.ts exports splitCompletedKey helper", () => {
26
- assert.ok(
27
- forensicsSrc.includes("export function splitCompletedKey("),
28
- "forensics.ts must export splitCompletedKey()",
29
- );
30
- });
31
-
32
- it("splitCompletedKey handles hook/ prefix by splitting on the second slash", () => {
33
- assert.ok(
34
- forensicsSrc.includes('key.startsWith("hook/")'),
35
- 'splitCompletedKey must branch on key.startsWith("hook/")',
36
- );
37
- assert.ok(
38
- forensicsSrc.includes('key.indexOf("/", 5)'),
39
- 'splitCompletedKey must use indexOf("/", 5) to find second slash past "hook/"',
40
- );
41
- });
42
-
43
- it("detectMissingArtifacts delegates to splitCompletedKey", () => {
44
- const fnStart = forensicsSrc.indexOf("function detectMissingArtifacts(");
45
- assert.ok(fnStart !== -1, "detectMissingArtifacts must exist in forensics.ts");
46
- const fnBody = forensicsSrc.slice(fnStart, fnStart + 1000);
47
- assert.ok(
48
- fnBody.includes("splitCompletedKey("),
49
- "detectMissingArtifacts must call splitCompletedKey() rather than inline the split logic",
50
- );
51
- });
52
-
53
- it("doctor-runtime-checks.ts imports and uses splitCompletedKey", () => {
54
- assert.ok(
55
- doctorSrc.includes('from "./forensics.js"'),
56
- 'doctor-runtime-checks.ts must import from "./forensics.js"',
57
- );
58
- assert.ok(
59
- doctorSrc.includes("splitCompletedKey"),
60
- "doctor-runtime-checks.ts must use splitCompletedKey()",
61
- );
62
- });
63
-
64
- it("splitCompletedKey unit: plain type", () => {
65
- // Inline test of the helper logic to guard against future regressions
66
- // without needing a filesystem setup.
67
- const src = forensicsSrc;
68
- // Confirm the plain-type branch also exists
69
- assert.ok(
70
- src.includes('slashIdx = key.indexOf("/")') || src.includes("key.indexOf(\"/\")"),
71
- "splitCompletedKey must handle plain (non-hook) keys via first-slash split",
72
- );
73
- });
74
- });