gsd-pi 2.78.1-dev.84a383f51 → 2.78.1

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 (474) hide show
  1. package/README.md +7 -7
  2. package/dist/cli.js +55 -95
  3. package/dist/headless-query.d.ts +0 -22
  4. package/dist/headless-query.js +4 -24
  5. package/dist/headless.d.ts +0 -10
  6. package/dist/headless.js +1 -16
  7. package/dist/loader.js +10 -7
  8. package/dist/onboarding.d.ts +0 -10
  9. package/dist/onboarding.js +2 -2
  10. package/dist/provider-migrations.d.ts +2 -2
  11. package/dist/provider-migrations.js +2 -5
  12. package/dist/resource-loader.d.ts +2 -5
  13. package/dist/resource-loader.js +5 -28
  14. package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +601 -0
  15. package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +651 -0
  16. package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +91 -0
  17. package/dist/resources/extensions/gsd/auto/loop.js +0 -23
  18. package/dist/resources/extensions/gsd/auto/phases.js +2 -2
  19. package/dist/resources/extensions/gsd/auto/run-unit.js +1 -3
  20. package/dist/resources/extensions/gsd/auto/session.js +0 -3
  21. package/dist/resources/extensions/gsd/auto-recovery.js +4 -43
  22. package/dist/resources/extensions/gsd/auto-start.js +1 -1
  23. package/dist/resources/extensions/gsd/auto-tool-tracking.js +2 -2
  24. package/dist/resources/extensions/gsd/auto-worktree.js +0 -30
  25. package/dist/resources/extensions/gsd/auto.js +5 -14
  26. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +2 -14
  27. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +5 -7
  28. package/dist/resources/extensions/gsd/bootstrap/query-tools.js +2 -2
  29. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +4 -5
  30. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +31 -94
  31. package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +6 -11
  32. package/dist/resources/extensions/gsd/bootstrap/system-context.js +8 -34
  33. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +2 -38
  34. package/dist/resources/extensions/gsd/commands/catalog.js +5 -69
  35. package/dist/resources/extensions/gsd/commands/handlers/core.js +1 -22
  36. package/dist/resources/extensions/gsd/commands-mcp-status.js +1 -3
  37. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +1 -10
  38. package/dist/resources/extensions/gsd/dashboard-overlay.js +1 -1
  39. package/dist/resources/extensions/gsd/docs/preferences-reference.md +0 -4
  40. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +1 -39
  41. package/dist/resources/extensions/gsd/error-classifier.js +1 -1
  42. package/dist/resources/extensions/gsd/forensics.js +2 -2
  43. package/dist/resources/extensions/gsd/git-service.js +5 -12
  44. package/dist/resources/extensions/gsd/gsd-db.js +2 -11
  45. package/dist/resources/extensions/gsd/guided-flow.js +23 -23
  46. package/dist/resources/extensions/gsd/memory-store.js +31 -66
  47. package/dist/resources/extensions/gsd/model-router.js +9 -114
  48. package/dist/resources/extensions/gsd/native-git-bridge.js +1 -7
  49. package/dist/resources/extensions/gsd/preferences-models.js +15 -91
  50. package/dist/resources/extensions/gsd/preferences-types.js +0 -2
  51. package/dist/resources/extensions/gsd/preferences-validation.js +0 -32
  52. package/dist/resources/extensions/gsd/preferences.js +3 -5
  53. package/dist/resources/extensions/gsd/prompt-loader.js +12 -23
  54. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +3 -9
  55. package/dist/resources/extensions/gsd/state.js +0 -42
  56. package/dist/resources/extensions/gsd/templates/PREFERENCES.md +0 -1
  57. package/dist/resources/extensions/gsd/tests/auto-supervisor.test.mjs +53 -0
  58. package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +112 -0
  59. package/dist/resources/extensions/gsd/tests/resolve-ts-hooks.mjs +23 -0
  60. package/dist/resources/extensions/gsd/tests/resolve-ts.mjs +5 -0
  61. package/dist/resources/extensions/gsd/tools/memory-tools.js +1 -18
  62. package/dist/resources/extensions/gsd/visualizer-overlay.js +1 -1
  63. package/dist/resources/extensions/gsd/watch/header-renderer.js +1 -3
  64. package/dist/resources/extensions/gsd/worktree-command.js +46 -26
  65. package/dist/resources/extensions/mcp-client/index.js +3 -6
  66. package/dist/resources/extensions/slash-commands/create-extension.js +22 -36
  67. package/dist/resources/skills/create-gsd-extension/SKILL.md +5 -9
  68. package/dist/resources/skills/create-gsd-extension/references/custom-commands.md +1 -1
  69. package/dist/resources/skills/create-gsd-extension/references/custom-rendering.md +5 -5
  70. package/dist/resources/skills/create-gsd-extension/references/custom-tools.md +4 -4
  71. package/dist/resources/skills/create-gsd-extension/references/custom-ui.md +6 -6
  72. package/dist/resources/skills/create-gsd-extension/references/events-reference.md +3 -3
  73. package/dist/resources/skills/create-gsd-extension/references/packaging-distribution.md +1 -1
  74. package/dist/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +3 -3
  75. package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +12 -32
  76. package/dist/resources/skills/github-workflows/references/gh/tests/__init__.py +0 -0
  77. package/dist/resources/skills/github-workflows/references/gh/tests/test_github_project_setup.py +608 -0
  78. package/dist/rtk-shared.d.ts +0 -3
  79. package/dist/rtk-shared.js +0 -17
  80. package/dist/rtk.d.ts +5 -2
  81. package/dist/rtk.js +20 -3
  82. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  83. package/dist/web/standalone/.next/BUILD_ID +1 -1
  84. package/dist/web/standalone/.next/app-path-routes-manifest.json +13 -13
  85. package/dist/web/standalone/.next/build-manifest.json +4 -4
  86. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  87. package/dist/web/standalone/.next/react-loadable-manifest.json +4 -44
  88. package/dist/web/standalone/.next/required-server-files.json +3 -3
  89. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  90. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  91. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  92. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  100. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  101. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  102. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  103. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  104. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  106. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  108. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  109. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  110. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  111. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  113. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  116. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  128. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  148. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  158. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -4
  164. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
  178. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  180. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  182. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  184. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  193. package/dist/web/standalone/.next/server/app/index.html +1 -1
  194. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  195. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  196. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  197. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  198. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  199. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  200. package/dist/web/standalone/.next/server/app/page.js +2 -2
  201. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  202. package/dist/web/standalone/.next/server/app-paths-manifest.json +13 -13
  203. package/dist/web/standalone/.next/server/chunks/63.js +3 -3
  204. package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
  205. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  206. package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
  207. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  208. package/dist/web/standalone/.next/server/middleware.js +2 -2
  209. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  210. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  211. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  212. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  213. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  214. package/dist/web/standalone/.next/server/webpack-runtime.js +1 -1
  215. package/dist/web/standalone/.next/static/chunks/2826.e9f5195e91f9cad2.js +11 -0
  216. package/dist/web/standalone/.next/static/chunks/3621.fc7480022c972438.js +20 -0
  217. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-f2a7482d42a5614b.js → page-2f24283c162b6ab3.js} +1 -1
  218. package/dist/web/standalone/.next/static/chunks/app/{layout-a16c7a7ecdf0c2cf.js → layout-9ecfd95f343793f0.js} +1 -1
  219. package/dist/web/standalone/.next/static/chunks/app/page-151349214571e2b6.js +1 -0
  220. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +1 -0
  221. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +1 -0
  222. package/dist/web/standalone/.next/static/chunks/webpack-2e68521d7c82f7c2.js +1 -0
  223. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  224. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  225. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  226. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  227. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  228. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  229. package/dist/web/standalone/package.json +1 -2
  230. package/dist/web/standalone/server.js +1 -1
  231. package/package.json +1 -1
  232. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  233. package/packages/mcp-server/dist/workflow-tools.js +46 -74
  234. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  235. package/packages/mcp-server/src/workflow-tools.test.ts +0 -26
  236. package/packages/mcp-server/src/workflow-tools.ts +58 -93
  237. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  238. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  239. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
  240. package/packages/pi-ai/dist/providers/anthropic-shared.js +19 -48
  241. package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
  242. package/packages/pi-ai/dist/types.d.ts +0 -13
  243. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  244. package/packages/pi-ai/dist/types.js.map +1 -1
  245. package/packages/pi-ai/dist/utils/repair-tool-json.d.ts.map +1 -1
  246. package/packages/pi-ai/dist/utils/repair-tool-json.js +3 -24
  247. package/packages/pi-ai/dist/utils/repair-tool-json.js.map +1 -1
  248. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js +0 -26
  249. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js.map +1 -1
  250. package/packages/pi-ai/src/providers/anthropic-shared.ts +20 -52
  251. package/packages/pi-ai/src/types.ts +0 -13
  252. package/packages/pi-ai/src/utils/repair-tool-json.ts +3 -24
  253. package/packages/pi-ai/src/utils/tests/repair-tool-json.test.ts +0 -32
  254. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  255. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  256. package/packages/pi-coding-agent/dist/core/agent-session.js +0 -6
  257. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  258. package/packages/pi-coding-agent/dist/core/messages.d.ts.map +1 -1
  259. package/packages/pi-coding-agent/dist/core/messages.js +0 -4
  260. package/packages/pi-coding-agent/dist/core/messages.js.map +1 -1
  261. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +2 -19
  262. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
  263. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +0 -10
  264. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  265. package/packages/pi-coding-agent/dist/core/model-registry.js +0 -18
  266. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  267. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +0 -13
  268. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  269. package/packages/pi-coding-agent/dist/core/system-prompt.js +16 -20
  270. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  271. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +1 -1
  272. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  273. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +1 -14
  274. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  275. package/packages/pi-coding-agent/src/core/agent-session.ts +0 -7
  276. package/packages/pi-coding-agent/src/core/messages.ts +0 -4
  277. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +2 -32
  278. package/packages/pi-coding-agent/src/core/model-registry.ts +0 -21
  279. package/packages/pi-coding-agent/src/core/system-prompt.ts +15 -33
  280. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +1 -17
  281. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +1 -1
  282. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  283. package/packages/pi-tui/dist/__tests__/autocomplete.test.js +3 -17
  284. package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
  285. package/packages/pi-tui/src/__tests__/autocomplete.test.ts +3 -20
  286. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  287. package/src/resources/extensions/gsd/auto/loop.ts +2 -24
  288. package/src/resources/extensions/gsd/auto/phases.ts +3 -3
  289. package/src/resources/extensions/gsd/auto/run-unit.ts +1 -3
  290. package/src/resources/extensions/gsd/auto/session.ts +0 -3
  291. package/src/resources/extensions/gsd/auto/types.ts +0 -1
  292. package/src/resources/extensions/gsd/auto-recovery.ts +8 -46
  293. package/src/resources/extensions/gsd/auto-start.ts +1 -1
  294. package/src/resources/extensions/gsd/auto-tool-tracking.ts +4 -2
  295. package/src/resources/extensions/gsd/auto-worktree.ts +0 -38
  296. package/src/resources/extensions/gsd/auto.ts +4 -14
  297. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +13 -15
  298. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +7 -8
  299. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +2 -2
  300. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +9 -10
  301. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +31 -102
  302. package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +6 -12
  303. package/src/resources/extensions/gsd/bootstrap/system-context.ts +8 -39
  304. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +11 -39
  305. package/src/resources/extensions/gsd/commands/catalog.ts +5 -75
  306. package/src/resources/extensions/gsd/commands/handlers/core.ts +1 -22
  307. package/src/resources/extensions/gsd/commands-mcp-status.ts +1 -3
  308. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +1 -15
  309. package/src/resources/extensions/gsd/dashboard-overlay.ts +1 -1
  310. package/src/resources/extensions/gsd/docs/preferences-reference.md +0 -4
  311. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +1 -39
  312. package/src/resources/extensions/gsd/doctor-types.ts +1 -3
  313. package/src/resources/extensions/gsd/error-classifier.ts +1 -1
  314. package/src/resources/extensions/gsd/forensics.ts +2 -2
  315. package/src/resources/extensions/gsd/git-service.ts +5 -13
  316. package/src/resources/extensions/gsd/gsd-db.ts +2 -12
  317. package/src/resources/extensions/gsd/guided-flow.ts +25 -25
  318. package/src/resources/extensions/gsd/memory-store.ts +28 -81
  319. package/src/resources/extensions/gsd/model-router.ts +9 -172
  320. package/src/resources/extensions/gsd/native-git-bridge.ts +1 -7
  321. package/src/resources/extensions/gsd/preferences-models.ts +15 -101
  322. package/src/resources/extensions/gsd/preferences-types.ts +0 -6
  323. package/src/resources/extensions/gsd/preferences-validation.ts +0 -35
  324. package/src/resources/extensions/gsd/preferences.ts +2 -16
  325. package/src/resources/extensions/gsd/prompt-loader.ts +12 -26
  326. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +3 -9
  327. package/src/resources/extensions/gsd/state.ts +0 -42
  328. package/src/resources/extensions/gsd/templates/PREFERENCES.md +0 -1
  329. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +1 -178
  330. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +0 -58
  331. package/src/resources/extensions/gsd/tests/auto-session-encapsulation.test.ts +5 -9
  332. package/src/resources/extensions/gsd/tests/auto-supervisor.test.mjs +4 -21
  333. package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +1 -1
  334. package/src/resources/extensions/gsd/tests/budget-prediction.test.ts +211 -138
  335. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +59 -142
  336. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +4 -7
  337. package/src/resources/extensions/gsd/tests/completed-at-reconcile.test.ts +32 -89
  338. package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +22 -0
  339. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +23 -41
  340. package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +43 -3
  341. package/src/resources/extensions/gsd/tests/debug-logger.test.ts +3 -5
  342. package/src/resources/extensions/gsd/tests/discuss-empty-db-fallback.test.ts +87 -22
  343. package/src/resources/extensions/gsd/tests/discuss-queued-milestones.test.ts +118 -7
  344. package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +47 -0
  345. package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +60 -18
  346. package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +76 -14
  347. package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +75 -0
  348. package/src/resources/extensions/gsd/tests/false-degraded-mode-warning.test.ts +83 -22
  349. package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +63 -1
  350. package/src/resources/extensions/gsd/tests/forensics-stuck-loops.test.ts +1 -26
  351. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +0 -30
  352. package/src/resources/extensions/gsd/tests/headless-answers.test.ts +4 -14
  353. package/src/resources/extensions/gsd/tests/health-widget.test.ts +12 -22
  354. package/src/resources/extensions/gsd/tests/init-prefs-routing.test.ts +1 -64
  355. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +0 -22
  356. package/src/resources/extensions/gsd/tests/integration/token-savings.test.ts +23 -0
  357. package/src/resources/extensions/gsd/tests/memory-store.test.ts +0 -128
  358. package/src/resources/extensions/gsd/tests/memory-tools.test.ts +1 -33
  359. package/src/resources/extensions/gsd/tests/model-router.test.ts +8 -169
  360. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +0 -8
  361. package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +43 -32
  362. package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +10 -4
  363. package/src/resources/extensions/gsd/tests/preferences.test.ts +0 -127
  364. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +0 -16
  365. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +0 -7
  366. package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +6 -6
  367. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +19 -168
  368. package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +1 -7
  369. package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +1 -23
  370. package/src/resources/extensions/gsd/tests/token-profile.test.ts +4 -51
  371. package/src/resources/extensions/gsd/tests/turn-epoch.test.ts +16 -7
  372. package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +7 -5
  373. package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +1 -15
  374. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +6 -6
  375. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +0 -15
  376. package/src/resources/extensions/gsd/tools/memory-tools.ts +1 -17
  377. package/src/resources/extensions/gsd/unit-context-manifest.ts +8 -8
  378. package/src/resources/extensions/gsd/visualizer-overlay.ts +1 -1
  379. package/src/resources/extensions/gsd/watch/header-renderer.ts +1 -3
  380. package/src/resources/extensions/gsd/workflow-logger.ts +0 -1
  381. package/src/resources/extensions/gsd/worktree-command.ts +44 -31
  382. package/src/resources/extensions/mcp-client/index.ts +3 -6
  383. package/src/resources/extensions/slash-commands/create-extension.ts +24 -38
  384. package/src/resources/skills/create-gsd-extension/SKILL.md +5 -9
  385. package/src/resources/skills/create-gsd-extension/references/custom-commands.md +1 -1
  386. package/src/resources/skills/create-gsd-extension/references/custom-rendering.md +5 -5
  387. package/src/resources/skills/create-gsd-extension/references/custom-tools.md +4 -4
  388. package/src/resources/skills/create-gsd-extension/references/custom-ui.md +6 -6
  389. package/src/resources/skills/create-gsd-extension/references/events-reference.md +3 -3
  390. package/src/resources/skills/create-gsd-extension/references/packaging-distribution.md +1 -1
  391. package/src/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +3 -3
  392. package/src/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +2 -2
  393. package/src/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +3 -3
  394. package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +12 -32
  395. package/dist/cli-policy.d.ts +0 -13
  396. package/dist/cli-policy.js +0 -17
  397. package/dist/resources/.managed-resources-content-hash +0 -1
  398. package/dist/resources/extensions/gsd/auto-runtime-state.js +0 -31
  399. package/dist/resources/extensions/gsd/milestone-id-reservation.js +0 -36
  400. package/dist/resources/extensions/gsd/worktree-session-state.js +0 -33
  401. package/dist/runtime-checks.d.ts +0 -27
  402. package/dist/runtime-checks.js +0 -38
  403. package/dist/web/standalone/.next/static/chunks/2556.0527fea66e123b7f.js +0 -1
  404. package/dist/web/standalone/.next/static/chunks/2824.08296bc2f9654698.js +0 -1
  405. package/dist/web/standalone/.next/static/chunks/3026.3af53b279375f082.js +0 -1
  406. package/dist/web/standalone/.next/static/chunks/315.6f68ae79b67d25cf.js +0 -1
  407. package/dist/web/standalone/.next/static/chunks/3497.4bfc60a3b3dea717.js +0 -1
  408. package/dist/web/standalone/.next/static/chunks/5516.4a07c872b5c3a663.js +0 -1
  409. package/dist/web/standalone/.next/static/chunks/8336.31b019697882acfb.js +0 -10
  410. package/dist/web/standalone/.next/static/chunks/8845.c9702695e8c5a9c5.js +0 -2
  411. package/dist/web/standalone/.next/static/chunks/9058.01ef3a463bda88f1.js +0 -20
  412. package/dist/web/standalone/.next/static/chunks/9441.1081da1125d1764f.js +0 -1
  413. package/dist/web/standalone/.next/static/chunks/app/page-9bf2e0c50fb2ca05.js +0 -1
  414. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +0 -1
  415. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +0 -1
  416. package/dist/web/standalone/.next/static/chunks/webpack-f9f0dc45e4f3ac10.js +0 -1
  417. package/dist/worktree-status-banner.d.ts +0 -1
  418. package/dist/worktree-status-banner.js +0 -132
  419. package/packages/mcp-server/dist/alias-telemetry.d.ts +0 -8
  420. package/packages/mcp-server/dist/alias-telemetry.d.ts.map +0 -1
  421. package/packages/mcp-server/dist/alias-telemetry.js +0 -30
  422. package/packages/mcp-server/dist/alias-telemetry.js.map +0 -1
  423. package/packages/mcp-server/src/alias-telemetry.test.ts +0 -78
  424. package/packages/mcp-server/src/alias-telemetry.ts +0 -30
  425. package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.d.ts +0 -2
  426. package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.d.ts.map +0 -1
  427. package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.js +0 -231
  428. package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.js.map +0 -1
  429. package/packages/pi-ai/src/providers/anthropic-shared.cache-breakpoint.test.ts +0 -289
  430. package/packages/pi-coding-agent/dist/core/token-telemetry.d.ts +0 -37
  431. package/packages/pi-coding-agent/dist/core/token-telemetry.d.ts.map +0 -1
  432. package/packages/pi-coding-agent/dist/core/token-telemetry.js +0 -49
  433. package/packages/pi-coding-agent/dist/core/token-telemetry.js.map +0 -1
  434. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.d.ts +0 -2
  435. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.d.ts.map +0 -1
  436. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +0 -133
  437. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +0 -1
  438. package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.d.ts +0 -2
  439. package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.d.ts.map +0 -1
  440. package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.js +0 -78
  441. package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.js.map +0 -1
  442. package/packages/pi-coding-agent/dist/tests/token-telemetry.test.d.ts +0 -2
  443. package/packages/pi-coding-agent/dist/tests/token-telemetry.test.d.ts.map +0 -1
  444. package/packages/pi-coding-agent/dist/tests/token-telemetry.test.js +0 -181
  445. package/packages/pi-coding-agent/dist/tests/token-telemetry.test.js.map +0 -1
  446. package/packages/pi-coding-agent/src/core/token-telemetry.ts +0 -77
  447. package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +0 -212
  448. package/packages/pi-coding-agent/src/tests/system-prompt-cache-stability.test.ts +0 -102
  449. package/packages/pi-coding-agent/src/tests/token-telemetry.test.ts +0 -200
  450. package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts +0 -2
  451. package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts.map +0 -1
  452. package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js +0 -161
  453. package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js.map +0 -1
  454. package/packages/pi-tui/src/components/__tests__/leak-fixes-runtime.test.ts +0 -219
  455. package/src/resources/extensions/gsd/auto-runtime-state.ts +0 -51
  456. package/src/resources/extensions/gsd/milestone-id-reservation.ts +0 -47
  457. package/src/resources/extensions/gsd/tests/deferred-milestone-dir-4996.test.ts +0 -116
  458. package/src/resources/extensions/gsd/tests/doctor-orphan-milestone-4996.test.ts +0 -100
  459. package/src/resources/extensions/gsd/tests/ensure-preconditions-guard-4996.test.ts +0 -93
  460. package/src/resources/extensions/gsd/tests/find-missing-summaries-closed-runtime.test.ts +0 -47
  461. package/src/resources/extensions/gsd/tests/gitignore-bg-shell-runtime.test.ts +0 -63
  462. package/src/resources/extensions/gsd/tests/gsd-no-project-error-runtime.test.ts +0 -81
  463. package/src/resources/extensions/gsd/tests/help-menu-coverage.test.ts +0 -57
  464. package/src/resources/extensions/gsd/tests/import-done-milestones-runtime.test.ts +0 -145
  465. package/src/resources/extensions/gsd/tests/merge-self-branch-guard.test.ts +0 -124
  466. package/src/resources/extensions/gsd/tests/milestone-id-gap-reuse-4996.test.ts +0 -152
  467. package/src/resources/extensions/gsd/tests/native-git-infra-errors.test.ts +0 -50
  468. package/src/resources/extensions/gsd/tests/register-hooks-compaction-checkpoint.test.ts +0 -93
  469. package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +0 -101
  470. package/src/resources/extensions/gsd/worktree-session-state.ts +0 -35
  471. package/src/resources/extensions/mcp-client/tests/global-config.test.ts +0 -91
  472. package/src/resources/skills/create-gsd-extension/templates/templates.test.ts +0 -58
  473. /package/dist/web/standalone/.next/static/{UF5VF4F1tB0miEtJS7LyX → 7afp7gq8-DVbxum83zRQ-}/_buildManifest.js +0 -0
  474. /package/dist/web/standalone/.next/static/{UF5VF4F1tB0miEtJS7LyX → 7afp7gq8-DVbxum83zRQ-}/_ssgManifest.js +0 -0
@@ -7,20 +7,20 @@
7
7
  *
8
8
  * Testing strategy:
9
9
  * 1. Source-code regression guards: structural checks on register-hooks.ts.
10
- * 2. Behavioral integration tests: fire the live session handlers with fake
11
- * contexts and confirm footer/widget behavior from runtime effects.
10
+ * 2. Behavioral integration test: fires the live session_start handler with a
11
+ * fake ctx when isAutoActive() is false (default) and confirms neither
12
+ * setFooter nor setWidget("gsd-health") is called.
12
13
  *
13
14
  * Relates to #4314.
14
15
  */
15
16
 
16
17
  import test from "node:test";
17
18
  import assert from "node:assert/strict";
18
- import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
19
+ import { mkdirSync, readFileSync, rmSync } from "node:fs";
19
20
  import { join, dirname } from "node:path";
20
21
  import { tmpdir } from "node:os";
21
22
  import { fileURLToPath } from "node:url";
22
23
 
23
- import { autoSession } from "../auto-runtime-state.ts";
24
24
  import { registerHooks } from "../bootstrap/register-hooks.ts";
25
25
 
26
26
  const __dirname = dirname(fileURLToPath(import.meta.url));
@@ -68,89 +68,27 @@ test("session_start handler guards initHealthWidget with !isAutoActive()", () =>
68
68
  );
69
69
  });
70
70
 
71
- test("session_switch toggles gsd-health from runtime auto state without touching the footer", async (t) => {
72
- const dir = join(
73
- tmpdir(),
74
- `gsd-session-switch-widget-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
75
- );
76
- mkdirSync(join(dir, ".gsd"), { recursive: true });
77
- const tempGsdHome = join(dir, "home");
78
- mkdirSync(tempGsdHome, { recursive: true });
79
-
80
- const originalCwd = process.cwd();
81
- const originalGsdHome = process.env.GSD_HOME;
82
- process.env.GSD_HOME = tempGsdHome;
83
- process.chdir(dir);
84
- autoSession.reset();
85
- t.after(() => {
86
- autoSession.reset();
87
- process.chdir(originalCwd);
88
- if (originalGsdHome === undefined) delete process.env.GSD_HOME;
89
- else process.env.GSD_HOME = originalGsdHome;
90
- try { rmSync(dir, { recursive: true, force: true }); } catch { /* best-effort */ }
91
- });
92
-
93
- const handlers = new Map<string, (event: unknown, ctx: any) => Promise<void> | void>();
94
- const pi = {
95
- on(event: string, handler: (event: unknown, ctx: any) => Promise<void> | void) {
96
- handlers.set(event, handler);
97
- },
98
- } as any;
71
+ test("session_switch handler suppresses gsd-health when isAutoActive()", () => {
72
+ const sessionSwitchIdx = HOOKS_SOURCE.indexOf('"session_switch"');
73
+ assert.ok(sessionSwitchIdx > -1, "session_switch handler must exist");
99
74
 
100
- registerHooks(pi, []);
75
+ const beforeAgentStartIdx = HOOKS_SOURCE.indexOf('"before_agent_start"');
76
+ assert.ok(beforeAgentStartIdx > sessionSwitchIdx, "before_agent_start handler must follow session_switch");
101
77
 
102
- const sessionSwitch = handlers.get("session_switch");
103
- assert.ok(sessionSwitch, "session_switch handler must be registered");
78
+ const sessionSwitchBody = HOOKS_SOURCE.slice(sessionSwitchIdx, beforeAgentStartIdx);
104
79
 
105
- let setFooterCallCount = 0;
106
- const widgetCalls: Array<{ key: string; value: unknown }> = [];
107
- const ctx = {
108
- hasUI: true,
109
- ui: {
110
- notify: () => {},
111
- setStatus: () => {},
112
- setFooter: (_footer: unknown) => {
113
- setFooterCallCount++;
114
- },
115
- setWorkingMessage: () => {},
116
- onTerminalInput: () => () => {},
117
- setWidget: (key: string, value: unknown) => {
118
- widgetCalls.push({ key, value });
119
- },
120
- },
121
- sessionManager: { getSessionId: () => null },
122
- model: null,
123
- modelRegistry: {
124
- setDisabledModelProviders: () => {},
125
- getProviderAuthMode: () => undefined,
126
- isProviderRequestReady: () => false,
127
- },
128
- };
129
-
130
- autoSession.active = true;
131
- await sessionSwitch!({ reason: "resume" }, ctx);
132
- assert.deepEqual(
133
- widgetCalls.filter((call) => call.key === "gsd-health").map((call) => call.value),
134
- [undefined],
135
- "session_switch should hide gsd-health when auto is active",
80
+ assert.ok(
81
+ sessionSwitchBody.includes("isAutoActive()"),
82
+ "session_switch handler must call isAutoActive()",
83
+ );
84
+ assert.ok(
85
+ sessionSwitchBody.includes('setWidget("gsd-health", undefined)'),
86
+ "session_switch handler must call setWidget(\"gsd-health\", undefined) when auto is active",
136
87
  );
137
- assert.equal(setFooterCallCount, 0, "session_switch must not call setFooter when auto is active");
138
-
139
- widgetCalls.length = 0;
140
- autoSession.active = false;
141
- await sessionSwitch!({ reason: "resume" }, ctx);
142
- const healthWidgetValues = widgetCalls
143
- .filter((call) => call.key === "gsd-health")
144
- .map((call) => call.value);
145
-
146
- assert.ok(healthWidgetValues.length >= 2, "session_switch should initialize gsd-health when auto is inactive");
147
88
  assert.ok(
148
- healthWidgetValues.every((value) => value !== undefined),
149
- "session_switch must not hide gsd-health when auto is inactive",
89
+ !sessionSwitchBody.includes("setFooter"),
90
+ "session_switch handler must NOT call setFooter",
150
91
  );
151
- assert.ok(Array.isArray(healthWidgetValues[0]), "initHealthWidget should publish initial health lines");
152
- assert.equal(typeof healthWidgetValues.at(-1), "function", "initHealthWidget should register the live widget factory");
153
- assert.equal(setFooterCallCount, 0, "session_switch must not call setFooter when auto is inactive");
154
92
  });
155
93
 
156
94
  // ─── Behavioral test: neither setFooter nor health suppression when auto inactive ─
@@ -205,90 +143,3 @@ test("session_start does NOT call setFooter or suppress gsd-health when isAutoAc
205
143
  assert.equal(setFooterCallCount, 0, "setFooter must NOT be called when isAutoActive() is false");
206
144
  assert.equal(healthWidgetHideCount, 0, "gsd-health must NOT be hidden when isAutoActive() is false");
207
145
  });
208
-
209
- test("session_start and session_switch apply disabled model provider policy from current preferences", async (t) => {
210
- const dir = join(
211
- tmpdir(),
212
- `gsd-disabled-provider-policy-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
213
- );
214
- mkdirSync(join(dir, ".gsd"), { recursive: true });
215
- const tempGsdHome = join(dir, "home");
216
- mkdirSync(tempGsdHome, { recursive: true });
217
-
218
- const originalCwd = process.cwd();
219
- const originalGsdHome = process.env.GSD_HOME;
220
- process.env.GSD_HOME = tempGsdHome;
221
- process.chdir(dir);
222
- t.after(() => {
223
- process.chdir(originalCwd);
224
- if (originalGsdHome === undefined) delete process.env.GSD_HOME;
225
- else process.env.GSD_HOME = originalGsdHome;
226
- try { rmSync(dir, { recursive: true, force: true }); } catch { /* best-effort */ }
227
- });
228
-
229
- const writePrefs = (providers: string[]) => {
230
- writeFileSync(
231
- join(dir, ".gsd", "PREFERENCES.md"),
232
- [
233
- "---",
234
- "version: 1",
235
- "disabled_model_providers:",
236
- ...providers.map((provider) => ` - ${provider}`),
237
- "---",
238
- "",
239
- ].join("\n"),
240
- "utf-8",
241
- );
242
- };
243
-
244
- const appliedPolicies: string[][] = [];
245
- const handlers = new Map<string, (event: unknown, ctx: any) => Promise<void> | void>();
246
- const pi = {
247
- on(event: string, handler: (event: unknown, ctx: any) => Promise<void> | void) {
248
- handlers.set(event, handler);
249
- },
250
- } as any;
251
- const ctx = {
252
- hasUI: true,
253
- ui: {
254
- notify: () => {},
255
- setStatus: () => {},
256
- setFooter: () => {},
257
- setWorkingMessage: () => {},
258
- onTerminalInput: () => () => {},
259
- setWidget: () => {},
260
- },
261
- sessionManager: { getSessionId: () => null },
262
- model: null,
263
- modelRegistry: {
264
- setDisabledModelProviders: (providers: string[]) => {
265
- appliedPolicies.push([...providers]);
266
- },
267
- getProviderAuthMode: () => undefined,
268
- isProviderRequestReady: () => false,
269
- },
270
- };
271
-
272
- registerHooks(pi, []);
273
-
274
- const sessionStart = handlers.get("session_start");
275
- const sessionSwitch = handlers.get("session_switch");
276
- assert.ok(sessionStart, "session_start handler must be registered");
277
- assert.ok(sessionSwitch, "session_switch handler must be registered");
278
-
279
- writePrefs(["google-gemini-cli", " google-gemini-cli ", "openai-codex"]);
280
- await sessionStart!({}, ctx);
281
- assert.deepEqual(
282
- appliedPolicies.at(-1),
283
- ["google-gemini-cli", "openai-codex"],
284
- "session_start should apply normalized disabled providers before the first agent turn",
285
- );
286
-
287
- writePrefs(["anthropic"]);
288
- await sessionSwitch!({ reason: "resume" }, ctx);
289
- assert.deepEqual(
290
- appliedPolicies.at(-1),
291
- ["anthropic"],
292
- "session_switch should re-read preferences for the switched project/session context",
293
- );
294
- });
@@ -11,7 +11,7 @@ import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync
11
11
  import { join, dirname } from "node:path";
12
12
  import { tmpdir } from "node:os";
13
13
  import { fileURLToPath } from "node:url";
14
- import { restoreSliceState, SLICE_WORKER_AUTO_ARGS } from "../slice-parallel-orchestrator.ts";
14
+ import { restoreSliceState } from "../slice-parallel-orchestrator.ts";
15
15
 
16
16
  const __dirname = dirname(fileURLToPath(import.meta.url));
17
17
  const gsdDir = join(__dirname, "..");
@@ -100,12 +100,6 @@ describe("slice-parallel-orchestrator structural tests", () => {
100
100
  );
101
101
  });
102
102
 
103
- it("slice workers use headless auto instead of print-mode slash commands", () => {
104
- const args: readonly string[] = SLICE_WORKER_AUTO_ARGS;
105
- assert.deepEqual([...args], ["headless", "--json", "auto"]);
106
- assert.equal(args.includes("--print"), false);
107
- });
108
-
109
103
  it("maxWorkers default is 2", () => {
110
104
  const source = readFileSync(join(gsdDir, "slice-parallel-orchestrator.ts"), "utf-8");
111
105
  // Check that default max workers is 2 (in opts.maxWorkers ?? 2 or similar)
@@ -48,28 +48,6 @@ test("guided-flow complete branch offers a chooser for next milestone or status"
48
48
 
49
49
  assert.match(branchChunk, /showNextAction\(/, "complete branch should present a chooser");
50
50
  assert.match(branchChunk, /findMilestoneIds\(basePath\)/, "complete branch should compute the next milestone id");
51
- assert.match(
52
- branchChunk,
53
- /nextMilestoneIdReserved\(milestoneIds,\s*uniqueMilestoneIds,\s*basePath\)/,
54
- "complete branch should derive the next milestone id",
55
- );
51
+ assert.match(branchChunk, /nextMilestoneId(?:Reserved)?\(milestoneIds, uniqueMilestoneIds\)/, "complete branch should derive the next milestone id");
56
52
  assert.match(branchChunk, /dispatchWorkflow\(pi, await prepareAndBuildDiscussPrompt\(/, "complete branch should dispatch the prepared discuss prompt");
57
53
  });
58
-
59
- test("guided-flow needs-discussion skip branch opens the project DB before reserving a new milestone", () => {
60
- const guidedFlowSource = readFileSync(join(import.meta.dirname, "..", "guided-flow.ts"), "utf-8");
61
- const laterDbOpenIdx = guidedFlowSource.indexOf("// Ensure DB is open before querying slices (#2560).");
62
- assert.ok(laterDbOpenIdx > -1, "guided-flow.ts should contain the post-draft DB-open guard");
63
-
64
- const branchPrefix = guidedFlowSource.slice(0, laterDbOpenIdx);
65
- const skipBranchIdx = branchPrefix.lastIndexOf('choice === "skip_milestone"');
66
- assert.ok(skipBranchIdx > -1, "needs-discussion skip branch should be present");
67
-
68
- const branchChunk = branchPrefix.slice(skipBranchIdx);
69
- const ensureIdx = branchChunk.indexOf("ensureDbOpen(basePath)");
70
- const reserveIdx = branchChunk.indexOf("nextMilestoneIdReserved");
71
-
72
- assert.ok(ensureIdx > -1, "skip branch should open the project DB");
73
- assert.ok(reserveIdx > -1, "skip branch should reserve the next milestone ID");
74
- assert.ok(ensureIdx < reserveIdx, "project DB must be opened before milestone ID reservation");
75
- });
@@ -107,50 +107,6 @@ test("profile: resolveProfileDefaults exists and handles all 4 tiers", () => {
107
107
  );
108
108
  });
109
109
 
110
- test("profile: PROFILE_TIER_MAP defines tier intentions for all profiles", async () => {
111
- const { getProfileTierMap } = await import("../preferences-models.ts");
112
- const profileMaps = {
113
- budget: getProfileTierMap("budget"),
114
- balanced: getProfileTierMap("balanced"),
115
- quality: getProfileTierMap("quality"),
116
- };
117
-
118
- assert.deepEqual(
119
- Object.keys(profileMaps).sort(),
120
- ["balanced", "budget", "quality"],
121
- "PROFILE_TIER_MAP should include the profile default tiers",
122
- );
123
-
124
- const expectedPhaseKeys = ["completion", "execution", "execution_simple", "planning", "research", "subagent"];
125
- const validTiers = new Set(["light", "standard", "heavy"]);
126
- for (const [profile, tierMap] of Object.entries(profileMaps)) {
127
- assert.deepEqual(
128
- Object.keys(tierMap).sort(),
129
- expectedPhaseKeys,
130
- `${profile} should define all model-bearing phases`,
131
- );
132
- for (const [phase, tier] of Object.entries(tierMap)) {
133
- assert.ok(validTiers.has(tier), `${profile}.${phase} should be a tier name`);
134
- assert.ok(!tier.includes("claude-"), `${profile}.${phase} should not be a model ID`);
135
- }
136
- }
137
- });
138
-
139
- test("profile: resolveProfileDefaults is provider-agnostic — picks OpenAI when only OpenAI is available", async () => {
140
- // Behavioral check: with only OpenAI models in the available list, no slot
141
- // should resolve to a claude-* model. Source-grep cannot prove this — only
142
- // exercising the function with a controlled available-model list can.
143
- const { resolveProfileDefaults } = await import("../preferences-models.ts");
144
- const defaults = resolveProfileDefaults("balanced", ["gpt-4o", "gpt-4o-mini"]);
145
- assert.ok(defaults.models, "balanced profile should populate models");
146
- for (const [phase, modelId] of Object.entries(defaults.models!)) {
147
- assert.ok(
148
- typeof modelId === "string" && !String(modelId).startsWith("claude-"),
149
- `${phase} resolved to ${modelId} but only OpenAI is available`,
150
- );
151
- }
152
- });
153
-
154
110
  test("profile: budget profile sets phase skips to true", () => {
155
111
  // Extract the budget case block
156
112
  const budgetIdx = preferencesSrc.indexOf('case "budget":');
@@ -266,14 +222,11 @@ test("merge: mergePreferences handles phases with spread", () => {
266
222
  // Subagent Model Routing
267
223
  // ═══════════════════════════════════════════════════════════════════════════
268
224
 
269
- test("subagent: budget profile assigns light tier for subagent", () => {
270
- // PROFILE_TIER_MAP.budget.subagent should be "light"
271
- const tierMapIdx = preferencesSrc.indexOf("PROFILE_TIER_MAP");
272
- const budgetIdx = preferencesSrc.indexOf("budget:", tierMapIdx);
273
- const balancedIdx = preferencesSrc.indexOf("balanced:", tierMapIdx);
225
+ test("subagent: budget profile sets subagent model", () => {
226
+ const budgetIdx = preferencesSrc.indexOf('case "budget":');
227
+ const balancedIdx = preferencesSrc.indexOf('case "balanced":');
274
228
  const budgetBlock = preferencesSrc.slice(budgetIdx, balancedIdx);
275
- assert.ok(budgetBlock.includes("subagent:"), "budget profile should define subagent tier");
276
- assert.ok(budgetBlock.includes('"light"'), "budget subagent should use light tier");
229
+ assert.ok(budgetBlock.includes("subagent:"), "budget profile should set subagent model");
277
230
  });
278
231
 
279
232
  test("subagent: resolveModelWithFallbacksForUnit handles subagent unit types", () => {
@@ -144,10 +144,19 @@ test("recoverTimedOutUnit: no top-level bumpTurnGeneration — steering branches
144
144
  );
145
145
  });
146
146
 
147
- // Removed: source-grep count of `bumpAndResolveSynthetic\s*\(` occurrences.
148
- // A literal 4 hardcodes the current branch shape, not behaviour. The
149
- // behavioural invariant "advance branches supersede atomically; non-advance
150
- // branches do not bump" — is enforced by the previous test (no direct
151
- // bumpTurnGeneration calls) plus the per-branch behavioural tests above
152
- // (`recoverTimedOutUnit: …`). Refactors that split a branch into two would
153
- // trip a count test without affecting correctness. Refs #4851.
147
+ test("recoverTimedOutUnit: bumpAndResolveSynthetic appears exactly four times (one per advance branch)", async () => {
148
+ const fs = await import("node:fs");
149
+ const path = await import("node:path");
150
+ const url = await import("node:url");
151
+ const here = path.dirname(url.fileURLToPath(import.meta.url));
152
+ const src = fs.readFileSync(
153
+ path.join(here, "..", "auto-timeout-recovery.ts"),
154
+ "utf-8",
155
+ );
156
+ const matches = src.match(/bumpAndResolveSynthetic\s*\(/g) ?? [];
157
+ assert.equal(
158
+ matches.length,
159
+ 4,
160
+ `expected 4 advance-branch supersede sites (durableComplete, execute-task-exhausted, artifact-already-exists, non-execute-exhausted); found ${matches.length}`,
161
+ );
162
+ });
@@ -76,11 +76,13 @@ describe("#3615 — structural: fallback exists with correct guards", () => {
76
76
  );
77
77
  });
78
78
 
79
- // Removed: source-grep count of `return null;` occurrences. The behaviour
80
- // we care about ("function returns null only when no auto-dispatch /
81
- // guided-resume / fallback path matches") is exercised by the behavioural
82
- // tests below counting literal `return null;` tokens encodes statement
83
- // shape, not contract. Refs #4851.
79
+ test("only one return null at the end", () => {
80
+ const returnNulls = fnBody.match(/return null;/g);
81
+ assert.ok(
82
+ returnNulls && returnNulls.length === 1,
83
+ `expected exactly 1 'return null' (at end after fallback), got ${returnNulls?.length ?? 0}`,
84
+ );
85
+ });
84
86
  });
85
87
 
86
88
  // ── Behavioral tests: RESUME_INTENT_PATTERNS ────────────────────────
@@ -4,7 +4,7 @@ import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
4
4
  import { tmpdir } from "node:os";
5
5
  import { join } from "node:path";
6
6
  import { execSync } from "node:child_process";
7
- import { handleTurnGitActionError, runTurnGitAction } from "../git-service.ts";
7
+ import { runTurnGitAction } from "../git-service.ts";
8
8
 
9
9
  function run(cmd: string, cwd: string): string {
10
10
  return execSync(cmd, { cwd, stdio: "pipe", encoding: "utf-8" }).trim();
@@ -83,17 +83,3 @@ test("uok gitops turn action commit creates commit with unit trailer", () => {
83
83
  rmSync(repo, { recursive: true, force: true });
84
84
  }
85
85
  });
86
-
87
- test("uok gitops turn action rethrows infrastructure failures", () => {
88
- const err = Object.assign(new Error("ENFILE: file table overflow"), { code: "ENFILE" });
89
-
90
- assert.throws(() => handleTurnGitActionError("commit", err), (thrown) => thrown === err);
91
- });
92
-
93
- test("uok gitops turn action keeps non-infrastructure git failures recoverable", () => {
94
- const result = handleTurnGitActionError("commit", new Error("nothing to commit"));
95
-
96
- assert.equal(result.action, "commit");
97
- assert.equal(result.status, "failed");
98
- assert.equal(result.error, "nothing to commit");
99
- });
@@ -13,7 +13,7 @@
13
13
  import { test } from "node:test";
14
14
  import assert from "node:assert/strict";
15
15
 
16
- import { GSDVisualizerOverlay, TAB_COUNT } from "../visualizer-overlay.ts";
16
+ import { GSDVisualizerOverlay } from "../visualizer-overlay.ts";
17
17
 
18
18
  function makeTui() {
19
19
  const renders: number[] = [];
@@ -93,16 +93,16 @@ test("overlay switches tabs via 1–9,0 digit keys", (t) => {
93
93
 
94
94
  test("overlay Tab key cycles forward and wraps around at TAB_COUNT", (t) => {
95
95
  const { overlay } = makeOverlay(t);
96
- overlay.activeTab = TAB_COUNT - 1;
96
+ overlay.activeTab = 9;
97
97
  overlay.handleInput("\t");
98
- assert.equal(overlay.activeTab, 0, `Tab wraps from ${TAB_COUNT - 1} back to 0`);
98
+ assert.equal(overlay.activeTab, 0, "Tab wraps from 9 back to 0");
99
99
  });
100
100
 
101
101
  test("overlay Shift+Tab cycles backward and wraps", (t) => {
102
102
  const { overlay } = makeOverlay(t);
103
103
  overlay.activeTab = 0;
104
104
  overlay.handleInput("\u001b[Z");
105
- assert.equal(overlay.activeTab, TAB_COUNT - 1, `Shift+Tab wraps from 0 to ${TAB_COUNT - 1}`);
105
+ assert.equal(overlay.activeTab, 9, "Shift+Tab wraps from 0 to 9");
106
106
  });
107
107
 
108
108
  // ─── Filter mode ─────────────────────────────────────────────────────────
@@ -331,9 +331,9 @@ test("overlay footer hint mentions tab navigation, filter, scroll, and help", (t
331
331
 
332
332
  // ─── Scroll offsets array is sized to TAB_COUNT ──────────────────────────
333
333
 
334
- test("overlay scrollOffsets array has one slot per tab", (t) => {
334
+ test("overlay scrollOffsets array has one slot per tab (10 tabs total)", (t) => {
335
335
  const { overlay } = makeOverlay(t);
336
- assert.equal(overlay.scrollOffsets.length, TAB_COUNT, "scrollOffsets sized to TAB_COUNT");
336
+ assert.equal(overlay.scrollOffsets.length, 10, "scrollOffsets sized to TAB_COUNT=10");
337
337
  assert.ok(overlay.scrollOffsets.every((n: number) => n === 0), "initialized to zero");
338
338
  });
339
339
 
@@ -10,7 +10,6 @@ import assert from 'node:assert/strict';
10
10
  import { join, sep } from 'node:path';
11
11
 
12
12
  import { shouldBlockPlanningUnit } from '../bootstrap/write-gate.ts';
13
- import { isDeterministicPolicyError } from '../auto-tool-tracking.ts';
14
13
  import type { ToolsPolicy } from '../unit-context-manifest.ts';
15
14
 
16
15
  const BASE = join('/tmp', 'fake-project');
@@ -37,20 +36,6 @@ test('planning-unit: blocks edit to user source (the b23 forensic)', () => {
37
36
  assert.match(r.reason!, /discuss-milestone/);
38
37
  });
39
38
 
40
- test('planning-unit: deterministic block reason is suitable for retry short-circuiting', () => {
41
- const r = shouldBlockPlanningUnit(
42
- 'edit',
43
- 'src/main.ts',
44
- BASE,
45
- 'discuss-milestone',
46
- PLANNING,
47
- );
48
- assert.strictEqual(r.block, true);
49
- assert.match(r.reason!, /HARD BLOCK/);
50
- assert.match(r.reason!, /tools-policy/);
51
- assert.strictEqual(isDeterministicPolicyError(r.reason!), true);
52
- });
53
-
54
39
  test('planning-unit: blocks write to user source via relative path', () => {
55
40
  const r = shouldBlockPlanningUnit('write', 'src/main.ts', BASE, 'plan-milestone', PLANNING);
56
41
  assert.strictEqual(r.block, true);
@@ -96,24 +96,8 @@ export function executeMemoryCapture(params: MemoryCaptureParams): ToolExecution
96
96
  const tags = normalizeTags(params.tags);
97
97
 
98
98
  const structuredFields = normalizeStructuredFields(params.structuredFields);
99
- let id: string | null;
100
- try {
101
- id = createMemory({ category, content, confidence, scope, tags, structuredFields });
102
- } catch (err) {
103
- // Surface the underlying SQL message (e.g. "database disk image is
104
- // malformed", "no such table: memories") so the operator gets the
105
- // actionable signal instead of an opaque "create_failed". See #4967.
106
- const message = err instanceof Error ? err.message : String(err);
107
- return {
108
- content: [{ type: "text", text: `Error: failed to create memory: ${message}` }],
109
- details: { operation: "memory_capture", error: message },
110
- isError: true,
111
- };
112
- }
99
+ const id = createMemory({ category, content, confidence, scope, tags, structuredFields });
113
100
  if (!id) {
114
- // DB unavailable or adapter missing — distinct from the SQL-error path
115
- // above. Keep the legacy create_failed token here so any consumers that
116
- // explicitly key on the unavailable case continue to work.
117
101
  return {
118
102
  content: [{ type: "text", text: "Error: failed to create memory." }],
119
103
  details: { operation: "memory_capture", error: "create_failed" },
@@ -93,10 +93,10 @@ export type PreferencesPolicy = "none" | "active-only" | "full";
93
93
  /**
94
94
  * Tool-access policy per unit type (#4934).
95
95
  *
96
- * Runtime-enforced by the GSD write gate for active auto-mode units. The
97
- * manifest declares the allowed tool surface; register-hooks.ts resolves the
98
- * active unit's manifest before each tool call and write-gate.ts rejects
99
- * violations before the tool executes.
96
+ * Declarative-only in this PR runtime enforcement (write-gate.ts predicate
97
+ * + dispatch-time isolation) lands in follow-up PRs. The shape is the
98
+ * agreement between manifest authors and enforcement; surfacing it now lets
99
+ * reviewers ratify per-unit policy intent before any blocking logic ships.
100
100
  *
101
101
  * Modes:
102
102
  * - "all" — Read + Edit/Write/MultiEdit/NotebookEdit + Bash + Task.
@@ -214,10 +214,10 @@ export interface UnitContextManifest {
214
214
  /** Preferences block policy. */
215
215
  readonly preferences: PreferencesPolicy;
216
216
  /**
217
- * Tool-access policy (#4934). Runtime enforcement covers path-scoped write
218
- * blocking, subagent denial, and bash allowlisting for active auto-mode
219
- * units. Required on every manifest so missing entries fail loud via the CI
220
- * invariant test rather than defaulting to "all" silently.
217
+ * Tool-access policy (#4934). Declarative in this PR; runtime enforcement
218
+ * (path-scoped write blocking + subagent denial + bash allowlist) lands
219
+ * in follow-ups. Required on every manifest so missing entries fail loud
220
+ * via the CI invariant test rather than defaulting to "all" silently.
221
221
  */
222
222
  readonly tools: ToolsPolicy;
223
223
  /** Artifact handling: inline (full body), excerpt (compact), or on-demand (path only). */
@@ -20,7 +20,7 @@ import { writeExportFile } from "./export.js";
20
20
  import { gsdRoot } from "./paths.js";
21
21
  import { stripAnsi } from "../shared/mod.js";
22
22
 
23
- export const TAB_COUNT = 10;
23
+ const TAB_COUNT = 10;
24
24
  const TAB_LABELS = [
25
25
  "1 Progress",
26
26
  "2 Timeline",
@@ -98,15 +98,13 @@ export function readGitBranch(projectRoot: string): string {
98
98
  }
99
99
 
100
100
  /**
101
- * Read MCP server names from .mcp.json, .gsd/mcp.json, and the global
102
- * ~/.gsd/mcp.json (or $GSD_HOME/mcp.json).
101
+ * Read MCP server names from .mcp.json or .gsd/mcp.json.
103
102
  * Returns array of server name strings.
104
103
  */
105
104
  export function readMcpServerNames(projectRoot: string): string[] {
106
105
  const configPaths = [
107
106
  join(projectRoot, ".mcp.json"),
108
107
  join(projectRoot, ".gsd", "mcp.json"),
109
- join(process.env.GSD_HOME || join(homedir(), ".gsd"), "mcp.json"),
110
108
  ];
111
109
  const names: string[] = [];
112
110
  const seen = new Set<string>();
@@ -66,7 +66,6 @@ export type LogComponent =
66
66
  | "memory-embeddings" // Memory layer embedding generation
67
67
  | "memory-ingest" // Memory layer ingestion pipeline
68
68
  | "memory-backfill" // ADR-013: decisions->memories backfill
69
- | "memory-store" // Memory CRUD layer — surfaces SQLite/store-level faults (#4967)
70
69
  | "context-mode" // Context-mode exec sandbox and compaction snapshot
71
70
  | "preflight" // Clean-root preflight gate at milestone completion
72
71
  | "postUnit"; // Post-unit processing (abandon detection, overrides)