@iislee/opencodex 2.11.0 → 2.31.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 (675) hide show
  1. package/AGENTS_INSTALL.md +109 -0
  2. package/README.md +114 -19
  3. package/bin/ocx.mjs +164 -36
  4. package/bin/package-main.mjs +1 -1
  5. package/gui/dist/assets/index-BF38heuV.js +104 -0
  6. package/gui/dist/assets/index-DMiI18Kv.css +1 -0
  7. package/gui/dist/index.html +2 -2
  8. package/gui/dist/provider-icons/alibaba-color.svg +1 -1
  9. package/gui/dist/provider-icons/antigravity-color.svg +1 -1
  10. package/gui/dist/provider-icons/claude-color.svg +1 -1
  11. package/gui/dist/provider-icons/cline-color.svg +16 -0
  12. package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -1
  13. package/gui/dist/provider-icons/commandcode-color.svg +1 -0
  14. package/gui/dist/provider-icons/copilot-color.svg +1 -1
  15. package/gui/dist/provider-icons/cursor-color.svg +1 -1
  16. package/gui/dist/provider-icons/deepseek-color.svg +1 -1
  17. package/gui/dist/provider-icons/firepass-color.svg +1 -1
  18. package/gui/dist/provider-icons/fireworks-color.svg +1 -1
  19. package/gui/dist/provider-icons/gemini-color.svg +1 -1
  20. package/gui/dist/provider-icons/github-copilot-color.svg +1 -1
  21. package/gui/dist/provider-icons/gitlab-duo-color.svg +1 -1
  22. package/gui/dist/provider-icons/grok.svg +1 -1
  23. package/gui/dist/provider-icons/groq-color.svg +1 -1
  24. package/gui/dist/provider-icons/huggingface-color.svg +1 -1
  25. package/gui/dist/provider-icons/kimi-color.svg +1 -1
  26. package/gui/dist/provider-icons/kiro-color.svg +2 -2
  27. package/gui/dist/provider-icons/lm-studio-color.svg +1 -1
  28. package/gui/dist/provider-icons/mistral-color.svg +1 -1
  29. package/gui/dist/provider-icons/moonshot-color.svg +1 -1
  30. package/gui/dist/provider-icons/nvidia-color.svg +1 -1
  31. package/gui/dist/provider-icons/ollama-color.svg +1 -1
  32. package/gui/dist/provider-icons/openai.svg +1 -1
  33. package/gui/dist/provider-icons/opencode.svg +2 -1
  34. package/gui/dist/provider-icons/openrouter-color.svg +1 -1
  35. package/gui/dist/provider-icons/pi.svg +2 -2
  36. package/gui/dist/provider-icons/qianfan-color.svg +1 -1
  37. package/gui/dist/provider-icons/qwen-portal-color.svg +1 -1
  38. package/gui/dist/provider-icons/vercel-ai-gateway-color.svg +1 -1
  39. package/gui/dist/provider-icons/vllm-color.svg +1 -1
  40. package/gui/dist/provider-icons/xiaomi-color.svg +1 -1
  41. package/package.json +19 -10
  42. package/src/adapters/anthropic-output-schema.ts +137 -0
  43. package/src/adapters/anthropic.ts +376 -52
  44. package/src/adapters/base.ts +54 -7
  45. package/src/adapters/client-fingerprint.ts +18 -12
  46. package/src/adapters/cline-pass-deepseek-v4-tool-replay.ts +69 -0
  47. package/src/adapters/command-code.ts +601 -0
  48. package/src/adapters/cursor/checkpoint-store.ts +303 -0
  49. package/src/adapters/cursor/cursor-errors.ts +129 -6
  50. package/src/adapters/cursor/discovery.ts +61 -4
  51. package/src/adapters/cursor/effort-map.ts +27 -3
  52. package/src/adapters/cursor/framing.ts +39 -0
  53. package/src/adapters/cursor/h2-pool.ts +123 -0
  54. package/src/adapters/cursor/http1-bidi.ts +361 -0
  55. package/src/adapters/cursor/images.ts +704 -0
  56. package/src/adapters/cursor/live-models.ts +174 -58
  57. package/src/adapters/cursor/live-transport.ts +609 -170
  58. package/src/adapters/cursor/native-exec-common.ts +23 -2
  59. package/src/adapters/cursor/native-exec-fs.ts +10 -7
  60. package/src/adapters/cursor/native-exec-network.ts +1 -1
  61. package/src/adapters/cursor/native-exec-shell.ts +0 -1
  62. package/src/adapters/cursor/native-exec.ts +101 -14
  63. package/src/adapters/cursor/protobuf-events.ts +829 -11
  64. package/src/adapters/cursor/protobuf-request.ts +383 -65
  65. package/src/adapters/cursor/request-builder.ts +237 -31
  66. package/src/adapters/cursor/tool-definitions.ts +242 -12
  67. package/src/adapters/cursor/tool-result-normalize.ts +92 -0
  68. package/src/adapters/cursor/transport.ts +22 -0
  69. package/src/adapters/cursor/types.ts +28 -1
  70. package/src/adapters/cursor.ts +133 -7
  71. package/src/adapters/google-antigravity-replay.ts +558 -34
  72. package/src/adapters/google-antigravity-wire.ts +43 -10
  73. package/src/adapters/google-http.ts +38 -10
  74. package/src/adapters/google-tool-schema.ts +80 -15
  75. package/src/adapters/google-truncation.ts +11 -0
  76. package/src/adapters/google.ts +618 -74
  77. package/src/adapters/identity.ts +39 -6
  78. package/src/adapters/kiro-errors.ts +11 -0
  79. package/src/adapters/kiro-events.ts +19 -1
  80. package/src/adapters/kiro-thinking.ts +18 -2
  81. package/src/adapters/kiro-tools.ts +10 -1
  82. package/src/adapters/kiro.ts +92 -54
  83. package/src/adapters/mimo-free.ts +17 -0
  84. package/src/adapters/openai-chat-url.ts +11 -0
  85. package/src/adapters/openai-chat.ts +1311 -336
  86. package/src/adapters/openai-responses-url.ts +16 -0
  87. package/src/adapters/openai-responses.ts +830 -56
  88. package/src/adapters/registry.ts +175 -0
  89. package/src/adapters/responses-tool-schema.ts +67 -0
  90. package/src/adapters/tool-call-id.ts +119 -0
  91. package/src/adapters/tool-catalog-nudge.ts +104 -21
  92. package/src/adapters/xai-web-search.ts +185 -0
  93. package/src/bridge.ts +428 -61
  94. package/src/chat/inbound.ts +43 -19
  95. package/src/chat/outbound.ts +82 -26
  96. package/src/claude/agents-inject.ts +32 -9
  97. package/src/claude/context-windows.ts +21 -5
  98. package/src/claude/desktop-3p.ts +243 -9
  99. package/src/claude/gateway-cache.ts +41 -4
  100. package/src/claude/inbound.ts +72 -3
  101. package/src/claude/model-info.ts +38 -15
  102. package/src/claude/outbound.ts +70 -16
  103. package/src/cli/account-api.ts +35 -1
  104. package/src/cli/account-auth.ts +33 -6
  105. package/src/cli/account-catalog-refresh.ts +14 -0
  106. package/src/cli/account-extended.ts +389 -2
  107. package/src/cli/account-main.ts +317 -0
  108. package/src/cli/account.ts +30 -6
  109. package/src/cli/agent.ts +45 -1
  110. package/src/cli/claude-agent-startup-sync.ts +73 -0
  111. package/src/cli/claude-desktop.ts +29 -4
  112. package/src/cli/claude.ts +103 -34
  113. package/src/cli/codex-log-guard-doctor.ts +103 -0
  114. package/src/cli/codex-shim-autorestore.ts +2 -0
  115. package/src/cli/codex-shim-readiness.ts +76 -0
  116. package/src/cli/combo.ts +8 -0
  117. package/src/cli/config-command.ts +74 -10
  118. package/src/cli/dispatch.ts +593 -0
  119. package/src/cli/doctor.ts +315 -43
  120. package/src/cli/ensure-desired-integrations.ts +152 -0
  121. package/src/cli/export-command.ts +46 -20
  122. package/src/cli/help.ts +20 -271
  123. package/src/cli/index.ts +378 -519
  124. package/src/cli/init.ts +4 -17
  125. package/src/cli/integrations.ts +120 -2
  126. package/src/cli/lab.ts +607 -0
  127. package/src/cli/launcher-context.ts +77 -0
  128. package/src/cli/minimax.ts +497 -0
  129. package/src/cli/models-runtime.ts +35 -2
  130. package/src/cli/models.ts +100 -14
  131. package/src/cli/observe.ts +92 -3
  132. package/src/cli/opencode.ts +4 -2
  133. package/src/cli/provider-runtime.ts +18 -1
  134. package/src/cli/provider.ts +24 -3
  135. package/src/cli/ready.ts +301 -0
  136. package/src/cli/registry.ts +437 -0
  137. package/src/cli/root.ts +86 -0
  138. package/src/cli/route-policy.ts +92 -0
  139. package/src/cli/runtime-api.ts +6 -3
  140. package/src/cli/star-prompt.ts +71 -15
  141. package/src/cli/status.ts +10 -3
  142. package/src/cli/system-restart-client.ts +146 -0
  143. package/src/cli/tray-proxy.ts +153 -6
  144. package/src/cli/v2.ts +105 -10
  145. package/src/cli.ts +1 -1
  146. package/src/clients/config-export.ts +1358 -21
  147. package/src/codex/account-label.ts +14 -1
  148. package/src/codex/account-lifecycle.ts +130 -13
  149. package/src/codex/account-namespaces.ts +49 -3
  150. package/src/codex/account-priority.ts +83 -0
  151. package/src/codex/account-store.ts +29 -2
  152. package/src/codex/account-usability.ts +25 -2
  153. package/src/codex/admission.ts +256 -0
  154. package/src/codex/affinity-debug.ts +162 -0
  155. package/src/codex/app-server-processes.ts +493 -106
  156. package/src/codex/app-server-restart-service.ts +232 -0
  157. package/src/codex/auth-api.ts +849 -242
  158. package/src/codex/auth-collision.ts +5 -3
  159. package/src/codex/auth-context.ts +345 -32
  160. package/src/codex/autostart-health.ts +8 -1
  161. package/src/codex/catalog/account-models.ts +67 -0
  162. package/src/codex/catalog/aggregation.ts +68 -10
  163. package/src/codex/catalog/bundled.ts +331 -33
  164. package/src/codex/catalog/effort.ts +121 -30
  165. package/src/codex/catalog/filesystem-evidence.ts +302 -0
  166. package/src/codex/catalog/kinds.ts +2 -0
  167. package/src/codex/catalog/metadata.ts +529 -45
  168. package/src/codex/catalog/native-models.ts +72 -0
  169. package/src/codex/catalog/parsing.ts +224 -30
  170. package/src/codex/catalog/provider-fetch.ts +1460 -134
  171. package/src/codex/catalog/sync.ts +1449 -186
  172. package/src/codex/catalog-admission.ts +199 -0
  173. package/src/codex/catalog-refresh-status.ts +105 -0
  174. package/src/codex/catalog-write-serialization.ts +242 -0
  175. package/src/codex/catalog.ts +6 -3
  176. package/src/codex/codex-write-lock.ts +384 -0
  177. package/src/codex/convergence-types.ts +614 -0
  178. package/src/codex/convergence.ts +651 -0
  179. package/src/codex/coordinator-doctor.ts +332 -0
  180. package/src/codex/custom-model-catalog-migration.ts +176 -0
  181. package/src/codex/desired-state.ts +230 -0
  182. package/src/codex/features.ts +636 -39
  183. package/src/codex/generation.ts +202 -0
  184. package/src/codex/history-job.ts +407 -0
  185. package/src/codex/history-lock.ts +242 -0
  186. package/src/codex/history-migration-guardian.ts +26 -20
  187. package/src/codex/history-provider.ts +231 -28
  188. package/src/codex/history-transition.ts +105 -0
  189. package/src/codex/history-worker.ts +220 -0
  190. package/src/codex/inject-coordination.ts +290 -0
  191. package/src/codex/inject.ts +1073 -152
  192. package/src/codex/injected-marker.ts +37 -3
  193. package/src/codex/integration-record.ts +266 -0
  194. package/src/codex/internal/catalog-writer.ts +203 -0
  195. package/src/codex/internal/history-writer.ts +80 -0
  196. package/src/codex/journal.ts +66 -4
  197. package/src/codex/log-guard/inspect.ts +506 -0
  198. package/src/codex/log-guard/lock.ts +150 -0
  199. package/src/codex/log-guard/maintenance.ts +403 -0
  200. package/src/codex/log-guard/path-safety.ts +88 -0
  201. package/src/codex/log-guard/policy.ts +44 -0
  202. package/src/codex/log-guard/processes.ts +205 -0
  203. package/src/codex/log-guard/protection.ts +489 -0
  204. package/src/codex/log-guard/sqlite-errors.ts +9 -0
  205. package/src/codex/main-account-cache.ts +24 -0
  206. package/src/codex/main-account.ts +29 -1
  207. package/src/codex/management-convergence.ts +167 -0
  208. package/src/codex/model-cache.ts +56 -10
  209. package/src/codex/model-entitlements.ts +353 -0
  210. package/src/codex/native-main-admission.ts +47 -0
  211. package/src/codex/native-main-auth-temp.ts +187 -0
  212. package/src/codex/native-main-claim.ts +178 -0
  213. package/src/codex/native-main-lock-file.ts +162 -0
  214. package/src/codex/native-main-owner.ts +329 -0
  215. package/src/codex/native-profile-api.ts +247 -0
  216. package/src/codex/native-profile-manager.ts +1531 -0
  217. package/src/codex/native-profile-processes.ts +121 -0
  218. package/src/codex/native-profile-recovery.ts +99 -0
  219. package/src/codex/native-profile-stage-store.ts +387 -0
  220. package/src/codex/native-profile-startup.ts +492 -0
  221. package/src/codex/native-profile-store.ts +855 -0
  222. package/src/codex/native-profile-types.ts +120 -0
  223. package/src/codex/native-residue.ts +682 -0
  224. package/src/codex/paths.ts +80 -1
  225. package/src/codex/plan-from-token.ts +140 -0
  226. package/src/codex/plan.ts +40 -0
  227. package/src/codex/plugins-doctor.ts +1 -1
  228. package/src/codex/pool-rotation.ts +74 -4
  229. package/src/codex/project-config-warnings.ts +20 -6
  230. package/src/codex/prompt-journal.ts +352 -0
  231. package/src/codex/prompt-layers.ts +967 -0
  232. package/src/codex/prompt-lock.ts +143 -0
  233. package/src/codex/quota-rejection.ts +298 -0
  234. package/src/codex/quota.ts +175 -13
  235. package/src/codex/refresh.ts +11 -2
  236. package/src/codex/reset-credit-recovery.ts +1044 -0
  237. package/src/codex/routing.ts +505 -94
  238. package/src/codex/runtime.ts +159 -38
  239. package/src/codex/shim.ts +1009 -28
  240. package/src/codex/subagent-model-fallback.ts +350 -35
  241. package/src/codex/sync.ts +191 -2
  242. package/src/codex/transition-state.ts +612 -0
  243. package/src/codex/upstream-host-health.ts +368 -0
  244. package/src/codex/user-identity.ts +557 -0
  245. package/src/codex/warmup.ts +187 -81
  246. package/src/codex/write-coordination.ts +114 -0
  247. package/src/combos/failover.ts +20 -0
  248. package/src/combos/index.ts +4 -0
  249. package/src/combos/request.ts +32 -0
  250. package/src/combos/types.ts +81 -9
  251. package/src/config/provider-name.ts +24 -0
  252. package/src/config.ts +1762 -140
  253. package/src/generated/compatibility-version.json +3164 -0
  254. package/src/generated/{jawcode-model-metadata.ts → model-metadata.ts} +19 -17
  255. package/src/grok/inject.ts +16 -5
  256. package/src/grok/inspect.ts +45 -0
  257. package/src/grok/sync.ts +2 -2
  258. package/src/images/loop.ts +152 -29
  259. package/src/images/plan.ts +23 -13
  260. package/src/integrations/config-io.ts +269 -0
  261. package/src/integrations/journal.ts +315 -0
  262. package/src/integrations/merge.ts +135 -0
  263. package/src/integrations/mutation-flight.ts +71 -0
  264. package/src/integrations/native/ownership-preflight.ts +202 -0
  265. package/src/integrations/omp-yaml-source.ts +358 -0
  266. package/src/integrations/owned-refresh.ts +74 -0
  267. package/src/integrations/ownership.ts +111 -0
  268. package/src/integrations/registry.ts +159 -0
  269. package/src/integrations/serialize.ts +314 -0
  270. package/src/integrations/state.ts +361 -0
  271. package/src/integrations/store.ts +103 -0
  272. package/src/integrations/writer-lock.ts +98 -0
  273. package/src/integrations/writer.ts +691 -0
  274. package/src/lab/artifacts/sanitize.ts +586 -0
  275. package/src/lab/artifacts/secure-fs.ts +475 -0
  276. package/src/lab/artifacts/store.ts +310 -0
  277. package/src/lab/automation/budgets.ts +78 -0
  278. package/src/lab/automation/config-persistence.ts +256 -0
  279. package/src/lab/automation/constants.ts +39 -0
  280. package/src/lab/automation/cooldown.ts +103 -0
  281. package/src/lab/automation/dispatch.ts +211 -0
  282. package/src/lab/automation/index.ts +13 -0
  283. package/src/lab/automation/orchestrator.ts +499 -0
  284. package/src/lab/automation/persistence.ts +512 -0
  285. package/src/lab/automation/planner.ts +371 -0
  286. package/src/lab/automation/policy.ts +136 -0
  287. package/src/lab/automation/queue.ts +191 -0
  288. package/src/lab/automation/recovery.ts +24 -0
  289. package/src/lab/automation/route-context.ts +21 -0
  290. package/src/lab/automation/run-key.ts +44 -0
  291. package/src/lab/automation/runs-query.ts +34 -0
  292. package/src/lab/automation/types.ts +160 -0
  293. package/src/lab/conformance/assertion.ts +325 -0
  294. package/src/lab/conformance/digest.ts +22 -0
  295. package/src/lab/conformance/executor.ts +741 -0
  296. package/src/lab/conformance/fixture-provider.ts +27 -0
  297. package/src/lab/conformance/fixtures/live-v1-cases.json +175 -0
  298. package/src/lab/conformance/fixtures/protocol-v1-cases.json +461 -0
  299. package/src/lab/conformance/harness-budget.ts +47 -0
  300. package/src/lab/conformance/index.ts +5 -0
  301. package/src/lab/conformance/jcs.ts +64 -0
  302. package/src/lab/conformance/json-pointer.ts +39 -0
  303. package/src/lab/conformance/manifest.ts +180 -0
  304. package/src/lab/conformance/mcp-stub.ts +179 -0
  305. package/src/lab/conformance/negative-controls.ts +164 -0
  306. package/src/lab/conformance/observation.ts +355 -0
  307. package/src/lab/conformance/runner.ts +68 -0
  308. package/src/lab/conformance/sse-normalize.ts +59 -0
  309. package/src/lab/conformance/suite-manifest.ts +78 -0
  310. package/src/lab/conformance/types.ts +214 -0
  311. package/src/lab/constants.ts +126 -0
  312. package/src/lab/digest.ts +64 -0
  313. package/src/lab/events/errors.ts +9 -0
  314. package/src/lab/events/limits.ts +117 -0
  315. package/src/lab/events/types.ts +229 -0
  316. package/src/lab/events/validate.ts +781 -0
  317. package/src/lab/fabric/constants.ts +40 -0
  318. package/src/lab/fabric/executor.ts +492 -0
  319. package/src/lab/fabric/index.ts +80 -0
  320. package/src/lab/fabric/manifest.ts +222 -0
  321. package/src/lab/fabric/observe.ts +489 -0
  322. package/src/lab/fabric/patch.ts +79 -0
  323. package/src/lab/fabric/producer-child.ts +139 -0
  324. package/src/lab/fabric/producer-isolate.ts +276 -0
  325. package/src/lab/fabric/producer-protocol.ts +61 -0
  326. package/src/lab/fabric/scratch.ts +439 -0
  327. package/src/lab/fabric/subject.ts +106 -0
  328. package/src/lab/fabric/types.ts +134 -0
  329. package/src/lab/fabric/verifier.ts +98 -0
  330. package/src/lab/index.ts +54 -0
  331. package/src/lab/ledger/artifact-refs.ts +127 -0
  332. package/src/lab/ledger/invalidation.ts +136 -0
  333. package/src/lab/ledger/purge.ts +310 -0
  334. package/src/lab/ledger/store.ts +532 -0
  335. package/src/lab/live/credential-lease.ts +53 -0
  336. package/src/lab/live/destination.ts +155 -0
  337. package/src/lab/live/executor.ts +336 -0
  338. package/src/lab/live/inert-tools.ts +56 -0
  339. package/src/lab/live/manifest.ts +85 -0
  340. package/src/lab/live/mcp-loopback.ts +57 -0
  341. package/src/lab/live/runner.ts +19 -0
  342. package/src/lab/live/sandbox.ts +61 -0
  343. package/src/lab/live/suite-manifest.ts +41 -0
  344. package/src/lab/live/transport.ts +118 -0
  345. package/src/lab/live/types.ts +197 -0
  346. package/src/lab/observe/from-conformance.ts +301 -0
  347. package/src/lab/observe/from-live.ts +117 -0
  348. package/src/lab/paths.ts +153 -0
  349. package/src/lab/projection/rebuild.ts +495 -0
  350. package/src/lab/projection/schema.ts +135 -0
  351. package/src/lab/projection/verdicts.ts +474 -0
  352. package/src/lab/projection/verification.ts +412 -0
  353. package/src/lab/public/bundle.ts +217 -0
  354. package/src/lab/public/community-authority.ts +175 -0
  355. package/src/lab/public/community-files.ts +29 -0
  356. package/src/lab/public/community.ts +479 -0
  357. package/src/lab/public/file-safety.ts +155 -0
  358. package/src/lab/public/ids.ts +26 -0
  359. package/src/lab/public/index.ts +16 -0
  360. package/src/lab/public/mutation-lock.ts +424 -0
  361. package/src/lab/public/operator.ts +353 -0
  362. package/src/lab/public/origin-purge.ts +79 -0
  363. package/src/lab/public/origin.ts +203 -0
  364. package/src/lab/public/privacy.ts +143 -0
  365. package/src/lab/public/private-file.ts +261 -0
  366. package/src/lab/public/project.ts +124 -0
  367. package/src/lab/public/purge-test-fault.ts +21 -0
  368. package/src/lab/public/purge.ts +223 -0
  369. package/src/lab/public/registry.ts +44 -0
  370. package/src/lab/public/revocation.ts +252 -0
  371. package/src/lab/public/signature.ts +243 -0
  372. package/src/lab/public/storage.ts +105 -0
  373. package/src/lab/public/strict-json.ts +206 -0
  374. package/src/lab/public/time.ts +26 -0
  375. package/src/lab/public/types.ts +172 -0
  376. package/src/lab/public/validate.ts +391 -0
  377. package/src/lab/query/catalog.ts +101 -0
  378. package/src/lab/query/connection.ts +107 -0
  379. package/src/lab/query/constants.ts +4 -0
  380. package/src/lab/query/cursor.ts +132 -0
  381. package/src/lab/query/dto-map.ts +277 -0
  382. package/src/lab/query/errors.ts +22 -0
  383. package/src/lab/query/freshness.ts +53 -0
  384. package/src/lab/query/index.ts +45 -0
  385. package/src/lab/query/latest-observation.ts +59 -0
  386. package/src/lab/query/passive-production.ts +159 -0
  387. package/src/lab/query/queries.ts +444 -0
  388. package/src/lab/query/types.ts +266 -0
  389. package/src/lab/subject/behavior-fingerprint.ts +77 -0
  390. package/src/lab/subject/installation-salt.ts +112 -0
  391. package/src/lab/subject/protocol-subject.ts +80 -0
  392. package/src/lab/subject/route-subject.ts +74 -0
  393. package/src/lib/app-owned-memory-stores.ts +22 -0
  394. package/src/lib/bounded-body.ts +153 -9
  395. package/src/lib/bun-runtime.ts +125 -12
  396. package/src/lib/bun-stream-caps.ts +13 -9
  397. package/src/lib/codex-restart-contract.ts +120 -0
  398. package/src/lib/config-ownership.ts +6 -2
  399. package/src/lib/destination-policy.ts +65 -1
  400. package/src/lib/errors.ts +44 -2
  401. package/src/lib/fabric-task-execution-authority.ts +7 -0
  402. package/src/lib/fabric-task-host.ts +29 -0
  403. package/src/lib/lab-activation.ts +223 -0
  404. package/src/lib/lab-live-execution-authority.ts +13 -0
  405. package/src/lib/lab-live-host.ts +30 -0
  406. package/src/lib/lab-live-pinned-sender.ts +56 -0
  407. package/src/lib/lab-live-route-production.ts +130 -0
  408. package/src/lib/lab-passive-linker-registration.ts +26 -0
  409. package/src/lib/local-management-attestation.ts +51 -0
  410. package/src/lib/local-management-capability.ts +100 -0
  411. package/src/lib/local-provider-reload-contract.ts +100 -0
  412. package/src/lib/optional-shutdown-hooks.ts +57 -0
  413. package/src/lib/pinned-http.ts +145 -26
  414. package/src/lib/process-control.ts +4 -1
  415. package/src/lib/provider-outbound.ts +49 -9
  416. package/src/lib/redact.ts +419 -3
  417. package/src/lib/self-launch-argv.ts +15 -0
  418. package/src/lib/server-resource-ownership.ts +71 -0
  419. package/src/lib/shadow-call.ts +35 -4
  420. package/src/lib/sse-decoder.ts +41 -0
  421. package/src/lib/state-store-registrations.ts +10 -2
  422. package/src/lib/system-restart-contract.ts +73 -0
  423. package/src/lib/token-estimate.ts +19 -2
  424. package/src/lib/tool-argument-integers.ts +202 -0
  425. package/src/lib/translator-budget.ts +44 -0
  426. package/src/lib/upstream-http-version.ts +57 -0
  427. package/src/lib/upstream-reachability.ts +95 -0
  428. package/src/lib/upstream-retry.ts +156 -3
  429. package/src/lib/windows-atomic-replace.ts +155 -0
  430. package/src/lib/windows-elevation.ts +70 -2
  431. package/src/lib/windows-secret-acl.ts +409 -69
  432. package/src/lib/windows-service-wrappers.ts +72 -0
  433. package/src/lib/windows-text.ts +106 -0
  434. package/src/lib/windows-user-principal.ts +341 -0
  435. package/src/lib/winsw.ts +33 -5
  436. package/src/oauth/account-import/google-antigravity-adapter.ts +74 -0
  437. package/src/oauth/account-import/index.ts +15 -0
  438. package/src/oauth/account-import/parser.ts +83 -0
  439. package/src/oauth/account-import/registry.ts +18 -0
  440. package/src/oauth/account-import/service.ts +75 -0
  441. package/src/oauth/account-import/types.ts +91 -0
  442. package/src/oauth/anthropic.ts +12 -1
  443. package/src/oauth/callback-server.ts +8 -2
  444. package/src/oauth/chatgpt.ts +12 -1
  445. package/src/oauth/command-code.ts +239 -0
  446. package/src/oauth/cursor.ts +46 -5
  447. package/src/oauth/google-antigravity.ts +35 -3
  448. package/src/oauth/health.ts +20 -12
  449. package/src/oauth/index.ts +398 -66
  450. package/src/oauth/key-providers.ts +16 -0
  451. package/src/oauth/kimi.ts +16 -2
  452. package/src/oauth/kiro.ts +50 -6
  453. package/src/oauth/local-token-detect.ts +11 -2
  454. package/src/oauth/log.ts +3 -1
  455. package/src/oauth/login-cli.ts +88 -28
  456. package/src/oauth/nous.ts +798 -0
  457. package/src/oauth/store.ts +119 -21
  458. package/src/oauth/token-guardian.ts +9 -3
  459. package/src/pi/models.ts +2 -2
  460. package/src/providers/alibaba-region-migration.ts +1 -1
  461. package/src/providers/antigravity-models.ts +521 -31
  462. package/src/providers/base-url-choices.ts +10 -0
  463. package/src/providers/codex-capacity.ts +292 -0
  464. package/src/providers/command-code-efforts.ts +144 -0
  465. package/src/providers/context-cap.ts +22 -5
  466. package/src/providers/cursor-pool.ts +72 -0
  467. package/src/providers/derive.ts +253 -6
  468. package/src/providers/fastwire.ts +501 -0
  469. package/src/providers/free-directory.ts +10 -7
  470. package/src/providers/google-vertex-location.ts +14 -0
  471. package/src/providers/key-failover.ts +71 -3
  472. package/src/providers/label.ts +1 -1
  473. package/src/providers/model-discovery-limits.ts +16 -0
  474. package/src/providers/model-discovery.ts +115 -22
  475. package/src/providers/model-rename-migration.ts +255 -0
  476. package/src/providers/model-rename-startup.ts +28 -0
  477. package/src/providers/openai-sidecar.ts +72 -4
  478. package/src/providers/openai-tier-startup.ts +31 -2
  479. package/src/providers/openai-tiers.ts +119 -4
  480. package/src/providers/openai-virtual-models.ts +1 -0
  481. package/src/providers/opencode-zen-rate-limit.ts +102 -0
  482. package/src/providers/provider-id-rewrite.ts +29 -0
  483. package/src/providers/quota.ts +1319 -38
  484. package/src/providers/registry.ts +1429 -111
  485. package/src/providers/request-pacing.ts +310 -0
  486. package/src/providers/service-tier.ts +277 -0
  487. package/src/providers/slug-codec.ts +42 -6
  488. package/src/providers/static-model-discovery.ts +86 -0
  489. package/src/providers/xai-responses-opt-in.ts +15 -0
  490. package/src/providers/xai-transport.ts +11 -4
  491. package/src/reasoning-effort.ts +49 -1
  492. package/src/responses/compaction.ts +26 -1
  493. package/src/responses/custom-tool-compat.ts +266 -0
  494. package/src/responses/hosted-tool-policy.ts +9 -0
  495. package/src/responses/namespace-tool-compat.ts +355 -0
  496. package/src/responses/parser.ts +220 -38
  497. package/src/responses/provider-continuation.ts +98 -0
  498. package/src/responses/provider-opaque-metadata.ts +73 -0
  499. package/src/responses/reasoning-envelope.ts +9 -1
  500. package/src/responses/reasoning-replay-cache.ts +426 -0
  501. package/src/responses/schema.ts +7 -1
  502. package/src/responses/spill-store.ts +75 -10
  503. package/src/responses/state.ts +565 -27
  504. package/src/responses/thought-signature-replay.ts +347 -0
  505. package/src/responses/tool-search-compat.ts +301 -0
  506. package/src/responses/truncated-stop-reason.ts +60 -0
  507. package/src/router.ts +366 -30
  508. package/src/routing/analytics.ts +378 -0
  509. package/src/routing/capability.ts +244 -0
  510. package/src/routing/compatibility/assemble.ts +73 -0
  511. package/src/routing/compatibility/behavior.ts +278 -0
  512. package/src/routing/compatibility/catalog.ts +99 -0
  513. package/src/routing/compatibility/endpoint.ts +52 -0
  514. package/src/routing/compatibility/lab-evidence-provider.ts +130 -0
  515. package/src/routing/compatibility/policy.ts +181 -0
  516. package/src/routing/compatibility/provider-slot.ts +56 -0
  517. package/src/routing/compatibility/reader.ts +110 -0
  518. package/src/routing/compatibility/subject.ts +191 -0
  519. package/src/routing/compatibility/types.ts +64 -0
  520. package/src/routing/compatibility/version.ts +104 -0
  521. package/src/routing/cost.ts +77 -0
  522. package/src/routing/evaluator.ts +495 -0
  523. package/src/routing/health.ts +412 -0
  524. package/src/routing/history/cursor.ts +43 -0
  525. package/src/routing/history/indexer.ts +605 -0
  526. package/src/routing/history/schema.ts +72 -0
  527. package/src/routing/profile-namespace.ts +15 -0
  528. package/src/routing/profile.ts +547 -0
  529. package/src/routing/quota.ts +145 -0
  530. package/src/routing/request-evidence.ts +45 -0
  531. package/src/routing/trace.ts +776 -0
  532. package/src/server/adapter-resolve.ts +2 -29
  533. package/src/server/auth-cors.ts +267 -46
  534. package/src/server/background-lifecycle.ts +182 -0
  535. package/src/server/chat-completions.ts +130 -56
  536. package/src/server/chat-native-sse.ts +331 -0
  537. package/src/server/chat-native.ts +426 -0
  538. package/src/server/claude-messages.ts +159 -43
  539. package/src/server/direct-local-http.ts +347 -0
  540. package/src/server/effort-policy.ts +18 -0
  541. package/src/server/github-copilot-responses-repair.ts +338 -0
  542. package/src/server/gui-static.ts +39 -10
  543. package/src/server/images.ts +94 -12
  544. package/src/server/index.ts +865 -181
  545. package/src/server/lifecycle.ts +284 -13
  546. package/src/server/live.ts +136 -17
  547. package/src/server/local-management-read-client.ts +90 -0
  548. package/src/server/local-provider-reload-client.ts +137 -0
  549. package/src/server/management/agent-settings-routes.ts +398 -103
  550. package/src/server/management/api-key-usage.ts +31 -5
  551. package/src/server/management/body.ts +6 -0
  552. package/src/server/management/combo-routes.ts +62 -24
  553. package/src/server/management/config-routes.ts +464 -51
  554. package/src/server/management/context.ts +80 -2
  555. package/src/server/management/integration-routes.ts +498 -0
  556. package/src/server/management/lab-automation-routes.ts +206 -0
  557. package/src/server/management/lab-routes.ts +563 -0
  558. package/src/server/management/logs-usage-routes.ts +101 -32
  559. package/src/server/management/model-routes.ts +189 -131
  560. package/src/server/management/model-rows.ts +163 -0
  561. package/src/server/management/native-integration-routes.ts +769 -0
  562. package/src/server/management/oauth-account-routes.ts +80 -4
  563. package/src/server/management/provider-capability-config.ts +48 -0
  564. package/src/server/management/provider-routes.ts +764 -157
  565. package/src/server/management/request-history-routes.ts +191 -0
  566. package/src/server/management/routing-analytics-routes.ts +74 -0
  567. package/src/server/management/routing-profile-routes.ts +380 -0
  568. package/src/server/management/shared.ts +27 -11
  569. package/src/server/management/sidebar-routes.ts +47 -31
  570. package/src/server/management/storage-log-guard-routes.ts +186 -0
  571. package/src/server/management/sync-response.ts +69 -0
  572. package/src/server/management/system-restart.ts +288 -32
  573. package/src/server/management/system-routes.ts +77 -0
  574. package/src/server/management/usage-summary-cache.ts +9 -1
  575. package/src/server/management/vision-sidecar-options.ts +167 -0
  576. package/src/server/management/web-search-sidecar-options.ts +120 -0
  577. package/src/server/management-api.ts +115 -14
  578. package/src/server/management-auth.ts +220 -5
  579. package/src/server/passive-route-linker.ts +66 -0
  580. package/src/server/ports.ts +41 -1
  581. package/src/server/proxy-liveness.ts +132 -5
  582. package/src/server/readiness.ts +99 -0
  583. package/src/server/relay-eager.ts +82 -42
  584. package/src/server/relay.ts +236 -76
  585. package/src/server/request-decompress.ts +113 -6
  586. package/src/server/request-log.ts +235 -22
  587. package/src/server/responses/agent-task-recovery-cache.ts +143 -0
  588. package/src/server/responses/agent-task-recovery.ts +465 -0
  589. package/src/server/responses/collaboration.ts +204 -35
  590. package/src/server/responses/compact.ts +442 -55
  591. package/src/server/responses/core.ts +2872 -331
  592. package/src/server/responses/empty-completion-guard.ts +276 -0
  593. package/src/server/responses/encrypted-payload.ts +62 -39
  594. package/src/server/responses/fetch-helpers.ts +79 -4
  595. package/src/server/responses/input-admission.ts +185 -0
  596. package/src/server/responses/pacing-overload.ts +13 -0
  597. package/src/server/responses/policy-fallback.ts +178 -0
  598. package/src/server/responses/responses-field-backfill.ts +251 -0
  599. package/src/server/responses/terminal-guard.ts +26 -5
  600. package/src/server/responses/upstream-error.ts +5 -0
  601. package/src/server/responses/ws-upstream.ts +308 -0
  602. package/src/server/responses-custom-tool-repair.ts +282 -0
  603. package/src/server/responses-item-id-repair.ts +54 -6
  604. package/src/server/responses-json-events.ts +90 -0
  605. package/src/server/responses-model-rewrite.ts +29 -0
  606. package/src/server/responses-reasoning-summary-rewrite.ts +178 -0
  607. package/src/server/responses-snapshot-repair.ts +621 -0
  608. package/src/server/responses-terminal-repair.ts +342 -0
  609. package/src/server/responses-tool-search-repair.ts +267 -0
  610. package/src/server/responses-undeclared-tool-guard.ts +153 -0
  611. package/src/server/responses.ts +18 -2
  612. package/src/server/search.ts +78 -13
  613. package/src/server/sse-frame-buffer.ts +292 -0
  614. package/src/server/sse-payload-rewrite.ts +110 -22
  615. package/src/server/startup-action-control.ts +8 -1
  616. package/src/server/startup-health-cache.ts +19 -1
  617. package/src/server/system-env.ts +80 -9
  618. package/src/server/ws-bridge.ts +39 -38
  619. package/src/service-manager-probe.ts +892 -0
  620. package/src/service.ts +1111 -90
  621. package/src/sidecar/auth.ts +92 -0
  622. package/src/sidecar/candidates.ts +83 -0
  623. package/src/storage/cleanup.ts +2 -2
  624. package/src/storage/scanner.ts +1 -1
  625. package/src/storage/worker-lifecycle.ts +14 -14
  626. package/src/tray/windows-tray.ps1 +83 -9
  627. package/src/tray/windows.ts +43 -16
  628. package/src/types/accounts.ts +37 -0
  629. package/src/types/config.ts +845 -0
  630. package/src/types/provider.ts +545 -0
  631. package/src/types/request.ts +384 -0
  632. package/src/types/tools.ts +131 -0
  633. package/src/types/wire.ts +80 -0
  634. package/src/types.ts +104 -1236
  635. package/src/update/index.ts +32 -19
  636. package/src/update/job.ts +442 -67
  637. package/src/update/notify.ts +12 -6
  638. package/src/update/npm-cache-preflight.d.mts +47 -0
  639. package/src/update/npm-cache-preflight.mjs +201 -0
  640. package/src/update/transactional-install.d.mts +22 -0
  641. package/src/update/transactional-install.mjs +259 -0
  642. package/src/usage/cost.ts +0 -0
  643. package/src/usage/expected-prices.ts +268 -16
  644. package/src/usage/log.ts +606 -41
  645. package/src/usage/summary.ts +177 -9
  646. package/src/usage/user-cost-overlay-reconciler.ts +313 -0
  647. package/src/usage/user-cost-overlays.ts +314 -0
  648. package/src/vision/anthropic-describe.ts +10 -6
  649. package/src/vision/backends.ts +97 -0
  650. package/src/vision/describe.ts +9 -3
  651. package/src/vision/eligibility.ts +250 -0
  652. package/src/vision/index.ts +238 -24
  653. package/src/vision/reasoning.ts +55 -0
  654. package/src/vision/routed-describe.ts +175 -0
  655. package/src/vision/timeout-bounds.ts +9 -0
  656. package/src/web-search/anthropic-executor.ts +13 -7
  657. package/src/web-search/backends.ts +108 -0
  658. package/src/web-search/exa-executor.ts +88 -0
  659. package/src/web-search/executor.ts +11 -3
  660. package/src/web-search/gemini-executor.ts +141 -0
  661. package/src/web-search/index.ts +150 -15
  662. package/src/web-search/loop.ts +279 -50
  663. package/src/web-search/parse.ts +125 -30
  664. package/src/web-search/sources.ts +60 -0
  665. package/src/web-search/xai-executor.ts +219 -0
  666. package/gui/dist/assets/index-DTpMHS4F.js +0 -67
  667. package/gui/dist/assets/index-ZNVDE3C7.css +0 -1
  668. package/gui/dist/provider-icons/antigravity.svg +0 -1
  669. package/gui/dist/provider-icons/claude.svg +0 -1
  670. package/gui/dist/provider-icons/copilot.svg +0 -1
  671. package/gui/dist/provider-icons/cursor.svg +0 -2
  672. package/gui/dist/provider-icons/gemini.svg +0 -1
  673. package/gui/dist/provider-icons/grok-color.svg +0 -1
  674. package/gui/dist/provider-icons/kiro.svg +0 -14
  675. package/src/cli/internal-dispatch.ts +0 -20
@@ -0,0 +1,489 @@
1
+ import { createArtifactStore, type ArtifactStore } from "../artifacts/store";
2
+ import { sanitizeDiagnostic, truncateUtf8 } from "../artifacts/sanitize";
3
+ import {
4
+ LAB_EVENT_SCHEMA_VERSION,
5
+ LAB_PRODUCER,
6
+ LAB_PRODUCER_VERSION,
7
+ OBSERVATION_LIMIT_NAMES,
8
+ OUTCOMES,
9
+ } from "../constants";
10
+ import { FAILURE_CLASSIFICATIONS } from "../conformance/types";
11
+ import { fixtureDigest, isSha256Hex, jcsStringify, subjectIdForSubject } from "../digest";
12
+ import type { ObservationEvent, RouteSubjectV1, TaskSubjectV1 } from "../events/types";
13
+ import { LabValidationError } from "../events/errors";
14
+ import { assignEventId, validateSubject } from "../events/validate";
15
+ import { withLedgerMutation } from "../ledger/store";
16
+ import { ensureLabDirs } from "../paths";
17
+ import {
18
+ FABRIC_EVIDENCE_LAYER,
19
+ FABRIC_SCENARIO_ID,
20
+ FABRIC_SCENARIO_VERSION,
21
+ FABRIC_SUITE_ID,
22
+ FABRIC_SUITE_VERSION,
23
+ FABRIC_LIMITS,
24
+ FABRIC_VERIFIER_ID,
25
+ } from "./constants";
26
+ import {
27
+ expandFabricScenario,
28
+ expandFabricSuiteManifest,
29
+ fabricScenarioManifestDigest,
30
+ fabricSuiteManifestDigest,
31
+ loadFabricCaseAuthority,
32
+ } from "./manifest";
33
+ import type { FabricLimitsV1, FabricTaskOutcomeV1, FabricTaskRunResult } from "./types";
34
+ import { FabricTaskError } from "./types";
35
+
36
+ /** CL-07 fabric task outcome validation and observation persistence. */
37
+
38
+ /** Options for building or persisting a fabric observation event. */
39
+ export interface PersistFabricOptions {
40
+ configDir?: string;
41
+ recordedAt?: number;
42
+ producerVersion?: string;
43
+ artifactStore?: ArtifactStore;
44
+ attempt?: number;
45
+ }
46
+
47
+ /** Result of appending a fabric observation to the compatibility ledger. */
48
+ export interface PersistedFabricObservation {
49
+ event: ObservationEvent;
50
+ ledgerPath: string;
51
+ }
52
+
53
+ const OUTCOME_KEYS = new Set([
54
+ "schemaVersion",
55
+ "taskClassId",
56
+ "taskClassVersion",
57
+ "routeSubject",
58
+ "taskSubject",
59
+ "subjectId",
60
+ "taskFixtureDigest",
61
+ "verifierManifestDigest",
62
+ "fabricCompatibilityVersion",
63
+ "sandboxProfileDigest",
64
+ "startedAt",
65
+ "completedAt",
66
+ "limits",
67
+ "usage",
68
+ "outcome",
69
+ "verifier",
70
+ "failure",
71
+ "artifactDigests",
72
+ "sourceRefs",
73
+ ]);
74
+
75
+ const VERIFIER_KEYS = new Set(["verifierId", "manifestDigest", "passed", "pathSummaries", "reason"]);
76
+ const PATH_SUMMARY_KEYS = new Set(["path", "kind", "beforeDigest", "afterDigest", "reason"]);
77
+ const PATH_SUMMARY_KINDS = new Set(["unchanged", "modified", "added", "deleted", "rejected"]);
78
+ const USAGE_KEYS = ["inputBytes", "outputBytes", "patchOperations", "filesTouched", "artifactBytes", "elapsedMs", "inactiveMs"] as const;
79
+ const LIMIT_KEYS = Object.keys(FABRIC_LIMITS) as Array<keyof FabricLimitsV1>;
80
+ const FAILURE_KEYS = new Set(["class", "code", "retryable", "attribution"]);
81
+ const FAILURE_ATTRIBUTIONS = new Set(["opencodex", "route", "environment", "harness"]);
82
+
83
+ /** Require a non-null plain object or throw a harness-class FabricTaskError. */
84
+ function assertPlainObject(value: unknown, label: string): Record<string, unknown> {
85
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
86
+ throw new FabricTaskError(`malformed producer outcome: ${label}`, "malformed_producer_outcome", "harness");
87
+ }
88
+ return value as Record<string, unknown>;
89
+ }
90
+
91
+ /** Require a non-empty string field on a producer outcome object. */
92
+ function assertStringField(obj: Record<string, unknown>, key: string): string {
93
+ const value = obj[key];
94
+ if (typeof value !== "string" || value.length === 0) {
95
+ throw new FabricTaskError(`malformed producer outcome: ${key}`, "malformed_producer_outcome", "harness");
96
+ }
97
+ return value;
98
+ }
99
+
100
+ /** Require an integer field on a producer outcome object. */
101
+ function assertIntegerField(obj: Record<string, unknown>, key: string): number {
102
+ const value = obj[key];
103
+ if (typeof value !== "number" || !Number.isInteger(value)) {
104
+ throw new FabricTaskError(`malformed producer outcome: ${key}`, "malformed_producer_outcome", "harness");
105
+ }
106
+ return value;
107
+ }
108
+
109
+ /** Require a non-negative integer field on a producer outcome object. */
110
+ function assertNonNegativeIntegerField(obj: Record<string, unknown>, key: string): number {
111
+ const value = assertIntegerField(obj, key);
112
+ if (value < 0) {
113
+ throw new FabricTaskError(`malformed producer outcome: ${key}`, "malformed_producer_outcome", "harness");
114
+ }
115
+ return value;
116
+ }
117
+
118
+ /** Map LabValidationError into FabricTaskError for producer outcome parsing. */
119
+ function wrapValidationError(error: unknown): never {
120
+ if (error instanceof LabValidationError) {
121
+ throw new FabricTaskError(error.message, "malformed_producer_outcome", "harness");
122
+ }
123
+ throw error;
124
+ }
125
+
126
+ /** Validate verifier payload shape and reject unknown nested verifier fields. */
127
+ function validateFabricVerifier(raw: Record<string, unknown>): void {
128
+ for (const key of Object.keys(raw)) {
129
+ if (!VERIFIER_KEYS.has(key)) {
130
+ throw new FabricTaskError(`unknown verifier field ${key}`, "malformed_producer_outcome", "harness");
131
+ }
132
+ }
133
+ if (raw.verifierId !== FABRIC_VERIFIER_ID) {
134
+ throw new FabricTaskError("malformed producer outcome: verifierId", "malformed_producer_outcome", "harness");
135
+ }
136
+ const manifestDigest = assertStringField(raw, "manifestDigest");
137
+ if (!isSha256Hex(manifestDigest)) {
138
+ throw new FabricTaskError("malformed producer outcome: manifestDigest", "malformed_producer_outcome", "harness");
139
+ }
140
+ if (typeof raw.passed !== "boolean") {
141
+ throw new FabricTaskError("malformed producer outcome: passed", "malformed_producer_outcome", "harness");
142
+ }
143
+ if (!Array.isArray(raw.pathSummaries)) {
144
+ throw new FabricTaskError("malformed producer outcome: pathSummaries", "malformed_producer_outcome", "harness");
145
+ }
146
+ for (const row of raw.pathSummaries) {
147
+ const summary = assertPlainObject(row, "pathSummaries[]");
148
+ for (const key of Object.keys(summary)) {
149
+ if (!PATH_SUMMARY_KEYS.has(key)) {
150
+ throw new FabricTaskError(`unknown path summary field ${key}`, "malformed_producer_outcome", "harness");
151
+ }
152
+ }
153
+ assertStringField(summary, "path");
154
+ const kind = assertStringField(summary, "kind");
155
+ if (!PATH_SUMMARY_KINDS.has(kind)) {
156
+ throw new FabricTaskError("malformed producer outcome: path summary kind", "malformed_producer_outcome", "harness");
157
+ }
158
+ if (summary.beforeDigest !== undefined && !isSha256Hex(assertStringField(summary, "beforeDigest"))) {
159
+ throw new FabricTaskError("malformed producer outcome: beforeDigest", "malformed_producer_outcome", "harness");
160
+ }
161
+ if (summary.afterDigest !== undefined && !isSha256Hex(assertStringField(summary, "afterDigest"))) {
162
+ throw new FabricTaskError("malformed producer outcome: afterDigest", "malformed_producer_outcome", "harness");
163
+ }
164
+ if (summary.reason !== undefined && typeof summary.reason !== "string") {
165
+ throw new FabricTaskError("malformed producer outcome: path summary reason", "malformed_producer_outcome", "harness");
166
+ }
167
+ }
168
+ if (raw.reason !== undefined && typeof raw.reason !== "string") {
169
+ throw new FabricTaskError("malformed producer outcome: reason", "malformed_producer_outcome", "harness");
170
+ }
171
+ }
172
+
173
+ /** Validate non-negative usage counters on a producer outcome. */
174
+ function validateFabricUsage(raw: Record<string, unknown>): void {
175
+ for (const key of Object.keys(raw)) {
176
+ if (!(USAGE_KEYS as readonly string[]).includes(key)) {
177
+ throw new FabricTaskError(`unknown usage field ${key}`, "malformed_producer_outcome", "harness");
178
+ }
179
+ }
180
+ for (const key of USAGE_KEYS) {
181
+ assertNonNegativeIntegerField(raw, key);
182
+ }
183
+ }
184
+
185
+ /** Validate non-negative limit fields on a producer outcome. */
186
+ function validateFabricLimits(raw: Record<string, unknown>): void {
187
+ for (const key of Object.keys(raw)) {
188
+ if (!(LIMIT_KEYS as readonly string[]).includes(key)) {
189
+ throw new FabricTaskError(`unknown limit field ${key}`, "malformed_producer_outcome", "harness");
190
+ }
191
+ }
192
+ for (const key of LIMIT_KEYS) {
193
+ assertNonNegativeIntegerField(raw, key);
194
+ }
195
+ }
196
+
197
+ /** Validate failure record shape and known attribution values. */
198
+ function validateFailureRecord(raw: Record<string, unknown>): void {
199
+ for (const key of Object.keys(raw)) {
200
+ if (!FAILURE_KEYS.has(key)) {
201
+ throw new FabricTaskError(`unknown failure field ${key}`, "malformed_producer_outcome", "harness");
202
+ }
203
+ }
204
+ const failureClass = assertStringField(raw, "class");
205
+ if (!FAILURE_CLASSIFICATIONS.includes(failureClass as typeof FAILURE_CLASSIFICATIONS[number])) {
206
+ throw new FabricTaskError("malformed producer outcome: failure.class", "malformed_producer_outcome", "harness");
207
+ }
208
+ assertStringField(raw, "code");
209
+ if (typeof raw.retryable !== "boolean") {
210
+ throw new FabricTaskError("malformed producer outcome: failure.retryable", "malformed_producer_outcome", "harness");
211
+ }
212
+ const attribution = assertStringField(raw, "attribution");
213
+ if (!FAILURE_ATTRIBUTIONS.has(attribution)) {
214
+ throw new FabricTaskError("malformed producer outcome: failure.attribution", "malformed_producer_outcome", "harness");
215
+ }
216
+ }
217
+
218
+ /** Compare top-level and nested route subjects by canonical JCS representation. */
219
+ function routeSubjectsMatch(top: RouteSubjectV1, nested: RouteSubjectV1): boolean {
220
+ return jcsStringify(top) === jcsStringify(nested);
221
+ }
222
+
223
+ /** Build an allowlisted verifier_summary artifact with sanitized diagnostics. */
224
+ function sanitizedVerifierSummary(outcome: FabricTaskOutcomeV1): Record<string, unknown> {
225
+ const verifier = {
226
+ verifierId: outcome.verifier.verifierId,
227
+ manifestDigest: outcome.verifier.manifestDigest,
228
+ passed: outcome.verifier.passed,
229
+ pathSummaries: outcome.verifier.pathSummaries.map((row) => ({
230
+ path: row.path,
231
+ kind: row.kind,
232
+ ...(row.beforeDigest ? { beforeDigest: row.beforeDigest } : {}),
233
+ ...(row.afterDigest ? { afterDigest: row.afterDigest } : {}),
234
+ ...(row.reason ? { reason: truncateUtf8(sanitizeDiagnostic(row.reason), 512) } : {}),
235
+ })),
236
+ ...(outcome.verifier.reason
237
+ ? { reason: truncateUtf8(sanitizeDiagnostic(outcome.verifier.reason), 512) }
238
+ : {}),
239
+ };
240
+ return {
241
+ scenarioId: FABRIC_SCENARIO_ID,
242
+ passed: outcome.verifier.passed,
243
+ verifier,
244
+ usage: outcome.usage,
245
+ outcome: outcome.outcome,
246
+ };
247
+ }
248
+
249
+ /** Parse and deeply validate a fabric producer outcome before persistence. */
250
+ export function assertFabricOutcomeV1(raw: unknown): FabricTaskOutcomeV1 {
251
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
252
+ throw new FabricTaskError("malformed producer outcome", "malformed_producer_outcome", "harness");
253
+ }
254
+ const obj = raw as Record<string, unknown>;
255
+ for (const key of Object.keys(obj)) {
256
+ if (!OUTCOME_KEYS.has(key)) {
257
+ throw new FabricTaskError(`unknown outcome field ${key}`, "malformed_producer_outcome", "harness");
258
+ }
259
+ }
260
+ if (obj.schemaVersion !== 1) {
261
+ throw new FabricTaskError("schemaVersion must be 1", "malformed_producer_outcome", "harness");
262
+ }
263
+
264
+ const taskSubjectObj = assertPlainObject(obj.taskSubject, "taskSubject");
265
+ const routeSubjectObj = assertPlainObject(obj.routeSubject, "routeSubject");
266
+
267
+ let taskSubject!: TaskSubjectV1;
268
+ let routeSubject!: RouteSubjectV1;
269
+ try {
270
+ taskSubject = validateSubject(taskSubjectObj, "task_effectiveness") as TaskSubjectV1;
271
+ routeSubject = validateSubject(routeSubjectObj, "live_route_compatibility") as RouteSubjectV1;
272
+ } catch (error) {
273
+ wrapValidationError(error);
274
+ }
275
+ if (jcsStringify(taskSubjectObj) !== jcsStringify(taskSubject)) {
276
+ throw new FabricTaskError("taskSubject contains undeclared fields", "malformed_producer_outcome", "harness");
277
+ }
278
+ if (jcsStringify(routeSubjectObj) !== jcsStringify(routeSubject)) {
279
+ throw new FabricTaskError("routeSubject contains undeclared fields", "malformed_producer_outcome", "harness");
280
+ }
281
+ if (!routeSubjectsMatch(routeSubject, taskSubject.routeSubject)) {
282
+ throw new FabricTaskError("contradictory route subjects", "layer_subject_mismatch", "harness");
283
+ }
284
+
285
+ const taskClassId = assertStringField(obj, "taskClassId");
286
+ const taskClassVersion = assertStringField(obj, "taskClassVersion");
287
+ const subjectId = assertStringField(obj, "subjectId");
288
+ if (!isSha256Hex(subjectId)) {
289
+ throw new FabricTaskError("malformed producer outcome: subjectId", "malformed_producer_outcome", "harness");
290
+ }
291
+ const taskFixtureDigest = assertStringField(obj, "taskFixtureDigest");
292
+ const verifierManifestDigest = assertStringField(obj, "verifierManifestDigest");
293
+ if (!isSha256Hex(taskFixtureDigest) || !isSha256Hex(verifierManifestDigest)) {
294
+ throw new FabricTaskError("malformed producer outcome: digest field", "malformed_producer_outcome", "harness");
295
+ }
296
+ const fabricCompatibilityVersion = assertStringField(obj, "fabricCompatibilityVersion");
297
+ const sandboxProfileDigest = assertStringField(obj, "sandboxProfileDigest");
298
+ if (!isSha256Hex(sandboxProfileDigest)) {
299
+ throw new FabricTaskError("malformed producer outcome: sandboxProfileDigest", "malformed_producer_outcome", "harness");
300
+ }
301
+ if (subjectId !== subjectIdForSubject(taskSubject)) {
302
+ throw new FabricTaskError("subjectId does not match taskSubject", "malformed_producer_outcome", "harness");
303
+ }
304
+ if (
305
+ taskClassId !== taskSubject.taskClassId
306
+ || taskClassVersion !== taskSubject.taskClassVersion
307
+ || taskFixtureDigest !== taskSubject.taskFixtureDigest
308
+ || verifierManifestDigest !== taskSubject.verifierManifestDigest
309
+ || fabricCompatibilityVersion !== taskSubject.fabricCompatibilityVersion
310
+ || sandboxProfileDigest !== taskSubject.sandboxProfileDigest
311
+ ) {
312
+ throw new FabricTaskError("task identity fields do not match taskSubject", "malformed_producer_outcome", "harness");
313
+ }
314
+ const startedAt = assertNonNegativeIntegerField(obj, "startedAt");
315
+ const completedAt = assertNonNegativeIntegerField(obj, "completedAt");
316
+ if (completedAt < startedAt) {
317
+ throw new FabricTaskError("invalid execution timestamps", "malformed_producer_outcome", "harness");
318
+ }
319
+ validateFabricLimits(assertPlainObject(obj.limits, "limits"));
320
+ validateFabricUsage(assertPlainObject(obj.usage, "usage"));
321
+ const verifier = assertPlainObject(obj.verifier, "verifier");
322
+ validateFabricVerifier(verifier);
323
+ if (verifier.manifestDigest !== verifierManifestDigest) {
324
+ throw new FabricTaskError("verifier manifest digest does not match outcome", "malformed_producer_outcome", "harness");
325
+ }
326
+ if (!OUTCOMES.includes(obj.outcome as typeof OUTCOMES[number])) {
327
+ throw new FabricTaskError("malformed producer outcome: outcome", "malformed_producer_outcome", "harness");
328
+ }
329
+ if (!Array.isArray(obj.artifactDigests)) {
330
+ throw new FabricTaskError("malformed producer outcome: artifactDigests", "malformed_producer_outcome", "harness");
331
+ }
332
+ for (const digest of obj.artifactDigests) {
333
+ if (typeof digest !== "string" || !isSha256Hex(digest)) {
334
+ throw new FabricTaskError("malformed producer outcome: artifactDigests", "malformed_producer_outcome", "harness");
335
+ }
336
+ }
337
+ if (obj.failure !== undefined) {
338
+ validateFailureRecord(assertPlainObject(obj.failure, "failure"));
339
+ }
340
+ if (obj.sourceRefs !== undefined) {
341
+ if (!Array.isArray(obj.sourceRefs) || !obj.sourceRefs.every((row) => typeof row === "string" && row.length > 0)) {
342
+ throw new FabricTaskError("malformed producer outcome: sourceRefs", "malformed_producer_outcome", "harness");
343
+ }
344
+ }
345
+
346
+ return raw as FabricTaskOutcomeV1;
347
+ }
348
+
349
+ /** Convert a validated fabric outcome into a ledger-ready observation and artifacts. */
350
+ export function observationFromFabricOutcome(
351
+ outcomeRaw: unknown,
352
+ opts: PersistFabricOptions = {},
353
+ ): { event: ObservationEvent; artifacts: ReturnType<ArtifactStore["put"]>[] } {
354
+ const outcome = assertFabricOutcomeV1(outcomeRaw);
355
+ const taskSubject = outcome.taskSubject as TaskSubjectV1;
356
+ const routeSubject = outcome.routeSubject as RouteSubjectV1;
357
+ if (taskSubject.subjectKind !== "task") {
358
+ throw new FabricTaskError("task layer requires TaskSubjectV1", "layer_subject_mismatch", "harness");
359
+ }
360
+ if (routeSubject.subjectKind !== "route") {
361
+ throw new FabricTaskError("nested route subject required", "layer_subject_mismatch", "harness");
362
+ }
363
+
364
+ const paths = ensureLabDirs(opts.configDir);
365
+ const ownsStore = !opts.artifactStore;
366
+ const store = opts.artifactStore ?? createArtifactStore(paths.artifactsDir);
367
+ try {
368
+ const authority = loadFabricCaseAuthority();
369
+ const caseRecord = authority.cases.find((row) => row.id === FABRIC_SCENARIO_ID);
370
+ if (!caseRecord) {
371
+ throw new FabricTaskError(`missing fabric scenario ${FABRIC_SCENARIO_ID}`, "harness_failure", "harness");
372
+ }
373
+ const scenarioDigest = fabricScenarioManifestDigest(caseRecord, authority);
374
+ const suiteDigest = fabricSuiteManifestDigest(FABRIC_SUITE_ID, authority);
375
+ const expandedScenario = expandFabricScenario(caseRecord, authority);
376
+ const expandedSuite = expandFabricSuiteManifest(FABRIC_SUITE_ID, authority);
377
+ const fixtureBytes = new TextEncoder().encode(caseRecord.fixture.bytesUtf8);
378
+ const fixtureDigests = [fixtureDigest(fixtureBytes)];
379
+
380
+ const artifacts: ReturnType<ArtifactStore["put"]>[] = [];
381
+ artifacts.push(store.put({
382
+ artifactClass: "fixture",
383
+ payload: fixtureBytes,
384
+ expectedDigest: fixtureDigests[0],
385
+ mediaType: caseRecord.fixture.mediaType,
386
+ }));
387
+ artifacts.push(store.put({
388
+ artifactClass: "scenario_manifest",
389
+ payload: expandedScenario,
390
+ expectedDigest: scenarioDigest,
391
+ }));
392
+ artifacts.push(store.put({
393
+ artifactClass: "suite_manifest",
394
+ payload: expandedSuite,
395
+ expectedDigest: suiteDigest,
396
+ }));
397
+ artifacts.push(store.put({
398
+ artifactClass: "verifier_summary",
399
+ payload: sanitizedVerifierSummary(outcome),
400
+ }));
401
+
402
+ const limits: Record<string, number | null> = {};
403
+ for (const key of OBSERVATION_LIMIT_NAMES) {
404
+ if (key in authority.manifestDefaults.executionLimits) {
405
+ limits[key] = authority.manifestDefaults.executionLimits[key] ?? null;
406
+ }
407
+ }
408
+
409
+ const recordedAt = opts.recordedAt ?? outcome.completedAt;
410
+ const eventWithoutId = {
411
+ schemaVersion: LAB_EVENT_SCHEMA_VERSION,
412
+ eventKind: "observation" as const,
413
+ recordedAt,
414
+ producer: LAB_PRODUCER,
415
+ producerVersion: opts.producerVersion ?? LAB_PRODUCER_VERSION,
416
+ evidenceLayer: FABRIC_EVIDENCE_LAYER,
417
+ scenarioId: FABRIC_SCENARIO_ID,
418
+ scenarioVersion: FABRIC_SCENARIO_VERSION,
419
+ scenarioManifestDigest: scenarioDigest,
420
+ suiteId: FABRIC_SUITE_ID,
421
+ suiteVersion: FABRIC_SUITE_VERSION,
422
+ suiteManifestDigest: suiteDigest,
423
+ fixtureDigests,
424
+ subject: outcome.taskSubject,
425
+ subjectId: outcome.subjectId,
426
+ startedAt: outcome.startedAt,
427
+ completedAt: outcome.completedAt,
428
+ executionMode: "fabric" as const,
429
+ attempt: opts.attempt ?? 1,
430
+ limits,
431
+ outcome: outcome.outcome,
432
+ assertions: [{
433
+ id: "exact-tree-diff-pass",
434
+ operator: "equals",
435
+ required: true,
436
+ passed: outcome.verifier.passed,
437
+ expectedSummary: "pass",
438
+ observedSummary: truncateUtf8(sanitizeDiagnostic(outcome.verifier.reason ?? (outcome.verifier.passed ? "pass" : "fail")), 512),
439
+ }],
440
+ environment: {
441
+ runtime: {
442
+ platform: process.platform,
443
+ arch: process.arch,
444
+ bunVersion: process.versions.bun ?? Bun.version,
445
+ },
446
+ },
447
+ artifactRefs: artifacts,
448
+ ...(outcome.failure ? { failure: outcome.failure } : {}),
449
+ ...(outcome.sourceRefs ? { sourceRefs: [...outcome.sourceRefs] } : {}),
450
+ };
451
+ return { event: assignEventId(eventWithoutId) as ObservationEvent, artifacts };
452
+ } finally {
453
+ if (ownsStore) store.close();
454
+ }
455
+ }
456
+
457
+ /** Module-private ledger append helper; production evidence must use {@link persistFabricRunResult}. */
458
+ function persistFabricOutcome(
459
+ outcome: FabricTaskOutcomeV1,
460
+ opts: PersistFabricOptions = {},
461
+ ): PersistedFabricObservation {
462
+ const paths = ensureLabDirs(opts.configDir);
463
+ const ownsStore = !opts.artifactStore;
464
+ const store = opts.artifactStore ?? createArtifactStore(paths.artifactsDir);
465
+ try {
466
+ return withLedgerMutation(paths.ledgerPath, (ledger) => {
467
+ const { event } = observationFromFabricOutcome(outcome, { ...opts, artifactStore: store });
468
+ ledger.appendIfAbsent(event);
469
+ return { event, ledgerPath: paths.ledgerPath };
470
+ });
471
+ } finally {
472
+ if (ownsStore) store.close();
473
+ }
474
+ }
475
+
476
+ /** Persist production fabric evidence from a trusted-route run result. */
477
+ export function persistFabricRunResult(
478
+ result: FabricTaskRunResult,
479
+ opts: PersistFabricOptions = {},
480
+ ): PersistedFabricObservation {
481
+ if (result.executionAuthority !== "trusted_route") {
482
+ throw new FabricTaskError(
483
+ "fabric evidence requires trusted route execution authority",
484
+ "malformed_producer_outcome",
485
+ "harness",
486
+ );
487
+ }
488
+ return persistFabricOutcome(result.outcome, opts);
489
+ }
@@ -0,0 +1,79 @@
1
+ import { FABRIC_LIMITS, SYNTHETIC_VALUE_PATH } from "./constants";
2
+ import { assertSafeRelativePosixPath, writeScratchFileUtf8 } from "./scratch";
3
+ import { FabricTaskError, type SyntheticPatchV1 } from "./types";
4
+
5
+ const ALLOWED_KEYS = new Set(["schemaVersion", "operations"]);
6
+ const OP_KEYS = new Set(["op", "path", "contentUtf8"]);
7
+
8
+ /** Parse and validate a synthetic-patch producer payload. */
9
+ export function parseSyntheticPatchV1(raw: unknown): SyntheticPatchV1 {
10
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
11
+ throw new FabricTaskError("malformed producer outcome: patch must be object", "malformed_producer_outcome", "harness");
12
+ }
13
+ const obj = raw as Record<string, unknown>;
14
+ for (const key of Object.keys(obj)) {
15
+ if (!ALLOWED_KEYS.has(key)) {
16
+ throw new FabricTaskError(`malformed producer outcome: unknown field ${key}`, "malformed_producer_outcome", "harness");
17
+ }
18
+ }
19
+ if (obj.schemaVersion !== 1) {
20
+ throw new FabricTaskError("malformed producer outcome: schemaVersion", "malformed_producer_outcome", "harness");
21
+ }
22
+ if (!Array.isArray(obj.operations)) {
23
+ throw new FabricTaskError("malformed producer outcome: operations", "malformed_producer_outcome", "harness");
24
+ }
25
+ if (obj.operations.length !== 1) {
26
+ throw new FabricTaskError("exactly one patch operation is required", "malformed_producer_outcome", "harness");
27
+ }
28
+ const opRaw = obj.operations[0];
29
+ if (!opRaw || typeof opRaw !== "object" || Array.isArray(opRaw)) {
30
+ throw new FabricTaskError("malformed producer outcome: operation", "malformed_producer_outcome", "harness");
31
+ }
32
+ const op = opRaw as Record<string, unknown>;
33
+ for (const key of Object.keys(op)) {
34
+ if (!OP_KEYS.has(key)) {
35
+ throw new FabricTaskError(`malformed producer outcome: unknown op field ${key}`, "malformed_producer_outcome", "harness");
36
+ }
37
+ }
38
+ if (op.op !== "replace" || typeof op.path !== "string" || typeof op.contentUtf8 !== "string") {
39
+ throw new FabricTaskError("malformed producer outcome: replace shape", "malformed_producer_outcome", "harness");
40
+ }
41
+ try {
42
+ assertSafeRelativePosixPath(op.path);
43
+ } catch (error) {
44
+ if (error instanceof FabricTaskError) throw error;
45
+ throw new FabricTaskError("patch path escapes scratch", "sandbox_violation", "harness");
46
+ }
47
+ if (op.path !== SYNTHETIC_VALUE_PATH) {
48
+ throw new FabricTaskError("patch path must be src/value.txt", "behavioral_failure", "route");
49
+ }
50
+ const contentBytes = Buffer.byteLength(op.contentUtf8, "utf8");
51
+ if (contentBytes > FABRIC_LIMITS.maxAggregateIoBytes) {
52
+ throw new FabricTaskError("patch content exceeds io budget", "budget_exhausted", "environment");
53
+ }
54
+ return {
55
+ schemaVersion: 1,
56
+ operations: [{ op: "replace", path: SYNTHETIC_VALUE_PATH, contentUtf8: op.contentUtf8 }],
57
+ };
58
+ }
59
+
60
+ /** Apply a validated synthetic patch inside the scratch tree under budget limits. */
61
+ export function applySyntheticPatch(scratchRoot: string, patch: SyntheticPatchV1): { bytesWritten: number; filesTouched: number; patchOperations: number } {
62
+ if (patch.operations.length > FABRIC_LIMITS.maxPatchOperations) {
63
+ throw new FabricTaskError("too many patch operations", "budget_exhausted", "environment");
64
+ }
65
+ let bytesWritten = 0;
66
+ for (const operation of patch.operations) {
67
+ bytesWritten += writeScratchFileUtf8(
68
+ scratchRoot,
69
+ operation.path,
70
+ operation.contentUtf8,
71
+ FABRIC_LIMITS.maxAggregateIoBytes,
72
+ );
73
+ }
74
+ return {
75
+ bytesWritten,
76
+ filesTouched: patch.operations.length,
77
+ patchOperations: patch.operations.length,
78
+ };
79
+ }