@tekmidian/pai 0.54.1 → 0.56.0

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 (251) hide show
  1. package/dist/{aibroker-client-CNfIBrl5.mjs → aibroker-client-B8Wtasez.mjs} +1 -1
  2. package/dist/{aibroker-client-DzkTpVjx.mjs → aibroker-client-BK1h--W_.mjs} +3 -3
  3. package/dist/{aibroker-client-DzkTpVjx.mjs.map → aibroker-client-BK1h--W_.mjs.map} +1 -1
  4. package/dist/{indexer-backend-CdvCJCkD.mjs → async-CLvuY7b-.mjs} +7 -7
  5. package/dist/async-CLvuY7b-.mjs.map +1 -0
  6. package/dist/auto-route-CF8WNaoy.mjs +100 -0
  7. package/dist/auto-route-CF8WNaoy.mjs.map +1 -0
  8. package/dist/{chain-CZKlI0hq.mjs → chain-26f7uGUs.mjs} +4 -4
  9. package/dist/{chain-CZKlI0hq.mjs.map → chain-26f7uGUs.mjs.map} +1 -1
  10. package/dist/cli/index.mjs +22 -23
  11. package/dist/cli/index.mjs.map +1 -1
  12. package/dist/cli/program.d.mts.map +1 -1
  13. package/dist/cli/program.mjs +22 -23
  14. package/dist/{clusters-Cw_P6lO-.mjs → clusters-Ci1mseh2.mjs} +4 -36
  15. package/dist/clusters-Ci1mseh2.mjs.map +1 -0
  16. package/dist/{config-B3EPzRjf.mjs → config-B93YS8tP.mjs} +3 -3
  17. package/dist/{config-B3EPzRjf.mjs.map → config-B93YS8tP.mjs.map} +1 -1
  18. package/dist/{config-Bn9jpblO.mjs → config-D1omG_UU.mjs} +3 -3
  19. package/dist/{config-Bn9jpblO.mjs.map → config-D1omG_UU.mjs.map} +1 -1
  20. package/dist/{config-RjeVGJ7K.mjs → config-DCYWFaEi.mjs} +1 -1
  21. package/dist/{context-handover-cache-CXyH6QsC.mjs → context-handover-cache-k2kWbE6G.mjs} +82 -99
  22. package/dist/context-handover-cache-k2kWbE6G.mjs.map +1 -0
  23. package/dist/daemon/index.mjs +18 -24
  24. package/dist/daemon/index.mjs.map +1 -1
  25. package/dist/daemon-BOWol-LF.mjs +19 -0
  26. package/dist/{daemon-aJTxzg20.mjs → daemon-BsuM0UdV.mjs} +97 -466
  27. package/dist/daemon-BsuM0UdV.mjs.map +1 -0
  28. package/dist/daemon-mcp/index.mjs +10 -10
  29. package/dist/daemon-mcp/index.mjs.map +1 -1
  30. package/dist/{detector-DWXkeTlk.mjs → detector-3g7XuU1r.mjs} +5 -12
  31. package/dist/detector-3g7XuU1r.mjs.map +1 -0
  32. package/dist/detector-DgDn56j-.mjs +3 -0
  33. package/dist/{embeddings-ClqKtLZ8.mjs → embeddings-BNv3TQC5.mjs} +1 -1
  34. package/dist/{embeddings-DvRKcQyt.mjs → embeddings-DfrYNIng.mjs} +1 -1
  35. package/dist/{embeddings-DvRKcQyt.mjs.map → embeddings-DfrYNIng.mjs.map} +1 -1
  36. package/dist/factory-C9wGUe30.mjs +3 -0
  37. package/dist/factory-DiuntvwG.mjs +250 -0
  38. package/dist/factory-DiuntvwG.mjs.map +1 -0
  39. package/dist/{fallback-CCFIpPha.mjs → fallback-CVe3sb94.mjs} +192 -134
  40. package/dist/fallback-CVe3sb94.mjs.map +1 -0
  41. package/dist/federation-db-CJDw_Pwq.mjs +3 -0
  42. package/dist/{db-DJ8rk0VM.mjs → federation-db-w8e-sKjp.mjs} +5 -5
  43. package/dist/federation-db-w8e-sKjp.mjs.map +1 -0
  44. package/dist/{helpers-crDEr6S2.mjs → helpers-D9WkIf9R.mjs} +1 -1
  45. package/dist/{helpers-crDEr6S2.mjs.map → helpers-D9WkIf9R.mjs.map} +1 -1
  46. package/dist/hooks/capture-all-events.mjs.map +1 -1
  47. package/dist/hooks/capture-session-summary.mjs.map +1 -1
  48. package/dist/hooks/capture-tool-output.mjs.map +1 -1
  49. package/dist/hooks/context-compression-hook.mjs.map +1 -1
  50. package/dist/hooks/load-core-context.mjs +5 -0
  51. package/dist/hooks/load-core-context.mjs.map +2 -2
  52. package/dist/hooks/load-project-context.mjs.map +1 -1
  53. package/dist/hooks/post-compact-inject.mjs.map +1 -1
  54. package/dist/hooks/route-agents-to-worker.mjs.map +1 -1
  55. package/dist/hooks/route-edits-to-worker.mjs +1 -1
  56. package/dist/hooks/route-edits-to-worker.mjs.map +2 -2
  57. package/dist/hooks/security-validator.mjs +8367 -19
  58. package/dist/hooks/security-validator.mjs.map +4 -4
  59. package/dist/hooks/stop-hook.mjs.map +2 -2
  60. package/dist/hooks/whisper-rules.mjs.map +2 -2
  61. package/dist/hooks/worker-proxy.mjs.map +1 -1
  62. package/dist/hooks/worker-status-line.mjs.map +2 -2
  63. package/dist/hooks/worker-supervision.mjs.map +1 -1
  64. package/dist/index.d.mts +327 -100
  65. package/dist/index.d.mts.map +1 -1
  66. package/dist/index.mjs +7 -11
  67. package/dist/indexer-backend-Cc-_NK3q.mjs +1 -0
  68. package/dist/indexer-backend-DcDtin1O.mjs +5 -0
  69. package/dist/{ipc-client-C6NryMMb.mjs → ipc-client-Dasm515c.mjs} +2 -2
  70. package/dist/{ipc-client-C6NryMMb.mjs.map → ipc-client-Dasm515c.mjs.map} +1 -1
  71. package/dist/kg-entity-Cj8Q6YmU.mjs +29 -0
  72. package/dist/kg-entity-Cj8Q6YmU.mjs.map +1 -0
  73. package/dist/{latent-ideas-BfL4nCQ3.mjs → latent-ideas-BRy6HNwg.mjs} +4 -4
  74. package/dist/{latent-ideas-BfL4nCQ3.mjs.map → latent-ideas-BRy6HNwg.mjs.map} +1 -1
  75. package/dist/{link-boost-C5PaNdzm.mjs → link-boost-BptbAPuv.mjs} +1 -1
  76. package/dist/{link-boost-C5PaNdzm.mjs.map → link-boost-BptbAPuv.mjs.map} +1 -1
  77. package/dist/{main-resolver-Bt1f6jJc.mjs → main-resolver-Dx-pxic1.mjs} +56 -31
  78. package/dist/main-resolver-Dx-pxic1.mjs.map +1 -0
  79. package/dist/main-resolver-uDtK9p6e.mjs +7 -0
  80. package/dist/merge-BncjJTfb.mjs +3 -0
  81. package/dist/merge-xoyfZQ4W.mjs +6 -0
  82. package/dist/merge-xoyfZQ4W.mjs.map +1 -0
  83. package/dist/{migrate-CfERwXhY.mjs → migrate-BD7D8EEh.mjs} +21 -54
  84. package/dist/migrate-BD7D8EEh.mjs.map +1 -0
  85. package/dist/{neighborhood-CETR_P4y.mjs → neighborhood-D8uscnGy.mjs} +4 -25
  86. package/dist/neighborhood-D8uscnGy.mjs.map +1 -0
  87. package/dist/{note-context-DCcRWBoN.mjs → note-context-CgffaUMh.mjs} +3 -23
  88. package/dist/note-context-CgffaUMh.mjs.map +1 -0
  89. package/dist/{pai-home-ChAOupZc.mjs → pai-home-CeOIYltV.mjs} +2 -2
  90. package/dist/pai-home-CeOIYltV.mjs.map +1 -0
  91. package/dist/{pai-marker-B20KqhA8.mjs → pai-marker-D1MMswkz.mjs} +1 -1
  92. package/dist/{pai-marker-B20KqhA8.mjs.map → pai-marker-D1MMswkz.mjs.map} +1 -1
  93. package/dist/{planner-D3keWys5.mjs → planner-ye7wrrfB.mjs} +7 -7
  94. package/dist/{planner-D3keWys5.mjs.map → planner-ye7wrrfB.mjs.map} +1 -1
  95. package/dist/{postgres-CUSXWgTG.mjs → postgres-nvU5pShF.mjs} +863 -4
  96. package/dist/postgres-nvU5pShF.mjs.map +1 -0
  97. package/dist/{program-B3eRMhff.mjs → program-DuC1RcaO.mjs} +2268 -1402
  98. package/dist/program-DuC1RcaO.mjs.map +1 -0
  99. package/dist/query-feedback-COYCnvHQ.mjs +3 -0
  100. package/dist/{query-feedback-CTs_jx6i.mjs → query-feedback-xz5axTj3.mjs} +3 -3
  101. package/dist/query-feedback-xz5axTj3.mjs.map +1 -0
  102. package/dist/{db-Ddns80yf.mjs → registry-db-Bkpbp7Gf.mjs} +5 -5
  103. package/dist/registry-db-Bkpbp7Gf.mjs.map +1 -0
  104. package/dist/registry-db-DwXpf7yF.mjs +3 -0
  105. package/dist/registry-postgres-B07-hmn8.mjs +795 -0
  106. package/dist/registry-postgres-B07-hmn8.mjs.map +1 -0
  107. package/dist/registry-sqlite-CkGND_tm.mjs +593 -0
  108. package/dist/registry-sqlite-CkGND_tm.mjs.map +1 -0
  109. package/dist/{reranker-B5qUTamW.mjs → reranker-BS5gqGeF.mjs} +1 -1
  110. package/dist/{reranker-HHmhZk6v.mjs → reranker-CRVawoEh.mjs} +1 -1
  111. package/dist/{reranker-HHmhZk6v.mjs.map → reranker-CRVawoEh.mjs.map} +1 -1
  112. package/dist/router-BXOf_e9e.mjs +3 -0
  113. package/dist/{router-DBAZfE7X.mjs → router-BdxdsAvs.mjs} +2 -2
  114. package/dist/{router-DBAZfE7X.mjs.map → router-BdxdsAvs.mjs.map} +1 -1
  115. package/dist/{run-DLG25bzt.mjs → run-CqRvXGjd.mjs} +309 -49
  116. package/dist/run-CqRvXGjd.mjs.map +1 -0
  117. package/dist/{runtime-paths-B0P1TvUr.mjs → runtime-paths-BRwDeBEg.mjs} +1 -1
  118. package/dist/{runtime-paths-B0P1TvUr.mjs.map → runtime-paths-BRwDeBEg.mjs.map} +1 -1
  119. package/dist/search-BQHL5wDr.mjs +3 -0
  120. package/dist/search-BaTbyWjK.mjs +107 -0
  121. package/dist/search-BaTbyWjK.mjs.map +1 -0
  122. package/dist/{server-CGiHdaUp.mjs → server-CGuZFOeR.mjs} +4 -4
  123. package/dist/{server-CGiHdaUp.mjs.map → server-CGuZFOeR.mjs.map} +1 -1
  124. package/dist/{session-keepalive-DklS8VmU.mjs → session-keepalive-BQ6AQ9ez.mjs} +7 -7
  125. package/dist/{session-keepalive-DklS8VmU.mjs.map → session-keepalive-BQ6AQ9ez.mjs.map} +1 -1
  126. package/dist/skills/Plan/SKILL.md +1 -1
  127. package/dist/{sources-KBGEA_E6.mjs → sources-BBe3AZ-W.mjs} +8 -27
  128. package/dist/sources-BBe3AZ-W.mjs.map +1 -0
  129. package/dist/sqlite-D9p5a4qe.mjs +935 -0
  130. package/dist/sqlite-D9p5a4qe.mjs.map +1 -0
  131. package/dist/state-CwlGAKgF.mjs +3 -0
  132. package/dist/{state-DwrsOoMi.mjs → state-n13uPK5B.mjs} +6 -5
  133. package/dist/state-n13uPK5B.mjs.map +1 -0
  134. package/dist/{stop-words-BaMEGVeY.mjs → stop-words-ClCwO8mZ.mjs} +1 -1
  135. package/dist/{stop-words-BaMEGVeY.mjs.map → stop-words-ClCwO8mZ.mjs.map} +1 -1
  136. package/dist/{themes-BVoAnLZj.mjs → themes-B2v7RNnA.mjs} +3 -3
  137. package/dist/{themes-BVoAnLZj.mjs.map → themes-B2v7RNnA.mjs.map} +1 -1
  138. package/dist/{tools-BEqiJt_j.mjs → tools-Diro2s8J.mjs} +157 -398
  139. package/dist/tools-Diro2s8J.mjs.map +1 -0
  140. package/dist/{tools-BwsOTmjh.mjs → tools-KgL1rkPD.mjs} +4 -4
  141. package/dist/{trace-Cy8quQTm.mjs → trace-BRflVyBi.mjs} +1 -1
  142. package/dist/{trace-Cy8quQTm.mjs.map → trace-BRflVyBi.mjs.map} +1 -1
  143. package/dist/{utils-BD8g8oSf.mjs → utils-BrX9FLeK.mjs} +1 -1
  144. package/dist/{utils-CJymHkYm.mjs → utils-C9HsYDpO.mjs} +1 -1
  145. package/dist/{utils-CJymHkYm.mjs.map → utils-C9HsYDpO.mjs.map} +1 -1
  146. package/dist/{vault-indexer-C5i-OAyr.mjs → vault-indexer-DHYBpRZ5.mjs} +2 -2
  147. package/dist/{vault-indexer-C5i-OAyr.mjs.map → vault-indexer-DHYBpRZ5.mjs.map} +1 -1
  148. package/dist/{wakeup-Yk5lQ0jb.mjs → wakeup-D0uvqLsE.mjs} +95 -4
  149. package/dist/wakeup-D0uvqLsE.mjs.map +1 -0
  150. package/dist/work-queue-worker-DEbWsrDQ.mjs +11 -0
  151. package/dist/{work-queue-worker-utPp4hUv.mjs → work-queue-worker-DufMOtrL.mjs} +9 -9
  152. package/dist/work-queue-worker-DufMOtrL.mjs.map +1 -0
  153. package/dist/{zettelkasten-DezbXghl.mjs → zettelkasten-BPxSOalU.mjs} +4 -4
  154. package/dist/{zettelkasten-DezbXghl.mjs.map → zettelkasten-BPxSOalU.mjs.map} +1 -1
  155. package/docker/init.sql +5 -1
  156. package/docs/commands/README.md +5 -0
  157. package/docs/commands/audit.md +1 -1
  158. package/docs/commands/backup.md +1 -1
  159. package/docs/commands/clear-names.md +1 -1
  160. package/docs/commands/config.md +4 -4
  161. package/docs/commands/daemon.md +1 -1
  162. package/docs/commands/db.md +15 -1
  163. package/docs/commands/end.md +1 -1
  164. package/docs/commands/help.md +1 -1
  165. package/docs/commands/hooks-db.md +47 -0
  166. package/docs/commands/identity.md +1 -1
  167. package/docs/commands/kg.md +1 -1
  168. package/docs/commands/launch.md +1 -1
  169. package/docs/commands/mcp.md +1 -1
  170. package/docs/commands/memory.md +1 -1
  171. package/docs/commands/notify.md +1 -1
  172. package/docs/commands/observation.md +1 -1
  173. package/docs/commands/obsidian.md +1 -1
  174. package/docs/commands/pause.md +1 -1
  175. package/docs/commands/project.md +1 -1
  176. package/docs/commands/projects.md +1 -1
  177. package/docs/commands/registry.md +1 -1
  178. package/docs/commands/restore.md +1 -1
  179. package/docs/commands/session.md +2 -2
  180. package/docs/commands/sessions.md +1 -1
  181. package/docs/commands/setup.md +1 -1
  182. package/docs/commands/shell-init.md +1 -1
  183. package/docs/commands/skill.md +1 -1
  184. package/docs/commands/task.md +1 -1
  185. package/docs/commands/topic.md +1 -1
  186. package/docs/commands/update.md +1 -1
  187. package/docs/commands/worker.md +1 -1
  188. package/docs/commands/zettel.md +1 -1
  189. package/docs/design/postgres-only.md +438 -0
  190. package/docs/design/registry-method-map.md +174 -0
  191. package/package.json +1 -1
  192. package/src/hooks/pre-compact.sh +2 -40
  193. package/src/hooks/session-hooks-db.test.ts +93 -0
  194. package/src/hooks/session-stop.sh +2 -26
  195. package/src/hooks/ts/lib/edit-gate.test.ts +9 -0
  196. package/src/hooks/ts/lib/edit-gate.ts +5 -2
  197. package/src/hooks/ts/lib/plutil-guard.test.ts +54 -0
  198. package/src/hooks/ts/lib/plutil-guard.ts +43 -0
  199. package/src/hooks/ts/lib/worker-git-guard.test.ts +134 -0
  200. package/src/hooks/ts/lib/worker-git-guard.ts +103 -0
  201. package/src/hooks/ts/pre-tool-use/security-validator.test.ts +68 -0
  202. package/src/hooks/ts/pre-tool-use/security-validator.ts +69 -21
  203. package/src/hooks/ts/session-start/load-core-context.ts +13 -0
  204. package/src/hooks/ts/session-start/session-start-worker-guard.test.ts +13 -0
  205. package/dist/auto-route-CcD0OWWB.mjs +0 -86
  206. package/dist/auto-route-CcD0OWWB.mjs.map +0 -1
  207. package/dist/clusters-Cw_P6lO-.mjs.map +0 -1
  208. package/dist/context-handover-cache-CXyH6QsC.mjs.map +0 -1
  209. package/dist/daemon-CknQ6YGZ.mjs +0 -25
  210. package/dist/daemon-aJTxzg20.mjs.map +0 -1
  211. package/dist/db-BOBfewFH.mjs +0 -3
  212. package/dist/db-DJ8rk0VM.mjs.map +0 -1
  213. package/dist/db-DbY2O8QO.mjs +0 -3
  214. package/dist/db-Ddns80yf.mjs.map +0 -1
  215. package/dist/detect-Bf2z-oKB.mjs +0 -86
  216. package/dist/detect-Bf2z-oKB.mjs.map +0 -1
  217. package/dist/detector-CkwkXuGh.mjs +0 -5
  218. package/dist/detector-DWXkeTlk.mjs.map +0 -1
  219. package/dist/factory-Ba8j9K7q.mjs +0 -3
  220. package/dist/factory-Bt7TWQje.mjs +0 -150
  221. package/dist/factory-Bt7TWQje.mjs.map +0 -1
  222. package/dist/fallback-CCFIpPha.mjs.map +0 -1
  223. package/dist/indexer-backend-CdvCJCkD.mjs.map +0 -1
  224. package/dist/kg-entity-BSW7ra8i.mjs +0 -176
  225. package/dist/kg-entity-BSW7ra8i.mjs.map +0 -1
  226. package/dist/main-resolver-Bt1f6jJc.mjs.map +0 -1
  227. package/dist/main-resolver-DYHhw5Ig.mjs +0 -7
  228. package/dist/migrate-CfERwXhY.mjs.map +0 -1
  229. package/dist/neighborhood-CETR_P4y.mjs.map +0 -1
  230. package/dist/note-context-DCcRWBoN.mjs.map +0 -1
  231. package/dist/pai-home-ChAOupZc.mjs.map +0 -1
  232. package/dist/postgres-CUSXWgTG.mjs.map +0 -1
  233. package/dist/program-B3eRMhff.mjs.map +0 -1
  234. package/dist/query-feedback-Bm6XvCmg.mjs +0 -3
  235. package/dist/query-feedback-CTs_jx6i.mjs.map +0 -1
  236. package/dist/router-CremHKTI.mjs +0 -3
  237. package/dist/run-DLG25bzt.mjs.map +0 -1
  238. package/dist/search-B69cQwDB.mjs +0 -303
  239. package/dist/search-B69cQwDB.mjs.map +0 -1
  240. package/dist/search-fb-5ovj4.mjs +0 -4
  241. package/dist/sources-KBGEA_E6.mjs.map +0 -1
  242. package/dist/sqlite-By6r2YhZ.mjs +0 -271
  243. package/dist/sqlite-By6r2YhZ.mjs.map +0 -1
  244. package/dist/state-Ca0ltLgI.mjs +0 -3
  245. package/dist/state-DwrsOoMi.mjs.map +0 -1
  246. package/dist/sync-Btcb6xA4.mjs +0 -310
  247. package/dist/sync-Btcb6xA4.mjs.map +0 -1
  248. package/dist/tools-BEqiJt_j.mjs.map +0 -1
  249. package/dist/wakeup-Yk5lQ0jb.mjs.map +0 -1
  250. package/dist/work-queue-worker-DsdJx-jn.mjs +0 -14
  251. package/dist/work-queue-worker-utPp4hUv.mjs.map +0 -1
@@ -1,6 +1,6 @@
1
- import { n as openRegistry, r as registryDbPath } from "./db-Ddns80yf.mjs";
2
- import { C as readWorkersSection, E as resolveProviderKey, S as providerKeyPath, T as resolveModelCapability, _ as isModelCapability, d as WorkersConfigError, f as assertProviderRunnable, p as classModelCapability } from "./config-B3EPzRjf.mjs";
3
- import { _ as ledgerPath, a as claudeCommand, b as workersLogDir, c as isQuotaFailure, f as resolveCapabilityRun, g as eventsPath, h as ensureNoMcpConfig, i as buildRunEnv, l as nextAutoProvider, m as setCooldown, n as ensureProxyRunning, o as capabilityForRun, p as resolveTarget, t as DEFAULT_PROXY_PORT, v as panesDir, y as statusPath } from "./server-CGiHdaUp.mjs";
1
+ import { i as getRegistryBackend } from "./factory-DiuntvwG.mjs";
2
+ import { C as readWorkersSection, E as resolveProviderKey, S as providerKeyPath, T as resolveModelCapability, _ as isModelCapability, d as WorkersConfigError, f as assertProviderRunnable, p as classModelCapability } from "./config-B93YS8tP.mjs";
3
+ import { _ as ledgerPath, a as claudeCommand, b as workersLogDir, c as isQuotaFailure, f as resolveCapabilityRun, g as eventsPath, h as ensureNoMcpConfig, i as buildRunEnv, l as nextAutoProvider, m as setCooldown, n as ensureProxyRunning, o as capabilityForRun, p as resolveTarget, t as DEFAULT_PROXY_PORT, v as panesDir, y as statusPath } from "./server-CGuZFOeR.mjs";
4
4
  import { appendFileSync, closeSync, existsSync, mkdirSync, mkdtempSync, openSync, readFileSync, readdirSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync, writeSync } from "node:fs";
5
5
  import { homedir, tmpdir } from "node:os";
6
6
  import { dirname, isAbsolute, join, relative, resolve } from "node:path";
@@ -454,6 +454,18 @@ function ageOf(ts, now = /* @__PURE__ */ new Date()) {
454
454
  const s = Math.max(0, Math.floor((now.getTime() - t) / 1e3));
455
455
  return s < 90 ? `${s}s` : `${Math.floor(s / 60)}m`;
456
456
  }
457
+ /** Precise elapsed time: "45s", "1m 23s", "12m 05s", "1h 02m 05s" — seconds zero-padded after a larger unit. */
458
+ function elapsedOf(ts, now = /* @__PURE__ */ new Date()) {
459
+ const t = Date.parse(ts.replace(" ", "T"));
460
+ if (Number.isNaN(t)) return "?";
461
+ const secs = Math.max(0, Math.floor((now.getTime() - t) / 1e3));
462
+ const hours = Math.floor(secs / 3600);
463
+ const mins = Math.floor(secs % 3600 / 60);
464
+ const sec = secs % 60;
465
+ if (hours > 0) return `${hours}h ${String(mins).padStart(2, "0")}m ${String(sec).padStart(2, "0")}s`;
466
+ if (mins > 0) return `${mins}m ${String(sec).padStart(2, "0")}s`;
467
+ return `${sec}s`;
468
+ }
457
469
  /** One-line description of a tool call, e.g. "Bash: npm test". */
458
470
  function describeTool(name, inp) {
459
471
  if (typeof inp !== "object" || inp === null) return name;
@@ -563,8 +575,8 @@ function worktreeBranch(id) {
563
575
  function worktreePath(logDir, id) {
564
576
  return join(worktreesDir(logDir), id);
565
577
  }
566
- /** Run git in `cwd`, returning trimmed stdout; throws with stderr on failure. */
567
- function git(cwd, args) {
578
+ /** Run git in `cwd` with an optional env override, trimmed stdout, stderr on failure. */
579
+ function runGit(cwd, args, env) {
568
580
  try {
569
581
  return execFileSync("git", [
570
582
  "-C",
@@ -577,7 +589,8 @@ function git(cwd, args) {
577
589
  "ignore",
578
590
  "pipe",
579
591
  "pipe"
580
- ]
592
+ ],
593
+ ...env ? { env } : {}
581
594
  }).trim();
582
595
  } catch (e) {
583
596
  const err = e;
@@ -585,6 +598,10 @@ function git(cwd, args) {
585
598
  throw new Error(`git ${args.join(" ")} in ${cwd}: ${why.trim()}`);
586
599
  }
587
600
  }
601
+ /** Run git in `cwd`, returning trimmed stdout; throws with stderr on failure. */
602
+ function git(cwd, args) {
603
+ return runGit(cwd, args);
604
+ }
588
605
  /** Is `cwd` inside a git repository (a .git dir — worktrees: a .git file)? */
589
606
  function isGitRepo(cwd) {
590
607
  try {
@@ -618,7 +635,43 @@ function worktreeWanted(flag, opts) {
618
635
  return !promptLooksReadonly(opts.prompt ?? "");
619
636
  }
620
637
  /**
621
- * Create the worktree and branch for `id` from `cwd`'s HEAD. Throws when git
638
+ * Commit `cwd`'s current index + working tree (including untracked files) as
639
+ * a floating commit on top of HEAD, without touching the real index, working
640
+ * tree or HEAD: a temporary `GIT_INDEX_FILE` collects the snapshot, `git
641
+ * commit-tree` writes the commit object directly (it updates no ref). The
642
+ * caller then branches a worktree from that commit, so the worktree sees
643
+ * exactly what was on disk, uncommitted or not.
644
+ */
645
+ function snapshotUncommitted(cwd, id, head) {
646
+ const idxDir = mkdtempSync(join(tmpdir(), "pai-worktree-idx-"));
647
+ const idx = join(idxDir, "index");
648
+ try {
649
+ const env = {
650
+ ...process.env,
651
+ GIT_INDEX_FILE: idx
652
+ };
653
+ runGit(cwd, ["read-tree", head], env);
654
+ runGit(cwd, ["add", "-A"], env);
655
+ return runGit(cwd, [
656
+ "commit-tree",
657
+ runGit(cwd, ["write-tree"], env),
658
+ "-p",
659
+ head,
660
+ "-m",
661
+ `worker ${id}: snapshot of uncommitted checkout`
662
+ ]);
663
+ } finally {
664
+ rmSync(idxDir, {
665
+ recursive: true,
666
+ force: true
667
+ });
668
+ }
669
+ }
670
+ /**
671
+ * Create the worktree and branch for `id` from `cwd`'s HEAD — or, when the
672
+ * checkout has uncommitted changes, from a snapshot commit of that dirty
673
+ * state (see `snapshotUncommitted`), so a worktree worker sees the same
674
+ * files the operator sees, not just what was last committed. Throws when git
622
675
  * refuses (no commits yet, branch exists, …) — the caller decides whether to
623
676
  * degrade to an in-place run.
624
677
  */
@@ -630,18 +683,22 @@ function addWorktree(logDir, id, cwd) {
630
683
  });
631
684
  const dir = worktreePath(logDir, id);
632
685
  const branch = worktreeBranch(id);
633
- const base = git(cwd, ["rev-parse", "HEAD"]);
686
+ const head = git(cwd, ["rev-parse", "HEAD"]);
687
+ const dirty = dirtyPaths(cwd).length > 0;
688
+ const base = dirty ? snapshotUncommitted(cwd, id, head) : head;
634
689
  git(cwd, [
635
690
  "worktree",
636
691
  "add",
637
692
  dir,
638
693
  "-b",
639
- branch
694
+ branch,
695
+ base
640
696
  ]);
641
697
  return {
642
698
  dir,
643
699
  branch,
644
- base
700
+ base,
701
+ snapshot: dirty
645
702
  };
646
703
  }
647
704
  /**
@@ -707,6 +764,7 @@ function recordWorktree(logDir, status, info, ok) {
707
764
  s.commits = commitsSince(info.dir, info.base);
708
765
  s.worktreeDir = info.dir;
709
766
  s.worktreeBase = info.base;
767
+ s.worktreeSnapshot = info.snapshot;
710
768
  } else {
711
769
  removeWorktree(s.cwd, info.dir, true);
712
770
  try {
@@ -720,6 +778,7 @@ function recordWorktree(logDir, status, info, ok) {
720
778
  s.worktreeDir = null;
721
779
  s.worktreeBase = null;
722
780
  s.commits = null;
781
+ s.worktreeSnapshot = null;
723
782
  }
724
783
  saveStatus(logDir, s);
725
784
  return s;
@@ -839,6 +898,118 @@ function assertWorktreeClean(wtDir, id) {
839
898
  const leftover = uncommittedPaths(wtDir);
840
899
  if (leftover.length) throw new Error(`worker ${id}: the worktree ${wtDir} still holds uncommitted changes (${leftover.join(", ")}) — it was NOT removed; commit or copy them by hand, then re-run merge`);
841
900
  }
901
+ /** Blob sha of `path` at `rev` in `cwd`, or null when it does not exist there. */
902
+ function blobAt(cwd, rev, path) {
903
+ try {
904
+ return git(cwd, [
905
+ "rev-parse",
906
+ "--verify",
907
+ "-q",
908
+ `${rev}:${path}`
909
+ ]);
910
+ } catch {
911
+ return null;
912
+ }
913
+ }
914
+ /** Blob sha of `path` as it sits on disk in `cwd`, or null when it is absent. */
915
+ function workingBlob(cwd, path) {
916
+ if (!existsSync(join(cwd, path))) return null;
917
+ try {
918
+ return git(cwd, [
919
+ "hash-object",
920
+ "--",
921
+ path
922
+ ]);
923
+ } catch {
924
+ return null;
925
+ }
926
+ }
927
+ /**
928
+ * Refuse a snapshot merge when the checkout differs from the snapshot the
929
+ * worker branched from, for any path the branch touched: the operator edited
930
+ * it, or it was created/deleted since — applying the branch's diff on top
931
+ * would silently discard that. Absent-in-both counts as equal.
932
+ */
933
+ function assertNoSnapshotDrift(cwd, snapshot, paths, id) {
934
+ const drifted = paths.filter((p) => blobAt(cwd, snapshot, p) !== workingBlob(cwd, p)).sort();
935
+ if (!drifted.length) return;
936
+ throw new Error(`worker ${id}: the checkout ${cwd} has changed since the worktree's snapshot in paths the branch touches: ${drifted.join(", ")}. Resolve by hand, then re-run: pai worker merge ${id}. No merge was made; the worktree was kept.`);
937
+ }
938
+ /**
939
+ * `pai worker merge <id>` for a snapshot-based worktree (see `addWorktree`):
940
+ * git's own merge only moves committed history, and the snapshot commit was
941
+ * never on any branch reachable from `cwd`'s HEAD, so there is nothing to
942
+ * `git merge` here. Instead the worker's own changes — `git diff --binary
943
+ * <snapshot> <branch>` — are applied straight onto the checkout's working
944
+ * tree as uncommitted edits, exactly like the uncommitted state the worker
945
+ * started from. Works even if `cwd`'s HEAD moved since the snapshot: the
946
+ * diff is applied to files, not merged into a tree.
947
+ */
948
+ function mergeSnapshotWorker(logDir, id, st) {
949
+ const snapshot = st.worktreeBase;
950
+ const branch = st.branch;
951
+ const worktreeDir = st.worktreeDir;
952
+ const salvaged = existsSync(worktreeDir) ? salvageUncommitted(worktreeDir, st.label || UNLABELED) : [];
953
+ if ((parseInt(git(st.cwd, [
954
+ "rev-list",
955
+ "--count",
956
+ `${snapshot}..${branch}`
957
+ ]), 10) || 0) <= 0) throw new Error(`worker ${id}: branch ${branch} has no commits beyond its snapshot to merge. The worktree ${worktreeDir} was NOT removed — uncommitted work there would be destroyed. Commit it yourself, or drop everything with: pai worker discard ${id}`);
958
+ const changedPaths = git(st.cwd, [
959
+ "diff",
960
+ "--name-only",
961
+ snapshot,
962
+ branch
963
+ ]).split("\n").filter(Boolean);
964
+ assertNoSnapshotDrift(st.cwd, snapshot, changedPaths, id);
965
+ const diff = execFileSync("git", [
966
+ "-C",
967
+ st.cwd,
968
+ "diff",
969
+ "--binary",
970
+ snapshot,
971
+ branch
972
+ ], {
973
+ encoding: "utf8",
974
+ timeout: 3e4,
975
+ maxBuffer: 64 * 1024 * 1024
976
+ });
977
+ if (diff.trim()) try {
978
+ execFileSync("git", [
979
+ "-C",
980
+ st.cwd,
981
+ "apply",
982
+ "--binary"
983
+ ], {
984
+ input: diff,
985
+ encoding: "utf8",
986
+ timeout: 3e4,
987
+ stdio: [
988
+ "pipe",
989
+ "pipe",
990
+ "pipe"
991
+ ]
992
+ });
993
+ } catch (e) {
994
+ const err = e;
995
+ const why = (typeof err.stderr === "string" ? err.stderr : err.stderr?.toString("utf8")) || err.message || String(e);
996
+ throw new Error(`worker ${id}: git refused to apply ${branch}'s changes to ${st.cwd} — ${why.trim()}. The worktree ${worktreeDir} was kept: resolve by hand, then re-run merge`);
997
+ }
998
+ removeWorktree(st.cwd, worktreeDir, true);
999
+ try {
1000
+ git(st.cwd, [
1001
+ "branch",
1002
+ "-D",
1003
+ branch
1004
+ ]);
1005
+ } catch {}
1006
+ saveStatus(logDir, {
1007
+ ...st,
1008
+ merged: true
1009
+ });
1010
+ const base = `applied worker ${id}'s changes (branch ${branch}) to ${st.cwd} as uncommitted changes: ${changedPaths.join(", ")} (worktree removed, branch deleted)`;
1011
+ return salvaged.length ? `${base}; salvaged ${salvaged.length} uncommitted change(s) onto the branch first: ${salvaged.join(", ")}` : base;
1012
+ }
842
1013
  /**
843
1014
  * `pai worker merge <id>`: salvage whatever the worker left uncommitted onto
844
1015
  * its branch, refuse when the original checkout is dirty in paths the branch
@@ -851,6 +1022,7 @@ function assertWorktreeClean(wtDir, id) {
851
1022
  function mergeWorker(logDir, id) {
852
1023
  const st = mustHaveBranch(logDir, id);
853
1024
  if (st.merged) return `worker ${id}: branch ${st.branch} already merged`;
1025
+ if (st.worktreeSnapshot) return mergeSnapshotWorker(logDir, id, st);
854
1026
  const salvaged = existsSync(st.worktreeDir) ? salvageUncommitted(st.worktreeDir, st.label || UNLABELED) : [];
855
1027
  if ((parseInt(git(st.cwd, [
856
1028
  "rev-list",
@@ -919,6 +1091,7 @@ function discardWorker(logDir, id) {
919
1091
  branch: null,
920
1092
  worktreeDir: null,
921
1093
  worktreeBase: null,
1094
+ worktreeSnapshot: null,
922
1095
  commits: null,
923
1096
  merged: false
924
1097
  });
@@ -935,14 +1108,28 @@ function mustHaveBranch(logDir, id) {
935
1108
  * own branch (the no-commit rule holds for the main branch only), it must not
936
1109
  * merge or push itself, and the parent or operator merges.
937
1110
  */
938
- function worktreeSystemPrompt(id, branch, dir) {
1111
+ function worktreeSystemPrompt(id, branch, dir, snapshot = false) {
939
1112
  return [
940
1113
  "You are running in your own git worktree:",
941
1114
  ` ${dir} on branch ${branch} (worker id ${id}).`,
942
1115
  "Commit your work on that branch as you go (git add / git commit) — committing here is expected;",
943
1116
  "the no-commit rule applies to the main branch only, and this is not it.",
944
1117
  "Do not merge, rebase or push; the operator merges your branch back with `pai worker merge`.",
945
- "Use ONLY relative paths inside the worktree, never absolute worktree paths — absolute paths break after merge and leak machine layout."
1118
+ "Use ONLY relative paths inside the worktree, never absolute worktree paths — absolute paths break after merge and leak machine layout.",
1119
+ ...snapshot ? ["This worktree was branched from a snapshot that includes files the parent checkout had uncommitted at spawn time — not just its last commit."] : []
1120
+ ].join("\n");
1121
+ }
1122
+ /**
1123
+ * For headless runs WITHOUT a worktree: the worker shares the operator's
1124
+ * checkout with other in-flight workers, so a hook blocks git stash (except
1125
+ * list/show), reset, clean, checkout/restore of paths, switch, rebase and
1126
+ * merge — take baselines from measurements before editing, not from stash.
1127
+ */
1128
+ function inPlaceSystemPrompt() {
1129
+ return [
1130
+ "You are running in the operator's shared git checkout, alongside other workers editing it at the same time.",
1131
+ "A hook blocks git stash (except list/show), reset, clean, checkout/restore of files, switch, rebase and merge — take baselines from measurements taken before you edit, not from stashing.",
1132
+ "Read-only git (status, diff, log, show, stash list) is fine."
946
1133
  ].join("\n");
947
1134
  }
948
1135
 
@@ -2333,6 +2520,53 @@ function renderReport(c, prefix, r, cwd = "") {
2333
2520
  if (r.notes) out.push(`${prefix}${c("bold", "notes")} ${shortText(r.notes, 120)}`);
2334
2521
  return out;
2335
2522
  }
2523
+ /** A summary that names its own deletion — the path is expected to be gone. */
2524
+ const DELETED_RE = /\b(delete|deleted|deleting|remove|removed|removing)\b/i;
2525
+ /**
2526
+ * Check every path a report's `changed` list claims against the filesystem:
2527
+ * it must exist (mtime at or after `startMs`, the run's start) unless its
2528
+ * summary says it was deleted, in which case it must be absent. Mechanical
2529
+ * only — counts, row totals and other free-text claims are not checked (a
2530
+ * worker's R report is trusted as written; a 2026-09-23 report claimed "181
2531
+ * rows saved" while it had written 31, and only its listed paths are
2532
+ * something the filesystem can confirm or refute).
2533
+ */
2534
+ function verifyReportChanges(changed, cwd, startMs) {
2535
+ const failures = [];
2536
+ for (const ch of changed ?? []) {
2537
+ const raw = (ch.path ?? "").trim();
2538
+ if (!raw) continue;
2539
+ const abs = isAbsolute(raw) ? raw : resolve(cwd, raw);
2540
+ let mtimeMs;
2541
+ try {
2542
+ mtimeMs = statSync(abs).mtimeMs;
2543
+ } catch {
2544
+ mtimeMs = null;
2545
+ }
2546
+ if (DELETED_RE.test(ch.summary ?? "")) {
2547
+ if (mtimeMs !== null) failures.push({
2548
+ path: raw,
2549
+ reason: "not-deleted"
2550
+ });
2551
+ } else if (mtimeMs === null) failures.push({
2552
+ path: raw,
2553
+ reason: "missing"
2554
+ });
2555
+ else if (mtimeMs < startMs) failures.push({
2556
+ path: raw,
2557
+ reason: "stale"
2558
+ });
2559
+ }
2560
+ return {
2561
+ ok: failures.length === 0,
2562
+ failures
2563
+ };
2564
+ }
2565
+ /** The one-line note appended to a report/ledger when verify fails. */
2566
+ function verifyFailNote(v) {
2567
+ const paths = v.failures.map((f) => f.path).slice(0, 5).join(", ");
2568
+ return `verify: ${v.failures.length} claimed change${v.failures.length === 1 ? "" : "s"} not confirmed: ${paths}`;
2569
+ }
2336
2570
  /** repo-relative display of a changed path when it lies under cwd. */
2337
2571
  function relShort(p, cwd) {
2338
2572
  if (!cwd) return p;
@@ -2362,35 +2596,30 @@ function asStringArray(v) {
2362
2596
  /**
2363
2597
  * The launch config of the project whose root_path is `cwd` or an ancestor
2364
2598
  * of it (longest match wins) — null when no registered project covers it,
2365
- * or when the matching project has no mcp/tools pin set. `dbPath` is
2366
- * injectable for tests; production callers take the default.
2599
+ * or when the matching project has no mcp/tools pin set. `registry` is
2600
+ * injectable for tests; production callers take the process-wide backend.
2367
2601
  */
2368
- function projectLaunchConfig(cwd, dbPath = registryDbPath()) {
2602
+ async function projectLaunchConfig(cwd, registry) {
2369
2603
  const target = resolve(cwd);
2370
- const db = openRegistry(dbPath);
2371
- try {
2372
- const rows = db.prepare(`SELECT root_path, session_config FROM projects WHERE status != 'archived' ORDER BY LENGTH(root_path) DESC`).all();
2373
- for (const row of rows) {
2374
- const root = resolve(row.root_path);
2375
- if (target !== root && !target.startsWith(root + "/")) continue;
2376
- if (!row.session_config) return null;
2377
- let parsed;
2378
- try {
2379
- parsed = JSON.parse(row.session_config);
2380
- } catch {
2381
- return null;
2382
- }
2383
- const mcp = asStringArray(parsed.mcp);
2384
- const tools = asStringArray(parsed.tools);
2385
- return mcp || tools ? {
2386
- mcp,
2387
- tools
2388
- } : null;
2604
+ const rows = await (registry ?? await getRegistryBackend()).listProjectsByPathLengthDesc({ excludeArchived: true });
2605
+ for (const row of rows) {
2606
+ const root = resolve(row.root_path);
2607
+ if (target !== root && !target.startsWith(root + "/")) continue;
2608
+ if (!row.session_config) return null;
2609
+ let parsed;
2610
+ try {
2611
+ parsed = JSON.parse(row.session_config);
2612
+ } catch {
2613
+ return null;
2389
2614
  }
2390
- return null;
2391
- } finally {
2392
- db.close();
2615
+ const mcp = asStringArray(parsed.mcp);
2616
+ const tools = asStringArray(parsed.tools);
2617
+ return mcp || tools ? {
2618
+ mcp,
2619
+ tools
2620
+ } : null;
2393
2621
  }
2622
+ return null;
2394
2623
  }
2395
2624
 
2396
2625
  //#endregion
@@ -2770,7 +2999,7 @@ async function runWorker(opts) {
2770
2999
  const logDir = workersLogDir(config);
2771
3000
  mkdirSync(logDir, { recursive: true });
2772
3001
  if (opts.className === "plan" && !opts._planner) {
2773
- const { runPlanner } = await import("./planner-D3keWys5.mjs");
3002
+ const { runPlanner } = await import("./planner-ye7wrrfB.mjs");
2774
3003
  return runPlanner(opts);
2775
3004
  }
2776
3005
  const parent = launchParent(opts.parent);
@@ -3117,7 +3346,7 @@ async function executeRun(a) {
3117
3346
  ];
3118
3347
  } else if (!headless && !parsed.callerMcpConfig) {
3119
3348
  const explicitMcp = [...a.mcpFlag ? [a.mcpFlag] : [], ...parsed.mcp];
3120
- const projectLaunch = projectLaunchConfig(cwd);
3349
+ const projectLaunch = await projectLaunchConfig(cwd);
3121
3350
  const picked = interactiveMcpTools(explicitMcp, parsed.callerTools, projectLaunch);
3122
3351
  if (picked.mcpNames.length) mcpArgs = [
3123
3352
  "--strict-mcp-config",
@@ -3136,7 +3365,8 @@ async function executeRun(a) {
3136
3365
  if (headless) {
3137
3366
  cmd.push("--output-format", "stream-json", "--verbose", "--input-format", "stream-json");
3138
3367
  if (!parsed.callerSystemPrompt) cmd.push("--append-system-prompt", workerContractPrompt(a.className, a.reportFormat));
3139
- if (worktree) cmd.push("--append-system-prompt", worktreeSystemPrompt(wid, worktree.branch, worktree.dir));
3368
+ if (worktree) cmd.push("--append-system-prompt", worktreeSystemPrompt(wid, worktree.branch, worktree.dir, worktree.snapshot));
3369
+ else cmd.push("--append-system-prompt", inPlaceSystemPrompt());
3140
3370
  }
3141
3371
  cmd = ensureToolSearch(cmd);
3142
3372
  if (a.printCmd) {
@@ -3146,7 +3376,7 @@ async function executeRun(a) {
3146
3376
  }));
3147
3377
  return 0;
3148
3378
  }
3149
- const status = {
3379
+ let status = {
3150
3380
  id: wid,
3151
3381
  pid: process.pid,
3152
3382
  label,
@@ -3175,7 +3405,8 @@ async function executeRun(a) {
3175
3405
  ...worktree ? {
3176
3406
  worktreeDir: worktree.dir,
3177
3407
  branch: worktree.branch,
3178
- worktreeBase: worktree.base
3408
+ worktreeBase: worktree.base,
3409
+ worktreeSnapshot: worktree.snapshot
3179
3410
  } : {},
3180
3411
  ...a.specPath ? { spec: a.specPath } : {}
3181
3412
  };
@@ -3377,6 +3608,20 @@ async function executeRun(a) {
3377
3608
  } catch {}
3378
3609
  }
3379
3610
  }
3611
+ if (headless && ctx.resultReport?.changed?.length) {
3612
+ const verify = verifyReportChanges(ctx.resultReport.changed, worktree?.dir ?? cwd, t0);
3613
+ if (!verify.ok) {
3614
+ status.reportValid = false;
3615
+ const note = verifyFailNote(verify);
3616
+ status.last = shortText(note, 90);
3617
+ ctx.resultReport.notes = ctx.resultReport.notes ? `${ctx.resultReport.notes} — ${note}` : note;
3618
+ appendLedger(ledger, "REPORT-UNVERIFIED", {
3619
+ id: wid,
3620
+ failures: verify.failures.length,
3621
+ paths: verify.failures.map((f) => f.path).slice(0, 5).join(",")
3622
+ });
3623
+ }
3624
+ }
3380
3625
  saveStatus(logDir, status);
3381
3626
  appendLedger(ledger, "WORKER-END", {
3382
3627
  id: wid,
@@ -3389,7 +3634,7 @@ async function executeRun(a) {
3389
3634
  tools: status.tools,
3390
3635
  label
3391
3636
  });
3392
- if (worktree) recordWorktree(logDir, status, worktree, ok);
3637
+ if (worktree) status = recordWorktree(logDir, status, worktree, ok);
3393
3638
  if (headless && !a.quiet) printResult(parsed.outputFormat, resultEvent, rc, logDir, wid, ctx.resultReport, worktreeExtras(status));
3394
3639
  const resultText = resultEvent?.result ?? "";
3395
3640
  if (!ok && headless && a.target.via === "auto" && config.routing.retryOnQuota && status.turns <= 1 && status.tools === 0 && isQuotaFailure(resultText)) {
@@ -3508,8 +3753,8 @@ async function executeCodexRun(a) {
3508
3753
  });
3509
3754
  }
3510
3755
  env.PAI_WORKER_ID = wid;
3511
- const prompt = (worktree ? worktreeSystemPrompt(wid, worktree.branch, worktree.dir) + "\n\n" : "") + parsed.prompt;
3512
- const status = {
3756
+ const prompt = (worktree ? worktreeSystemPrompt(wid, worktree.branch, worktree.dir, worktree.snapshot) + "\n\n" : "") + parsed.prompt;
3757
+ let status = {
3513
3758
  id: wid,
3514
3759
  pid: process.pid,
3515
3760
  label,
@@ -3538,7 +3783,8 @@ async function executeCodexRun(a) {
3538
3783
  ...worktree ? {
3539
3784
  worktreeDir: worktree.dir,
3540
3785
  branch: worktree.branch,
3541
- worktreeBase: worktree.base
3786
+ worktreeBase: worktree.base,
3787
+ worktreeSnapshot: worktree.snapshot
3542
3788
  } : {},
3543
3789
  ...a.specPath ? { spec: a.specPath } : {}
3544
3790
  };
@@ -3648,6 +3894,20 @@ async function executeCodexRun(a) {
3648
3894
  status.rc = rc;
3649
3895
  status.secs = secs;
3650
3896
  status.last = shortText(report?.notes ?? finalText, 90) || (ok ? "done" : "failed");
3897
+ if (report?.changed?.length) {
3898
+ const verify = verifyReportChanges(report.changed, worktree?.dir ?? cwd, t0);
3899
+ if (!verify.ok) {
3900
+ status.reportValid = false;
3901
+ const note = verifyFailNote(verify);
3902
+ status.last = shortText(note, 90);
3903
+ report.notes = report.notes ? `${report.notes} — ${note}` : note;
3904
+ appendLedger(ledger, "REPORT-UNVERIFIED", {
3905
+ id: wid,
3906
+ failures: verify.failures.length,
3907
+ paths: verify.failures.map((f) => f.path).slice(0, 5).join(",")
3908
+ });
3909
+ }
3910
+ }
3651
3911
  saveStatus(logDir, status);
3652
3912
  appendLedger(ledger, "WORKER-END", {
3653
3913
  id: wid,
@@ -3661,7 +3921,7 @@ async function executeCodexRun(a) {
3661
3921
  tools: status.tools,
3662
3922
  label
3663
3923
  });
3664
- if (worktree) recordWorktree(logDir, status, worktree, ok);
3924
+ if (worktree) status = recordWorktree(logDir, status, worktree, ok);
3665
3925
  if (!a.quiet) printResult(parsed.outputFormat, resultEvent, rc, logDir, wid, report, worktreeExtras(status));
3666
3926
  const finalRc = rc !== 0 ? rc : ok ? 0 : 1;
3667
3927
  if (status.parent && isWorkerId(logDir, status.parent)) try {
@@ -3814,5 +4074,5 @@ function resultFromOutput(out) {
3814
4074
  }
3815
4075
 
3816
4076
  //#endregion
3817
- export { contextLabel as A, setWorkerLabel as B, mergeWorker as C, UNLABELED as D, ledgerSummary as E, loadStatuses as F, describeMcp as G, longInlinePromptHint as H, newWorkerId as I, expandMcpNames as K, nowStamp as L, isChatPane as M, isLive as N, ageOf as O, loadStatus as P, ownsPid as R, discardWorker as S, appendLedger as T, parseRunnerArgs as U, waitForTerminalStatus as V, shortText as W, itermUuid as _, projectLaunchConfig as a, sessionTag as b, handoffFromInside as c, workerDepth as d, checkPaneForWorker as f, itermForClaudeSession as g, currentTabKey as h, usageContextTokens as i, contextPercent as j, alive as k, readInbox as l, openPaneForWorker as m, runWorker as n, parseWorkerReport as o, openFollowPane as p, testProvider as r, renderReport as s, printResult as t, sayToWorker as u, resolveSession as v, worktreesDir as w, workerInScope as x, sessionMapPath as y, saveStatus as z };
3818
- //# sourceMappingURL=run-DLG25bzt.mjs.map
4077
+ export { contextLabel as A, saveStatus as B, mergeWorker as C, UNLABELED as D, ledgerSummary as E, loadStatus as F, shortText as G, waitForTerminalStatus as H, loadStatuses as I, describeMcp as K, newWorkerId as L, elapsedOf as M, isChatPane as N, ageOf as O, isLive as P, nowStamp as R, discardWorker as S, appendLedger as T, longInlinePromptHint as U, setWorkerLabel as V, parseRunnerArgs as W, itermUuid as _, projectLaunchConfig as a, sessionTag as b, handoffFromInside as c, workerDepth as d, checkPaneForWorker as f, itermForClaudeSession as g, currentTabKey as h, usageContextTokens as i, contextPercent as j, alive as k, readInbox as l, openPaneForWorker as m, runWorker as n, parseWorkerReport as o, openFollowPane as p, expandMcpNames as q, testProvider as r, renderReport as s, printResult as t, sayToWorker as u, resolveSession as v, worktreesDir as w, workerInScope as x, sessionMapPath as y, ownsPid as z };
4078
+ //# sourceMappingURL=run-CqRvXGjd.mjs.map