gsd-pi 2.82.0 → 3.0.0-dev.1b44e695b

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 (799) hide show
  1. package/README.md +125 -32
  2. package/dist/cli.js +20 -9
  3. package/dist/headless-ui.js +13 -6
  4. package/dist/headless.js +9 -2
  5. package/dist/resources/.managed-resources-content-hash +1 -1
  6. package/dist/resources/GSD-WORKFLOW.md +10 -1
  7. package/dist/resources/extensions/browser-tools/tools/screenshot.js +1 -0
  8. package/dist/resources/extensions/browser-tools/tools/zoom.js +1 -0
  9. package/dist/resources/extensions/claude-code-cli/partial-builder.js +2 -1
  10. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +44 -6
  11. package/dist/resources/extensions/cmux/index.js +5 -0
  12. package/dist/resources/extensions/gsd/auto/detect-stuck.js +1 -1
  13. package/dist/resources/extensions/gsd/auto/infra-errors.js +9 -3
  14. package/dist/resources/extensions/gsd/auto/loop.js +122 -40
  15. package/dist/resources/extensions/gsd/auto/orchestrator.js +126 -8
  16. package/dist/resources/extensions/gsd/auto/phases.js +143 -49
  17. package/dist/resources/extensions/gsd/auto/session.js +6 -0
  18. package/dist/resources/extensions/gsd/auto/unit-runner-events.js +7 -1
  19. package/dist/resources/extensions/gsd/auto/workflow-kernel.js +3 -0
  20. package/dist/resources/extensions/gsd/auto/workflow-memory-pressure.js +12 -0
  21. package/dist/resources/extensions/gsd/auto-budget.js +9 -0
  22. package/dist/resources/extensions/gsd/auto-dashboard.js +66 -1
  23. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +1 -0
  24. package/dist/resources/extensions/gsd/auto-dispatch.js +144 -30
  25. package/dist/resources/extensions/gsd/auto-model-selection.js +2 -0
  26. package/dist/resources/extensions/gsd/auto-post-unit.js +329 -137
  27. package/dist/resources/extensions/gsd/auto-prompts.js +47 -13
  28. package/dist/resources/extensions/gsd/auto-recovery.js +82 -16
  29. package/dist/resources/extensions/gsd/auto-start.js +99 -16
  30. package/dist/resources/extensions/gsd/auto-timers.js +11 -3
  31. package/dist/resources/extensions/gsd/auto-verification.js +146 -34
  32. package/dist/resources/extensions/gsd/auto-worktree.js +185 -26
  33. package/dist/resources/extensions/gsd/auto.js +251 -99
  34. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +65 -10
  35. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +13 -10
  36. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +19 -4
  37. package/dist/resources/extensions/gsd/bootstrap/subagent-input.js +21 -9
  38. package/dist/resources/extensions/gsd/bootstrap/system-context.js +55 -12
  39. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +24 -9
  40. package/dist/resources/extensions/gsd/clean-root-preflight.js +170 -8
  41. package/dist/resources/extensions/gsd/commands/catalog.js +10 -1
  42. package/dist/resources/extensions/gsd/commands/handlers/core.js +39 -1
  43. package/dist/resources/extensions/gsd/commands/handlers/ops.js +20 -0
  44. package/dist/resources/extensions/gsd/commands-bootstrap.js +5 -0
  45. package/dist/resources/extensions/gsd/commands-handlers.js +17 -2
  46. package/dist/resources/extensions/gsd/commands-mcp-status.js +9 -0
  47. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +10 -2
  48. package/dist/resources/extensions/gsd/commands-verdict.js +139 -0
  49. package/dist/resources/extensions/gsd/context-store.js +112 -0
  50. package/dist/resources/extensions/gsd/crash-recovery.js +55 -7
  51. package/dist/resources/extensions/gsd/db/auto-workers.js +30 -0
  52. package/dist/resources/extensions/gsd/db/milestone-leases.js +24 -0
  53. package/dist/resources/extensions/gsd/db/unit-dispatches.js +3 -2
  54. package/dist/resources/extensions/gsd/db-base-schema.js +2 -0
  55. package/dist/resources/extensions/gsd/db-migration-steps.js +4 -0
  56. package/dist/resources/extensions/gsd/db-task-slice-rows.js +2 -0
  57. package/dist/resources/extensions/gsd/db-writer.js +150 -84
  58. package/dist/resources/extensions/gsd/dispatch-guard.js +46 -2
  59. package/dist/resources/extensions/gsd/docs/preferences-reference.md +11 -1
  60. package/dist/resources/extensions/gsd/doctor-git-checks.js +87 -7
  61. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +28 -11
  62. package/dist/resources/extensions/gsd/doctor.js +2 -28
  63. package/dist/resources/extensions/gsd/export-html.js +27 -425
  64. package/dist/resources/extensions/gsd/forensics.js +10 -3
  65. package/dist/resources/extensions/gsd/git-service.js +152 -15
  66. package/dist/resources/extensions/gsd/gsd-db.js +76 -33
  67. package/dist/resources/extensions/gsd/guided-flow-queue.js +4 -3
  68. package/dist/resources/extensions/gsd/guided-flow.js +110 -117
  69. package/dist/resources/extensions/gsd/guided-unit-context.js +23 -0
  70. package/dist/resources/extensions/gsd/init-wizard.js +17 -2
  71. package/dist/resources/extensions/gsd/knowledge-backfill.js +144 -0
  72. package/dist/resources/extensions/gsd/knowledge-capture.js +136 -0
  73. package/dist/resources/extensions/gsd/knowledge-parser.js +154 -0
  74. package/dist/resources/extensions/gsd/knowledge-projection.js +210 -0
  75. package/dist/resources/extensions/gsd/markdown-renderer.js +20 -12
  76. package/dist/resources/extensions/gsd/mcp-filter.js +58 -0
  77. package/dist/resources/extensions/gsd/md-importer.js +1 -1
  78. package/dist/resources/extensions/gsd/memory-backfill.js +73 -17
  79. package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +222 -0
  80. package/dist/resources/extensions/gsd/migrate/command.js +5 -0
  81. package/dist/resources/extensions/gsd/migrate/parsers.js +121 -2
  82. package/dist/resources/extensions/gsd/migrate/preview.js +9 -0
  83. package/dist/resources/extensions/gsd/migrate/transformer.js +51 -4
  84. package/dist/resources/extensions/gsd/migrate/writer.js +11 -1
  85. package/dist/resources/extensions/gsd/migration-auto-check.js +12 -17
  86. package/dist/resources/extensions/gsd/milestone-actions.js +11 -4
  87. package/dist/resources/extensions/gsd/native-git-bridge.js +57 -14
  88. package/dist/resources/extensions/gsd/parallel-orchestrator.js +3 -0
  89. package/dist/resources/extensions/gsd/paths.js +4 -0
  90. package/dist/resources/extensions/gsd/pending-auto-start.js +52 -0
  91. package/dist/resources/extensions/gsd/planning-path-scope.js +9 -3
  92. package/dist/resources/extensions/gsd/post-execution-checks.js +73 -9
  93. package/dist/resources/extensions/gsd/pre-execution-checks.js +54 -19
  94. package/dist/resources/extensions/gsd/preferences-mcp.js +19 -0
  95. package/dist/resources/extensions/gsd/preferences-types.js +3 -0
  96. package/dist/resources/extensions/gsd/preferences-validation.js +147 -0
  97. package/dist/resources/extensions/gsd/preferences.js +6 -0
  98. package/dist/resources/extensions/gsd/prompt-loader.js +1 -1
  99. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  100. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  101. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
  102. package/dist/resources/extensions/gsd/prompts/discuss.md +9 -9
  103. package/dist/resources/extensions/gsd/prompts/forensics.md +3 -3
  104. package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
  105. package/dist/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
  106. package/dist/resources/extensions/gsd/prompts/plan-slice.md +4 -4
  107. package/dist/resources/extensions/gsd/prompts/queue.md +4 -4
  108. package/dist/resources/extensions/gsd/prompts/reactive-execute.md +1 -1
  109. package/dist/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  110. package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  111. package/dist/resources/extensions/gsd/prompts/system.md +2 -2
  112. package/dist/resources/extensions/gsd/provider-switch-observer.js +146 -0
  113. package/dist/resources/extensions/gsd/queue-reorder-ui.js +30 -13
  114. package/dist/resources/extensions/gsd/repo-identity.js +39 -22
  115. package/dist/resources/extensions/gsd/repository-registry.js +44 -0
  116. package/dist/resources/extensions/gsd/safety/evidence-collector.js +2 -0
  117. package/dist/resources/extensions/gsd/safety/evidence-cross-ref.js +42 -18
  118. package/dist/resources/extensions/gsd/session-lock.js +15 -2
  119. package/dist/resources/extensions/gsd/slice-parallel-conflict.js +2 -2
  120. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +84 -5
  121. package/dist/resources/extensions/gsd/smart-entry-routing.js +36 -0
  122. package/dist/resources/extensions/gsd/state-reconciliation/drift/merge-state.js +6 -1
  123. package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +9 -14
  124. package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +19 -24
  125. package/dist/resources/extensions/gsd/state.js +28 -7
  126. package/dist/resources/extensions/gsd/status-guards.js +14 -2
  127. package/dist/resources/extensions/gsd/templates/PREFERENCES.md +1 -0
  128. package/dist/resources/extensions/gsd/templates/knowledge.md +2 -2
  129. package/dist/resources/extensions/gsd/templates/plan.md +9 -5
  130. package/dist/resources/extensions/gsd/templates/task-plan.md +10 -2
  131. package/dist/resources/extensions/gsd/tools/complete-milestone.js +15 -9
  132. package/dist/resources/extensions/gsd/tools/complete-slice.js +56 -10
  133. package/dist/resources/extensions/gsd/tools/exec-tool.js +87 -5
  134. package/dist/resources/extensions/gsd/tools/plan-milestone.js +7 -1
  135. package/dist/resources/extensions/gsd/tools/plan-slice.js +151 -15
  136. package/dist/resources/extensions/gsd/tools/validate-milestone.js +32 -1
  137. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +185 -40
  138. package/dist/resources/extensions/gsd/unit-context-composer.js +2 -0
  139. package/dist/resources/extensions/gsd/unit-context-manifest.js +69 -17
  140. package/dist/resources/extensions/gsd/validation.js +23 -1
  141. package/dist/resources/extensions/gsd/verification-gate.js +142 -7
  142. package/dist/resources/extensions/gsd/verification-verdict.js +26 -0
  143. package/dist/resources/extensions/gsd/workflow-manifest.js +2 -0
  144. package/dist/resources/extensions/gsd/workflow-mcp.js +17 -1
  145. package/dist/resources/extensions/gsd/workflow-projections.js +6 -8
  146. package/dist/resources/extensions/gsd/worktree-lifecycle.js +86 -19
  147. package/dist/resources/extensions/gsd/worktree-manager.js +11 -2
  148. package/dist/resources/extensions/gsd/worktree-safety.js +43 -4
  149. package/dist/resources/extensions/gsd/worktree-state-projection.js +31 -0
  150. package/dist/resources/extensions/gsd/worktree-telemetry.js +32 -0
  151. package/dist/resources/extensions/shared/html-shell.js +388 -0
  152. package/dist/resources/extensions/shared/interview-ui.js +6 -4
  153. package/dist/resources/extensions/shared/next-action-ui.js +13 -5
  154. package/dist/resources/extensions/subagent/index.js +448 -78
  155. package/dist/resources/extensions/subagent/launch.js +77 -0
  156. package/dist/resources/extensions/subagent/run-store.js +148 -0
  157. package/dist/resources/extensions/ttsr/ttsr-manager.js +3 -1
  158. package/dist/resources/extensions/visual-brief/artifact-policy.js +29 -0
  159. package/dist/resources/extensions/visual-brief/extension-manifest.json +8 -0
  160. package/dist/resources/extensions/visual-brief/index.js +5 -0
  161. package/dist/resources/extensions/visual-brief/page-contract.js +124 -0
  162. package/dist/resources/extensions/visual-brief/prompts.js +140 -0
  163. package/dist/resources/skills/forensics/SKILL.md +1 -1
  164. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  165. package/dist/web/standalone/.next/BUILD_ID +1 -1
  166. package/dist/web/standalone/.next/app-path-routes-manifest.json +8 -8
  167. package/dist/web/standalone/.next/build-manifest.json +4 -4
  168. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  169. package/dist/web/standalone/.next/react-loadable-manifest.json +5 -5
  170. package/dist/web/standalone/.next/required-server-files.json +4 -4
  171. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  172. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  174. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  175. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  176. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  177. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  178. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  179. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  180. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  181. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  182. package/dist/web/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  183. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  184. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  185. package/dist/web/standalone/.next/server/app/_not-found.rsc +4 -7
  186. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -7
  187. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  188. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -5
  189. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  190. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  191. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -5
  192. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  193. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  194. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  195. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  196. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  197. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  198. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  199. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  200. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  201. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  202. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  203. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  204. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  205. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  206. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  207. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  208. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  209. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  210. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  211. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  212. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  213. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  214. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  215. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  216. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  217. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  218. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  219. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  220. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  221. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  222. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  223. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  224. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  225. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  226. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  227. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  228. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  229. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  230. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  231. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  232. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  233. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  234. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  235. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  236. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  237. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  238. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  239. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  240. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  241. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  242. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  243. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  244. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  245. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  246. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  247. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  248. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  249. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  250. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  251. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  252. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  253. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  254. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  255. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  256. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  257. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  258. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  259. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  260. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  261. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  262. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  263. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  264. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  265. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  266. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +2 -2
  267. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  268. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  269. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  270. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  271. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  272. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  273. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  274. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  275. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  276. package/dist/web/standalone/.next/server/app/index.html +1 -1
  277. package/dist/web/standalone/.next/server/app/index.rsc +5 -8
  278. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  279. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +5 -8
  280. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  281. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -5
  282. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -5
  283. package/dist/web/standalone/.next/server/app/page.js +2 -2
  284. package/dist/web/standalone/.next/server/app/page.js.nft.json +1 -1
  285. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  286. package/dist/web/standalone/.next/server/app-paths-manifest.json +8 -8
  287. package/dist/web/standalone/.next/server/chunks/4266.js +2 -0
  288. package/dist/web/standalone/.next/server/chunks/63.js +3 -3
  289. package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
  290. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  291. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  292. package/dist/web/standalone/.next/server/middleware.js +2 -2
  293. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  294. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  295. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  296. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  297. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  298. package/dist/web/standalone/.next/static/chunks/2973.33f26573894b6153.js +2 -0
  299. package/dist/web/standalone/.next/static/chunks/8359.65b24fac92188a6b.js +10 -0
  300. package/dist/web/standalone/.next/static/chunks/9441.ff70bb53f6835771.js +1 -0
  301. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  302. package/dist/web/standalone/.next/static/chunks/app/layout-8c10ec293ae0f1d5.js +1 -0
  303. package/dist/web/standalone/.next/static/chunks/app/page-752f1e2ebdaa3e45.js +1 -0
  304. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  305. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  306. package/dist/web/standalone/.next/static/chunks/{webpack-de742b64187e13fe.js → webpack-855d616060cb6e59.js} +1 -1
  307. package/dist/web/standalone/.next/static/css/746ee28c929d1880.css +1 -0
  308. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  309. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  310. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  311. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  312. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  313. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  314. package/dist/web/standalone/server.js +1 -1
  315. package/package.json +6 -5
  316. package/packages/contracts/dist/rpc.test.js +7 -0
  317. package/packages/contracts/dist/rpc.test.js.map +1 -1
  318. package/packages/contracts/dist/workflow.d.ts +21 -0
  319. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  320. package/packages/contracts/dist/workflow.js +24 -0
  321. package/packages/contracts/dist/workflow.js.map +1 -1
  322. package/packages/contracts/src/rpc.test.ts +8 -0
  323. package/packages/contracts/src/workflow.ts +24 -0
  324. package/packages/daemon/package.json +2 -2
  325. package/packages/mcp-server/README.md +14 -3
  326. package/packages/mcp-server/dist/workflow-tools.d.ts +0 -3
  327. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  328. package/packages/mcp-server/dist/workflow-tools.js +80 -0
  329. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  330. package/packages/mcp-server/package.json +2 -2
  331. package/packages/mcp-server/src/workflow-tools-parity.test.ts +244 -0
  332. package/packages/mcp-server/src/workflow-tools.test.ts +23 -1
  333. package/packages/mcp-server/src/workflow-tools.ts +168 -0
  334. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  335. package/packages/native/package.json +1 -1
  336. package/packages/native/tsconfig.json +2 -1
  337. package/packages/native/tsconfig.tsbuildinfo +1 -1
  338. package/packages/pi-agent-core/package.json +1 -1
  339. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  340. package/packages/pi-ai/dist/index.d.ts +2 -2
  341. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  342. package/packages/pi-ai/dist/index.js +1 -1
  343. package/packages/pi-ai/dist/index.js.map +1 -1
  344. package/packages/pi-ai/dist/providers/google-gemini-cli.d.ts.map +1 -1
  345. package/packages/pi-ai/dist/providers/google-gemini-cli.js +5 -0
  346. package/packages/pi-ai/dist/providers/google-gemini-cli.js.map +1 -1
  347. package/packages/pi-ai/dist/providers/google-gemini-cli.test.d.ts +2 -0
  348. package/packages/pi-ai/dist/providers/google-gemini-cli.test.d.ts.map +1 -0
  349. package/packages/pi-ai/dist/providers/google-gemini-cli.test.js +41 -0
  350. package/packages/pi-ai/dist/providers/google-gemini-cli.test.js.map +1 -0
  351. package/packages/pi-ai/dist/providers/openai-codex-responses.d.ts.map +1 -1
  352. package/packages/pi-ai/dist/providers/openai-codex-responses.js +82 -1
  353. package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
  354. package/packages/pi-ai/dist/providers/openai-codex-responses.test.d.ts +2 -0
  355. package/packages/pi-ai/dist/providers/openai-codex-responses.test.d.ts.map +1 -0
  356. package/packages/pi-ai/dist/providers/openai-codex-responses.test.js +52 -0
  357. package/packages/pi-ai/dist/providers/openai-codex-responses.test.js.map +1 -0
  358. package/packages/pi-ai/dist/providers/simple-options.d.ts +2 -4
  359. package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
  360. package/packages/pi-ai/dist/providers/simple-options.js +5 -6
  361. package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
  362. package/packages/pi-ai/dist/providers/simple-options.test.d.ts +2 -0
  363. package/packages/pi-ai/dist/providers/simple-options.test.d.ts.map +1 -0
  364. package/packages/pi-ai/dist/providers/simple-options.test.js +50 -0
  365. package/packages/pi-ai/dist/providers/simple-options.test.js.map +1 -0
  366. package/packages/pi-ai/dist/providers/transform-messages.d.ts +11 -0
  367. package/packages/pi-ai/dist/providers/transform-messages.d.ts.map +1 -1
  368. package/packages/pi-ai/dist/providers/transform-messages.js +20 -0
  369. package/packages/pi-ai/dist/providers/transform-messages.js.map +1 -1
  370. package/packages/pi-ai/package.json +1 -1
  371. package/packages/pi-ai/src/index.ts +7 -2
  372. package/packages/pi-ai/src/providers/google-gemini-cli.test.ts +49 -0
  373. package/packages/pi-ai/src/providers/google-gemini-cli.ts +7 -0
  374. package/packages/pi-ai/src/providers/openai-codex-responses.test.ts +63 -0
  375. package/packages/pi-ai/src/providers/openai-codex-responses.ts +91 -1
  376. package/packages/pi-ai/src/providers/simple-options.test.ts +60 -0
  377. package/packages/pi-ai/src/providers/simple-options.ts +5 -6
  378. package/packages/pi-ai/src/providers/transform-messages.ts +24 -0
  379. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  380. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts +2 -0
  381. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts.map +1 -0
  382. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js +66 -0
  383. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js.map +1 -0
  384. package/packages/pi-coding-agent/dist/core/agent-session.js +1 -1
  385. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  386. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +44 -3
  387. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
  388. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +6 -1
  389. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  390. package/packages/pi-coding-agent/dist/core/compaction/compaction.js +7 -2
  391. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  392. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js +14 -1
  393. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js.map +1 -1
  394. package/packages/pi-coding-agent/dist/core/sdk.js +1 -1
  395. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  396. package/packages/pi-coding-agent/dist/core/system-prompt.js +4 -4
  397. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  398. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +8 -2
  399. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  400. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  401. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +24 -6
  402. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  403. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +1 -1
  404. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  405. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  406. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +82 -97
  407. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  408. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +7 -7
  409. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  410. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +11 -0
  411. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  412. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.js +25 -1
  413. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.js.map +1 -1
  414. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +2 -0
  415. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  416. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +24 -10
  417. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  418. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.d.ts +2 -0
  419. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.d.ts.map +1 -0
  420. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.js +17 -0
  421. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.js.map +1 -0
  422. package/packages/pi-coding-agent/package.json +1 -1
  423. package/packages/pi-coding-agent/src/core/agent-session-thinking-level.test.ts +79 -0
  424. package/packages/pi-coding-agent/src/core/agent-session.ts +1 -1
  425. package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +53 -3
  426. package/packages/pi-coding-agent/src/core/compaction/compaction.test.ts +23 -1
  427. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +7 -2
  428. package/packages/pi-coding-agent/src/core/sdk.ts +1 -1
  429. package/packages/pi-coding-agent/src/core/system-prompt.ts +4 -4
  430. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +17 -1
  431. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +23 -7
  432. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +1 -1
  433. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +91 -102
  434. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +15 -1
  435. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +9 -9
  436. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-ordering.test.ts +30 -1
  437. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +29 -10
  438. package/packages/pi-coding-agent/src/tests/system-prompt-file-safety.test.ts +22 -0
  439. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  440. package/packages/pi-tui/dist/__tests__/terminal.test.d.ts +2 -0
  441. package/packages/pi-tui/dist/__tests__/terminal.test.d.ts.map +1 -0
  442. package/packages/pi-tui/dist/__tests__/terminal.test.js +103 -0
  443. package/packages/pi-tui/dist/__tests__/terminal.test.js.map +1 -0
  444. package/packages/pi-tui/dist/__tests__/tui.test.js +45 -2
  445. package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
  446. package/packages/pi-tui/dist/terminal.d.ts +2 -0
  447. package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
  448. package/packages/pi-tui/dist/terminal.js +12 -0
  449. package/packages/pi-tui/dist/terminal.js.map +1 -1
  450. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  451. package/packages/pi-tui/dist/tui.js +108 -24
  452. package/packages/pi-tui/dist/tui.js.map +1 -1
  453. package/packages/pi-tui/package.json +1 -1
  454. package/packages/pi-tui/src/__tests__/terminal.test.ts +121 -0
  455. package/packages/pi-tui/src/__tests__/tui.test.ts +59 -2
  456. package/packages/pi-tui/src/terminal.ts +11 -0
  457. package/packages/pi-tui/src/tui.ts +111 -24
  458. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  459. package/packages/rpc-client/package.json +1 -1
  460. package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
  461. package/pkg/package.json +1 -1
  462. package/src/resources/GSD-WORKFLOW.md +10 -1
  463. package/src/resources/extensions/browser-tools/tools/screenshot.ts +1 -0
  464. package/src/resources/extensions/browser-tools/tools/zoom.ts +1 -0
  465. package/src/resources/extensions/claude-code-cli/partial-builder.ts +2 -1
  466. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +52 -6
  467. package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +19 -2
  468. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +49 -2
  469. package/src/resources/extensions/cmux/index.ts +6 -0
  470. package/src/resources/extensions/gsd/auto/contracts.ts +64 -16
  471. package/src/resources/extensions/gsd/auto/detect-stuck.ts +1 -0
  472. package/src/resources/extensions/gsd/auto/infra-errors.ts +9 -3
  473. package/src/resources/extensions/gsd/auto/loop.ts +123 -40
  474. package/src/resources/extensions/gsd/auto/orchestrator.ts +131 -8
  475. package/src/resources/extensions/gsd/auto/phases.ts +174 -60
  476. package/src/resources/extensions/gsd/auto/session.ts +16 -0
  477. package/src/resources/extensions/gsd/auto/types.ts +3 -0
  478. package/src/resources/extensions/gsd/auto/unit-runner-events.ts +6 -2
  479. package/src/resources/extensions/gsd/auto/workflow-kernel.ts +5 -1
  480. package/src/resources/extensions/gsd/auto/workflow-memory-pressure.ts +13 -0
  481. package/src/resources/extensions/gsd/auto-budget.ts +11 -0
  482. package/src/resources/extensions/gsd/auto-dashboard.ts +72 -1
  483. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +1 -0
  484. package/src/resources/extensions/gsd/auto-dispatch.ts +164 -29
  485. package/src/resources/extensions/gsd/auto-model-selection.ts +2 -1
  486. package/src/resources/extensions/gsd/auto-post-unit.ts +369 -148
  487. package/src/resources/extensions/gsd/auto-prompts.ts +47 -16
  488. package/src/resources/extensions/gsd/auto-recovery.ts +86 -13
  489. package/src/resources/extensions/gsd/auto-start.ts +109 -14
  490. package/src/resources/extensions/gsd/auto-timers.ts +10 -3
  491. package/src/resources/extensions/gsd/auto-verification.ts +174 -42
  492. package/src/resources/extensions/gsd/auto-worktree.ts +202 -30
  493. package/src/resources/extensions/gsd/auto.ts +296 -107
  494. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +66 -10
  495. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +13 -10
  496. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +19 -4
  497. package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +19 -7
  498. package/src/resources/extensions/gsd/bootstrap/system-context.ts +58 -15
  499. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +27 -10
  500. package/src/resources/extensions/gsd/clean-root-preflight.ts +174 -8
  501. package/src/resources/extensions/gsd/commands/catalog.ts +10 -1
  502. package/src/resources/extensions/gsd/commands/handlers/core.ts +42 -1
  503. package/src/resources/extensions/gsd/commands/handlers/ops.ts +21 -0
  504. package/src/resources/extensions/gsd/commands-bootstrap.ts +10 -0
  505. package/src/resources/extensions/gsd/commands-handlers.ts +21 -2
  506. package/src/resources/extensions/gsd/commands-mcp-status.ts +8 -0
  507. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +11 -3
  508. package/src/resources/extensions/gsd/commands-verdict.ts +202 -0
  509. package/src/resources/extensions/gsd/context-store.ts +120 -1
  510. package/src/resources/extensions/gsd/crash-recovery.ts +55 -6
  511. package/src/resources/extensions/gsd/db/auto-workers.ts +37 -0
  512. package/src/resources/extensions/gsd/db/milestone-leases.ts +26 -0
  513. package/src/resources/extensions/gsd/db/unit-dispatches.ts +4 -3
  514. package/src/resources/extensions/gsd/db-base-schema.ts +2 -0
  515. package/src/resources/extensions/gsd/db-migration-steps.ts +5 -0
  516. package/src/resources/extensions/gsd/db-task-slice-rows.ts +4 -0
  517. package/src/resources/extensions/gsd/db-writer.ts +167 -84
  518. package/src/resources/extensions/gsd/dispatch-guard.ts +60 -2
  519. package/src/resources/extensions/gsd/docs/preferences-reference.md +11 -1
  520. package/src/resources/extensions/gsd/doctor-git-checks.ts +89 -7
  521. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +25 -13
  522. package/src/resources/extensions/gsd/doctor-types.ts +3 -0
  523. package/src/resources/extensions/gsd/doctor.ts +2 -27
  524. package/src/resources/extensions/gsd/export-html.ts +27 -427
  525. package/src/resources/extensions/gsd/forensics.ts +9 -3
  526. package/src/resources/extensions/gsd/git-service.ts +182 -16
  527. package/src/resources/extensions/gsd/gsd-db.ts +80 -31
  528. package/src/resources/extensions/gsd/guided-flow-queue.ts +4 -3
  529. package/src/resources/extensions/gsd/guided-flow.ts +142 -134
  530. package/src/resources/extensions/gsd/guided-unit-context.ts +30 -0
  531. package/src/resources/extensions/gsd/init-wizard.ts +17 -2
  532. package/src/resources/extensions/gsd/journal.ts +8 -1
  533. package/src/resources/extensions/gsd/knowledge-backfill.ts +164 -0
  534. package/src/resources/extensions/gsd/knowledge-capture.ts +160 -0
  535. package/src/resources/extensions/gsd/knowledge-parser.ts +174 -0
  536. package/src/resources/extensions/gsd/knowledge-projection.ts +241 -0
  537. package/src/resources/extensions/gsd/markdown-renderer.ts +20 -12
  538. package/src/resources/extensions/gsd/mcp-filter.ts +80 -0
  539. package/src/resources/extensions/gsd/md-importer.ts +1 -1
  540. package/src/resources/extensions/gsd/memory-backfill.ts +89 -17
  541. package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +277 -0
  542. package/src/resources/extensions/gsd/migrate/command.ts +5 -0
  543. package/src/resources/extensions/gsd/migrate/parsers.ts +139 -2
  544. package/src/resources/extensions/gsd/migrate/preview.ts +10 -0
  545. package/src/resources/extensions/gsd/migrate/transformer.ts +58 -4
  546. package/src/resources/extensions/gsd/migrate/writer.ts +14 -1
  547. package/src/resources/extensions/gsd/migration-auto-check.ts +15 -23
  548. package/src/resources/extensions/gsd/milestone-actions.ts +10 -4
  549. package/src/resources/extensions/gsd/native-git-bridge.ts +63 -14
  550. package/src/resources/extensions/gsd/parallel-orchestrator.ts +3 -0
  551. package/src/resources/extensions/gsd/paths.ts +5 -0
  552. package/src/resources/extensions/gsd/pending-auto-start.ts +79 -0
  553. package/src/resources/extensions/gsd/planning-path-scope.ts +10 -2
  554. package/src/resources/extensions/gsd/post-execution-checks.ts +87 -12
  555. package/src/resources/extensions/gsd/pre-execution-checks.ts +67 -19
  556. package/src/resources/extensions/gsd/preferences-mcp.ts +27 -0
  557. package/src/resources/extensions/gsd/preferences-types.ts +35 -0
  558. package/src/resources/extensions/gsd/preferences-validation.ts +154 -0
  559. package/src/resources/extensions/gsd/preferences.ts +9 -0
  560. package/src/resources/extensions/gsd/prompt-loader.ts +1 -1
  561. package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  562. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  563. package/src/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
  564. package/src/resources/extensions/gsd/prompts/discuss.md +9 -9
  565. package/src/resources/extensions/gsd/prompts/forensics.md +3 -3
  566. package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
  567. package/src/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
  568. package/src/resources/extensions/gsd/prompts/plan-slice.md +4 -4
  569. package/src/resources/extensions/gsd/prompts/queue.md +4 -4
  570. package/src/resources/extensions/gsd/prompts/reactive-execute.md +1 -1
  571. package/src/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  572. package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  573. package/src/resources/extensions/gsd/prompts/system.md +2 -2
  574. package/src/resources/extensions/gsd/provider-switch-observer.ts +185 -0
  575. package/src/resources/extensions/gsd/queue-reorder-ui.ts +31 -13
  576. package/src/resources/extensions/gsd/repo-identity.ts +45 -25
  577. package/src/resources/extensions/gsd/repository-registry.ts +77 -0
  578. package/src/resources/extensions/gsd/safety/evidence-collector.ts +2 -0
  579. package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +54 -19
  580. package/src/resources/extensions/gsd/session-lock.ts +15 -2
  581. package/src/resources/extensions/gsd/slice-parallel-conflict.ts +2 -2
  582. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +75 -3
  583. package/src/resources/extensions/gsd/smart-entry-routing.ts +77 -0
  584. package/src/resources/extensions/gsd/state-reconciliation/drift/merge-state.ts +8 -1
  585. package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +12 -15
  586. package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +17 -25
  587. package/src/resources/extensions/gsd/state.ts +33 -7
  588. package/src/resources/extensions/gsd/status-guards.ts +16 -2
  589. package/src/resources/extensions/gsd/templates/PREFERENCES.md +1 -0
  590. package/src/resources/extensions/gsd/templates/knowledge.md +2 -2
  591. package/src/resources/extensions/gsd/templates/plan.md +9 -5
  592. package/src/resources/extensions/gsd/templates/task-plan.md +10 -2
  593. package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +1 -1
  594. package/src/resources/extensions/gsd/tests/auto-abort-pause-regression.test.ts +10 -1
  595. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +71 -0
  596. package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +116 -0
  597. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +875 -59
  598. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +637 -16
  599. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +151 -12
  600. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +53 -2
  601. package/src/resources/extensions/gsd/tests/auto-post-unit-step-message.test.ts +18 -6
  602. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +136 -13
  603. package/src/resources/extensions/gsd/tests/auto-remote-session-lock-cleanup.test.ts +64 -0
  604. package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +12 -0
  605. package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +4 -4
  606. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +1 -0
  607. package/src/resources/extensions/gsd/tests/auto-stop-notification.test.ts +20 -0
  608. package/src/resources/extensions/gsd/tests/auto-workers.test.ts +29 -0
  609. package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +69 -1
  610. package/src/resources/extensions/gsd/tests/autocomplete-regressions-1675.test.ts +21 -0
  611. package/src/resources/extensions/gsd/tests/brief-command.test.ts +89 -0
  612. package/src/resources/extensions/gsd/tests/browser-tools-compatibility-declarations.test.ts +62 -0
  613. package/src/resources/extensions/gsd/tests/checkout-branch-stash-guard.test.ts +87 -0
  614. package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +107 -2
  615. package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +32 -4
  616. package/src/resources/extensions/gsd/tests/closeout-git-deferral.test.ts +16 -0
  617. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +378 -0
  618. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +55 -2
  619. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +60 -9
  620. package/src/resources/extensions/gsd/tests/complete-task.test.ts +3 -1
  621. package/src/resources/extensions/gsd/tests/context-store-decisions-from-memories.test.ts +312 -0
  622. package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +104 -2
  623. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +2 -0
  624. package/src/resources/extensions/gsd/tests/db-authority-regression.test.ts +208 -0
  625. package/src/resources/extensions/gsd/tests/db-task-slice-rows.test.ts +1 -0
  626. package/src/resources/extensions/gsd/tests/db-writer.test.ts +13 -8
  627. package/src/resources/extensions/gsd/tests/decisions-projection-from-memories.test.ts +453 -0
  628. package/src/resources/extensions/gsd/tests/decisions-stop-table-writes.test.ts +348 -0
  629. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +61 -2
  630. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +111 -1
  631. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +68 -1
  632. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +140 -1
  633. package/src/resources/extensions/gsd/tests/doctor-empty-worktree.test.ts +65 -0
  634. package/src/resources/extensions/gsd/tests/doctor-forensics-db-open-regression.test.ts +50 -0
  635. package/src/resources/extensions/gsd/tests/evidence-cross-ref.test.ts +97 -0
  636. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +99 -1
  637. package/src/resources/extensions/gsd/tests/execution-entry-missing-context-4671.test.ts +15 -1
  638. package/src/resources/extensions/gsd/tests/export-html-enhancements.test.ts +8 -0
  639. package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +8 -4
  640. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +28 -0
  641. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +11 -7
  642. package/src/resources/extensions/gsd/tests/gsdroot-worktree-detection.test.ts +5 -2
  643. package/src/resources/extensions/gsd/tests/guided-discuss-project-prompt-rendering.test.ts +2 -0
  644. package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +106 -0
  645. package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +59 -11
  646. package/src/resources/extensions/gsd/tests/guided-flow.test.ts +21 -0
  647. package/src/resources/extensions/gsd/tests/guided-tool-contract.test.ts +65 -0
  648. package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +7 -7
  649. package/src/resources/extensions/gsd/tests/hook-model-resolution.test.ts +5 -0
  650. package/src/resources/extensions/gsd/tests/infra-error.test.ts +2 -2
  651. package/src/resources/extensions/gsd/tests/infra-errors-cooldown.test.ts +9 -0
  652. package/src/resources/extensions/gsd/tests/init-prefs-routing.test.ts +22 -0
  653. package/src/resources/extensions/gsd/tests/integration/doctor-git.test.ts +44 -0
  654. package/src/resources/extensions/gsd/tests/integration/doctor-runtime.test.ts +20 -0
  655. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +226 -2
  656. package/src/resources/extensions/gsd/tests/integration/integration-lifecycle.test.ts +13 -5
  657. package/src/resources/extensions/gsd/tests/integration/migrate-command.test.ts +48 -3
  658. package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +5 -21
  659. package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +15 -0
  660. package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +6 -1
  661. package/src/resources/extensions/gsd/tests/interrupted-session-auto.test.ts +40 -0
  662. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +49 -3
  663. package/src/resources/extensions/gsd/tests/journal.test.ts +32 -0
  664. package/src/resources/extensions/gsd/tests/knowledge-backfill-projection.test.ts +323 -0
  665. package/src/resources/extensions/gsd/tests/knowledge-capture.test.ts +242 -0
  666. package/src/resources/extensions/gsd/tests/knowledge.test.ts +47 -2
  667. package/src/resources/extensions/gsd/tests/load-knowledge-block-rules-only.test.ts +209 -0
  668. package/src/resources/extensions/gsd/tests/mcp-filter.test.ts +287 -0
  669. package/src/resources/extensions/gsd/tests/mcp-status.test.ts +11 -0
  670. package/src/resources/extensions/gsd/tests/memory-consolidation-scanner.test.ts +316 -0
  671. package/src/resources/extensions/gsd/tests/merge-db-cycle.test.ts +179 -0
  672. package/src/resources/extensions/gsd/tests/merge-self-branch-guard.test.ts +21 -40
  673. package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +5 -1
  674. package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +59 -1
  675. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +6 -1
  676. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +26 -18
  677. package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +80 -2
  678. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +121 -1
  679. package/src/resources/extensions/gsd/tests/parallel-orchestrator-zombie-cleanup.test.ts +55 -0
  680. package/src/resources/extensions/gsd/tests/park-db-sync.test.ts +55 -1
  681. package/src/resources/extensions/gsd/tests/pending-autostart-scope.test.ts +29 -5
  682. package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +2 -1
  683. package/src/resources/extensions/gsd/tests/plan-milestone-sketch-render.test.ts +157 -0
  684. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +26 -0
  685. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +2 -0
  686. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +343 -3
  687. package/src/resources/extensions/gsd/tests/plan-task.test.ts +18 -1
  688. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +79 -1
  689. package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +105 -3
  690. package/src/resources/extensions/gsd/tests/post-unit-git-failure.test.ts +8 -1
  691. package/src/resources/extensions/gsd/tests/post-unit-state-rebuild.test.ts +84 -0
  692. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +147 -0
  693. package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +54 -0
  694. package/src/resources/extensions/gsd/tests/preferences-mcp.test.ts +128 -0
  695. package/src/resources/extensions/gsd/tests/preferences.test.ts +75 -0
  696. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +79 -0
  697. package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +42 -1
  698. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +8 -0
  699. package/src/resources/extensions/gsd/tests/prompt-loader.test.ts +23 -0
  700. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +37 -1
  701. package/src/resources/extensions/gsd/tests/provider-switch-observer.test.ts +252 -0
  702. package/src/resources/extensions/gsd/tests/quality-gates.test.ts +6 -0
  703. package/src/resources/extensions/gsd/tests/queue-reorder-ui.test.ts +54 -0
  704. package/src/resources/extensions/gsd/tests/remediation-completion-guard.test.ts +89 -2
  705. package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +28 -1
  706. package/src/resources/extensions/gsd/tests/repository-registry.test.ts +52 -0
  707. package/src/resources/extensions/gsd/tests/run-uat-replay-cap.test.ts +2 -3
  708. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +35 -0
  709. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +16 -4
  710. package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +59 -1
  711. package/src/resources/extensions/gsd/tests/slice-parallel-conflict.test.ts +2 -2
  712. package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +112 -1
  713. package/src/resources/extensions/gsd/tests/smart-entry-routing.test.ts +113 -0
  714. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +94 -2
  715. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +6 -0
  716. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +119 -23
  717. package/src/resources/extensions/gsd/tests/status-guards.test.ts +17 -1
  718. package/src/resources/extensions/gsd/tests/stuck-state-via-db.test.ts +64 -1
  719. package/src/resources/extensions/gsd/tests/subagent-model-dispatch.test.ts +2 -1
  720. package/src/resources/extensions/gsd/tests/summary-render-parity.test.ts +7 -3
  721. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +1 -0
  722. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +131 -9
  723. package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +111 -1
  724. package/src/resources/extensions/gsd/tests/validate-milestone-stuck-guard.test.ts +29 -2
  725. package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +68 -0
  726. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +42 -1
  727. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +188 -1
  728. package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +78 -0
  729. package/src/resources/extensions/gsd/tests/workflow-kernel.test.ts +7 -0
  730. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +19 -1
  731. package/src/resources/extensions/gsd/tests/workflow-memory-pressure.test.ts +21 -1
  732. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +153 -1
  733. package/src/resources/extensions/gsd/tests/worktree-git-pathspec.test.ts +39 -0
  734. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +64 -12
  735. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +73 -2
  736. package/src/resources/extensions/gsd/tests/worktree-preferences-sync.test.ts +25 -0
  737. package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +90 -0
  738. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +95 -0
  739. package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +16 -0
  740. package/src/resources/extensions/gsd/tests/worktree-write-gate.test.ts +27 -0
  741. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +59 -0
  742. package/src/resources/extensions/gsd/tools/complete-milestone.ts +18 -10
  743. package/src/resources/extensions/gsd/tools/complete-slice.ts +57 -10
  744. package/src/resources/extensions/gsd/tools/exec-tool.ts +98 -5
  745. package/src/resources/extensions/gsd/tools/plan-milestone.ts +5 -1
  746. package/src/resources/extensions/gsd/tools/plan-slice.ts +172 -12
  747. package/src/resources/extensions/gsd/tools/validate-milestone.ts +31 -0
  748. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +166 -17
  749. package/src/resources/extensions/gsd/types.ts +1 -1
  750. package/src/resources/extensions/gsd/unit-context-composer.ts +3 -0
  751. package/src/resources/extensions/gsd/unit-context-manifest.ts +86 -19
  752. package/src/resources/extensions/gsd/validation.ts +23 -1
  753. package/src/resources/extensions/gsd/verification-gate.ts +170 -6
  754. package/src/resources/extensions/gsd/verification-verdict.ts +47 -0
  755. package/src/resources/extensions/gsd/workflow-logger.ts +4 -0
  756. package/src/resources/extensions/gsd/workflow-manifest.ts +2 -0
  757. package/src/resources/extensions/gsd/workflow-mcp.ts +18 -1
  758. package/src/resources/extensions/gsd/workflow-projections.ts +6 -8
  759. package/src/resources/extensions/gsd/worktree-lifecycle.ts +98 -20
  760. package/src/resources/extensions/gsd/worktree-manager.ts +14 -2
  761. package/src/resources/extensions/gsd/worktree-safety.ts +57 -10
  762. package/src/resources/extensions/gsd/worktree-state-projection.ts +43 -0
  763. package/src/resources/extensions/gsd/worktree-telemetry.ts +39 -0
  764. package/src/resources/extensions/shared/html-shell.ts +412 -0
  765. package/src/resources/extensions/shared/interview-ui.ts +6 -4
  766. package/src/resources/extensions/shared/next-action-ui.ts +11 -5
  767. package/src/resources/extensions/shared/tests/interview-notes-loop.test.ts +15 -0
  768. package/src/resources/extensions/shared/tests/next-action-ui-hasui.test.ts +32 -0
  769. package/src/resources/extensions/subagent/index.ts +567 -103
  770. package/src/resources/extensions/subagent/launch.ts +131 -0
  771. package/src/resources/extensions/subagent/run-store.ts +218 -0
  772. package/src/resources/extensions/subagent/tests/launch.test.ts +115 -0
  773. package/src/resources/extensions/subagent/tests/run-store.test.ts +111 -0
  774. package/src/resources/extensions/ttsr/ttsr-manager.ts +5 -1
  775. package/src/resources/extensions/visual-brief/artifact-policy.ts +41 -0
  776. package/src/resources/extensions/visual-brief/extension-manifest.json +8 -0
  777. package/src/resources/extensions/visual-brief/index.ts +8 -0
  778. package/src/resources/extensions/visual-brief/page-contract.ts +136 -0
  779. package/src/resources/extensions/visual-brief/prompts.ts +183 -0
  780. package/src/resources/extensions/visual-brief/tests/visual-brief.test.ts +212 -0
  781. package/src/resources/skills/forensics/SKILL.md +1 -1
  782. package/dist/web/standalone/.next/server/chunks/5822.js +0 -2
  783. package/dist/web/standalone/.next/static/chunks/2556.0527fea66e123b7f.js +0 -1
  784. package/dist/web/standalone/.next/static/chunks/8359.e059d86b255fce1c.js +0 -10
  785. package/dist/web/standalone/.next/static/chunks/9441.1081da1125d1764f.js +0 -1
  786. package/dist/web/standalone/.next/static/chunks/app/layout-9ecfd95f343793f0.js +0 -1
  787. package/dist/web/standalone/.next/static/chunks/app/page-200592a7f3baf579.js +0 -1
  788. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  789. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  790. package/dist/web/standalone/.next/static/css/54ec2745c1da488b.css +0 -1
  791. package/dist/web/standalone/.next/static/css/de70bee13400563f.css +0 -1
  792. package/dist/web/standalone/.next/static/media/4cf2300e9c8272f7-s.p.woff2 +0 -0
  793. package/dist/web/standalone/.next/static/media/747892c23ea88013-s.woff2 +0 -0
  794. package/dist/web/standalone/.next/static/media/8d697b304b401681-s.woff2 +0 -0
  795. package/dist/web/standalone/.next/static/media/93f479601ee12b01-s.p.woff2 +0 -0
  796. package/dist/web/standalone/.next/static/media/9610d9e46709d722-s.woff2 +0 -0
  797. package/dist/web/standalone/.next/static/media/ba015fad6dcf6784-s.woff2 +0 -0
  798. /package/dist/web/standalone/.next/static/{S44UQTFCUdA44dkjfYt6S → Z8H5evS-hDo0qdP22XJPA}/_buildManifest.js +0 -0
  799. /package/dist/web/standalone/.next/static/{S44UQTFCUdA44dkjfYt6S → Z8H5evS-hDo0qdP22XJPA}/_ssgManifest.js +0 -0
@@ -0,0 +1,185 @@
1
+ // GSD-2 — ADR-005 Phase 3b: surface ProviderSwitchReport from pi-ai.
2
+ //
3
+ // pi-ai builds a ProviderSwitchReport on every cross-provider transform but
4
+ // only logs it to stderr when GSD_VERBOSE=1. This module installs a
5
+ // single-subscriber observer that surfaces non-empty reports through GSD's
6
+ // three usual telemetry surfaces:
7
+ //
8
+ // 1. UOK audit event (category model-policy, type provider-switch) — only
9
+ // when an auto trace is active.
10
+ // 2. Persistent notification (.gsd/notifications.jsonl, severity warning) —
11
+ // whenever the GSD basePath is known, so users see the loss in the
12
+ // dashboard / status surface without GSD_VERBOSE.
13
+ // 3. In-memory counter, exposed via getProviderSwitchStats() so any
14
+ // caller (dashboard, doctor, tests) can read the rollup.
15
+
16
+ import { setProviderSwitchObserver, type ProviderSwitchReport } from "@gsd/pi-ai";
17
+
18
+ import { autoSession } from "./auto-runtime-state.js";
19
+ import { appendNotification } from "./notification-store.js";
20
+ import { buildAuditEnvelope, emitUokAuditEvent } from "./uok/audit.js";
21
+
22
+ /** Rollup of cross-provider context transformations, grouped by trace. */
23
+ export interface ProviderSwitchStats {
24
+ /** Total non-empty reports observed since process start (or last reset). */
25
+ totalSwitches: number;
26
+ /** Sum of every counted transformation across all reports. */
27
+ totals: {
28
+ thinkingBlocksDropped: number;
29
+ thinkingBlocksDowngraded: number;
30
+ toolCallIdsRemapped: number;
31
+ syntheticToolResultsInserted: number;
32
+ thoughtSignaturesDropped: number;
33
+ };
34
+ /** Per-trace breakdown. Key "interactive" covers reports outside auto-mode. */
35
+ byTrace: Record<string, TraceSwitchStats>;
36
+ /** The most recent non-empty report, if any. */
37
+ lastReport: ProviderSwitchReport | null;
38
+ /** ISO timestamp of the most recent non-empty report, if any. */
39
+ lastAt: string | null;
40
+ }
41
+
42
+ export interface TraceSwitchStats {
43
+ switches: number;
44
+ lastReport: ProviderSwitchReport;
45
+ lastAt: string;
46
+ }
47
+
48
+ const INTERACTIVE_TRACE_KEY = "interactive";
49
+
50
+ interface MutableTraceStats {
51
+ switches: number;
52
+ lastReport: ProviderSwitchReport;
53
+ lastAt: string;
54
+ }
55
+
56
+ let installed = false;
57
+ let totalSwitches = 0;
58
+ const totals = {
59
+ thinkingBlocksDropped: 0,
60
+ thinkingBlocksDowngraded: 0,
61
+ toolCallIdsRemapped: 0,
62
+ syntheticToolResultsInserted: 0,
63
+ thoughtSignaturesDropped: 0,
64
+ };
65
+ const byTrace = new Map<string, MutableTraceStats>();
66
+ let lastReport: ProviderSwitchReport | null = null;
67
+ let lastAt: string | null = null;
68
+
69
+ /** Format a one-line summary suitable for a notification message. */
70
+ function summarize(report: ProviderSwitchReport): string {
71
+ const parts: string[] = [];
72
+ if (report.thinkingBlocksDropped > 0) parts.push(`${report.thinkingBlocksDropped} thinking dropped`);
73
+ if (report.thinkingBlocksDowngraded > 0) parts.push(`${report.thinkingBlocksDowngraded} thinking downgraded`);
74
+ if (report.toolCallIdsRemapped > 0) parts.push(`${report.toolCallIdsRemapped} tool ids remapped`);
75
+ if (report.syntheticToolResultsInserted > 0) parts.push(`${report.syntheticToolResultsInserted} synthetic tool results`);
76
+ if (report.thoughtSignaturesDropped > 0) parts.push(`${report.thoughtSignaturesDropped} thought signatures dropped`);
77
+ return `Provider switch ${report.fromApi} → ${report.toApi}: ${parts.join(", ")}`;
78
+ }
79
+
80
+ function recordReport(report: ProviderSwitchReport): void {
81
+ const now = new Date().toISOString();
82
+ totalSwitches += 1;
83
+ totals.thinkingBlocksDropped += report.thinkingBlocksDropped;
84
+ totals.thinkingBlocksDowngraded += report.thinkingBlocksDowngraded;
85
+ totals.toolCallIdsRemapped += report.toolCallIdsRemapped;
86
+ totals.syntheticToolResultsInserted += report.syntheticToolResultsInserted;
87
+ totals.thoughtSignaturesDropped += report.thoughtSignaturesDropped;
88
+ lastReport = report;
89
+ lastAt = now;
90
+
91
+ const traceKey = autoSession.currentTraceId ?? INTERACTIVE_TRACE_KEY;
92
+ const existing = byTrace.get(traceKey);
93
+ if (existing) {
94
+ existing.switches += 1;
95
+ existing.lastReport = report;
96
+ existing.lastAt = now;
97
+ } else {
98
+ byTrace.set(traceKey, { switches: 1, lastReport: report, lastAt: now });
99
+ }
100
+ }
101
+
102
+ function emitAudit(report: ProviderSwitchReport): void {
103
+ const traceId = autoSession.currentTraceId;
104
+ const basePath = autoSession.basePath;
105
+ if (!traceId || !basePath) return;
106
+ try {
107
+ emitUokAuditEvent(
108
+ basePath,
109
+ buildAuditEnvelope({
110
+ traceId,
111
+ category: "model-policy",
112
+ type: "provider-switch",
113
+ payload: {
114
+ fromApi: report.fromApi,
115
+ toApi: report.toApi,
116
+ thinkingBlocksDropped: report.thinkingBlocksDropped,
117
+ thinkingBlocksDowngraded: report.thinkingBlocksDowngraded,
118
+ toolCallIdsRemapped: report.toolCallIdsRemapped,
119
+ syntheticToolResultsInserted: report.syntheticToolResultsInserted,
120
+ thoughtSignaturesDropped: report.thoughtSignaturesDropped,
121
+ },
122
+ }),
123
+ );
124
+ } catch {
125
+ // Audit emission is best-effort. Counter + notification still fire.
126
+ }
127
+ }
128
+
129
+ function emitNotification(report: ProviderSwitchReport): void {
130
+ try {
131
+ appendNotification(summarize(report), "warning", "workflow-logger");
132
+ } catch {
133
+ // Notification persistence is best-effort.
134
+ }
135
+ }
136
+
137
+ function handleReport(report: ProviderSwitchReport): void {
138
+ recordReport(report);
139
+ emitAudit(report);
140
+ emitNotification(report);
141
+ }
142
+
143
+ /**
144
+ * Install the pi-ai observer. Idempotent — calling more than once is a no-op
145
+ * after the first install.
146
+ */
147
+ export function installProviderSwitchObserver(): void {
148
+ if (installed) return;
149
+ setProviderSwitchObserver(handleReport);
150
+ installed = true;
151
+ }
152
+
153
+ /** Uninstall the observer. Intended for tests. */
154
+ export function uninstallProviderSwitchObserver(): void {
155
+ setProviderSwitchObserver(undefined);
156
+ installed = false;
157
+ }
158
+
159
+ /** Read-only snapshot of the in-memory rollup. */
160
+ export function getProviderSwitchStats(): ProviderSwitchStats {
161
+ const trace: Record<string, TraceSwitchStats> = {};
162
+ for (const [key, value] of byTrace) {
163
+ trace[key] = { switches: value.switches, lastReport: { ...value.lastReport }, lastAt: value.lastAt };
164
+ }
165
+ return {
166
+ totalSwitches,
167
+ totals: { ...totals },
168
+ byTrace: trace,
169
+ lastReport: lastReport ? { ...lastReport } : null,
170
+ lastAt,
171
+ };
172
+ }
173
+
174
+ /** Reset the in-memory rollup. Intended for tests. */
175
+ export function _resetProviderSwitchStats(): void {
176
+ totalSwitches = 0;
177
+ totals.thinkingBlocksDropped = 0;
178
+ totals.thinkingBlocksDowngraded = 0;
179
+ totals.toolCallIdsRemapped = 0;
180
+ totals.syntheticToolResultsInserted = 0;
181
+ totals.thoughtSignaturesDropped = 0;
182
+ byTrace.clear();
183
+ lastReport = null;
184
+ lastAt = null;
185
+ }
@@ -43,6 +43,7 @@ export async function showQueueReorder(
43
43
  const items = [...pending];
44
44
  let cursor = 0;
45
45
  let grabbed = false;
46
+ let scrollOffset = 0;
46
47
  let cachedLines: string[] | undefined;
47
48
  let validation: DependencyValidation;
48
49
 
@@ -154,8 +155,10 @@ export async function showQueueReorder(
154
155
 
155
156
  const ui = makeUI(theme, width);
156
157
  const lines: string[] = [];
158
+ const queueRows: string[] = [];
157
159
  const push = (...rows: string[][]) => { for (const r of rows) lines.push(...r); };
158
160
  const add = (s: string) => truncateToWidth(s, width);
161
+ let cursorQueueRow = 0;
159
162
 
160
163
  const headerText = grabbed ? " Queue Reorder — Moving Item" : " Queue Reorder";
161
164
  push(ui.bar(), ui.blank(), ui.header(headerText), ui.blank());
@@ -188,11 +191,13 @@ export async function showQueueReorder(
188
191
  const label = item.title && item.title !== item.id ? `${item.id} ${item.title}` : item.id;
189
192
 
190
193
  if (isCursor && grabbed) {
191
- lines.push(add(` ${theme.fg("warning", `▸▸ ${num}. ${label}`)}`));
194
+ cursorQueueRow = queueRows.length;
195
+ queueRows.push(add(` ${theme.fg("warning", `▸▸ ${num}. ${label}`)}`));
192
196
  } else if (isCursor) {
193
- lines.push(add(` ${theme.fg("accent", `${GLYPH.cursor} ${num}. ${label}`)}`));
197
+ cursorQueueRow = queueRows.length;
198
+ queueRows.push(add(` ${theme.fg("accent", `${GLYPH.cursor} ${num}. ${label}`)}`));
194
199
  } else {
195
- lines.push(add(` ${theme.fg("text", `${num}. ${label}`)}`));
200
+ queueRows.push(add(` ${theme.fg("text", `${num}. ${label}`)}`));
196
201
  }
197
202
 
198
203
  // depends_on annotations
@@ -201,36 +206,37 @@ export async function showQueueReorder(
201
206
  if (completedIds.has(dep)) continue;
202
207
  const pairKey = `${item.id}:${dep}`;
203
208
  if (violatedPairs.has(pairKey)) {
204
- lines.push(add(` ${theme.fg("warning", `${GLYPH.statusWarning} depends_on: ${dep} — auto-removed on confirm`)}`));
209
+ queueRows.push(add(` ${theme.fg("warning", `${GLYPH.statusWarning} depends_on: ${dep} — auto-removed on confirm`)}`));
205
210
  } else if (redundantPairs.has(pairKey)) {
206
- lines.push(add(` ${theme.fg("dim", `↳ depends_on: ${dep} (redundant)`)}`));
211
+ queueRows.push(add(` ${theme.fg("dim", `↳ depends_on: ${dep} (redundant)`)}`));
207
212
  } else {
208
- lines.push(add(` ${theme.fg("dim", `↳ depends_on: ${dep}`)}`));
213
+ queueRows.push(add(` ${theme.fg("dim", `↳ depends_on: ${dep}`)}`));
209
214
  }
210
215
  }
211
216
 
212
217
  // Missing deps
213
218
  for (const v of validation.violations.filter(v => v.milestone === item.id && v.type === 'missing_dep')) {
214
- lines.push(add(` ${theme.fg("error", `${GLYPH.statusWarning} depends_on: ${v.dependsOn} (does not exist)`)}`));
219
+ queueRows.push(add(` ${theme.fg("error", `${GLYPH.statusWarning} depends_on: ${v.dependsOn} (does not exist)`)}`));
215
220
  }
216
221
  }
217
222
 
218
223
  // Removed deps feedback
224
+ const trailingLines: string[] = [];
219
225
  if (removedDeps.length > 0) {
220
- push(ui.blank());
226
+ trailingLines.push(...ui.blank());
221
227
  for (const r of removedDeps) {
222
- lines.push(add(` ${theme.fg("success", `${GLYPH.statusDone} Removed: ${r.milestone} depends_on ${r.dep}`)}`));
228
+ trailingLines.push(add(` ${theme.fg("success", `${GLYPH.statusDone} Removed: ${r.milestone} depends_on ${r.dep}`)}`));
223
229
  }
224
230
  }
225
231
 
226
232
  // Circular warning
227
233
  const circ = validation.violations.find(v => v.type === 'circular');
228
234
  if (circ) {
229
- push(ui.blank());
230
- lines.push(add(` ${theme.fg("error", `${GLYPH.statusWarning} ${circ.message}`)}`));
235
+ trailingLines.push(...ui.blank());
236
+ trailingLines.push(add(` ${theme.fg("error", `${GLYPH.statusWarning} ${circ.message}`)}`));
231
237
  }
232
238
 
233
- push(ui.blank());
239
+ trailingLines.push(...ui.blank());
234
240
 
235
241
  // Hints — context-sensitive based on grab state
236
242
  const hints: string[] = [];
@@ -250,7 +256,19 @@ export async function showQueueReorder(
250
256
  }
251
257
  hints.push("esc");
252
258
 
253
- push(ui.hints(hints), ui.bar());
259
+ trailingLines.push(...ui.hints(hints), ...ui.bar());
260
+
261
+ const maxOverlayRows = Math.max(10, process.stdout.rows ? Math.floor(process.stdout.rows * 0.8) : 24);
262
+ const availableQueueRows = Math.max(1, maxOverlayRows - lines.length - trailingLines.length);
263
+ const maxScroll = Math.max(0, queueRows.length - availableQueueRows);
264
+ if (cursorQueueRow < scrollOffset) {
265
+ scrollOffset = cursorQueueRow;
266
+ } else if (cursorQueueRow >= scrollOffset + availableQueueRows) {
267
+ scrollOffset = cursorQueueRow - availableQueueRows + 1;
268
+ }
269
+ scrollOffset = Math.min(Math.max(scrollOffset, 0), maxScroll);
270
+
271
+ lines.push(...queueRows.slice(scrollOffset, scrollOffset + availableQueueRows), ...trailingLines);
254
272
 
255
273
  cachedLines = lines;
256
274
  return lines;
@@ -427,22 +427,38 @@ function hasProjectState(externalPath: string): boolean {
427
427
  *
428
428
  * Returns the resolved external path (may differ from the computed identity).
429
429
  */
430
- function resolveExternalPathWithRecovery(projectPath: string): string {
431
- const computedPath = externalGsdRoot(projectPath);
430
+ function resolveExternalPathWithRecovery(projectPath: string): { path: string; identity: string } {
431
+ const base = process.env.GSD_STATE_DIR || gsdHome();
432
432
  const computedId = repoIdentity(projectPath);
433
+ const computedPath = join(base, "projects", computedId);
434
+ const computedHasState = hasProjectState(computedPath);
435
+ const markerId = readGsdIdMarker(projectPath);
436
+ const markerPath = markerId ? join(base, "projects", markerId) : null;
437
+ const markerHasState = markerPath ? hasProjectState(markerPath) : false;
438
+
439
+ // Split-brain guard: when marker and computed identities disagree and both
440
+ // directories contain state, prefer the marker-backed directory. This keeps
441
+ // all writers anchored to a single canonical project identity even if a
442
+ // transient identity computation produced a stale computed hash.
443
+ if (
444
+ markerId
445
+ && markerPath
446
+ && markerId !== computedId
447
+ && markerHasState
448
+ && computedHasState
449
+ ) {
450
+ return { path: markerPath, identity: markerId };
451
+ }
433
452
 
434
453
  // Check if computed path already has state — fast path, no recovery needed.
435
- if (hasProjectState(computedPath)) {
436
- return computedPath;
454
+ if (computedHasState) {
455
+ return { path: computedPath, identity: computedId };
437
456
  }
438
457
 
439
458
  // Check for .gsd-id marker from a previous location.
440
- const markerId = readGsdIdMarker(projectPath);
441
- if (markerId && markerId !== computedId) {
459
+ if (markerId && markerPath && markerId !== computedId) {
442
460
  // The marker points to a different identity — the repo was likely moved.
443
- const base = process.env.GSD_STATE_DIR || gsdHome();
444
- const markerPath = join(base, "projects", markerId);
445
- if (hasProjectState(markerPath)) {
461
+ if (markerHasState) {
446
462
  // Recover: use the old state directory and update the marker to the new identity.
447
463
  // Move the state from the old hash dir to the new one so future lookups work
448
464
  // without the marker.
@@ -465,12 +481,12 @@ function resolveExternalPathWithRecovery(projectPath: string): string {
465
481
  try { rmSync(markerPath, { recursive: true, force: true }); } catch { /* non-fatal */ }
466
482
  } catch {
467
483
  // If migration fails, just point at the old directory.
468
- return markerPath;
484
+ return { path: markerPath, identity: markerId };
469
485
  }
470
486
  }
471
487
  }
472
488
 
473
- return computedPath;
489
+ return { path: computedPath, identity: computedId };
474
490
  }
475
491
 
476
492
  // ─── Symlink Management ─────────────────────────────────────────────────────
@@ -489,20 +505,21 @@ function resolveExternalPathWithRecovery(projectPath: string): string {
489
505
  * Returns the resolved external path.
490
506
  */
491
507
  export function ensureGsdSymlink(projectPath: string): string {
492
- const result = ensureGsdSymlinkCore(projectPath);
508
+ const { path: result, identity } = ensureGsdSymlinkCore(projectPath);
493
509
 
494
510
  // Write .gsd-id marker so future relocations can recover this state (#2750).
495
511
  // Only write for the project root (not subdirectories or worktrees that
496
512
  // delegate to a parent .gsd).
497
513
  if (!isInsideWorktree(projectPath)) {
498
- writeGsdIdMarker(projectPath, repoIdentity(projectPath));
514
+ writeGsdIdMarker(projectPath, identity);
499
515
  }
500
516
 
501
517
  return result;
502
518
  }
503
519
 
504
- function ensureGsdSymlinkCore(projectPath: string): string {
505
- const externalPath = resolveExternalPathWithRecovery(projectPath);
520
+ function ensureGsdSymlinkCore(projectPath: string): { path: string; identity: string } {
521
+ const resolved = resolveExternalPathWithRecovery(projectPath);
522
+ const externalPath = resolved.path;
506
523
  const localGsd = join(projectPath, ".gsd");
507
524
  const inWorktree = isInsideWorktree(projectPath);
508
525
 
@@ -519,7 +536,7 @@ function ensureGsdSymlinkCore(projectPath: string): string {
519
536
  const localGsdNormalized = normalizeForGuard(localGsd);
520
537
  const gsdHomeNorm = normalizeForGuard(gsdHome());
521
538
  if (localGsdNormalized === gsdHomeNorm) {
522
- return localGsd;
539
+ return { path: localGsd, identity: resolved.identity };
523
540
  }
524
541
 
525
542
  // Guard: If projectPath is a plain subdirectory (not a worktree) of a git
@@ -538,7 +555,10 @@ function ensureGsdSymlinkCore(projectPath: string): string {
538
555
  try {
539
556
  const rootStat = lstatSync(rootGsd);
540
557
  if (rootStat.isSymbolicLink() || rootStat.isDirectory()) {
541
- return rootStat.isSymbolicLink() ? realpathSync(rootGsd) : rootGsd;
558
+ return {
559
+ path: rootStat.isSymbolicLink() ? realpathSync(rootGsd) : rootGsd,
560
+ identity: resolved.identity,
561
+ };
542
562
  }
543
563
  } catch {
544
564
  // Fall through to normal logic if we can't stat root .gsd
@@ -560,12 +580,12 @@ function ensureGsdSymlinkCore(projectPath: string): string {
560
580
  // Write repo metadata once so cleanup commands can identify this directory later.
561
581
  writeRepoMeta(externalPath, getRemoteUrl(projectPath), resolveGitRoot(projectPath));
562
582
 
563
- const replaceWithSymlink = (): string => {
583
+ const replaceWithSymlink = (): { path: string; identity: string } => {
564
584
  rmSync(localGsd, { recursive: true, force: true });
565
585
  // Defensive: remove any residual entry (e.g. dangling symlink) before creating.
566
586
  try { unlinkSync(localGsd); } catch { /* already gone */ }
567
587
  symlinkSync(externalPath, localGsd, "junction");
568
- return externalPath;
588
+ return resolved;
569
589
  };
570
590
 
571
591
  // Check for dangling symlinks (e.g. after relocation recovery removed the old
@@ -585,7 +605,7 @@ function ensureGsdSymlinkCore(projectPath: string): string {
585
605
  // Defensive: remove any residual entry to avoid EEXIST race (#2750).
586
606
  try { unlinkSync(localGsd); } catch { /* nothing to remove */ }
587
607
  symlinkSync(externalPath, localGsd, "junction");
588
- return externalPath;
608
+ return resolved;
589
609
  }
590
610
 
591
611
  try {
@@ -595,7 +615,7 @@ function ensureGsdSymlinkCore(projectPath: string): string {
595
615
  // Already a symlink — verify it points to the right place
596
616
  const target = realpathSync(localGsd);
597
617
  if (target === externalPath) {
598
- return externalPath; // correct symlink, no-op
618
+ return resolved; // correct symlink, no-op
599
619
  }
600
620
  // In a worktree, mismatched symlinks are always stale. Heal them so
601
621
  // the worktree points at the same external state dir as the main repo.
@@ -620,11 +640,11 @@ function ensureGsdSymlinkCore(projectPath: string): string {
620
640
  return replaceWithSymlink();
621
641
  } catch {
622
642
  // Migration failed — preserve old symlink
623
- return target;
643
+ return { path: target, identity: resolved.identity };
624
644
  }
625
645
  }
626
646
  // Outside worktrees, preserve custom overrides or legacy symlinks.
627
- return target;
647
+ return { path: target, identity: resolved.identity };
628
648
  }
629
649
 
630
650
  if (stat.isDirectory()) {
@@ -632,13 +652,13 @@ function ensureGsdSymlinkCore(projectPath: string): string {
632
652
  // In worktrees, keep the directory in place and let syncGsdStateToWorktree
633
653
  // refresh its contents. Replacing a git-tracked .gsd directory with a
634
654
  // symlink makes git think tracked planning files were deleted.
635
- return localGsd;
655
+ return { path: localGsd, identity: resolved.identity };
636
656
  }
637
657
  } catch {
638
658
  // lstat failed — path exists but we can't stat it
639
659
  }
640
660
 
641
- return localGsd;
661
+ return { path: localGsd, identity: resolved.identity };
642
662
  }
643
663
 
644
664
  // ─── Worktree Detection ─────────────────────────────────────────────────────
@@ -0,0 +1,77 @@
1
+ // GSD-2 + Repository registry seam for parent workspace multi-repo resolution.
2
+
3
+ import { isAbsolute, relative, resolve } from "node:path";
4
+ import type { GSDPreferences, WorkspacePreferences, WorkspaceRepositoryPreference } from "./preferences-types.js";
5
+ import { resolveGsdPathContract } from "./paths.js";
6
+
7
+ export interface RegisteredRepository {
8
+ id: string;
9
+ root: string;
10
+ role?: string;
11
+ verification?: string[];
12
+ commitPolicy?: "auto" | "skip";
13
+ }
14
+
15
+ export interface RepositoryRegistry {
16
+ projectRoot: string;
17
+ mode: "project" | "parent";
18
+ repositories: RegisteredRepository[];
19
+ byId: ReadonlyMap<string, RegisteredRepository>;
20
+ }
21
+
22
+ function assertInsideProjectRoot(projectRoot: string, candidateRoot: string, repoId: string): void {
23
+ const rel = relative(projectRoot, candidateRoot);
24
+ if (rel === "") return;
25
+ if (rel.startsWith("..") || isAbsolute(rel)) {
26
+ throw new Error(`workspace.repositories.${repoId}.path resolves outside project root: ${candidateRoot}`);
27
+ }
28
+ }
29
+
30
+ function resolveRepositoryRoot(
31
+ projectRoot: string,
32
+ repoId: string,
33
+ repo: WorkspaceRepositoryPreference,
34
+ ): RegisteredRepository {
35
+ const root = resolve(projectRoot, repo.path);
36
+ assertInsideProjectRoot(projectRoot, root, repoId);
37
+ return {
38
+ id: repoId,
39
+ root,
40
+ role: repo.role,
41
+ verification: repo.verification,
42
+ commitPolicy: repo.commit_policy,
43
+ };
44
+ }
45
+
46
+ export function createRepositoryRegistry(
47
+ basePath: string,
48
+ workspacePrefs?: WorkspacePreferences,
49
+ ): RepositoryRegistry {
50
+ const contract = resolveGsdPathContract(basePath);
51
+ const projectRoot = contract.projectRoot;
52
+ const mode = workspacePrefs?.mode ?? "project";
53
+ const repoMap = new Map<string, RegisteredRepository>();
54
+
55
+ // Backward-compatible default for single-repo projects.
56
+ // Explicit workspacePrefs?.repositories entries can override "project"
57
+ // via resolveRepositoryRoot to customize role/verification/commit policy.
58
+ repoMap.set("project", { id: "project", root: projectRoot });
59
+
60
+ for (const [repoId, repoConfig] of Object.entries(workspacePrefs?.repositories ?? {})) {
61
+ repoMap.set(repoId, resolveRepositoryRoot(projectRoot, repoId, repoConfig));
62
+ }
63
+
64
+ return {
65
+ projectRoot,
66
+ mode,
67
+ repositories: Array.from(repoMap.values()),
68
+ byId: repoMap,
69
+ };
70
+ }
71
+
72
+ export function createRepositoryRegistryFromPreferences(
73
+ basePath: string,
74
+ preferences?: Pick<GSDPreferences, "workspace">,
75
+ ): RepositoryRegistry {
76
+ return createRepositoryRegistry(basePath, preferences?.workspace);
77
+ }
@@ -53,6 +53,8 @@ export type EvidenceEntry = BashEvidence | FileWriteEvidence | FileEditEvidence;
53
53
  const EXECUTION_TOOL_NAMES = new Set([
54
54
  "bash",
55
55
  "Bash",
56
+ "PowerShell",
57
+ "async_bash",
56
58
  "gsd_exec",
57
59
  "gsd_exec_search",
58
60
  "mcp__gsd-workflow__gsd_exec",
@@ -1,3 +1,4 @@
1
+
1
2
  /**
2
3
  * Evidence cross-reference for auto-mode safety harness.
3
4
  * Compares the LLM's claimed verification evidence (command + exitCode)
@@ -14,6 +15,7 @@ export interface ClaimedEvidence {
14
15
  command: string;
15
16
  exitCode: number;
16
17
  verdict: string;
18
+ createdAt?: string;
17
19
  }
18
20
 
19
21
  export interface EvidenceMismatch {
@@ -40,7 +42,7 @@ export function crossReferenceEvidence(
40
42
  );
41
43
  const mismatches: EvidenceMismatch[] = [];
42
44
 
43
- for (const claimed of claimedEvidence) {
45
+ for (const claimed of latestClaimBatch(claimedEvidence)) {
44
46
  // Skip coerced entries — they're already flagged with exitCode: -1
45
47
  // and verdict: "unknown (coerced from string)" by db-tools.ts
46
48
  if (claimed.verdict?.includes("coerced from string")) continue;
@@ -49,10 +51,12 @@ export function crossReferenceEvidence(
49
51
  // Skip entries with empty or generic commands
50
52
  if (!claimed.command || claimed.command.length < 3) continue;
51
53
 
52
- // Find matching bash call by command substring match
53
- const match = findBestMatch(claimed.command, bashCalls);
54
+ // Find matching bash calls by command similarity. A command may be retried
55
+ // after a failed first run; the newest matching execution is the one that
56
+ // supports or rejects a claimed pass.
57
+ const matches = findMatches(claimed.command, bashCalls);
54
58
 
55
- if (!match) {
59
+ if (matches.length === 0) {
56
60
  mismatches.push({
57
61
  severity: "warning",
58
62
  claimed,
@@ -63,6 +67,7 @@ export function crossReferenceEvidence(
63
67
  }
64
68
 
65
69
  // Exit code mismatch: LLM claims success but actual command failed
70
+ const match = latestMatch(matches);
66
71
  if (claimed.exitCode === 0 && match.exitCode !== 0) {
67
72
  mismatches.push({
68
73
  severity: "error",
@@ -79,42 +84,72 @@ export function crossReferenceEvidence(
79
84
  // ─── Internals ──────────────────────────────────────────────────────────────
80
85
 
81
86
  /**
82
- * Find the best matching bash evidence entry for a claimed command.
87
+ * Verification evidence rows are append-only across retries, but a task
88
+ * completion inserts one batch at a single created_at timestamp. When that
89
+ * timestamp is present, safety should judge the newest completion claim only.
90
+ */
91
+ function latestClaimBatch(
92
+ claimedEvidence: readonly ClaimedEvidence[],
93
+ ): readonly ClaimedEvidence[] {
94
+ const dated = claimedEvidence
95
+ .map((claim) => ({
96
+ claim,
97
+ time: typeof claim.createdAt === "string" ? Date.parse(claim.createdAt) : Number.NaN,
98
+ }))
99
+ .filter((entry) => Number.isFinite(entry.time));
100
+
101
+ if (dated.length === 0) return claimedEvidence;
102
+
103
+ const latestTime = Math.max(...dated.map((entry) => entry.time));
104
+ return claimedEvidence.filter((claim) => (
105
+ typeof claim.createdAt === "string" && Date.parse(claim.createdAt) === latestTime
106
+ ));
107
+ }
108
+
109
+ /**
110
+ * Find bash evidence entries matching a claimed command.
83
111
  * Uses substring matching — the claimed command may be a shortened version
84
112
  * of the actual command, or vice versa.
85
113
  */
86
- function findBestMatch(
114
+ function findMatches(
87
115
  claimedCommand: string,
88
116
  bashCalls: readonly BashEvidence[],
89
- ): BashEvidence | null {
117
+ ): BashEvidence[] {
90
118
  const normalized = claimedCommand.trim();
91
119
 
92
- // Exact match first
93
- const exact = bashCalls.find(b => b.command.trim() === normalized);
94
- if (exact) return exact;
120
+ // Exact matches first
121
+ const exact = bashCalls.filter(b => b.command.trim() === normalized);
122
+ if (exact.length > 0) return exact;
95
123
 
96
124
  // Substring match: claimed is contained in actual or actual in claimed
97
- const substring = bashCalls.find(
125
+ const substring = bashCalls.filter(
98
126
  b => b.command.includes(normalized) || normalized.includes(b.command),
99
127
  );
100
- if (substring) return substring;
128
+ if (substring.length > 0) return substring;
101
129
 
102
130
  // Token match: split on whitespace and check significant overlap
103
131
  const claimedTokens = normalized.split(/\s+/).filter(t => t.length > 2);
104
- if (claimedTokens.length === 0) return null;
132
+ if (claimedTokens.length === 0) return [];
105
133
 
106
- let bestMatch: BashEvidence | null = null;
107
- let bestScore = 0;
134
+ const scoredMatches: Array<{ call: BashEvidence; score: number }> = [];
108
135
 
109
136
  for (const call of bashCalls) {
110
137
  const callTokens = new Set(call.command.split(/\s+/));
111
138
  const matchCount = claimedTokens.filter(t => callTokens.has(t)).length;
112
139
  const score = matchCount / claimedTokens.length;
113
- if (score > bestScore && score >= 0.5) {
114
- bestScore = score;
115
- bestMatch = call;
140
+ if (score >= 0.5) {
141
+ scoredMatches.push({ call, score });
116
142
  }
117
143
  }
118
144
 
119
- return bestMatch;
145
+ const bestScore = Math.max(0, ...scoredMatches.map((match) => match.score));
146
+ return scoredMatches
147
+ .filter((match) => match.score === bestScore)
148
+ .map((match) => match.call);
149
+ }
150
+
151
+ function latestMatch(matches: readonly BashEvidence[]): BashEvidence {
152
+ return matches.reduce((latest, match) => (
153
+ match.timestamp > latest.timestamp ? match : latest
154
+ ));
120
155
  }