@gajae-code/coding-agent 0.17.2 → 0.17.5

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 (390) hide show
  1. package/CHANGELOG.md +267 -0
  2. package/dist/types/cli/daemon-cli.d.ts +3 -1
  3. package/dist/types/cli/github-release.d.ts +17 -0
  4. package/dist/types/cli/public-command-entry.d.ts +56 -0
  5. package/dist/types/cli/public-command-errors.d.ts +126 -0
  6. package/dist/types/cli/public-command-evidence.d.ts +99 -0
  7. package/dist/types/cli/public-command-help.d.ts +65 -0
  8. package/dist/types/cli/public-command-registry.d.ts +69 -0
  9. package/dist/types/cli/session-picker.d.ts +1 -1
  10. package/dist/types/cli/setup-cli.d.ts +1 -0
  11. package/dist/types/cli/skills-cli.d.ts +5 -0
  12. package/dist/types/cli.d.ts +3 -0
  13. package/dist/types/commands/daemon.d.ts +4 -50
  14. package/dist/types/commands/sdk.d.ts +20 -37
  15. package/dist/types/commands/setup.d.ts +3 -0
  16. package/dist/types/commands/skills.d.ts +9 -0
  17. package/dist/types/config/autorouting-tier-map.d.ts +1049 -3
  18. package/dist/types/config/file-lock.d.ts +13 -3
  19. package/dist/types/config/model-profile-activation.d.ts +45 -1
  20. package/dist/types/config/model-registry.d.ts +14 -3
  21. package/dist/types/config/model-resolver.d.ts +1 -1
  22. package/dist/types/config/settings-schema.d.ts +11 -0
  23. package/dist/types/coordinator-mcp/question-state.d.ts +6 -1
  24. package/dist/types/daemon/operator-contract.d.ts +5 -1
  25. package/dist/types/eval/js/worker-protocol.d.ts +2 -0
  26. package/dist/types/exec/bash-executor.d.ts +2 -0
  27. package/dist/types/extensibility/extensions/types.d.ts +12 -0
  28. package/dist/types/extensibility/gjc-plugins/registry.d.ts +4 -0
  29. package/dist/types/extensibility/gjc-plugins/runtime-adapters.d.ts +11 -2
  30. package/dist/types/extensibility/runtime-skill-discovery.d.ts +18 -0
  31. package/dist/types/extensibility/shared-events.d.ts +3 -1
  32. package/dist/types/gjc-runtime/session-state-lock.d.ts +61 -0
  33. package/dist/types/gjc-runtime/state-writer.d.ts +14 -1
  34. package/dist/types/harness-control-plane/control-endpoint.d.ts +4 -1
  35. package/dist/types/harness-control-plane/finalize.d.ts +14 -3
  36. package/dist/types/internal-urls/embedded-protocol.d.ts +9 -0
  37. package/dist/types/internal-urls/index.d.ts +1 -0
  38. package/dist/types/internal-urls/parse.d.ts +9 -1
  39. package/dist/types/main.d.ts +23 -1
  40. package/dist/types/modes/acp/acp-agent.d.ts +55 -1
  41. package/dist/types/modes/acp/startup-provenance.d.ts +16 -0
  42. package/dist/types/modes/components/custom-provider-wizard.d.ts +19 -1
  43. package/dist/types/modes/components/session-selector.d.ts +5 -2
  44. package/dist/types/modes/components/user-message-selector.d.ts +5 -2
  45. package/dist/types/modes/controllers/command-controller.d.ts +1 -1
  46. package/dist/types/modes/controllers/selector-controller.d.ts +1 -1
  47. package/dist/types/modes/interactive-mode.d.ts +1 -1
  48. package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +11 -1
  49. package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +14 -1
  50. package/dist/types/modes/types.d.ts +2 -2
  51. package/dist/types/runtime/process-lifecycle.d.ts +2 -0
  52. package/dist/types/runtime-mcp/loader.d.ts +2 -0
  53. package/dist/types/runtime-mcp/manager.d.ts +69 -6
  54. package/dist/types/runtime-mcp/pool.d.ts +17 -0
  55. package/dist/types/runtime-mcp/redaction.d.ts +20 -0
  56. package/dist/types/runtime-mcp/startup-policy.d.ts +6 -0
  57. package/dist/types/runtime-mcp/tool-bridge.d.ts +9 -0
  58. package/dist/types/runtime-mcp/transports/http.d.ts +11 -0
  59. package/dist/types/sdk/broker/broker.d.ts +17 -4
  60. package/dist/types/sdk/broker/ensure.d.ts +3 -0
  61. package/dist/types/sdk/broker/identity.d.ts +5 -1
  62. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +23 -3
  63. package/dist/types/sdk/broker/lifecycle.d.ts +15 -8
  64. package/dist/types/sdk/broker/managed-task-dag.d.ts +1335 -0
  65. package/dist/types/sdk/broker/managed-task-verification.d.ts +37 -0
  66. package/dist/types/sdk/broker/runtime.d.ts +1 -1
  67. package/dist/types/sdk/broker/session-index.d.ts +22 -3
  68. package/dist/types/sdk/broker/spawn-authority.d.ts +12 -0
  69. package/dist/types/sdk/broker/startup-failure.d.ts +4 -0
  70. package/dist/types/sdk/broker/stderr-drainer.d.ts +13 -0
  71. package/dist/types/sdk/bus/index.d.ts +19 -0
  72. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +7 -1
  73. package/dist/types/sdk/bus/telegram-daemon.d.ts +5 -0
  74. package/dist/types/sdk/cli/master-cli.d.ts +6 -10
  75. package/dist/types/sdk/cli/rows.d.ts +19 -1
  76. package/dist/types/sdk/cli/session-cli.d.ts +22 -5
  77. package/dist/types/sdk/client/client.d.ts +2 -0
  78. package/dist/types/sdk/guides/cli.d.ts +3 -4
  79. package/dist/types/sdk/guides/verify.d.ts +2 -0
  80. package/dist/types/sdk/host/host.d.ts +9 -0
  81. package/dist/types/sdk/host/session-runtime.d.ts +31 -0
  82. package/dist/types/sdk/host/types.d.ts +10 -0
  83. package/dist/types/sdk/index.d.ts +1 -0
  84. package/dist/types/sdk/prompt-deadline-flush.d.ts +85 -0
  85. package/dist/types/sdk/prompt-deadline-manager.d.ts +37 -0
  86. package/dist/types/sdk/prompt-tool-boundary.d.ts +73 -0
  87. package/dist/types/sdk/router/session-router.d.ts +2 -0
  88. package/dist/types/sdk/session.d.ts +3 -3
  89. package/dist/types/sdk/startup-capability.d.ts +2 -0
  90. package/dist/types/sdk/transport/relay.d.ts +1 -0
  91. package/dist/types/sdk/transport/serve-cli.d.ts +48 -4
  92. package/dist/types/sdk/transport/stdio.d.ts +5 -1
  93. package/dist/types/session/agent-session.d.ts +175 -23
  94. package/dist/types/session/fallback-chain-controller.d.ts +6 -6
  95. package/dist/types/session/fold-coordinator.d.ts +17 -3
  96. package/dist/types/session/internal/managed-session-storage.d.ts +7 -1
  97. package/dist/types/session/session-manager.d.ts +64 -1
  98. package/dist/types/session/session-work-lease.d.ts +14 -0
  99. package/dist/types/setup/model-onboarding-guidance.d.ts +1 -1
  100. package/dist/types/setup/provider-onboarding.d.ts +81 -1
  101. package/dist/types/task/types.d.ts +2 -0
  102. package/dist/types/tools/bash-interactive.d.ts +1 -0
  103. package/dist/types/tools/bash.d.ts +37 -11
  104. package/dist/types/tools/fetch.d.ts +10 -1
  105. package/dist/types/tools/job.d.ts +1 -1
  106. package/dist/types/tools/steer-fold.d.ts +31 -0
  107. package/dist/types/tools/subagent.d.ts +8 -1
  108. package/dist/types/utils/git.d.ts +28 -2
  109. package/dist/types/utils/mupdf-embedded.d.ts +2 -0
  110. package/dist/types/utils/mupdf.d.ts +4 -0
  111. package/dist/types/utils/session-title-generation.d.ts +6 -0
  112. package/dist/types/utils/title-generator.d.ts +11 -2
  113. package/dist/types/web/scrapers/types.d.ts +3 -0
  114. package/package.json +18 -10
  115. package/scripts/build-binary.ts +9 -3
  116. package/scripts/compile-args.ts +0 -9
  117. package/scripts/embed-mupdf.ts +52 -0
  118. package/scripts/generate-sdk-operation-inventory.ts +31 -1
  119. package/scripts/vendor-markit.ts +196 -0
  120. package/src/async/job-manager.ts +22 -1
  121. package/src/cli/daemon-cli.ts +53 -18
  122. package/src/cli/github-release.ts +87 -5
  123. package/src/cli/mcp-cli.ts +38 -4
  124. package/src/cli/public-command-entry.ts +450 -0
  125. package/src/cli/public-command-errors.ts +581 -0
  126. package/src/cli/public-command-evidence.ts +717 -0
  127. package/src/cli/public-command-help.ts +360 -0
  128. package/src/cli/public-command-registry.ts +541 -0
  129. package/src/cli/session-picker.ts +2 -1
  130. package/src/cli/setup-cli.ts +10 -1
  131. package/src/cli/skills-cli.ts +46 -2
  132. package/src/cli/stats-cli.ts +11 -1
  133. package/src/cli.ts +61 -1
  134. package/src/commands/daemon.ts +65 -69
  135. package/src/commands/sdk.ts +175 -117
  136. package/src/commands/setup.ts +2 -0
  137. package/src/commands/skills.ts +11 -0
  138. package/src/config/autorouting-tier-map.ts +543 -3
  139. package/src/config/file-lock.ts +206 -65
  140. package/src/config/model-discovery-manager.ts +4 -4
  141. package/src/config/model-profile-activation.ts +417 -66
  142. package/src/config/model-registry.ts +254 -36
  143. package/src/config/model-resolver.ts +6 -1
  144. package/src/config/settings-schema.ts +26 -2
  145. package/src/coordinator-mcp/policy.ts +10 -5
  146. package/src/coordinator-mcp/question-gate-codec.ts +17 -0
  147. package/src/coordinator-mcp/question-state.ts +179 -9
  148. package/src/coordinator-mcp/server.ts +521 -87
  149. package/src/coordinator-mcp/session-reaper.ts +6 -4
  150. package/src/crash/record-loader.ts +6 -2
  151. package/src/daemon/operator-contract.ts +26 -12
  152. package/src/defaults/gjc/skills/ultragoal/SKILL.md +1 -1
  153. package/src/eval/js/context-manager.ts +8 -8
  154. package/src/eval/js/worker-core.ts +9 -4
  155. package/src/eval/js/worker-protocol.ts +2 -0
  156. package/src/exec/bash-executor.ts +3 -0
  157. package/src/extensibility/extensions/runner.ts +52 -4
  158. package/src/extensibility/extensions/types.ts +10 -0
  159. package/src/extensibility/gjc-plugins/registry.ts +196 -37
  160. package/src/extensibility/gjc-plugins/runtime-adapters.ts +46 -8
  161. package/src/extensibility/runtime-skill-discovery.ts +61 -3
  162. package/src/extensibility/shared-events.ts +3 -1
  163. package/src/gjc-runtime/session-state-lock.ts +165 -24
  164. package/src/gjc-runtime/state-writer.ts +317 -6
  165. package/src/gjc-runtime/ultragoal-succession.ts +31 -3
  166. package/src/harness-control-plane/control-endpoint.ts +24 -6
  167. package/src/harness-control-plane/finalize.ts +312 -25
  168. package/src/harness-control-plane/owner.ts +323 -89
  169. package/src/internal-urls/docs-index.generated.ts +23 -20
  170. package/src/internal-urls/embedded-protocol.ts +83 -0
  171. package/src/internal-urls/index.ts +1 -0
  172. package/src/internal-urls/parse.ts +21 -1
  173. package/src/internal-urls/router.ts +4 -2
  174. package/src/main.ts +192 -74
  175. package/src/modes/acp/acp-agent.ts +973 -56
  176. package/src/modes/acp/startup-provenance.ts +59 -0
  177. package/src/modes/components/custom-provider-wizard.ts +308 -7
  178. package/src/modes/components/gjc-bundle-settings.ts +21 -1
  179. package/src/modes/components/oauth-selector.ts +9 -0
  180. package/src/modes/components/session-selector.ts +47 -4
  181. package/src/modes/components/tool-status-header.ts +72 -6
  182. package/src/modes/components/user-message-selector.ts +57 -15
  183. package/src/modes/controllers/command-controller.ts +58 -32
  184. package/src/modes/controllers/extension-ui-controller.ts +33 -7
  185. package/src/modes/controllers/input-controller.ts +4 -0
  186. package/src/modes/controllers/runtime-mcp-command-controller.ts +1 -1
  187. package/src/modes/controllers/selector-controller.ts +161 -15
  188. package/src/modes/interactive-mode.ts +21 -7
  189. package/src/modes/runtime-init.ts +1 -0
  190. package/src/modes/shared/agent-wire/workflow-gate-broker.ts +124 -7
  191. package/src/modes/shared/agent-wire/workflow-gate-types.ts +16 -2
  192. package/src/modes/types.ts +2 -2
  193. package/src/prompts/agent-fragments/browser-aside.md +1 -0
  194. package/src/prompts/system/title-system.md +1 -1
  195. package/src/prompts/tools/bash.md +1 -1
  196. package/src/prompts/tools/job.md +1 -1
  197. package/src/prompts/tools/read.md +2 -0
  198. package/src/runtime/network-prewarm-service.test.ts +36 -1
  199. package/src/runtime/network-prewarm-service.ts +28 -3
  200. package/src/runtime/process-lifecycle.ts +22 -11
  201. package/src/runtime-mcp/config.ts +16 -1
  202. package/src/runtime-mcp/loader.ts +6 -3
  203. package/src/runtime-mcp/manager.ts +845 -109
  204. package/src/runtime-mcp/pool.test.ts +31 -0
  205. package/src/runtime-mcp/pool.ts +304 -28
  206. package/src/runtime-mcp/redaction.ts +42 -0
  207. package/src/runtime-mcp/startup-policy.ts +7 -0
  208. package/src/runtime-mcp/tool-bridge.ts +71 -0
  209. package/src/runtime-mcp/transports/http.ts +108 -25
  210. package/src/sdk/acp/adapter.ts +27 -8
  211. package/src/sdk/broker/broker.ts +1431 -198
  212. package/src/sdk/broker/ensure.ts +21 -3
  213. package/src/sdk/broker/identity.ts +22 -1
  214. package/src/sdk/broker/lifecycle-ledger.ts +95 -31
  215. package/src/sdk/broker/lifecycle.ts +690 -141
  216. package/src/sdk/broker/managed-task-dag.ts +1927 -0
  217. package/src/sdk/broker/managed-task-verification.ts +642 -0
  218. package/src/sdk/broker/runtime.ts +1 -1
  219. package/src/sdk/broker/session-index.ts +97 -4
  220. package/src/sdk/broker/spawn-authority.ts +175 -14
  221. package/src/sdk/broker/startup-failure.ts +80 -1
  222. package/src/sdk/broker/stderr-drainer.ts +59 -0
  223. package/src/sdk/broker/transport.ts +1 -0
  224. package/src/sdk/bus/chat-daemon-control.ts +2 -2
  225. package/src/sdk/bus/chat-daemon-runtime.ts +1 -0
  226. package/src/sdk/bus/index.ts +707 -81
  227. package/src/sdk/bus/telegram-daemon-cli.ts +31 -2
  228. package/src/sdk/bus/telegram-daemon-contract.ts +7 -1
  229. package/src/sdk/bus/telegram-daemon.ts +10 -3
  230. package/src/sdk/cli/master-cli.ts +47 -36
  231. package/src/sdk/cli/rows.ts +30 -7
  232. package/src/sdk/cli/session-cli.ts +705 -184
  233. package/src/sdk/client/client.ts +18 -0
  234. package/src/sdk/guides/catalog.ts +2 -2
  235. package/src/sdk/guides/cli.ts +20 -62
  236. package/src/sdk/guides/verify.ts +14 -0
  237. package/src/sdk/host/host.ts +49 -5
  238. package/src/sdk/host/session-runtime.test.ts +184 -2
  239. package/src/sdk/host/session-runtime.ts +322 -101
  240. package/src/sdk/host/types.ts +12 -1
  241. package/src/sdk/host/websocket-transport.lifecycle.test.ts +84 -0
  242. package/src/sdk/host/websocket-transport.ts +40 -6
  243. package/src/sdk/index.ts +11 -0
  244. package/src/sdk/lifecycle/service.ts +2 -0
  245. package/src/sdk/prompt-deadline-flush.ts +356 -0
  246. package/src/sdk/prompt-deadline-manager.ts +133 -1
  247. package/src/sdk/prompt-tool-boundary.ts +121 -0
  248. package/src/sdk/protocol/operation-inventory.generated.json +106 -0
  249. package/src/sdk/router/session-router.ts +9 -1
  250. package/src/sdk/session.ts +763 -116
  251. package/src/sdk/startup-capability.ts +1 -1
  252. package/src/sdk/transport/relay.ts +71 -6
  253. package/src/sdk/transport/serve-cli.ts +397 -42
  254. package/src/sdk/transport/socket.ts +12 -11
  255. package/src/sdk/transport/stdio.ts +7 -3
  256. package/src/session/agent-session.ts +2472 -407
  257. package/src/session/fallback-chain-controller.ts +6 -7
  258. package/src/session/fold-coordinator.ts +24 -5
  259. package/src/session/internal/managed-session-scope.ts +68 -18
  260. package/src/session/internal/managed-session-storage.ts +334 -12
  261. package/src/session/session-manager.ts +382 -44
  262. package/src/session/session-work-lease.ts +34 -0
  263. package/src/setup/model-onboarding-guidance.ts +1 -1
  264. package/src/setup/provider-onboarding.ts +397 -24
  265. package/src/setup/provider-presets.json +2 -1
  266. package/src/slash-commands/builtin-registry.ts +259 -15
  267. package/src/task/executor.ts +46 -17
  268. package/src/task/index.ts +14 -2
  269. package/src/task/types.ts +2 -0
  270. package/src/tools/bash-interactive.ts +2 -0
  271. package/src/tools/bash.ts +118 -78
  272. package/src/tools/fetch.ts +140 -25
  273. package/src/tools/job.ts +151 -25
  274. package/src/tools/output-meta.ts +15 -2
  275. package/src/tools/path-utils.ts +27 -3
  276. package/src/tools/read.ts +3 -3
  277. package/src/tools/steer-fold.ts +107 -0
  278. package/src/tools/subagent-render.ts +24 -1
  279. package/src/tools/subagent.ts +27 -1
  280. package/src/tools/tool-catalog.generated.ts +29 -2
  281. package/src/tools/tool-errors.ts +4 -0
  282. package/src/utils/git.ts +53 -3
  283. package/src/utils/markit.ts +55 -41
  284. package/src/utils/mupdf-assets.d.ts +4 -0
  285. package/src/utils/mupdf-embedded.ts +4 -0
  286. package/src/utils/mupdf.ts +136 -0
  287. package/src/utils/session-title-generation.ts +29 -0
  288. package/src/utils/title-generator.ts +46 -2
  289. package/src/web/scrapers/types.ts +24 -3
  290. package/vendor/markit-ai/LICENSE +21 -0
  291. package/vendor/markit-ai/MANIFEST.json +412 -0
  292. package/vendor/markit-ai/dist/commands/config.d.ts +4 -0
  293. package/vendor/markit-ai/dist/commands/config.js +139 -0
  294. package/vendor/markit-ai/dist/commands/convert.d.ts +6 -0
  295. package/vendor/markit-ai/dist/commands/convert.js +113 -0
  296. package/vendor/markit-ai/dist/commands/formats.d.ts +2 -0
  297. package/vendor/markit-ai/dist/commands/formats.js +92 -0
  298. package/vendor/markit-ai/dist/commands/init.d.ts +2 -0
  299. package/vendor/markit-ai/dist/commands/init.js +29 -0
  300. package/vendor/markit-ai/dist/commands/onboard.d.ts +2 -0
  301. package/vendor/markit-ai/dist/commands/onboard.js +61 -0
  302. package/vendor/markit-ai/dist/commands/plugin.d.ts +4 -0
  303. package/vendor/markit-ai/dist/commands/plugin.js +58 -0
  304. package/vendor/markit-ai/dist/config.d.ts +26 -0
  305. package/vendor/markit-ai/dist/config.js +42 -0
  306. package/vendor/markit-ai/dist/converters/audio.d.ts +7 -0
  307. package/vendor/markit-ai/dist/converters/audio.js +104 -0
  308. package/vendor/markit-ai/dist/converters/csv.d.ts +7 -0
  309. package/vendor/markit-ai/dist/converters/csv.js +83 -0
  310. package/vendor/markit-ai/dist/converters/docx.d.ts +6 -0
  311. package/vendor/markit-ai/dist/converters/docx.js +57 -0
  312. package/vendor/markit-ai/dist/converters/epub.d.ts +8 -0
  313. package/vendor/markit-ai/dist/converters/epub.js +128 -0
  314. package/vendor/markit-ai/dist/converters/github.d.ts +18 -0
  315. package/vendor/markit-ai/dist/converters/github.js +148 -0
  316. package/vendor/markit-ai/dist/converters/html.d.ts +6 -0
  317. package/vendor/markit-ai/dist/converters/html.js +30 -0
  318. package/vendor/markit-ai/dist/converters/image.d.ts +6 -0
  319. package/vendor/markit-ai/dist/converters/image.js +124 -0
  320. package/vendor/markit-ai/dist/converters/ipynb.d.ts +6 -0
  321. package/vendor/markit-ai/dist/converters/ipynb.js +75 -0
  322. package/vendor/markit-ai/dist/converters/iwork.d.ts +20 -0
  323. package/vendor/markit-ai/dist/converters/iwork.js +391 -0
  324. package/vendor/markit-ai/dist/converters/json.d.ts +6 -0
  325. package/vendor/markit-ai/dist/converters/json.js +21 -0
  326. package/vendor/markit-ai/dist/converters/pdf/columns.d.ts +35 -0
  327. package/vendor/markit-ai/dist/converters/pdf/columns.js +93 -0
  328. package/vendor/markit-ai/dist/converters/pdf/extract.d.ts +19 -0
  329. package/vendor/markit-ai/dist/converters/pdf/extract.js +514 -0
  330. package/vendor/markit-ai/dist/converters/pdf/grid.d.ts +25 -0
  331. package/vendor/markit-ai/dist/converters/pdf/grid.js +795 -0
  332. package/vendor/markit-ai/dist/converters/pdf/headers.d.ts +24 -0
  333. package/vendor/markit-ai/dist/converters/pdf/headers.js +108 -0
  334. package/vendor/markit-ai/dist/converters/pdf/index.d.ts +19 -0
  335. package/vendor/markit-ai/dist/converters/pdf/index.js +136 -0
  336. package/vendor/markit-ai/dist/converters/pdf/mupdf-loader.js +9 -0
  337. package/vendor/markit-ai/dist/converters/pdf/render.d.ts +24 -0
  338. package/vendor/markit-ai/dist/converters/pdf/render.js +513 -0
  339. package/vendor/markit-ai/dist/converters/pdf/types.d.ts +75 -0
  340. package/vendor/markit-ai/dist/converters/pdf/types.js +1 -0
  341. package/vendor/markit-ai/dist/converters/plain-text.d.ts +6 -0
  342. package/vendor/markit-ai/dist/converters/plain-text.js +87 -0
  343. package/vendor/markit-ai/dist/converters/pptx.d.ts +8 -0
  344. package/vendor/markit-ai/dist/converters/pptx.js +289 -0
  345. package/vendor/markit-ai/dist/converters/rss.d.ts +11 -0
  346. package/vendor/markit-ai/dist/converters/rss.js +138 -0
  347. package/vendor/markit-ai/dist/converters/wikipedia.d.ts +6 -0
  348. package/vendor/markit-ai/dist/converters/wikipedia.js +33 -0
  349. package/vendor/markit-ai/dist/converters/xlsx.d.ts +8 -0
  350. package/vendor/markit-ai/dist/converters/xlsx.js +147 -0
  351. package/vendor/markit-ai/dist/converters/xml.d.ts +6 -0
  352. package/vendor/markit-ai/dist/converters/xml.js +18 -0
  353. package/vendor/markit-ai/dist/converters/yaml.d.ts +6 -0
  354. package/vendor/markit-ai/dist/converters/yaml.js +17 -0
  355. package/vendor/markit-ai/dist/converters/zip.d.ts +8 -0
  356. package/vendor/markit-ai/dist/converters/zip.js +57 -0
  357. package/vendor/markit-ai/dist/index.d.ts +30 -0
  358. package/vendor/markit-ai/dist/index.js +26 -0
  359. package/vendor/markit-ai/dist/main.d.ts +2 -0
  360. package/vendor/markit-ai/dist/main.js +191 -0
  361. package/vendor/markit-ai/dist/markit.d.ts +45 -0
  362. package/vendor/markit-ai/dist/markit.js +267 -0
  363. package/vendor/markit-ai/dist/plugins/api.d.ts +7 -0
  364. package/vendor/markit-ai/dist/plugins/api.js +42 -0
  365. package/vendor/markit-ai/dist/plugins/index.d.ts +4 -0
  366. package/vendor/markit-ai/dist/plugins/index.js +3 -0
  367. package/vendor/markit-ai/dist/plugins/installer.d.ts +25 -0
  368. package/vendor/markit-ai/dist/plugins/installer.js +176 -0
  369. package/vendor/markit-ai/dist/plugins/loader.d.ts +6 -0
  370. package/vendor/markit-ai/dist/plugins/loader.js +61 -0
  371. package/vendor/markit-ai/dist/plugins/types.d.ts +25 -0
  372. package/vendor/markit-ai/dist/plugins/types.js +1 -0
  373. package/vendor/markit-ai/dist/providers/anthropic.d.ts +2 -0
  374. package/vendor/markit-ai/dist/providers/anthropic.js +47 -0
  375. package/vendor/markit-ai/dist/providers/index.d.ts +21 -0
  376. package/vendor/markit-ai/dist/providers/index.js +56 -0
  377. package/vendor/markit-ai/dist/providers/openai.d.ts +2 -0
  378. package/vendor/markit-ai/dist/providers/openai.js +76 -0
  379. package/vendor/markit-ai/dist/providers/types.d.ts +26 -0
  380. package/vendor/markit-ai/dist/providers/types.js +1 -0
  381. package/vendor/markit-ai/dist/types.d.ts +36 -0
  382. package/vendor/markit-ai/dist/types.js +1 -0
  383. package/vendor/markit-ai/dist/utils/exit-codes.d.ts +4 -0
  384. package/vendor/markit-ai/dist/utils/exit-codes.js +4 -0
  385. package/vendor/markit-ai/dist/utils/output.d.ts +22 -0
  386. package/vendor/markit-ai/dist/utils/output.js +31 -0
  387. package/vendor/markit-ai/dist/utils/turndown.d.ts +8 -0
  388. package/vendor/markit-ai/dist/utils/turndown.js +70 -0
  389. package/vendor/markit-ai/package.json +74 -0
  390. package/vendor/markit-ai.patch +49 -0
@@ -44,12 +44,14 @@ export type FileLockAcquireReason = "acquire_timeout" | "orphan_transition";
44
44
  * generation); this records the cause that exhaustion must report.
45
45
  */
46
46
  export interface FileLockStaleRemovalFailure {
47
- /** Guarded-removal outcome the acquire path can record, or `"error"` when the removal attempt threw. */
48
- outcome: "cleanup_failed" | "error";
47
+ /** Guarded-removal outcome; refusals are surfaced only after exhaustion revalidates the dead generation. */
48
+ outcome: "cleanup_failed" | "owner_changed" | "missing" | "error";
49
49
  /** Native/errno code carried by the refusal, when one was present. */
50
50
  code?: string;
51
51
  /** Human-readable cause surfaced to the operator at exhaustion. */
52
52
  message: string;
53
+ /** Platform-specific manual cleanup command, set only when the same dead owner persists at exhaustion. */
54
+ manualCleanupCommand?: string;
53
55
  }
54
56
 
55
57
  export class FileLockAcquireError extends Error {
@@ -70,10 +72,12 @@ export class FileLockAcquireError extends Error {
70
72
  removalFailure.code ? ` [${removalFailure.code}]` : ""
71
73
  })`
72
74
  : "";
75
+ const cleanupDetail = removalFailure?.manualCleanupCommand
76
+ ? `; manual cleanup is appropriate only after independently verifying this exact directory still belongs to the dead owner and no successor has taken it: ${removalFailure.manualCleanupCommand}`
77
+ : "";
73
78
  super(
74
79
  `Failed to acquire lock for ${filePath} after ${attempts} attempts: ${detail}${removalDetail} (${lockPath}); ` +
75
- `a live owner is never displaced — if this is an SDK broker (gjc sdk session list), it must finish or be stopped before retrying; ` +
76
- `the lock is a directory, remove it only by deleting the directory (${lockPath}) once no live owner remains`,
80
+ `a live owner is never displaced — if this is an SDK broker (gjc sdk session list), it must finish or be stopped before retrying${cleanupDetail}`,
77
81
  );
78
82
  this.code = reason;
79
83
  this.name = "FileLockAcquireError";
@@ -92,6 +96,15 @@ const DEFAULT_OPTIONS: Required<
92
96
  retryDelayMs: 100,
93
97
  };
94
98
 
99
+ /**
100
+ * Windows can transiently deny a no-replace publication while another handle still
101
+ * has the staged or destination path open without delete sharing. The native result
102
+ * is explicitly pre-mutation in this case, so retrying the same source name cannot
103
+ * publish twice or clean up a committed namespace change.
104
+ */
105
+ const PUBLICATION_SHARING_RETRY_ATTEMPTS = 3;
106
+ const PUBLICATION_SHARING_RETRY_DELAY_MS = 10;
107
+
95
108
  /** Release retries cover transient handle denial and a competing exact-removal quarantine cleanup. */
96
109
  export const FILE_LOCK_RELEASE_RETRY_ATTEMPTS = 20;
97
110
  export const FILE_LOCK_RELEASE_RETRY_DELAY_MS = 25;
@@ -232,6 +245,7 @@ type LockInfoFileState = {
232
245
  size: bigint;
233
246
  mtimeNs: bigint;
234
247
  ctimeNs: bigint;
248
+ birthtimeNs: bigint;
235
249
  nlink: bigint;
236
250
  };
237
251
 
@@ -246,6 +260,10 @@ type LockInfoPathState = {
246
260
 
247
261
  function lockInfoFileState(stats: BigIntStats): LockInfoFileState | null {
248
262
  if (stats.isSymbolicLink() || !stats.isFile()) return null;
263
+ // Some supported filesystems report creation time as missing or epoch zero. Keep
264
+ // the stable dev/inode identity and content evidence usable instead of wedging
265
+ // acquire/release/GC on a metadata field the filesystem cannot provide.
266
+ const birthtimeNs = typeof stats.birthtimeNs === "bigint" && stats.birthtimeNs > 0n ? stats.birthtimeNs : 0n;
249
267
  return {
250
268
  dev: stats.dev,
251
269
  ino: stats.ino,
@@ -253,18 +271,21 @@ function lockInfoFileState(stats: BigIntStats): LockInfoFileState | null {
253
271
  size: stats.size,
254
272
  mtimeNs: stats.mtimeNs,
255
273
  ctimeNs: stats.ctimeNs,
274
+ birthtimeNs,
256
275
  nlink: stats.nlink,
257
276
  };
258
277
  }
259
278
 
260
279
  function sameLockInfoFileState(left: LockInfoFileState, right: LockInfoFileState): boolean {
280
+ const birthtimeMatches =
281
+ left.birthtimeNs === 0n || right.birthtimeNs === 0n || left.birthtimeNs === right.birthtimeNs;
261
282
  return (
262
283
  left.dev === right.dev &&
263
284
  left.ino === right.ino &&
264
285
  left.mode === right.mode &&
265
286
  left.size === right.size &&
266
287
  left.mtimeNs === right.mtimeNs &&
267
- left.ctimeNs === right.ctimeNs &&
288
+ birthtimeMatches &&
268
289
  left.nlink === right.nlink
269
290
  );
270
291
  }
@@ -313,6 +334,7 @@ function fileLockDirIdentityFromPathState(state: LockInfoPathState, bytes: strin
313
334
  infoSize: String(state.file.size),
314
335
  infoMtimeNs: String(state.file.mtimeNs),
315
336
  infoCtimeNs: String(state.file.ctimeNs),
337
+ infoBirthtimeNs: String(state.file.birthtimeNs),
316
338
  infoSha256: crypto.createHash("sha256").update(bytes).digest("hex"),
317
339
  };
318
340
  }
@@ -680,6 +702,8 @@ function sameFileLockTreeAfterPublication(
680
702
  staged: NativeDirectoryTreeSnapshot,
681
703
  published: NativeDirectoryTreeSnapshot,
682
704
  ): boolean {
705
+ // ctime is intentionally omitted: native snapshots expose no birthtime, and a
706
+ // metadata-only change must not reject an otherwise identical published tree.
683
707
  return (
684
708
  staged.rootDev === published.rootDev &&
685
709
  staged.rootIno === published.rootIno &&
@@ -695,7 +719,6 @@ function sameFileLockTreeAfterPublication(
695
719
  entry.nlink === current.nlink &&
696
720
  entry.size === current.size &&
697
721
  entry.mtimeNs === current.mtimeNs &&
698
- (entry.relativePath === "" || entry.ctimeNs === current.ctimeNs) &&
699
722
  entry.sha256 === current.sha256
700
723
  );
701
724
  })
@@ -879,6 +902,7 @@ function isValidNativeNoReplaceResult(value: unknown): value is NativeNoReplaceR
879
902
  "interrupted",
880
903
  "identity_violation",
881
904
  "durability_not_provable",
905
+ "sharing_violation",
882
906
  "unknown",
883
907
  ] as const
884
908
  ).includes(value.reason as never) ||
@@ -954,25 +978,18 @@ function isValidNativeNoReplaceResult(value: unknown): value is NativeNoReplaceR
954
978
  function isSuccessfulNativePublication(value: unknown, operation: "primary" | "directory"): boolean {
955
979
  if (!isValidNativeNoReplaceResult(value) || !value.ok) return false;
956
980
  if (operation === "directory") return value.primitive === "mkdirat_renameat_noreplace";
957
- switch (process.platform) {
958
- case "linux":
959
- return value.primitive === "renameat2_noreplace";
960
- case "darwin":
961
- return value.primitive === "renameatx_np_excl";
962
- case "win32":
963
- return value.primitive === "windows_rename_noreplace";
964
- default:
965
- return false;
966
- }
981
+ // Native code records the primitive it actually invoked in the receipt. That
982
+ // primitive is the producer-platform evidence; process.platform is only ambient
983
+ // capability metadata and may be overridden by a coordinator discovery test.
984
+ return (
985
+ value.primitive === "renameat2_noreplace" ||
986
+ value.primitive === "renameatx_np_excl" ||
987
+ value.primitive === "windows_rename_noreplace"
988
+ );
967
989
  }
968
990
 
969
991
  function isCommittedDirectoryVerificationFailure(value: unknown): value is NativeNoReplaceResult {
970
- return (
971
- process.platform === "linux" &&
972
- isValidNativeNoReplaceResult(value) &&
973
- !value.ok &&
974
- value.mutationState === "committed"
975
- );
992
+ return isValidNativeNoReplaceResult(value) && !value.ok && value.mutationState === "committed";
976
993
  }
977
994
 
978
995
  /**
@@ -996,6 +1013,35 @@ function isPreMutationUnsupportedRenameResult(value: unknown): value is NativeNo
996
1013
  return true;
997
1014
  }
998
1015
 
1016
+ function isPreMutationSharingViolation(value: unknown): value is NativeNoReplaceResult {
1017
+ return (
1018
+ isValidNativeNoReplaceResult(value) &&
1019
+ !value.ok &&
1020
+ value.code === "sharing_violation" &&
1021
+ value.mutationState === "not_committed" &&
1022
+ value.durabilityState === "not_attempted" &&
1023
+ value.reason === "sharing_violation" &&
1024
+ value.phase === "rename"
1025
+ );
1026
+ }
1027
+
1028
+ async function publishNoReplaceWithSharingRetry(
1029
+ publish: (sourcePath: string, destinationPath: string) => Promise<NativeNoReplaceResult>,
1030
+ sourcePath: string,
1031
+ destinationPath: string,
1032
+ ): Promise<NativeNoReplaceResult> {
1033
+ let result = await publish(sourcePath, destinationPath);
1034
+ for (
1035
+ let attempt = 1;
1036
+ attempt < PUBLICATION_SHARING_RETRY_ATTEMPTS && isPreMutationSharingViolation(result);
1037
+ attempt++
1038
+ ) {
1039
+ await Bun.sleep(PUBLICATION_SHARING_RETRY_DELAY_MS * attempt);
1040
+ result = await publish(sourcePath, destinationPath);
1041
+ }
1042
+ return result;
1043
+ }
1044
+
999
1045
  async function localLockKey(lockPath: string): Promise<string> {
1000
1046
  try {
1001
1047
  return normalizeLockKey(await fs.realpath(lockPath));
@@ -1027,6 +1073,10 @@ function ownerIncarnationChanged(owner: FileLockOwnerToken, startTimeCache?: Map
1027
1073
  return currentStartTime !== null && currentStartTime !== owner.start_time;
1028
1074
  }
1029
1075
 
1076
+ function ownerGenerationIsDead(owner: FileLockOwnerToken): boolean {
1077
+ return ownerLiveness(owner.pid) === "dead" || ownerIncarnationChanged(owner);
1078
+ }
1079
+
1030
1080
  /** Outcome of a guarded lock-dir removal attempt (`removeFileLockDirForGc`). */
1031
1081
  export type FileLockGcRemoval = "removed" | "owner_changed" | "missing" | "cleanup_failed";
1032
1082
 
@@ -1034,7 +1084,14 @@ type LockStaleSnapshot =
1034
1084
  | { stale: false }
1035
1085
  | { stale: true; owner: FileLockOwnerToken; identity: GenericFileLockDirIdentity };
1036
1086
 
1037
- /** Identity evidence carried by the generic stale verdict into a later removal. */
1087
+ /**
1088
+ * Identity evidence carried by the generic stale verdict into a later removal.
1089
+ *
1090
+ * `ctimeNs` is a mutable metadata-change time on every supported filesystem, so
1091
+ * it is retained for diagnostics/legacy consumers but is not part of the lock
1092
+ * identity predicate. `infoBirthtimeNs` is the creation time that stays bound
1093
+ * to the file object.
1094
+ */
1038
1095
  export interface GenericFileLockDirIdentity {
1039
1096
  rootDev: string;
1040
1097
  rootIno: string;
@@ -1044,23 +1101,34 @@ export interface GenericFileLockDirIdentity {
1044
1101
  infoSize: string;
1045
1102
  infoMtimeNs: string;
1046
1103
  infoCtimeNs: string;
1104
+ infoBirthtimeNs: string;
1047
1105
  infoSha256: string;
1048
1106
  }
1049
1107
 
1050
- function sameGenericFileLockDirIdentity(left: GenericFileLockDirIdentity, right: GenericFileLockDirIdentity): boolean {
1108
+ function sameStableFileLockIdentity(left: GenericFileLockDirIdentity, right: GenericFileLockDirIdentity): boolean {
1051
1109
  return (
1052
1110
  left.rootDev === right.rootDev &&
1053
1111
  left.rootIno === right.rootIno &&
1054
1112
  left.infoDev === right.infoDev &&
1055
1113
  left.infoIno === right.infoIno &&
1114
+ left.infoBirthtimeNs === right.infoBirthtimeNs
1115
+ );
1116
+ }
1117
+
1118
+ /** Content/topology evidence kept separate from the stable file identity. */
1119
+ function sameFileLockContentEvidence(left: GenericFileLockDirIdentity, right: GenericFileLockDirIdentity): boolean {
1120
+ return (
1056
1121
  left.infoNlink === right.infoNlink &&
1057
1122
  left.infoSize === right.infoSize &&
1058
1123
  left.infoMtimeNs === right.infoMtimeNs &&
1059
- left.infoCtimeNs === right.infoCtimeNs &&
1060
1124
  left.infoSha256 === right.infoSha256
1061
1125
  );
1062
1126
  }
1063
1127
 
1128
+ function sameGenericFileLockDirIdentity(left: GenericFileLockDirIdentity, right: GenericFileLockDirIdentity): boolean {
1129
+ return sameStableFileLockIdentity(left, right) && sameFileLockContentEvidence(left, right);
1130
+ }
1131
+
1064
1132
  let nativeExactRemovalUsable: boolean | undefined;
1065
1133
  let nativeExactRemovalProbePromise: Promise<boolean> | undefined;
1066
1134
 
@@ -1171,26 +1239,54 @@ async function removeVerifiedOwnedLockDirWithoutNative(
1171
1239
  return "cleanup_failed";
1172
1240
  }
1173
1241
  const current = await captureFileLockDirIdentity(lockDir);
1174
- if (!current || !sameGenericFileLockDirIdentity(current, expected)) return "owner_changed";
1242
+ if (!current || !sameStableFileLockIdentity(current, expected)) return "owner_changed";
1175
1243
  const captured = nativeFileLockBindings().snapshotDirectoryTree(lockDir);
1176
1244
  if (!captured.ok || !captured.snapshot) return "owner_changed";
1177
1245
  const infoEntry = captured.snapshot.entries.find(entry => entry.relativePath === "info");
1178
1246
  if (
1179
- captured.snapshot.rootDev !== expected.rootDev ||
1180
- captured.snapshot.rootIno !== expected.rootIno ||
1181
1247
  !infoEntry ||
1182
- infoEntry.dev !== expected.infoDev ||
1183
- infoEntry.ino !== expected.infoIno ||
1184
- infoEntry.nlink !== expected.infoNlink ||
1185
- infoEntry.size !== expected.infoSize ||
1186
- infoEntry.mtimeNs !== expected.infoMtimeNs ||
1187
- infoEntry.ctimeNs !== expected.infoCtimeNs ||
1188
- infoEntry.sha256 !== expected.infoSha256
1248
+ !nativeFileLockInfoMatchesStableIdentity(
1249
+ captured.snapshot.rootDev,
1250
+ captured.snapshot.rootIno,
1251
+ infoEntry,
1252
+ expected,
1253
+ ) ||
1254
+ !nativeFileLockInfoMatchesContentEvidence(infoEntry, expected)
1189
1255
  )
1190
1256
  return "owner_changed";
1191
1257
  return await removeVerifiedLockDirWithoutNative(lockDir, captured.snapshot, owner);
1192
1258
  }
1193
1259
 
1260
+ function nativeFileLockInfoMatchesStableIdentity(
1261
+ rootDev: string,
1262
+ rootIno: string,
1263
+ infoEntry: NativeDirectoryTreeSnapshot["entries"][number],
1264
+ expected: GenericFileLockDirIdentity,
1265
+ ): boolean {
1266
+ return (
1267
+ rootDev === expected.rootDev &&
1268
+ rootIno === expected.rootIno &&
1269
+ infoEntry.dev === expected.infoDev &&
1270
+ infoEntry.ino === expected.infoIno
1271
+ );
1272
+ }
1273
+
1274
+ function nativeFileLockInfoMatchesContentEvidence(
1275
+ infoEntry: NativeDirectoryTreeSnapshot["entries"][number],
1276
+ expected: GenericFileLockDirIdentity,
1277
+ ): boolean {
1278
+ // Native snapshots expose a ctime-shaped field, but ctime is a mutable
1279
+ // metadata-change timestamp on every supported filesystem. The stable file
1280
+ // identity is checked separately; requiring ctime here would reject a
1281
+ // legitimate lock after chmod/ACL/indexer activity.
1282
+ return (
1283
+ infoEntry.nlink === expected.infoNlink &&
1284
+ infoEntry.size === expected.infoSize &&
1285
+ infoEntry.mtimeNs === expected.infoMtimeNs &&
1286
+ infoEntry.sha256 === expected.infoSha256
1287
+ );
1288
+ }
1289
+
1194
1290
  export type GenericFileLockDirStaleVerdict = { stale: false } | { stale: true; identity: GenericFileLockDirIdentity };
1195
1291
 
1196
1292
  /**
@@ -1254,17 +1350,17 @@ export async function removeFileLockDirForGc(
1254
1350
  if (!infoEntry?.sha256) return "owner_changed";
1255
1351
  const judgedDigest = crypto.createHash("sha256").update(onDiskBytes).digest("hex");
1256
1352
  if (infoEntry.sha256 !== judgedDigest) return "owner_changed";
1353
+ const currentIdentity = await captureFileLockDirIdentity(nativeCapturePath);
1354
+ if (!currentIdentity || !sameStableFileLockIdentity(currentIdentity, expectedIdentity)) return "owner_changed";
1257
1355
  if (
1258
1356
  !captured.snapshot.rootDev ||
1259
- captured.snapshot.rootDev !== expectedIdentity.rootDev ||
1260
- captured.snapshot.rootIno !== expectedIdentity.rootIno ||
1261
- infoEntry.dev !== expectedIdentity.infoDev ||
1262
- infoEntry.ino !== expectedIdentity.infoIno ||
1263
- infoEntry.nlink !== expectedIdentity.infoNlink ||
1264
- infoEntry.size !== expectedIdentity.infoSize ||
1265
- infoEntry.mtimeNs !== expectedIdentity.infoMtimeNs ||
1266
- infoEntry.ctimeNs !== expectedIdentity.infoCtimeNs ||
1267
- infoEntry.sha256 !== expectedIdentity.infoSha256
1357
+ !nativeFileLockInfoMatchesStableIdentity(
1358
+ captured.snapshot.rootDev,
1359
+ captured.snapshot.rootIno,
1360
+ infoEntry,
1361
+ expectedIdentity,
1362
+ ) ||
1363
+ !nativeFileLockInfoMatchesContentEvidence(infoEntry, expectedIdentity)
1268
1364
  )
1269
1365
  return "owner_changed";
1270
1366
  let removed: NativeExactUnlinkResult;
@@ -1462,13 +1558,17 @@ async function staleLockSnapshot(
1462
1558
 
1463
1559
  type StaleLockRemovalAttempt = { removed: true } | { removed: false; failure?: FileLockStaleRemovalFailure };
1464
1560
 
1465
- type RecordedStaleRemovalFailure = { owner: FileLockOwnerToken; failure: FileLockStaleRemovalFailure };
1561
+ type RecordedStaleRemovalFailure = {
1562
+ owner: FileLockOwnerToken;
1563
+ identity: GenericFileLockDirIdentity;
1564
+ failure: FileLockStaleRemovalFailure;
1565
+ };
1466
1566
 
1467
1567
  /**
1468
- * A recorded refusal describes exactly one dead owner generation. Re-read the pathname at
1469
- * exhaustion and report it only while that same generation still owns the directory, so a
1470
- * refusal recorded for a dead generation is never pinned onto a live successor that took
1471
- * the pathname over before the budget ran out.
1568
+ * A recorded refusal describes exactly one dead owner generation and directory identity.
1569
+ * Re-read the pathname at exhaustion and report it only while both still match, so a refusal
1570
+ * recorded for a dead generation is never pinned onto a successor that took the pathname over
1571
+ * before the budget ran out, even if its legacy owner bytes are identical.
1472
1572
  */
1473
1573
  async function staleRemovalFailureForCurrentGeneration(
1474
1574
  lockPath: string,
@@ -1476,13 +1576,31 @@ async function staleRemovalFailureForCurrentGeneration(
1476
1576
  ): Promise<FileLockStaleRemovalFailure | undefined> {
1477
1577
  if (!recorded) return undefined;
1478
1578
  try {
1479
- const current = await readLockInfo(lockPath);
1480
- return current && sameFileLockOwnerToken(current, recorded.owner) ? recorded.failure : undefined;
1579
+ const observation = await readLockInfoObservation(lockPath);
1580
+ if (!observation) return undefined;
1581
+ const current = parseLockInfoBytes(observation.bytes);
1582
+ if (!current || !sameFileLockOwnerToken(current, recorded.owner) || !ownerGenerationIsDead(current))
1583
+ return undefined;
1584
+ const currentIdentity = fileLockDirIdentityFromPathState(observation.state, observation.bytes);
1585
+ if (!sameGenericFileLockDirIdentity(recorded.identity, currentIdentity)) return undefined;
1586
+ return {
1587
+ ...recorded.failure,
1588
+ manualCleanupCommand: manualLockCleanupCommand(lockPath),
1589
+ };
1481
1590
  } catch {
1482
1591
  return undefined;
1483
1592
  }
1484
1593
  }
1485
1594
 
1595
+ function manualLockCleanupCommand(lockPath: string): string {
1596
+ if (process.platform === "win32") {
1597
+ const quotedPath = lockPath.replace(/'/g, "''");
1598
+ return `Remove-Item -LiteralPath '${quotedPath}' -Recurse -Force`;
1599
+ }
1600
+ const quotedPath = lockPath.replace(/'/g, "'\\''");
1601
+ return `rm -rf -- '${quotedPath}'`;
1602
+ }
1603
+
1486
1604
  async function removeStaleLockForAcquire(
1487
1605
  lockPath: string,
1488
1606
  snapshot: LockStaleSnapshot,
@@ -1491,8 +1609,21 @@ async function removeStaleLockForAcquire(
1491
1609
  try {
1492
1610
  const outcome = await removeFileLockDirForGc(lockPath, snapshot.owner, snapshot.identity);
1493
1611
  if (outcome === "removed") return { removed: true };
1494
- // `owner_changed`/`missing` mean a successor or a concurrent reclaimer already
1495
- // owns the pathname; that is ordinary contention, not a host removal failure.
1612
+ // Either refusal can mean a successor or an incomplete publication owns the path;
1613
+ // keep it only as a diagnostic candidate and expose it at exhaustion if the same
1614
+ // dead owner still persists. Never fall back to path-only deletion.
1615
+ if (outcome === "owner_changed" || outcome === "missing") {
1616
+ return {
1617
+ removed: false,
1618
+ failure: {
1619
+ outcome,
1620
+ message:
1621
+ outcome === "owner_changed"
1622
+ ? "the identity-bound removal guard returned owner_changed; no path-only fallback was attempted"
1623
+ : "the guarded removal could not read the owner record; no path-only fallback was attempted",
1624
+ },
1625
+ };
1626
+ }
1496
1627
  if (outcome !== "cleanup_failed") return { removed: false };
1497
1628
  return {
1498
1629
  removed: false,
@@ -1636,12 +1767,20 @@ async function tryAcquireLock(
1636
1767
  renameNoReplacePathAsync,
1637
1768
  renameDirectoryNoReplacePathAsync,
1638
1769
  };
1639
- const published = await publication.renameNoReplacePathAsync(canonicalPendingPath, destinationPath);
1770
+ const published = await publishNoReplaceWithSharingRetry(
1771
+ publication.renameNoReplacePathAsync,
1772
+ canonicalPendingPath,
1773
+ destinationPath,
1774
+ );
1640
1775
  let publishedSuccessfully = isSuccessfulNativePublication(published, "primary");
1641
1776
  if (published.ok && !publishedSuccessfully)
1642
1777
  throw new Error("Failed to publish file lock: invalid primary success receipt.");
1643
1778
  if (!published.ok && isPreMutationUnsupportedRenameResult(published)) {
1644
- const fallback = await publication.renameDirectoryNoReplacePathAsync(canonicalPendingPath, destinationPath);
1779
+ const fallback = await publishNoReplaceWithSharingRetry(
1780
+ publication.renameDirectoryNoReplacePathAsync,
1781
+ canonicalPendingPath,
1782
+ destinationPath,
1783
+ );
1645
1784
  const fallbackSuccessfully = isSuccessfulNativePublication(fallback, "directory");
1646
1785
  if (fallback.ok && !fallbackSuccessfully)
1647
1786
  throw new Error("Failed to publish file lock: invalid directory success receipt.");
@@ -1800,16 +1939,16 @@ async function quarantineReleasedLock(
1800
1939
  if (!captured.ok || !captured.snapshot) return false;
1801
1940
  const infoEntry = captured.snapshot.entries.find(entry => entry.relativePath === "info");
1802
1941
  if (!infoEntry?.sha256) return false;
1942
+ const currentIdentity = await captureFileLockDirIdentity(nativeCapturePath);
1943
+ if (!currentIdentity || !sameStableFileLockIdentity(currentIdentity, expectedIdentity)) return false;
1803
1944
  if (
1804
- captured.snapshot.rootDev !== expectedIdentity.rootDev ||
1805
- captured.snapshot.rootIno !== expectedIdentity.rootIno ||
1806
- infoEntry.dev !== expectedIdentity.infoDev ||
1807
- infoEntry.ino !== expectedIdentity.infoIno ||
1808
- infoEntry.nlink !== expectedIdentity.infoNlink ||
1809
- infoEntry.size !== expectedIdentity.infoSize ||
1810
- infoEntry.mtimeNs !== expectedIdentity.infoMtimeNs ||
1811
- infoEntry.ctimeNs !== expectedIdentity.infoCtimeNs ||
1812
- infoEntry.sha256 !== expectedIdentity.infoSha256
1945
+ !nativeFileLockInfoMatchesStableIdentity(
1946
+ captured.snapshot.rootDev,
1947
+ captured.snapshot.rootIno,
1948
+ infoEntry,
1949
+ expectedIdentity,
1950
+ ) ||
1951
+ !nativeFileLockInfoMatchesContentEvidence(infoEntry, expectedIdentity)
1813
1952
  )
1814
1953
  return false;
1815
1954
  // Bind the owner generation to the snapshot before exact removal. A successor
@@ -2111,7 +2250,9 @@ export async function acquireFileLock(filePath: string, options: FileLockOptions
2111
2250
  continue;
2112
2251
  }
2113
2252
  staleRemovalFailure =
2114
- stale.stale && staleRemoval.failure ? { owner: stale.owner, failure: staleRemoval.failure } : undefined;
2253
+ stale.stale && staleRemoval.failure
2254
+ ? { owner: stale.owner, identity: stale.identity, failure: staleRemoval.failure }
2255
+ : undefined;
2115
2256
  if (!opts.signal) {
2116
2257
  await Bun.sleep(opts.retryDelayMs);
2117
2258
  continue;
@@ -222,11 +222,11 @@ export class ModelDiscoveryManager<TProvider extends DiscoveryProvider> {
222
222
  ? result.stale
223
223
  ? "cached"
224
224
  : "ok"
225
- : result.fetched
225
+ : result.fetched ||
226
+ (result.cacheFresh && result.cacheAuthoritative && result.dynamicModelIds?.length === 0)
226
227
  ? "empty"
227
- : // No fetch happened (non-authoritative retry backoff, or an
228
- // ineligible cache) and no eligible row served models: the
229
- // provider is unvalidated, not authoritatively empty.
228
+ : // No fetch happened and no fresh authoritative empty row
229
+ // attested to this result, so the provider is unvalidated.
230
230
  "unavailable";
231
231
  const state: ProviderDiscoveryState = {
232
232
  provider: provider.provider,