@aiwg/cli 2026.10.1 → 2026.10.4

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 (361) hide show
  1. package/README.md +2 -2
  2. package/agentic/code/providers/capability-matrix.yaml +270 -0
  3. package/agentic/code/providers/model-capabilities.v1.json +3183 -24
  4. package/bin/aiwg.mjs +135 -47
  5. package/dist/src/a2a/codecs.js +9 -0
  6. package/dist/src/agents/grounding/knowledge-base.js +54 -6
  7. package/dist/src/artifacts/browser-export.js +6 -0
  8. package/dist/src/artifacts/checksum-manifest.js +1 -0
  9. package/dist/src/artifacts/citation-parser.js +173 -92
  10. package/dist/src/artifacts/citation-table-schema.js +59 -0
  11. package/dist/src/artifacts/cli.js +57 -18
  12. package/dist/src/artifacts/corpus-tools/snapshot.js +1 -1
  13. package/dist/src/artifacts/corpus-tools/vision-extract.js +107 -15
  14. package/dist/src/artifacts/corpus-views/ref-parser.js +3 -1
  15. package/dist/src/artifacts/corpus-views/renderers.js +3 -3
  16. package/dist/src/artifacts/discovery-eval.js +6 -4
  17. package/dist/src/artifacts/fortemi-core-query-adapter.js +36 -3
  18. package/dist/src/artifacts/fortemi-core-sync.js +166 -40
  19. package/dist/src/artifacts/framework-capabilities.js +171 -0
  20. package/dist/src/artifacts/framework-index-paths.js +73 -0
  21. package/dist/src/artifacts/framework-source-digest.js +75 -0
  22. package/dist/src/artifacts/index-builder.js +285 -131
  23. package/dist/src/artifacts/index-files.js +132 -18
  24. package/dist/src/artifacts/index-preparation.js +65 -0
  25. package/dist/src/artifacts/index-refresh.js +576 -0
  26. package/dist/src/artifacts/index-worker.mjs +9 -0
  27. package/dist/src/artifacts/prebuilt-build-lock.js +47 -4
  28. package/dist/src/artifacts/prebuilt-deployment.js +46 -0
  29. package/dist/src/artifacts/prebuilt-relations.js +80 -0
  30. package/dist/src/artifacts/query-engine.js +410 -88
  31. package/dist/src/artifacts/relations-builder.js +168 -0
  32. package/dist/src/artifacts/relations.js +148 -0
  33. package/dist/src/artifacts/repair.js +9 -4
  34. package/dist/src/artifacts/stats.js +5 -2
  35. package/dist/src/artifacts/types.js +30 -10
  36. package/dist/src/artifacts/watcher.js +1 -1
  37. package/dist/src/auth/credential-store.js +2 -1
  38. package/dist/src/catalog/cli.d.mts +5 -0
  39. package/dist/src/channel/manager.d.mts +20 -0
  40. package/dist/src/channel/manager.mjs +78 -12
  41. package/dist/src/cli/child-process-result.js +40 -0
  42. package/dist/src/cli/command-log.js +2 -3
  43. package/dist/src/cli/env.js +38 -16
  44. package/dist/src/cli/flag-parsing.js +236 -0
  45. package/dist/src/cli/handlers/artifacts.js +3 -0
  46. package/dist/src/cli/handlers/auth.js +3 -0
  47. package/dist/src/cli/handlers/decision.js +218 -5
  48. package/dist/src/cli/handlers/diagnose.js +13 -5
  49. package/dist/src/cli/handlers/effect.js +4 -2
  50. package/dist/src/cli/handlers/evidence.js +3 -0
  51. package/dist/src/cli/handlers/feedback.js +14 -5
  52. package/dist/src/cli/handlers/help.js +1 -0
  53. package/dist/src/cli/handlers/index.js +3 -1
  54. package/dist/src/cli/handlers/init.js +248 -30
  55. package/dist/src/cli/handlers/lint.js +5 -0
  56. package/dist/src/cli/handlers/mc.js +23 -0
  57. package/dist/src/cli/handlers/models.js +169 -10
  58. package/dist/src/cli/handlers/ralph-launcher.js +2 -0
  59. package/dist/src/cli/handlers/ralph.js +3 -0
  60. package/dist/src/cli/handlers/refresh.js +28 -0
  61. package/dist/src/cli/handlers/regenerate.js +14 -0
  62. package/dist/src/cli/handlers/resource-versions.js +3 -0
  63. package/dist/src/cli/handlers/rules.js +195 -0
  64. package/dist/src/cli/handlers/run.js +4 -0
  65. package/dist/src/cli/handlers/runtime-info.js +25 -11
  66. package/dist/src/cli/handlers/script-runner.js +19 -8
  67. package/dist/src/cli/handlers/session.js +406 -62
  68. package/dist/src/cli/handlers/sessions.js +243 -76
  69. package/dist/src/cli/handlers/setup-manifest.js +474 -79
  70. package/dist/src/cli/handlers/setup.js +180 -39
  71. package/dist/src/cli/handlers/steward.js +11 -0
  72. package/dist/src/cli/handlers/subcommands.js +60 -3
  73. package/dist/src/cli/handlers/team.js +18 -8
  74. package/dist/src/cli/handlers/uhp.js +3 -0
  75. package/dist/src/cli/handlers/use.js +307 -55
  76. package/dist/src/cli/handlers/utilities.js +125 -26
  77. package/dist/src/cli/handlers/version.js +8 -0
  78. package/dist/src/cli/prompt-utils.js +72 -0
  79. package/dist/src/cli/provider-resolution.js +11 -0
  80. package/dist/src/cli/router.js +15 -1
  81. package/dist/src/cli/services/deployment-verification.js +19 -9
  82. package/dist/src/cli/services/provider-prepare-coordinator.js +24 -0
  83. package/dist/src/cli/skill-usage.js +2 -3
  84. package/dist/src/config/aiwg-config.js +349 -35
  85. package/dist/src/config/cli.js +256 -23
  86. package/dist/src/config/decision-config.js +106 -0
  87. package/dist/src/config/dispatch-thresholds-runtime.d.mts +8 -0
  88. package/dist/src/config/dispatch-thresholds-runtime.mjs +38 -0
  89. package/dist/src/config/gitignore.js +50 -0
  90. package/dist/src/config/index-graph-overrides.js +36 -0
  91. package/dist/src/config/project-artifacts-health.d.mts +37 -0
  92. package/dist/src/config/project-artifacts-health.mjs +14 -3
  93. package/dist/src/config/project-artifacts-runtime.d.mts +16 -0
  94. package/dist/src/config/user-config-dir.d.mts +9 -0
  95. package/dist/src/config/user-config.js +38 -11
  96. package/dist/src/config/user-registry.js +23 -15
  97. package/dist/src/config/user-state.js +7 -0
  98. package/dist/src/decision/adapters/jev.js +75 -27
  99. package/dist/src/decision/ask.js +203 -43
  100. package/dist/src/decision/context-live-qualification.js +2 -2
  101. package/dist/src/decision/driver.js +14 -7
  102. package/dist/src/decision/ensemble/aggregate.js +23 -10
  103. package/dist/src/decision/ensemble-study/multifact-study.js +6 -2
  104. package/dist/src/decision/entry.js +25 -6
  105. package/dist/src/decision/graph-live-qualification.js +1 -1
  106. package/dist/src/decision/graph-run.js +9 -0
  107. package/dist/src/decision/heldout/collector.js +15 -14
  108. package/dist/src/decision/heldout/contract.js +30 -7
  109. package/dist/src/decision/index.js +1 -0
  110. package/dist/src/decision/interop.js +60 -8
  111. package/dist/src/decision/jev-credentials.js +15 -1
  112. package/dist/src/decision/ledger.js +942 -0
  113. package/dist/src/decision/offload-activation.js +137 -0
  114. package/dist/src/decision/offload.js +550 -0
  115. package/dist/src/decision/qualification/load.js +4 -6
  116. package/dist/src/decision/savings.js +28 -0
  117. package/dist/src/decision/validate.js +6 -3
  118. package/dist/src/effects/dispatch-verifier.js +252 -0
  119. package/dist/src/effects/index.js +1 -0
  120. package/dist/src/effects/types.js +5 -1
  121. package/dist/src/effects/verifiers/git.js +2 -1
  122. package/dist/src/effects/verifiers/tracker.js +26 -14
  123. package/dist/src/extensions/commands/definitions.js +19 -0
  124. package/dist/src/extensions/project-local-remove.js +36 -1
  125. package/dist/src/features/installer.js +2 -2
  126. package/dist/src/flow/graph-metadata.js +5 -0
  127. package/dist/src/gates/providers/loader.js +64 -18
  128. package/dist/src/installation/manager-command.d.mts +18 -0
  129. package/dist/src/installation/manager-command.mjs +15 -3
  130. package/dist/src/installation/manager.d.mts +49 -0
  131. package/dist/src/installation/manager.mjs +95 -5
  132. package/dist/src/issues/cli.js +4 -4
  133. package/dist/src/issues/local.js +24 -5
  134. package/dist/src/jobs/runner.js +1 -1
  135. package/dist/src/lint/cli.js +27 -1
  136. package/dist/src/lint/loader.js +2 -1
  137. package/dist/src/lint/reporters.js +25 -1
  138. package/dist/src/lint/rule-activation.js +43 -0
  139. package/dist/src/lint/runner.js +137 -62
  140. package/dist/src/mcp/adapters/codex-runtime.js +366 -56
  141. package/dist/src/mcp/claude-install.d.mts +4 -0
  142. package/dist/src/mcp/claude-install.mjs +41 -0
  143. package/dist/src/mcp/cli.d.mts +1 -0
  144. package/dist/src/mcp/cli.mjs +620 -85
  145. package/dist/src/mcp/config-file.d.mts +28 -0
  146. package/dist/src/mcp/config-file.mjs +279 -0
  147. package/dist/src/mcp/config-layers.d.mts +36 -0
  148. package/dist/src/mcp/config-layers.mjs +348 -0
  149. package/dist/src/mcp/credentials.d.mts +51 -0
  150. package/dist/src/mcp/credentials.mjs +484 -0
  151. package/dist/src/mcp/grok-build-config.d.mts +6 -0
  152. package/dist/src/mcp/grok-build-config.mjs +17 -27
  153. package/dist/src/mcp/helpers.mjs +109 -4
  154. package/dist/src/mcp/muse-native-config.d.mts +13 -0
  155. package/dist/src/mcp/muse-native-config.mjs +1 -0
  156. package/dist/src/mcp/omp-config.d.mts +4 -0
  157. package/dist/src/mcp/omp-config.mjs +50 -29
  158. package/dist/src/mcp/profiles.js +97 -23
  159. package/dist/src/mcp/profiles.mjs +99 -27
  160. package/dist/src/mcp/registry.js +248 -131
  161. package/dist/src/mcp/registry.mjs +169 -100
  162. package/dist/src/mcp/server-config.d.mts +3 -0
  163. package/dist/src/mcp/server-config.mjs +89 -0
  164. package/dist/src/mcp/server.mjs +127 -82
  165. package/dist/src/mcp/test-simple.mjs +2 -1
  166. package/dist/src/mcp/toml-editor.d.mts +4 -0
  167. package/dist/src/mcp/toml-string.d.mts +1 -0
  168. package/dist/src/mcp/toml-string.mjs +9 -0
  169. package/dist/src/mcp/toml-strip-mcp.d.mts +1 -0
  170. package/dist/src/mcp/toml-strip-mcp.mjs +135 -0
  171. package/dist/src/mcp/tool-filters.d.mts +46 -0
  172. package/dist/src/mcp/tool-filters.mjs +357 -0
  173. package/dist/src/mcp/tools/agentic-sandbox.mjs +3 -1
  174. package/dist/src/mcp/tools/decision.mjs +22 -3
  175. package/dist/src/mcp/tools/discovery.mjs +62 -55
  176. package/dist/src/mcp/tools/orchestration.mjs +50 -2
  177. package/dist/src/mcp/tools/subsystems.mjs +39 -8
  178. package/dist/src/mcp/tools/worker-invoke.mjs +2856 -0
  179. package/dist/src/mcp/tools/worker-shell-control.mjs +289 -0
  180. package/dist/src/mcp/tools/worker-stdin-runtime.mjs +79 -0
  181. package/dist/src/memory/project-registry.js +2 -2
  182. package/dist/src/mission-protocol/codecs.js +647 -1
  183. package/dist/src/mission-protocol/types.js +110 -0
  184. package/dist/src/mission-protocol/worker-status.js +2 -0
  185. package/dist/src/models/config-loader.js +76 -14
  186. package/dist/src/models/grok-build-models.js +93 -41
  187. package/dist/src/models/model-capabilities.v1.json +3183 -24
  188. package/dist/src/models/model-discovery.js +931 -67
  189. package/dist/src/models/provider-policy.js +719 -11
  190. package/dist/src/models/qualification-digest.d.mts +2 -0
  191. package/dist/src/models/qualification-digest.mjs +17 -0
  192. package/dist/src/models/resolver.js +261 -0
  193. package/dist/src/models/worker-direct-readiness.js +550 -0
  194. package/dist/src/models/worker-dispatch-offer.js +169 -0
  195. package/dist/src/models/worker-health-readiness.js +144 -0
  196. package/dist/src/models/worker-installation.d.mts +39 -0
  197. package/dist/src/models/worker-installation.mjs +986 -0
  198. package/dist/src/models/wrapper-route.js +18 -0
  199. package/dist/src/ops/registry.js +9 -14
  200. package/dist/src/plugins/standalone-packager.js +4 -3
  201. package/dist/src/process/bounded-child-process.d.mts +84 -0
  202. package/dist/src/process/bounded-child-process.mjs +430 -0
  203. package/dist/src/process/cli-command.d.mts +16 -0
  204. package/dist/src/process/cli-command.mjs +75 -0
  205. package/dist/src/process/signal-child.d.mts +6 -0
  206. package/dist/src/process/signal-child.mjs +7 -0
  207. package/dist/src/providers/capability-matrix.js +8 -0
  208. package/dist/src/providers/capability-matrix.yaml +270 -0
  209. package/dist/src/providers/deployed-skill-roots.js +20 -0
  210. package/dist/src/providers/grok-build-acp.js +3 -2
  211. package/dist/src/providers/grok-build-headless.js +53 -23
  212. package/dist/src/providers/grok-build-inspect.js +1 -0
  213. package/dist/src/providers/omp-agent.d.mts +8 -0
  214. package/dist/src/providers/omp-diagnostics.d.mts +1 -0
  215. package/dist/src/providers/omp-paths.d.mts +13 -0
  216. package/dist/src/providers/provider-definitions.js +9 -1
  217. package/dist/src/providers/provider-definitions.mjs +9 -2
  218. package/dist/src/providers/skill-ownership.d.mts +9 -0
  219. package/dist/src/providers/skill-ownership.mjs +88 -0
  220. package/dist/src/rules/activation.d.mts +21 -0
  221. package/dist/src/rules/activation.mjs +62 -0
  222. package/dist/src/rules/inline-budget.d.mts +26 -0
  223. package/dist/src/rules/inline-budget.mjs +66 -0
  224. package/dist/src/rules/inventory.js +129 -0
  225. package/dist/src/rules/pin-state.js +73 -0
  226. package/dist/src/rules/pins.d.mts +14 -0
  227. package/dist/src/rules/pins.mjs +112 -0
  228. package/dist/src/rules/rule-frontmatter.schema.json +197 -0
  229. package/dist/src/serve/executor-registry.js +16 -24
  230. package/dist/src/serve/fleet-mission-conductor.js +9 -0
  231. package/dist/src/serve/mission-conductor.js +47 -12
  232. package/dist/src/serve/shared-host-scheduler.js +2 -0
  233. package/dist/src/serve/worker-invocation.js +558 -0
  234. package/dist/src/serve/worker-stdin-frame.d.mts +10 -0
  235. package/dist/src/serve/worker-stdin-frame.mjs +107 -0
  236. package/dist/src/sessions/adapter-registry.js +49 -0
  237. package/dist/src/sessions/adapters/claude.js +39 -54
  238. package/dist/src/sessions/adapters/codex.js +82 -67
  239. package/dist/src/sessions/adapters/copilot.js +4 -4
  240. package/dist/src/sessions/adapters/cursor.js +40 -57
  241. package/dist/src/sessions/adapters/deepseek-harness.js +15 -12
  242. package/dist/src/sessions/adapters/factory.js +31 -27
  243. package/dist/src/sessions/adapters/generic.js +43 -9
  244. package/dist/src/sessions/adapters/grok-build.js +11 -11
  245. package/dist/src/sessions/adapters/grokbot-locator.js +111 -0
  246. package/dist/src/sessions/adapters/grokbot.js +434 -24
  247. package/dist/src/sessions/adapters/hermes.js +27 -29
  248. package/dist/src/sessions/adapters/muse-workspace-scan.js +128 -0
  249. package/dist/src/sessions/adapters/muse.js +200 -104
  250. package/dist/src/sessions/adapters/omp.js +28 -14
  251. package/dist/src/sessions/adapters/openclaw.js +89 -79
  252. package/dist/src/sessions/adapters/opencode.js +27 -24
  253. package/dist/src/sessions/adapters/openhuman.js +18 -60
  254. package/dist/src/sessions/adapters/pi.js +30 -14
  255. package/dist/src/sessions/adapters/warp.js +3 -3
  256. package/dist/src/sessions/adapters/windsurf.js +19 -48
  257. package/dist/src/sessions/batch-contracts.js +25 -5
  258. package/dist/src/sessions/batch-import.js +72 -51
  259. package/dist/src/sessions/candidates.js +47 -11
  260. package/dist/src/sessions/contracts.js +75 -2
  261. package/dist/src/sessions/coverage-preflight.js +134 -0
  262. package/dist/src/sessions/discovery.js +3 -0
  263. package/dist/src/sessions/export-plan.js +4 -3
  264. package/dist/src/sessions/grok-build-cli.js +67 -5
  265. package/dist/src/sessions/import-exclusions.js +72 -0
  266. package/dist/src/sessions/import-lease.js +34 -18
  267. package/dist/src/sessions/import-limits.js +37 -0
  268. package/dist/src/sessions/importer.js +84 -46
  269. package/dist/src/sessions/index.js +2 -0
  270. package/dist/src/sessions/lifecycle.js +45 -0
  271. package/dist/src/sessions/policy.js +133 -25
  272. package/dist/src/sessions/readers.js +106 -53
  273. package/dist/src/sessions/refresh.js +106 -0
  274. package/dist/src/sessions/repository.js +199 -63
  275. package/dist/src/sessions/workspace-discovery.js +315 -88
  276. package/dist/src/sessions/workspace-matching.js +107 -0
  277. package/dist/src/skills/adapters/clawhub.js +10 -8
  278. package/dist/src/skills/adapters/openclaw.js +10 -7
  279. package/dist/src/skills/importer.js +1 -0
  280. package/dist/src/smiths/context-pipeline/aiwg-md.js +11 -0
  281. package/dist/src/smiths/context-pipeline/claude-hook.js +3 -26
  282. package/dist/src/smiths/context-pipeline/finalization.js +6 -5
  283. package/dist/src/smiths/context-pipeline/generator.js +21 -4
  284. package/dist/src/smiths/context-pipeline/parallelism-section.js +195 -14
  285. package/dist/src/smiths/context-pipeline/workspace-context.js +116 -9
  286. package/dist/src/smiths/hook-bridge/codex-translator.js +6 -5
  287. package/dist/src/smiths/mcpsmith/example.js +1 -1
  288. package/dist/src/smiths/mcpsmith/generator.js +1 -1
  289. package/dist/src/smiths/toolsmith/runtime-discovery.d.mts +10 -0
  290. package/dist/src/smiths/toolsmith/runtime-discovery.mjs +85 -31
  291. package/dist/src/storage/backends/fs.js +18 -76
  292. package/dist/src/storage/backends/logseq.js +68 -7
  293. package/dist/src/storage/backends/obsidian.js +1 -0
  294. package/dist/src/storage/fortemi-qualification-receipt.js +2 -2
  295. package/dist/src/testing/generators/test-code-generator.js +57 -30
  296. package/dist/src/tracker/forge-http.js +2 -1
  297. package/dist/src/uhp/client.js +11 -1
  298. package/dist/src/uhp/mission.js +5 -0
  299. package/dist/src/update/checker.d.mts +2 -0
  300. package/dist/src/update/checker.mjs +5 -5
  301. package/dist/src/update/notifier.mjs +54 -2
  302. package/dist/src/update/service.d.mts +22 -0
  303. package/dist/src/utils/contained-filesystem.d.mts +37 -0
  304. package/dist/src/utils/contained-filesystem.mjs +683 -0
  305. package/dist/src/utils/temporary-directory.js +36 -0
  306. package/dist/src/writing/example-generator.js +1 -1
  307. package/dist/src/writing/fidelity.js +18 -1
  308. package/package.json +32 -2
  309. package/schemas/mission-v1.schema.json +2429 -0
  310. package/schemas/models/model-catalog.v1.schema.json +301 -0
  311. package/schemas/models/model-config-compatibility.v1.schema.json +281 -0
  312. package/schemas/models/model-policy.v1.schema.json +14 -0
  313. package/schemas/models/provider-model-capabilities.v1.schema.json +1072 -0
  314. package/tools/_resolve-impl.mjs +39 -2
  315. package/tools/agents/deploy-agents.mjs +64 -23
  316. package/tools/agents/providers/base.mjs +153 -166
  317. package/tools/agents/providers/claude.mjs +8 -24
  318. package/tools/agents/providers/codex.mjs +18 -11
  319. package/tools/agents/providers/cursor.mjs +19 -18
  320. package/tools/agents/providers/grok-build.mjs +3 -1
  321. package/tools/agents/providers/grokbot.mjs +11 -12
  322. package/tools/agents/providers/hermes.mjs +62 -49
  323. package/tools/agents/providers/omp.mjs +5 -2
  324. package/tools/agents/providers/openclaw-translator.mjs +19 -5
  325. package/tools/agents/providers/openclaw.mjs +9 -4
  326. package/tools/agents/providers/pi.mjs +5 -0
  327. package/tools/agents/providers/provider-prepare-channel.mjs +5 -0
  328. package/tools/agents/providers/provider-prepare-coordinator.mjs +247 -0
  329. package/tools/agents/providers/provider-prepare-worker.mjs +84 -0
  330. package/tools/agents/providers/rule-delivery.mjs +1270 -0
  331. package/tools/agents/providers/warp.mjs +20 -26
  332. package/tools/cli/decision-offload-report.mjs +40 -0
  333. package/tools/cli/workspace-status.mjs +862 -0
  334. package/tools/plugin/package-plugins.mjs +186 -8
  335. package/tools/plugin/plugin-links.mjs +114 -0
  336. package/tools/providers/antigravity-transport.mjs +3 -1
  337. package/tools/providers/deepseek-harness-transport.mjs +360 -0
  338. package/tools/providers/omp-transport.mjs +194 -0
  339. package/tools/ralph-external/lib/claude-adapter.mjs +389 -0
  340. package/tools/ralph-external/lib/codex-adapter.mjs +432 -0
  341. package/tools/ralph-external/lib/consecutive-failure-circuit-breaker.mjs +1748 -0
  342. package/tools/ralph-external/lib/deepseek-harness-adapter.mjs +397 -0
  343. package/tools/ralph-external/lib/factory-adapter.mjs +503 -0
  344. package/tools/ralph-external/lib/launcher-recovery-evidence.mjs +55 -0
  345. package/tools/ralph-external/lib/muse-adapter.mjs +364 -0
  346. package/tools/ralph-external/lib/omp-adapter.mjs +315 -0
  347. package/tools/ralph-external/lib/opencode-adapter.mjs +575 -0
  348. package/tools/ralph-external/lib/openhuman-adapter.mjs +75 -0
  349. package/tools/ralph-external/lib/pi-adapter.mjs +329 -0
  350. package/tools/ralph-external/lib/provider-adapter.mjs +748 -0
  351. package/tools/ralph-external/lib/recovery-probe.mjs +72 -0
  352. package/tools/ralph-external/lib/session-environment.mjs +28 -0
  353. package/tools/ralph-external/lib/systemd-client.mjs +49 -0
  354. package/tools/ralph-external/lib/worker-health.mjs +439 -0
  355. package/tools/ralph-external/lib/worker-isolation.mjs +717 -0
  356. package/tools/ralph-external/lib/worker-overflow.mjs +50 -0
  357. package/tools/ralph-external/process-monitor.mjs +1017 -0
  358. package/tools/ralph-external/session-launcher.mjs +5057 -0
  359. package/tools/scripts/resource-preflight.mjs +541 -0
  360. package/tools/skills/deploy-skills-codex.mjs +2 -1
  361. package/vscode-extension/schemas/aiwg.config.v1.json +2916 -0
@@ -0,0 +1,128 @@
1
+ import { open } from 'node:fs/promises';
2
+ import { schemaIssueDetail, SessionContractError } from '../contracts.js';
3
+ import { authorizeSourceFile } from '../policy.js';
4
+ // Discovery inspects metadata, not an entire import. Bound allocation before
5
+ // assembling a line (readline would buffer an arbitrarily large single line).
6
+ export const MUSE_WORKSPACE_SCAN_LIMITS = Object.freeze({
7
+ maxRecords: 10_000,
8
+ maxRecordBytes: 8 * 1024 * 1024,
9
+ maxTotalBytes: 32 * 1024 * 1024,
10
+ maxNestingDepth: 64,
11
+ });
12
+ export const MUSE_WORKSPACE_TAIL_BYTES = 1024 * 1024;
13
+ export class MuseWorkspaceLimitError extends SessionContractError {
14
+ limitName;
15
+ limitValue;
16
+ constructor(limitName, limitValue, observed) {
17
+ super('RESOURCE_LIMIT_EXCEEDED', `Muse workspace inspection exceeded ${limitName}=${limitValue}`, { limit: limitName, configured: limitValue, observed });
18
+ this.limitName = limitName;
19
+ this.limitValue = limitValue;
20
+ }
21
+ }
22
+ export async function* museWorkspaceScanLines(authorization, limits, progress, tailBytes) {
23
+ const allowed = await authorizeSourceFile(authorization);
24
+ const handle = await open(allowed.canonicalPath, 'r');
25
+ try {
26
+ const buffer = Buffer.allocUnsafe(64 * 1024);
27
+ let position = tailBytes === undefined ? 0 : Math.max(0, allowed.size - tailBytes);
28
+ // A tail window may start inside a record (or a UTF-8 code point).
29
+ // Discard that fragment before parsing any complete JSONL records.
30
+ let skipPartialLine = position > 0;
31
+ let parts = [];
32
+ let length = 0;
33
+ while (position < allowed.size) {
34
+ const remaining = limits.maxTotalBytes - progress.bytesInspected;
35
+ if (remaining <= 0)
36
+ throw scanLimit('maxTotalBytes', limits.maxTotalBytes, allowed.size);
37
+ const { bytesRead } = await handle.read(buffer, 0, Math.min(buffer.length, allowed.size - position, remaining), position);
38
+ if (bytesRead === 0) {
39
+ throw new SessionContractError('TRUNCATED_SOURCE', 'Muse source changed during inspection');
40
+ }
41
+ position += bytesRead;
42
+ let start = 0;
43
+ while (start < bytesRead) {
44
+ const newline = buffer.indexOf(10, start);
45
+ const end = newline >= 0 && newline < bytesRead ? newline + 1 : bytesRead;
46
+ const segment = buffer.subarray(start, end);
47
+ if (skipPartialLine) {
48
+ progress.bytesInspected += segment.length;
49
+ start = end;
50
+ if (newline >= 0 && newline < bytesRead)
51
+ skipPartialLine = false;
52
+ continue;
53
+ }
54
+ if (length + segment.length > limits.maxRecordBytes)
55
+ throw scanLimit('maxRecordBytes', limits.maxRecordBytes, length + segment.length);
56
+ parts.push(Buffer.from(segment));
57
+ length += segment.length;
58
+ progress.bytesInspected += segment.length;
59
+ start = end;
60
+ if (newline >= 0 && newline < bytesRead) {
61
+ const line = Buffer.concat(parts, length).toString('utf8');
62
+ parts = [];
63
+ length = 0;
64
+ if (line.trim() !== '') {
65
+ if (progress.recordsInspected >= limits.maxRecords)
66
+ throw scanLimit('maxRecords', limits.maxRecords, progress.recordsInspected + 1);
67
+ const value = parseMuseScanJson(line, limits.maxNestingDepth);
68
+ progress.recordsInspected += 1;
69
+ yield value;
70
+ }
71
+ }
72
+ }
73
+ }
74
+ if (length > 0) {
75
+ const line = Buffer.concat(parts, length).toString('utf8');
76
+ if (line.trim() !== '') {
77
+ if (progress.recordsInspected >= limits.maxRecords)
78
+ throw scanLimit('maxRecords', limits.maxRecords, progress.recordsInspected + 1);
79
+ let value;
80
+ try {
81
+ value = parseMuseScanJson(line, limits.maxNestingDepth);
82
+ }
83
+ catch (error) {
84
+ if (error instanceof SessionContractError && error.code === 'MALFORMED_SOURCE') {
85
+ throw new SessionContractError('TRUNCATED_SOURCE', 'Muse source has an incomplete JSONL tail');
86
+ }
87
+ throw error;
88
+ }
89
+ progress.recordsInspected += 1;
90
+ yield value;
91
+ }
92
+ }
93
+ const after = await handle.stat();
94
+ if (after.size !== allowed.size || after.mtimeMs !== allowed.mtimeMs) {
95
+ throw new SessionContractError('TRUNCATED_SOURCE', 'Muse source changed during inspection');
96
+ }
97
+ }
98
+ finally {
99
+ await handle.close();
100
+ }
101
+ }
102
+ export function parseMuseScanJson(line, maxDepth) {
103
+ let value;
104
+ try {
105
+ value = JSON.parse(line);
106
+ }
107
+ catch {
108
+ throw new SessionContractError('MALFORMED_SOURCE', 'Muse inspection encountered malformed JSON', schemaIssueDetail('<root>', 'invalid_json'));
109
+ }
110
+ // Check depth iteratively, including decoded retained children, before zod
111
+ // validation. Deep input must produce a limit diagnostic, not stack overflow.
112
+ const pending = [{ value, depth: 0 }];
113
+ while (pending.length > 0) {
114
+ const current = pending.pop();
115
+ if (current.depth > maxDepth)
116
+ throw scanLimit('maxNestingDepth', maxDepth, current.depth);
117
+ if (current.value !== null && typeof current.value === 'object') {
118
+ for (const child of Object.values(current.value)) {
119
+ pending.push({ value: child, depth: current.depth + 1 });
120
+ }
121
+ }
122
+ }
123
+ return value;
124
+ }
125
+ function scanLimit(limit, configured, observed) {
126
+ return new MuseWorkspaceLimitError(limit, configured, observed);
127
+ }
128
+ //# sourceMappingURL=muse-workspace-scan.js.map
@@ -42,8 +42,10 @@
42
42
  import { opendir } from 'node:fs/promises';
43
43
  import { resolve } from 'node:path';
44
44
  import { z } from 'zod';
45
- import { SessionContractError, assertSupportedSchemaMajor, } from '../contracts.js';
46
- import { readBoundedJson, readBoundedJsonLines, } from '../readers.js';
45
+ import { matchSessionWorkspace, WORKSPACE_MATCH_KINDS } from '../workspace-matching.js';
46
+ import { schemaRejectionDetail, schemaIssueDetail, SessionContractError, SessionErrorCodeSchema, SessionRejectionDetailSchema, assertSupportedSchemaMajor, } from '../contracts.js';
47
+ import { readBoundedJson, streamBoundedJsonLines, } from '../readers.js';
48
+ import { MUSE_WORKSPACE_SCAN_LIMITS, MUSE_WORKSPACE_TAIL_BYTES, MuseWorkspaceLimitError, museWorkspaceScanLines, parseMuseScanJson, } from './muse-workspace-scan.js';
47
49
  export const MUSE_ADAPTER_VERSION = '1.0.0';
48
50
  export const MUSE_EXPORT_SCHEMA_VERSION = '1.0.0';
49
51
  export const MUSE_EXPORT_SCHEMA_MAJOR = 1;
@@ -79,7 +81,9 @@ const MuseEnvelopeSchema = z.object({
79
81
  durability: z.string().optional(),
80
82
  payload_type: z.string().optional(),
81
83
  payload: z.object({
82
- event: z.object({ kind: z.string().min(1) }).passthrough().optional(),
84
+ // Muse Code 1.4.3 runtime.session mode records carry an event without a
85
+ // kind; eventKindOf() falls back to payload_type for those.
86
+ event: z.object({ kind: z.string().min(1).optional() }).passthrough().optional(),
83
87
  }).passthrough().optional(),
84
88
  }).passthrough();
85
89
  /**
@@ -170,7 +174,7 @@ export class MuseSessionAdapter {
170
174
  for (const root of [...scope.allowedRoots].sort()) {
171
175
  for await (const locator of museNativeSessionLogs(resolve(root))) {
172
176
  if (++count > this.maxFiles) {
173
- throw new SessionContractError('RESOURCE_LIMIT_EXCEEDED', 'Muse native session discovery exceeded the authorized file limit');
177
+ throw new SessionContractError('RESOURCE_LIMIT_EXCEEDED', 'Muse native session discovery exceeded the authorized file limit', { limit: 'maxFiles', configured: this.maxFiles, observed: count });
174
178
  }
175
179
  yield { provider: 'muse', locator, locatorClass: MUSE_NATIVE_LOCATOR_CLASS };
176
180
  }
@@ -200,7 +204,7 @@ export class MuseSessionAdapter {
200
204
  const native = await this.readNative(source);
201
205
  const start = parseEventCursor(cursor?.value);
202
206
  let outputIndex = 0;
203
- for (const record of native.records) {
207
+ for await (const record of this.readNativeRecords(source)) {
204
208
  const position = outputIndex;
205
209
  outputIndex += 1;
206
210
  if (position < start)
@@ -251,13 +255,13 @@ export class MuseSessionAdapter {
251
255
  }
252
256
  catch (error) {
253
257
  if (error instanceof SessionContractError && error.code === 'SCHEMA_DRIFT') {
254
- throw new SessionContractError('MALFORMED_SOURCE', 'muse export document is not valid JSON');
258
+ throw new SessionContractError('MALFORMED_SOURCE', 'muse export document is not valid JSON', error.detail);
255
259
  }
256
260
  throw error;
257
261
  }
258
262
  const parsed = MuseTrajectorySchema.safeParse(value);
259
263
  if (!parsed.success) {
260
- throw new SessionContractError('MALFORMED_SOURCE', 'input is not a declared muse export trajectory document');
264
+ throw new SessionContractError('MALFORMED_SOURCE', 'input is not a declared muse export trajectory document', schemaRejectionDetail(parsed.error));
261
265
  }
262
266
  assertSupportedSchemaMajor(`${parsed.data.export_schema_version}.0.0`, MUSE_EXPORT_SCHEMA_MAJOR);
263
267
  return { trajectory: parsed.data, bytesRead };
@@ -330,80 +334,89 @@ export class MuseSessionAdapter {
330
334
  };
331
335
  }
332
336
  async readNative(source) {
333
- this.assertSupportedLocator(source);
334
- let input;
337
+ const records = this.readNativeRecords(source);
338
+ let result = await records.next();
339
+ while (!result.done)
340
+ result = await records.next();
341
+ return result.value;
342
+ }
343
+ async *readNativeRecords(source) {
335
344
  try {
336
- input = await readBoundedJsonLines({ selectedPath: source.locator, allowedRoots: source.authorizedScope.allowedRoots }, { consistency: 'complete', limits: this.limits });
337
- }
338
- catch (error) {
339
- if (error instanceof SessionContractError && error.code === 'SCHEMA_DRIFT') {
340
- throw new SessionContractError('MALFORMED_SOURCE', 'Muse native session log contains malformed JSONL');
341
- }
342
- throw error;
343
- }
344
- const diagnostics = {};
345
- const records = [];
346
- let fallbackSessionId = nativeSessionIdFromLocator(source.locator) ?? source.sourceId;
347
- let complete = false;
348
- for (const line of input.records) {
349
- const value = line.value;
350
- if (isOmissionMarker(value)) {
351
- diagnostics.omitted_records = (diagnostics.omitted_records ?? 0) + 1;
352
- if (asObject(value).retained_marker === 'omitted_live_only') {
353
- diagnostics.omitted_live_only = (diagnostics.omitted_live_only ?? 0) + 1;
354
- }
355
- continue;
356
- }
357
- const retained = MuseRetainedFrameSchema.safeParse(value);
358
- if (retained.success) {
359
- diagnostics.retained_frames = (diagnostics.retained_frames ?? 0) + 1;
360
- for (const child of retained.data.children) {
361
- let decoded;
362
- try {
363
- decoded = JSON.parse(child.record_json);
345
+ this.assertSupportedLocator(source);
346
+ const input = await streamBoundedJsonLines({ selectedPath: source.locator, allowedRoots: source.authorizedScope.allowedRoots }, { consistency: 'complete', limits: this.limits });
347
+ const diagnostics = {};
348
+ let records = 0;
349
+ let fallbackSessionId = nativeSessionIdFromLocator(source.locator) ?? source.sourceId;
350
+ let complete = false;
351
+ for await (const line of input) {
352
+ const value = line.value;
353
+ if (isOmissionMarker(value)) {
354
+ diagnostics.omitted_records = (diagnostics.omitted_records ?? 0) + 1;
355
+ if (asObject(value).retained_marker === 'omitted_live_only') {
356
+ diagnostics.omitted_live_only = (diagnostics.omitted_live_only ?? 0) + 1;
364
357
  }
365
- catch {
366
- throw new SessionContractError('MALFORMED_SOURCE', 'Muse retained frame child record is malformed JSON');
367
- }
368
- const event = recordEventFromEnvelope(decoded);
369
- if (!event) {
370
- throw new SessionContractError('MALFORMED_SOURCE', 'Muse retained frame child record is malformed');
358
+ continue;
359
+ }
360
+ const retained = MuseRetainedFrameSchema.safeParse(value);
361
+ if (retained.success) {
362
+ diagnostics.retained_frames = (diagnostics.retained_frames ?? 0) + 1;
363
+ for (const child of retained.data.children) {
364
+ let decoded;
365
+ try {
366
+ decoded = JSON.parse(child.record_json);
367
+ }
368
+ catch {
369
+ throw new SessionContractError('MALFORMED_SOURCE', 'Muse retained frame child record is malformed JSON', schemaIssueDetail('children.record_json', 'invalid_json'));
370
+ }
371
+ const envelope = MuseEnvelopeSchema.safeParse(decoded);
372
+ if (!envelope.success) {
373
+ throw new SessionContractError('MALFORMED_SOURCE', 'Muse retained frame child record is malformed', schemaRejectionDetail(envelope.error));
374
+ }
375
+ const event = { kind: 'record', envelope: envelope.data };
376
+ fallbackSessionId = streamSessionIdOf(event.envelope) ?? fallbackSessionId;
377
+ complete ||= event.envelope.payload_type === 'session.end';
378
+ diagnostics.retained_frame_children = (diagnostics.retained_frame_children ?? 0) + 1;
379
+ records += 1;
380
+ yield {
381
+ event,
382
+ line,
383
+ retainedFrame: retained.data.retained_frame,
384
+ retainedChildIndex: child.child_index,
385
+ };
371
386
  }
372
- fallbackSessionId = streamSessionIdOf(event.envelope) ?? fallbackSessionId;
373
- complete ||= event.envelope.payload_type === 'session.end';
374
- diagnostics.retained_frame_children = (diagnostics.retained_frame_children ?? 0) + 1;
375
- records.push({
376
- event,
377
- line,
378
- retainedFrame: retained.data.retained_frame,
379
- retainedChildIndex: child.child_index,
380
- });
387
+ continue;
381
388
  }
382
- continue;
389
+ const envelope = MuseEnvelopeSchema.safeParse(value);
390
+ if (!envelope.success) {
391
+ throw new SessionContractError('MALFORMED_SOURCE', 'Muse native session log line is not a supported record shape', schemaRejectionDetail('retained_frame' in asObject(value) ? retained.error : envelope.error));
392
+ }
393
+ const event = { kind: 'record', envelope: envelope.data };
394
+ fallbackSessionId = streamSessionIdOf(event.envelope) ?? fallbackSessionId;
395
+ complete ||= event.envelope.payload_type === 'session.end';
396
+ records += 1;
397
+ yield { event, line };
383
398
  }
384
- const event = recordEventFromEnvelope(value);
385
- if (!event) {
386
- throw new SessionContractError('MALFORMED_SOURCE', 'Muse native session log line is not a supported record shape');
399
+ if (records === 0) {
400
+ throw new SessionContractError('MALFORMED_SOURCE', 'Muse native session log contains no record envelopes', schemaIssueDetail('<root>'));
387
401
  }
388
- fallbackSessionId = streamSessionIdOf(event.envelope) ?? fallbackSessionId;
389
- complete ||= event.envelope.payload_type === 'session.end';
390
- records.push({ event, line });
402
+ return {
403
+ complete,
404
+ context: {
405
+ locatorClass: MUSE_NATIVE_LOCATOR_CLASS,
406
+ sourceLabel: 'muse native session log',
407
+ bytesRead: input.bytesRead,
408
+ fallbackSessionId,
409
+ spawns: new Map(),
410
+ diagnostics,
411
+ },
412
+ };
391
413
  }
392
- if (records.length === 0) {
393
- throw new SessionContractError('MALFORMED_SOURCE', 'Muse native session log contains no record envelopes');
414
+ catch (error) {
415
+ if (error instanceof SessionContractError && error.code === 'SCHEMA_DRIFT') {
416
+ throw new SessionContractError('MALFORMED_SOURCE', 'Muse native session log contains malformed JSONL', error.detail);
417
+ }
418
+ throw error;
394
419
  }
395
- return {
396
- records,
397
- complete,
398
- context: {
399
- locatorClass: MUSE_NATIVE_LOCATOR_CLASS,
400
- sourceLabel: 'muse native session log',
401
- bytesRead: input.bytesRead,
402
- fallbackSessionId,
403
- spawns: new Map(),
404
- diagnostics,
405
- },
406
- };
407
420
  }
408
421
  assertSupportedLocator(source) {
409
422
  if (source.locatorClass !== MUSE_LOCATOR_CLASS && source.locatorClass !== MUSE_NATIVE_LOCATOR_CLASS) {
@@ -495,44 +508,130 @@ async function* museNativeSessionLogs(root) {
495
508
  }
496
509
  }
497
510
  }
498
- export async function museNativeSourceMatchesWorkspace(source, workspacePath) {
499
- let input;
511
+ export const MuseWorkspaceInspectionSchema = z.object({
512
+ outcome: z.enum(['matched', 'mismatch', 'inconclusive']),
513
+ attribution: z.enum(['matched', 'mismatch', 'unattributed']),
514
+ matchKind: z.enum(WORKSPACE_MATCH_KINDS).optional(),
515
+ reasonCode: z.string().nullable(),
516
+ recordsInspected: z.number().int().nonnegative(),
517
+ bytesInspected: z.number().int().nonnegative(),
518
+ completeInspection: z.boolean(),
519
+ limit: z.object({
520
+ name: z.enum(['maxRecords', 'maxRecordBytes', 'maxTotalBytes', 'maxNestingDepth']),
521
+ value: z.number().int().positive(),
522
+ }).optional(),
523
+ fallback: z.literal('bounded-tail').optional(),
524
+ detail: SessionRejectionDetailSchema.optional(),
525
+ });
526
+ /** Positive metadata evidence selects a source; import validates its full history. */
527
+ export async function inspectMuseNativeWorkspace(source, workspacePath, limitsInput) {
528
+ const limits = { ...MUSE_WORKSPACE_SCAN_LIMITS, ...limitsInput };
529
+ const progress = { recordsInspected: 0, bytesInspected: 0 };
530
+ let sawWorkspaceEvidence = false;
531
+ let retainedChildren = 0;
532
+ let limit;
533
+ let fallback;
534
+ const authorization = { selectedPath: source.locator, allowedRoots: source.authorizedScope.allowedRoots };
535
+ const receipt = (outcome, reasonCode, completeInspection = false) => ({
536
+ outcome, attribution: outcome === 'inconclusive' ? 'unattributed' : outcome,
537
+ reasonCode, ...progress, completeInspection,
538
+ ...(limit ? { limit } : {}), ...(fallback ? { fallback } : {}),
539
+ });
540
+ const envelopesFromLine = (value) => nativeEnvelopesFromLine(value, limits, (count) => {
541
+ retainedChildren += count;
542
+ if (retainedChildren > limits.maxRecords) {
543
+ throw new MuseWorkspaceLimitError('maxRecords', limits.maxRecords, retainedChildren);
544
+ }
545
+ });
500
546
  try {
501
- input = await readBoundedJsonLines({ selectedPath: source.locator, allowedRoots: source.authorizedScope.allowedRoots }, { consistency: 'complete', limits: { maxRecords: 100, maxRecordBytes: 8 * 1024 * 1024 } });
502
- }
503
- catch {
504
- return false;
547
+ if ([limits.maxRecords, limits.maxRecordBytes, limits.maxTotalBytes, limits.maxNestingDepth]
548
+ .some((limit) => !Number.isSafeInteger(limit) || limit <= 0)) {
549
+ throw new SessionContractError('INVALID_ARGUMENT', 'Muse inspection limits must be positive safe integers');
550
+ }
551
+ for await (const value of museWorkspaceScanLines(authorization, limits, progress)) {
552
+ const envelopes = envelopesFromLine(value);
553
+ for (const envelope of envelopes) {
554
+ const candidate = workspaceEvidenceOf(envelope);
555
+ if (!candidate)
556
+ continue;
557
+ sawWorkspaceEvidence = true;
558
+ const matchKind = await matchSessionWorkspace(candidate, workspacePath);
559
+ if (matchKind)
560
+ return { ...receipt('matched', null), matchKind };
561
+ }
562
+ }
563
+ return sawWorkspaceEvidence
564
+ ? receipt('mismatch', 'MUSE_WORKSPACE_MISMATCH', true)
565
+ : receipt('inconclusive', 'MUSE_WORKSPACE_EVIDENCE_ABSENT', true);
505
566
  }
506
- for (const line of input.records) {
507
- for (const envelope of nativeEnvelopesFromLine(line.value)) {
508
- const candidate = workspaceEvidenceOf(envelope);
509
- if (!candidate)
510
- continue;
511
- if (workspacePathEquals(candidate, workspacePath))
512
- return true;
567
+ catch (error) {
568
+ if (error instanceof MuseWorkspaceLimitError) {
569
+ limit = { name: error.limitName, value: error.limitValue };
570
+ fallback = 'bounded-tail';
571
+ const tailProgress = { recordsInspected: 0, bytesInspected: 0 };
572
+ const tailBytes = Math.min(MUSE_WORKSPACE_TAIL_BYTES, limits.maxTotalBytes);
573
+ retainedChildren = 0;
574
+ let matchKind;
575
+ try {
576
+ for await (const value of museWorkspaceScanLines(authorization, { ...limits, maxTotalBytes: tailBytes }, tailProgress, tailBytes)) {
577
+ for (const envelope of envelopesFromLine(value)) {
578
+ const candidate = workspaceEvidenceOf(envelope);
579
+ if (!candidate)
580
+ continue;
581
+ matchKind = await matchSessionWorkspace(candidate, workspacePath);
582
+ if (matchKind)
583
+ break;
584
+ }
585
+ if (matchKind)
586
+ break;
587
+ }
588
+ }
589
+ catch {
590
+ // Preserve the original limit receipt when the fallback cannot attribute.
591
+ }
592
+ progress.recordsInspected += tailProgress.recordsInspected;
593
+ progress.bytesInspected += tailProgress.bytesInspected;
594
+ if (matchKind)
595
+ return { ...receipt('matched', null), matchKind };
513
596
  }
597
+ return {
598
+ ...receipt('inconclusive', error instanceof SessionContractError
599
+ ? error.code : 'MUSE_SOURCE_UNREADABLE'),
600
+ ...(error instanceof SessionContractError && error.detail ? { detail: error.detail } : {}),
601
+ };
602
+ }
603
+ }
604
+ export async function museNativeSourceMatchesWorkspace(source, workspacePath) {
605
+ const result = await inspectMuseNativeWorkspace(source, workspacePath);
606
+ if (result.outcome === 'inconclusive') {
607
+ const code = SessionErrorCodeSchema.safeParse(result.reasonCode);
608
+ throw new SessionContractError(code.success ? code.data : 'SCHEMA_DRIFT', `Muse workspace inspection inconclusive: ${result.reasonCode}`, result.detail);
514
609
  }
515
- return false;
610
+ return result.outcome === 'matched';
516
611
  }
517
- function nativeEnvelopesFromLine(value) {
612
+ function nativeEnvelopesFromLine(value, limits, countChildren) {
518
613
  if (isOmissionMarker(value))
519
614
  return [];
520
- const event = recordEventFromEnvelope(value);
521
- if (event)
522
- return [event.envelope];
523
615
  const retained = MuseRetainedFrameSchema.safeParse(value);
524
- if (!retained.success)
525
- return [];
616
+ if (!retained.success) {
617
+ if (value === null || typeof value !== 'object' || Array.isArray(value)) {
618
+ throw new SessionContractError('MALFORMED_SOURCE', 'Muse inspection encountered a non-object native record', schemaIssueDetail('<root>'));
619
+ }
620
+ // Native logs carry record kinds the envelope schema does not model (for
621
+ // example runtime.session mode changes without payload.event.kind). They
622
+ // hold no workspace evidence, so skip them rather than fail the source.
623
+ const event = recordEventFromEnvelope(value);
624
+ return event ? [event.envelope] : [];
625
+ }
626
+ countChildren(retained.data.children.length);
526
627
  const envelopes = [];
527
628
  for (const child of retained.data.children) {
528
- try {
529
- const childEvent = recordEventFromEnvelope(JSON.parse(child.record_json));
530
- if (childEvent)
531
- envelopes.push(childEvent.envelope);
532
- }
533
- catch {
534
- return [];
629
+ if (Buffer.byteLength(child.record_json) > limits.maxRecordBytes) {
630
+ throw new MuseWorkspaceLimitError('maxRecordBytes', limits.maxRecordBytes, Buffer.byteLength(child.record_json));
535
631
  }
632
+ const childEvent = recordEventFromEnvelope(parseMuseScanJson(child.record_json, limits.maxNestingDepth));
633
+ if (childEvent)
634
+ envelopes.push(childEvent.envelope);
536
635
  }
537
636
  return envelopes;
538
637
  }
@@ -554,9 +653,6 @@ function workspaceEvidenceOf(envelope) {
554
653
  }
555
654
  return null;
556
655
  }
557
- function workspacePathEquals(candidate, workspacePath) {
558
- return resolve(candidate) === workspacePath;
559
- }
560
656
  function nativeSessionIdFromLocator(locator) {
561
657
  const parts = locator.replaceAll('\\', '/').split('/');
562
658
  const leaf = parts.at(-1);
@@ -703,7 +799,7 @@ function parseEventCursor(value) {
703
799
  if (value === undefined || value === '')
704
800
  return 0;
705
801
  if (!/^\d+$/.test(value))
706
- throw new SessionContractError('SCHEMA_DRIFT', 'muse event cursor is invalid');
802
+ throw new SessionContractError('SCHEMA_DRIFT', 'muse event cursor is invalid', schemaIssueDetail('cursor'));
707
803
  return Number(value);
708
804
  }
709
805
  //# sourceMappingURL=muse.js.map
@@ -1,8 +1,8 @@
1
1
  import { opendir } from 'node:fs/promises';
2
2
  import { resolve } from 'node:path';
3
3
  import { z } from 'zod';
4
- import { SessionContractError, } from '../contracts.js';
5
- import { readBoundedJsonLines, streamBoundedJsonLines } from '../readers.js';
4
+ import { schemaRejectionDetail, schemaIssueDetail, SessionContractError, } from '../contracts.js';
5
+ import { streamBoundedJsonLines } from '../readers.js';
6
6
  export const OMP_ADAPTER_VERSION = '1.0.0';
7
7
  export const OMP_SOURCE_SCHEMA_VERSION = '3.0.0';
8
8
  const Title = z.object({ type: z.literal('title'), v: z.literal(1), title: z.string(), source: z.enum(['auto', 'user']).optional(), updatedAt: z.string(), pad: z.string() });
@@ -30,7 +30,7 @@ export class OmpSessionAdapter {
30
30
  for (const root of [...scope.allowedRoots].sort()) {
31
31
  for await (const locator of jsonlFiles(resolve(root))) {
32
32
  if (++count > this.maxFiles)
33
- throw new SessionContractError('RESOURCE_LIMIT_EXCEEDED', 'OMP discovery file limit exceeded');
33
+ throw new SessionContractError('RESOURCE_LIMIT_EXCEEDED', 'OMP discovery file limit exceeded', { limit: 'maxFiles', configured: this.maxFiles, observed: count });
34
34
  yield { provider: 'omp', locator, locatorClass: 'omp-session-v3-jsonl' };
35
35
  }
36
36
  }
@@ -38,13 +38,23 @@ export class OmpSessionAdapter {
38
38
  async inspect(source) {
39
39
  let input;
40
40
  try {
41
- input = await readBoundedJsonLines({ selectedPath: source.locator,
41
+ input = await streamBoundedJsonLines({ selectedPath: source.locator,
42
42
  allowedRoots: source.authorizedScope.allowedRoots }, { consistency: 'provisional', limits: this.limits });
43
43
  }
44
44
  catch (error) {
45
45
  throw normalizeAuthorizationError(error);
46
46
  }
47
- const header = parseHeader(input.records[titleOffset(input.records[0]) ? 1 : 0]?.value);
47
+ let header;
48
+ let prefix = true;
49
+ for await (const line of input) {
50
+ if (prefix) {
51
+ prefix = false;
52
+ if (titleOffset(line))
53
+ continue;
54
+ }
55
+ header ??= parseHeader(line.value);
56
+ }
57
+ header ??= parseHeader(undefined);
48
58
  if (input.incompleteTail)
49
59
  throw new SessionContractError('TRUNCATED_SOURCE', 'OMP session has a truncated JSONL tail');
50
60
  return { sourceSchemaVersion: `${header.version}.0.0`, consistency: 'complete', operationalState: 'available' };
@@ -63,13 +73,13 @@ export class OmpSessionAdapter {
63
73
  let prefix = true;
64
74
  const start = cursor?.value.replace(/^byte:/, '') ?? '0';
65
75
  if (!/^\d+$/.test(start))
66
- throw new SessionContractError('SCHEMA_DRIFT', 'invalid OMP cursor');
76
+ throw new SessionContractError('SCHEMA_DRIFT', 'invalid OMP cursor', schemaIssueDetail('cursor'));
67
77
  let end = 0;
68
78
  const ids = new Set();
69
79
  for await (const line of input) {
70
80
  end = line.byteOffset + line.byteLength;
71
81
  if (Number(start) > line.byteOffset && Number(start) < end) {
72
- throw new SessionContractError('SCHEMA_DRIFT', 'OMP cursor is not a record boundary');
82
+ throw new SessionContractError('SCHEMA_DRIFT', 'OMP cursor is not a record boundary', schemaIssueDetail('cursor'));
73
83
  }
74
84
  if (prefix) {
75
85
  prefix = false;
@@ -83,7 +93,7 @@ export class OmpSessionAdapter {
83
93
  }
84
94
  const parsed = Entry.safeParse(line.value);
85
95
  if (!parsed.success)
86
- throw new SessionContractError('MALFORMED_SOURCE', 'OMP session entry is malformed');
96
+ throw new SessionContractError('MALFORMED_SOURCE', 'OMP session entry is malformed', schemaRejectionDetail(parsed.error));
87
97
  const entry = parsed.data;
88
98
  if (ids.has(entry.id))
89
99
  throw new SessionContractError('DUPLICATE_NATIVE_ID', 'OMP session contains a duplicate entry id');
@@ -107,9 +117,9 @@ export class OmpSessionAdapter {
107
117
  nativeType: entry.type, parentId: entry.parentId, ...metadata(entry, message) } };
108
118
  }
109
119
  if (!sessionId)
110
- throw new SessionContractError('MALFORMED_SOURCE', 'OMP session header is missing');
120
+ throw new SessionContractError('MALFORMED_SOURCE', 'OMP session header is missing', schemaIssueDetail('header'));
111
121
  if (Number(start) > end)
112
- throw new SessionContractError('SCHEMA_DRIFT', 'OMP cursor exceeds source size');
122
+ throw new SessionContractError('SCHEMA_DRIFT', 'OMP cursor exceeds source size', schemaIssueDetail('cursor'));
113
123
  if (input.incompleteTail)
114
124
  throw new SessionContractError('TRUNCATED_SOURCE', 'OMP session has a truncated JSONL tail');
115
125
  }
@@ -125,7 +135,7 @@ const KNOWN = new Set(['message', 'thinking_level_change', 'model_change', 'comp
125
135
  function parseHeader(value) {
126
136
  const parsed = Header.safeParse(value);
127
137
  if (!parsed.success)
128
- throw new SessionContractError('MALFORMED_SOURCE', 'OMP session header is malformed');
138
+ throw new SessionContractError('MALFORMED_SOURCE', 'OMP session header is malformed', schemaRejectionDetail(parsed.error));
129
139
  if (parsed.data.version !== 3)
130
140
  throw new SessionContractError('UNKNOWN_SCHEMA_MAJOR', `unsupported OMP session version: ${parsed.data.version}`);
131
141
  return parsed.data;
@@ -168,8 +178,12 @@ function normalizeAuthorizationError(error) {
168
178
  function titleOffset(line) {
169
179
  if (object(line?.value).type !== 'title')
170
180
  return 0;
171
- if (!Title.safeParse(line?.value).success || line?.byteLength !== 256) {
172
- throw new SessionContractError('MALFORMED_SOURCE', 'OMP title slot is malformed');
181
+ const parsed = Title.safeParse(line?.value);
182
+ if (!parsed.success) {
183
+ throw new SessionContractError('MALFORMED_SOURCE', 'OMP title slot is malformed', schemaRejectionDetail(parsed.error));
184
+ }
185
+ if (line?.byteLength !== 256) {
186
+ throw new SessionContractError('MALFORMED_SOURCE', 'OMP title slot is malformed', schemaIssueDetail('title'));
173
187
  }
174
188
  return 256;
175
189
  }
@@ -198,6 +212,6 @@ export async function readOmpSessionHeader(source) {
198
212
  }
199
213
  return parseHeader(line.value);
200
214
  }
201
- throw new SessionContractError('MALFORMED_SOURCE', 'OMP header is missing');
215
+ throw new SessionContractError('MALFORMED_SOURCE', 'OMP header is missing', schemaIssueDetail('header'));
202
216
  }
203
217
  //# sourceMappingURL=omp.js.map