sneakoscope 7.0.2 → 7.0.3

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 (468) hide show
  1. package/README.md +7 -5
  2. package/crates/sks-core/Cargo.lock +1 -1
  3. package/crates/sks-core/Cargo.toml +1 -1
  4. package/dist/bin/sks-dispatch.js +0 -3
  5. package/dist/cli/command-registry.js +0 -2
  6. package/dist/cli/install-helpers-codex-lb-chain.js +24 -2
  7. package/dist/cli/install-helpers-codex-lb-config.js +0 -7
  8. package/dist/cli/install-helpers-codex-lb-selftest-chain.js +0 -3
  9. package/dist/cli/install-helpers-codex-lb-selftest.js +0 -17
  10. package/dist/cli/install-helpers.js +81 -96
  11. package/dist/cli/router.js +0 -22
  12. package/dist/commands/codex-lb.js +176 -22
  13. package/dist/commands/codex.js +3 -8
  14. package/dist/commands/doctor.js +4 -14
  15. package/dist/commands/perf.js +5 -1
  16. package/dist/commands/zellij-slot-column-anchor.js +0 -2
  17. package/dist/commands/zellij-slot-pane.js +0 -7
  18. package/dist/commands/zellij.js +0 -2
  19. package/dist/config/skills-manifest.json +52 -52
  20. package/dist/core/agent-bridge/agent-manifest.js +192 -1
  21. package/dist/core/agent-bridge/agent-mode.js +0 -5
  22. package/dist/core/agent-bridge/host-capability-policy.js +189 -0
  23. package/dist/core/agent-bridge/host-capability-runtime.js +1395 -0
  24. package/dist/core/agent-bridge/mcp-server.js +1 -11
  25. package/dist/core/agents/agent-effort-policy.js +0 -3
  26. package/dist/core/agents/agent-orchestrator.js +0 -4
  27. package/dist/core/agents/agent-proof-evidence.js +0 -2
  28. package/dist/core/agents/agent-runner-ollama.js +0 -3
  29. package/dist/core/agents/agent-scheduler.js +0 -5
  30. package/dist/core/agents/native-cli-worker-runtime.js +5 -17
  31. package/dist/core/agents/work-partition/repo-inventory.js +0 -2
  32. package/dist/core/auto-review.js +0 -13
  33. package/dist/core/bench.js +0 -14
  34. package/dist/core/code-structure.js +0 -3
  35. package/dist/core/codex/agent-config-file-repair.js +0 -8
  36. package/dist/core/codex/codex-cli-update.js +122 -20
  37. package/dist/core/codex/codex-config-eperm-repair.js +0 -4
  38. package/dist/core/codex/codex-config-guard.js +0 -3
  39. package/dist/core/codex/codex-config-readability.js +0 -13
  40. package/dist/core/codex/codex-project-config-policy.js +0 -33
  41. package/dist/core/codex/official-goal-mode.js +0 -2
  42. package/dist/core/codex-app/codex-app-fast-ui-repair.js +5 -7
  43. package/dist/core/codex-app/codex-app-ui-state-snapshot.js +44 -7
  44. package/dist/core/codex-app/sks-menubar.js +0 -1
  45. package/dist/core/codex-app.js +0 -9
  46. package/dist/core/codex-compat/codex-hook-output-builders.js +9 -1
  47. package/dist/core/codex-compat/codex-hook-output-normalizer.js +1 -1
  48. package/dist/core/codex-compat/codex-hook-semantic-validator.js +3 -2
  49. package/dist/core/codex-compat/codex-hook-warning-detector.js +10 -2
  50. package/dist/core/codex-control/codex-lb-launch-recovery.js +0 -3
  51. package/dist/core/codex-control/codex-reliability-shield.js +0 -8
  52. package/dist/core/codex-control/codex-sdk-adapter.js +0 -3
  53. package/dist/core/codex-control/codex-sdk-config-policy.js +0 -2
  54. package/dist/core/codex-control/codex-sdk-env-policy.js +61 -16
  55. package/dist/core/codex-control/codex-task-runner.js +0 -7
  56. package/dist/core/codex-control/codex-thread-registry.js +0 -4
  57. package/dist/core/codex-lb/codex-lb-env.js +118 -20
  58. package/dist/core/codex-lb/codex-lb-tool-catalog.js +0 -4
  59. package/dist/core/codex-lb/codex-lb-tool-output-recovery.js +1 -1
  60. package/dist/core/codex-model-guard.js +0 -14
  61. package/dist/core/codex-native/codex-native-feature-broker.js +67 -22
  62. package/dist/core/codex-native/codex-native-interop-policy.js +81 -9
  63. package/dist/core/codex-native/confined-report-writer.js +21 -0
  64. package/dist/core/codex-native/core-skill-integrity.js +169 -20
  65. package/dist/core/codex-native/project-skill-dedupe.js +55 -13
  66. package/dist/core/codex-native/skill-registry-ledger.js +137 -16
  67. package/dist/core/codex-native/sks-skill-paths.js +185 -0
  68. package/dist/core/codex-runtime/codex-desktop-config-policy.js +0 -2
  69. package/dist/core/commands/agent-bridge-command.js +28 -8
  70. package/dist/core/commands/basic-cli.js +67 -26
  71. package/dist/core/commands/bench-command.js +5 -1
  72. package/dist/core/commands/command-utils.js +0 -5
  73. package/dist/core/commands/image-ux-review-command.js +0 -9
  74. package/dist/core/commands/mad-sks-command.js +0 -38
  75. package/dist/core/commands/naruto-command.js +46 -12
  76. package/dist/core/commands/ppt-command.js +0 -9
  77. package/dist/core/commands/run-command.js +8 -2
  78. package/dist/core/commands/seo-command.js +0 -6
  79. package/dist/core/commands/wiki-command.js +0 -14
  80. package/dist/core/computer-use-live-evidence.js +0 -5
  81. package/dist/core/config/secret-preservation.js +0 -11
  82. package/dist/core/daemon/sksd-hook-daemon-entrypoint.js +0 -2
  83. package/dist/core/daemon/sksd-hook-daemon.js +1 -29
  84. package/dist/core/daemon/sksd-hook-dispatch.js +0 -17
  85. package/dist/core/db-safety.js +0 -7
  86. package/dist/core/doctor/browser-use-repair.js +0 -2
  87. package/dist/core/doctor/doctor-codex-startup-repair.js +0 -3
  88. package/dist/core/doctor/doctor-readiness-matrix.js +12 -0
  89. package/dist/core/doctor/doctor-skill-reconcile.js +32 -0
  90. package/dist/core/doctor/imagegen-repair.js +0 -2
  91. package/dist/core/doctor/mcp-transport-collision-repair.js +0 -3
  92. package/dist/core/doctor/retired-managed-residue-private.js +0 -1
  93. package/dist/core/doctor/supabase-mcp-repair.js +0 -11
  94. package/dist/core/feature-fixture-executor.js +0 -48
  95. package/dist/core/feature-fixtures.js +0 -5
  96. package/dist/core/fsx.js +11 -12
  97. package/dist/core/hooks-runtime/code-pack-freshness-preflight.js +0 -5
  98. package/dist/core/hooks-runtime/hook-context.js +202 -0
  99. package/dist/core/hooks-runtime/hook-io.js +1 -12
  100. package/dist/core/hooks-runtime/light-turn.js +0 -2
  101. package/dist/core/hooks-runtime/naruto-decision-gate.js +4 -1
  102. package/dist/core/hooks-runtime/naruto-terminal-finalization.js +91 -0
  103. package/dist/core/hooks-runtime/official-subagent-lifecycle.js +370 -0
  104. package/dist/core/hooks-runtime/standalone-parent-host-capability.js +98 -0
  105. package/dist/core/hooks-runtime/subagent-context.js +59 -0
  106. package/dist/core/hooks-runtime/subagent-skill-availability-contract.js +29 -0
  107. package/dist/core/hooks-runtime/subagent-skill-availability-evidence.js +195 -0
  108. package/dist/core/hooks-runtime/subagent-skill-availability-guards.js +316 -0
  109. package/dist/core/hooks-runtime/subagent-skill-availability.js +217 -0
  110. package/dist/core/hooks-runtime.js +259 -535
  111. package/dist/core/image-ux-review/codex-app-generated-image-discovery.js +0 -17
  112. package/dist/core/image-ux-review/imagegen-adapter.js +0 -14
  113. package/dist/core/imagegen/imagegen-auth-readiness.js +0 -9
  114. package/dist/core/imagegen/imagegen-capability.js +0 -3
  115. package/dist/core/init/managed-skill-install.js +42 -0
  116. package/dist/core/init/skills.js +247 -74
  117. package/dist/core/init.js +15 -40
  118. package/dist/core/lean-engineering-policy.js +0 -2
  119. package/dist/core/locks/file-lock.js +0 -21
  120. package/dist/core/loops/loop-planner.js +0 -6
  121. package/dist/core/loops/loop-runtime.js +0 -1
  122. package/dist/core/loops/loop-worker-runtime.js +0 -19
  123. package/dist/core/mad-sks/executors/db-write-executor.js +0 -4
  124. package/dist/core/mad-sks/executors/executor-base.js +0 -10
  125. package/dist/core/mad-sks/immutable-harness-guard.js +0 -5
  126. package/dist/core/mad-sks/sql-plane/coordinator.js +0 -5
  127. package/dist/core/mad-sks/sql-plane/ledger.js +0 -4
  128. package/dist/core/mad-sks/sql-plane/lock.js +0 -4
  129. package/dist/core/mad-sks/sql-plane/mcp-executor.js +0 -9
  130. package/dist/core/mad-sks/sql-plane/policy-resolver.js +0 -2
  131. package/dist/core/mad-sks/sql-plane/postconditions.js +0 -4
  132. package/dist/core/mad-sks/sql-plane/recovery.js +0 -2
  133. package/dist/core/mad-sks/sql-plane/runtime-profile.js +0 -8
  134. package/dist/core/managed-assets/managed-assets-manifest.js +1 -7
  135. package/dist/core/mcp-config/health-check.js +10 -3
  136. package/dist/core/migration/migration-transaction-journal.js +0 -8
  137. package/dist/core/mission.js +0 -2
  138. package/dist/core/naruto/naruto-active-pool.js +0 -2
  139. package/dist/core/naruto/naruto-concurrency-governor.js +0 -1
  140. package/dist/core/naruto/naruto-real-write-proof.js +0 -4
  141. package/dist/core/naruto/naruto-write-e2e.js +0 -1
  142. package/dist/core/perf/perf-budget.js +0 -5
  143. package/dist/core/permission-gates.js +0 -2
  144. package/dist/core/pipeline-internals/runtime-core.js +15 -5
  145. package/dist/core/pipeline-internals/runtime-gates.js +0 -12
  146. package/dist/core/preflight/parallel-preflight-engine.js +0 -11
  147. package/dist/core/proof/evidence-collector.js +0 -2
  148. package/dist/core/proof/route-finalizer.js +0 -1
  149. package/dist/core/proof/selftest-proof-fixtures.js +0 -5
  150. package/dist/core/providers/glm/bench/glm-benchmark-runner.js +0 -2
  151. package/dist/core/providers/glm/glm-request-cache.js +0 -3
  152. package/dist/core/providers/glm/naruto/glm-naruto-command.js +0 -1
  153. package/dist/core/providers/glm/naruto/glm-naruto-decomposer.js +0 -1
  154. package/dist/core/providers/glm/naruto/glm-naruto-orchestrator.js +0 -6
  155. package/dist/core/providers/glm/naruto/glm-naruto-trace.js +0 -1
  156. package/dist/core/providers/glm/naruto/glm-naruto-worker-pool.js +0 -1
  157. package/dist/core/providers/glm/naruto/glm-naruto-worktree.js +0 -1
  158. package/dist/core/providers/openrouter/openrouter-secret-store.js +0 -1
  159. package/dist/core/providers/openrouter/openrouter-stream.js +0 -2
  160. package/dist/core/questions.js +3 -3
  161. package/dist/core/release/gate-manifest.js +0 -5
  162. package/dist/core/release/package-size-budget.js +1 -1
  163. package/dist/core/release/release-gate-batch-runner.js +11 -2
  164. package/dist/core/release/release-gate-cache-v2.js +0 -4
  165. package/dist/core/release/release-gate-hermetic-env.js +0 -5
  166. package/dist/core/release-parallel-full-coverage.js +0 -2
  167. package/dist/core/remote/ssh-worker-client.js +0 -3
  168. package/dist/core/research/research-adversarial-review.js +6 -2
  169. package/dist/core/responses-retry-policy.js +0 -10
  170. package/dist/core/retention.js +0 -7
  171. package/dist/core/routes/constants.js +0 -3
  172. package/dist/core/routes.js +89 -15
  173. package/dist/core/safety/command-contract/contracts.js +2 -0
  174. package/dist/core/safety/mutation-guard.js +0 -25
  175. package/dist/core/safety/mutation-ledger.js +0 -9
  176. package/dist/core/safety/requested-scope-contract.js +0 -0
  177. package/dist/core/security/high-risk-contracts.js +0 -1
  178. package/dist/core/skills/core-skill-card.js +0 -0
  179. package/dist/core/skills/core-skill-deployment.js +0 -13
  180. package/dist/core/skills/core-skill-epoch.js +0 -11
  181. package/dist/core/skills/core-skill-meta-update.js +0 -6
  182. package/dist/core/skills/core-skill-patch-apply.js +0 -7
  183. package/dist/core/skills/core-skill-patch.js +0 -8
  184. package/dist/core/skills/core-skill-reflection.js +0 -16
  185. package/dist/core/skills/core-skill-runtime.js +0 -6
  186. package/dist/core/skills/core-skill-scorer.js +0 -7
  187. package/dist/core/skills/core-skill-trainer.js +0 -11
  188. package/dist/core/skills/core-skill-types.js +0 -9
  189. package/dist/core/skills/core-skill-validation.js +0 -5
  190. package/dist/core/skills/rejected-skill-patch-buffer.js +0 -2
  191. package/dist/core/stop-gate/stop-gate-check.js +0 -8
  192. package/dist/core/stop-gate/stop-gate-resolver.js +0 -7
  193. package/dist/core/stop-gate/stop-gate-writer.js +0 -5
  194. package/dist/core/subagents/model-policy.js +0 -7
  195. package/dist/core/subagents/naruto-help-contract.js +1 -1
  196. package/dist/core/subagents/naruto-proof-projection.js +580 -12
  197. package/dist/core/subagents/official-subagent-config.js +0 -8
  198. package/dist/core/subagents/official-subagent-preparation.js +6 -5
  199. package/dist/core/subagents/official-subagent-prompt.js +29 -0
  200. package/dist/core/subagents/official-subagent-runner.js +343 -37
  201. package/dist/core/subagents/subagent-evidence.js +378 -9
  202. package/dist/core/subagents/thread-budget.js +5 -2
  203. package/dist/core/subagents/triwiki-attention.js +0 -4
  204. package/dist/core/subagents/wave-parent-guidance.js +54 -9
  205. package/dist/core/telegram/runtime.js +0 -1
  206. package/dist/core/triwiki/code-index-scanner.js +0 -3
  207. package/dist/core/triwiki/code-pack-head-freshness.js +0 -10
  208. package/dist/core/triwiki/code-pack.js +0 -2
  209. package/dist/core/triwiki/triwiki-cache-key.js +0 -1
  210. package/dist/core/triwiki/triwiki-proof-bank.js +0 -1
  211. package/dist/core/triwiki-attention.js +0 -10
  212. package/dist/core/triwiki-provenance.js +0 -5
  213. package/dist/core/triwiki-runtime.js +0 -12
  214. package/dist/core/triwiki-wrongness/wrongness-ledger.js +0 -7
  215. package/dist/core/triwiki-wrongness/wrongness-schema.js +0 -3
  216. package/dist/core/trust-kernel/trust-report.js +0 -7
  217. package/dist/core/update/update-migration-state.js +21 -39
  218. package/dist/core/update-check.js +2 -14
  219. package/dist/core/version-manager.js +2 -0
  220. package/dist/core/version.js +1 -1
  221. package/dist/core/work-order-ledger.js +0 -17
  222. package/dist/core/zellij/zellij-clipboard-config.js +0 -18
  223. package/dist/core/zellij/zellij-lane-renderer.js +5 -46
  224. package/dist/core/zellij/zellij-lane-runtime.js +0 -1
  225. package/dist/core/zellij/zellij-launcher.js +0 -26
  226. package/dist/core/zellij/zellij-official-subagent-activity.js +0 -5
  227. package/dist/core/zellij/zellij-official-subagent-telemetry.js +0 -5
  228. package/dist/core/zellij/zellij-screen-proof.js +0 -7
  229. package/dist/core/zellij/zellij-slot-column-anchor.js +0 -1
  230. package/dist/core/zellij/zellij-slot-pane-renderer.js +0 -9
  231. package/dist/core/zellij/zellij-slot-telemetry.js +0 -12
  232. package/dist/core/zellij/zellij-ui-mode.js +0 -7
  233. package/dist/core/zellij/zellij-update.js +0 -29
  234. package/dist/core/zellij/zellij-worker-pane-manager.js +0 -39
  235. package/dist/native/sks-menubar/Sources/ProvidersViewController.swift +213 -27
  236. package/dist/native/sks-menubar/Sources/UpdatesViewController.swift +95 -12
  237. package/dist/scripts/agent-message-bus-reader-check.js +0 -1
  238. package/dist/scripts/all-feature-deep-completion-check.js +0 -1
  239. package/dist/scripts/appshots-thread-attachment-discovery-check.js +0 -1
  240. package/dist/scripts/architecture-guard-check.js +0 -1
  241. package/dist/scripts/build-dist.js +0 -1
  242. package/dist/scripts/build-once-runner-check.js +0 -1
  243. package/dist/scripts/canonical-test-runner.js +0 -2
  244. package/dist/scripts/certificate-sla-check.js +0 -1
  245. package/dist/scripts/changelog-check.js +0 -1
  246. package/dist/scripts/check-cli-entrypoint.js +0 -1
  247. package/dist/scripts/check-command-module-budget.js +0 -7
  248. package/dist/scripts/check-feature-quality.js +0 -1
  249. package/dist/scripts/check-legacy-free.js +0 -1
  250. package/dist/scripts/check-pipeline-runtime.js +0 -1
  251. package/dist/scripts/check-runtime-schemas.js +0 -1
  252. package/dist/scripts/codex-0-134-runner-truth-check.js +0 -1
  253. package/dist/scripts/codex-0-137-compat-check.js +0 -1
  254. package/dist/scripts/codex-0138-capability-artifact-check.js +0 -1
  255. package/dist/scripts/codex-0138-capability-check.js +0 -1
  256. package/dist/scripts/codex-0138-doctor-check.js +0 -1
  257. package/dist/scripts/codex-0138-feature-probes-check.js +0 -1
  258. package/dist/scripts/codex-0144-core-real-probes-check.js +0 -1
  259. package/dist/scripts/codex-app-handoff-check.js +0 -1
  260. package/dist/scripts/codex-app-handoff-launch-check.js +0 -1
  261. package/dist/scripts/codex-config-load-probe.js +0 -5
  262. package/dist/scripts/codex-control-all-pipelines-check.js +0 -1
  263. package/dist/scripts/codex-control-event-stream-ledger-check.js +0 -1
  264. package/dist/scripts/codex-control-tool-output-continuity-audit-check.js +0 -1
  265. package/dist/scripts/codex-permission-profiles-check.js +0 -1
  266. package/dist/scripts/codex-plugin-app-template-policy-check.js +0 -1
  267. package/dist/scripts/codex-project-config-policy-splitter-check.js +0 -1
  268. package/dist/scripts/codex-sdk-all-pipelines-check.js +0 -1
  269. package/dist/scripts/codex-sdk-backend-router-check.js +0 -1
  270. package/dist/scripts/codex-sdk-capability-check.js +0 -1
  271. package/dist/scripts/codex-sdk-event-stream-ledger-check.js +0 -1
  272. package/dist/scripts/codex-sdk-real-smoke-check.js +0 -1
  273. package/dist/scripts/concurrent-session-collision-check.js +9 -0
  274. package/dist/scripts/context7-evidence-dedupe-check.js +0 -1
  275. package/dist/scripts/core-skill-card-schema-check.js +0 -11
  276. package/dist/scripts/core-skill-deployment-snapshot-check.js +0 -10
  277. package/dist/scripts/core-skill-heldout-validation-check.js +0 -11
  278. package/dist/scripts/core-skill-no-inference-optimizer-check.js +0 -11
  279. package/dist/scripts/core-skill-patch-check.js +0 -11
  280. package/dist/scripts/core-skill-route-runtime-integration-check.js +0 -11
  281. package/dist/scripts/current-surface-update-e2e-check.js +0 -4
  282. package/dist/scripts/current-upgrade-matrix-check.js +0 -1
  283. package/dist/scripts/dfix-fixture-check.js +0 -1
  284. package/dist/scripts/dfix-patch-handoff-check.js +0 -1
  285. package/dist/scripts/dfix-verification-check.js +0 -1
  286. package/dist/scripts/dfix-verification-recommendation-check.js +0 -1
  287. package/dist/scripts/docs-truthfulness-check.js +3 -3
  288. package/dist/scripts/doctor-fastpath-check.js +0 -1
  289. package/dist/scripts/doctor-fix-proves-codex-read-check.js +0 -11
  290. package/dist/scripts/doctor-fixes-codex-app-fast-ui-check.js +0 -4
  291. package/dist/scripts/doctor-idempotence-check.js +0 -1
  292. package/dist/scripts/doctor-ops-semantics-check.js +0 -1
  293. package/dist/scripts/ensure-bin-executable.js +0 -1
  294. package/dist/scripts/evidence-flagship-coverage-check.js +0 -1
  295. package/dist/scripts/fast-codex-service-tier-proof-check.js +0 -1
  296. package/dist/scripts/fixtures/fake-codex-config-loader.js +0 -5
  297. package/dist/scripts/fsx-hotpath-check.js +0 -1
  298. package/dist/scripts/gate-policy-audit-check.js +1 -1
  299. package/dist/scripts/geo-claim-evidence-check.js +0 -1
  300. package/dist/scripts/geo-cli-blackbox-check.js +0 -1
  301. package/dist/scripts/geo-crawler-policy-check.js +0 -1
  302. package/dist/scripts/git-worktree-diff-envelope-check.js +0 -1
  303. package/dist/scripts/git-worktree-dirty-lock-check.js +0 -1
  304. package/dist/scripts/git-worktree-dirty-main-detection-check.js +0 -1
  305. package/dist/scripts/git-worktree-integration-primary-check.js +0 -1
  306. package/dist/scripts/git-worktree-manifest-append-check.js +0 -1
  307. package/dist/scripts/git-worktree-untracked-diff-check.js +0 -1
  308. package/dist/scripts/high-risk-contracts-check.js +0 -1
  309. package/dist/scripts/hook-latency-budget-check.js +0 -1
  310. package/dist/scripts/hook-latency-quantum-check.js +0 -1
  311. package/dist/scripts/image-artifact-path-contract-check.js +0 -1
  312. package/dist/scripts/imagegen-real-smoke-check.js +0 -1
  313. package/dist/scripts/import-graph-budget-check.js +0 -1
  314. package/dist/scripts/installed-package-smoke-check.js +0 -1
  315. package/dist/scripts/legacy-gate-purge-check.js +0 -1
  316. package/dist/scripts/lib/codex-sdk-gate-lib.js +0 -3
  317. package/dist/scripts/lib/ensure-dist-fresh.js +0 -1
  318. package/dist/scripts/lib/valid-png-fixture.js +0 -1
  319. package/dist/scripts/local-collab-all-pipelines-final-gpt-check.js +0 -1
  320. package/dist/scripts/loop-directive-check-lib.js +0 -1
  321. package/dist/scripts/loop-worker-fixture-child.js +0 -1
  322. package/dist/scripts/mad-preflight-blocks-unreadable-config-check.js +0 -10
  323. package/dist/scripts/mad-sks-sql-plane-lifecycle-hook-decision-check.js +0 -1
  324. package/dist/scripts/mad-sks-sql-plane-result-lifecycle-check.js +0 -1
  325. package/dist/scripts/mcp-plugin-inventory-check.js +0 -1
  326. package/dist/scripts/mcp-tool-naming-parity-check.js +0 -1
  327. package/dist/scripts/model-call-concurrency-check.js +0 -1
  328. package/dist/scripts/mutation-callsite-coverage-check.js +0 -5
  329. package/dist/scripts/naruto-codex-e2e-check.js +0 -1
  330. package/dist/scripts/naruto-worktree-coding-blackbox.js +0 -1
  331. package/dist/scripts/official-subagent-workflow-check.js +3 -1
  332. package/dist/scripts/ops-diagnostics-bundle-check.js +0 -1
  333. package/dist/scripts/packlist-performance-check.js +1 -3
  334. package/dist/scripts/perf-budget-check.js +0 -1
  335. package/dist/scripts/ppt-full-e2e-blackbox-check.js +0 -1
  336. package/dist/scripts/ppt-real-export-adapter-check.js +0 -1
  337. package/dist/scripts/ppt-real-imagegen-smoke-check.js +0 -1
  338. package/dist/scripts/ppt-real-imagegen-wiring-check.js +0 -1
  339. package/dist/scripts/ppt-reexport-rereview-check.js +0 -1
  340. package/dist/scripts/prepublish-fast-check.js +0 -23
  341. package/dist/scripts/prepublish-release-check-or-fast.js +0 -7
  342. package/dist/scripts/probe-memoization-check.js +0 -1
  343. package/dist/scripts/product-design-plugin-routing-check.js +0 -1
  344. package/dist/scripts/project-skill-dedupe-blackbox.js +36 -9
  345. package/dist/scripts/prompt-placeholder-guard-check.js +0 -1
  346. package/dist/scripts/python-codex-sdk-all-pipelines-check.js +0 -3
  347. package/dist/scripts/qa-loop-app-handoff-capability-check.js +0 -1
  348. package/dist/scripts/qa-loop-app-handoff-check.js +0 -1
  349. package/dist/scripts/qa-loop-app-handoff-cli-check.js +0 -1
  350. package/dist/scripts/qa-loop-app-handoff-confirmation-check.js +0 -1
  351. package/dist/scripts/qa-loop-app-handoff-gate-lifecycle-check.js +0 -1
  352. package/dist/scripts/qa-loop-app-handoff-launch-check.js +0 -1
  353. package/dist/scripts/qa-loop-app-handoff-status-lifecycle-check.js +0 -1
  354. package/dist/scripts/qa-loop-budget-policy-check.js +0 -1
  355. package/dist/scripts/qa-loop-effort-escalation-check.js +0 -1
  356. package/dist/scripts/qa-loop-image-path-exposure-check.js +0 -1
  357. package/dist/scripts/qa-loop-image-path-prompt-injection-check.js +0 -1
  358. package/dist/scripts/release-cache-glob-hashing-check.js +0 -1
  359. package/dist/scripts/release-cache-input-classifier-check.js +0 -1
  360. package/dist/scripts/release-cache-neutralization-report-check.js +0 -1
  361. package/dist/scripts/release-cache-version-neutral-fixture-check.js +0 -1
  362. package/dist/scripts/release-check-stamp.js +0 -4
  363. package/dist/scripts/release-dist-freshness-check.js +0 -1
  364. package/dist/scripts/release-full-parallelism-blackbox.js +3 -3
  365. package/dist/scripts/release-gate-batch-runner-check.js +22 -0
  366. package/dist/scripts/release-gate-budget-check.js +0 -6
  367. package/dist/scripts/release-gate-dag-runner-check.js +0 -1
  368. package/dist/scripts/release-latency-slo-check.js +0 -1
  369. package/dist/scripts/release-metadata-1-19-check.js +0 -1
  370. package/dist/scripts/release-metadata-check.js +0 -3
  371. package/dist/scripts/release-parallel-speed-budget-check.js +0 -5
  372. package/dist/scripts/release-proof-truth-check.js +0 -1
  373. package/dist/scripts/release-provenance-check.js +0 -1
  374. package/dist/scripts/release-real-check.js +0 -1
  375. package/dist/scripts/release-runtime-truth-matrix-check.js +0 -1
  376. package/dist/scripts/release-version-truth-check.js +0 -1
  377. package/dist/scripts/research-blueprint-densifier-check.js +0 -1
  378. package/dist/scripts/research-claim-builder-check.js +0 -1
  379. package/dist/scripts/research-complete-package-fixture-check.js +0 -1
  380. package/dist/scripts/research-final-reviewer-blackbox.js +0 -1
  381. package/dist/scripts/responses-retry-policy-centralized-check.js +0 -1
  382. package/dist/scripts/retention-apply-smoke-check.js +0 -1
  383. package/dist/scripts/retention-budget-check.js +0 -1
  384. package/dist/scripts/retention-dry-run-check.js +0 -1
  385. package/dist/scripts/rollback-recovery-smoke-check.js +0 -1
  386. package/dist/scripts/route-intent-regression-check.js +0 -1
  387. package/dist/scripts/runtime-current-terminal-check.js +0 -1
  388. package/dist/scripts/runtime-dist-parity-check.js +0 -1
  389. package/dist/scripts/runtime-no-src-mjs-check.js +0 -1
  390. package/dist/scripts/runtime-proof-summary-check.js +0 -1
  391. package/dist/scripts/runtime-ts-rust-boundary-check.js +0 -15
  392. package/dist/scripts/runtime-ts-source-of-truth-check.js +0 -1
  393. package/dist/scripts/scheduler-batch-dispatch-check.js +0 -1
  394. package/dist/scripts/scheduler-parallel-proof-consistency-check.js +0 -1
  395. package/dist/scripts/scheduler-utilization-integral-check.js +0 -1
  396. package/dist/scripts/search-visibility-gate-lib.js +0 -1
  397. package/dist/scripts/seo-audit-fixture-check.js +0 -1
  398. package/dist/scripts/seo-cli-blackbox-check.js +0 -1
  399. package/dist/scripts/seo-geo-geo-disambiguation-check.js +0 -1
  400. package/dist/scripts/seo-geo-route-identity-check.js +0 -1
  401. package/dist/scripts/seo-geo-skill-rich-content-check.js +0 -1
  402. package/dist/scripts/seo-marketing-truthfulness-check.js +0 -1
  403. package/dist/scripts/seo-metadata-sync-check.js +0 -1
  404. package/dist/scripts/seo-no-mutation-by-default-check.js +0 -1
  405. package/dist/scripts/shared-memory-fixture-check.js +0 -1
  406. package/dist/scripts/side-effect-runtime-report-check.js +0 -1
  407. package/dist/scripts/sizecheck.js +0 -1
  408. package/dist/scripts/sks-1-11-gate-lib.js +0 -1
  409. package/dist/scripts/sks-1-12-real-execution-check-lib.js +0 -1
  410. package/dist/scripts/sks-1-18-gate-lib.js +0 -1
  411. package/dist/scripts/sks-menubar-install-check.js +0 -3
  412. package/dist/scripts/sksd-daemon-check.js +0 -1
  413. package/dist/scripts/super-search-live-smoke-check.js +0 -1
  414. package/dist/scripts/super-search-local-http-smoke-check.js +0 -1
  415. package/dist/scripts/super-search-offline-contract-check.js +0 -1
  416. package/dist/scripts/super-search-provider-interface-check.js +0 -1
  417. package/dist/scripts/triwiki-cache-key-check.js +0 -1
  418. package/dist/scripts/triwiki-proof-bank-blackbox.js +0 -1
  419. package/dist/scripts/triwiki-proof-bank-check.js +0 -1
  420. package/dist/scripts/triwiki-proof-card-check.js +0 -1
  421. package/dist/scripts/trust-fixture-check.js +0 -1
  422. package/dist/scripts/ultra-router-auto-router-check.js +0 -1
  423. package/dist/scripts/update-fastpath-check.js +0 -1
  424. package/dist/scripts/upgrade-migration-matrix-check.js +0 -1
  425. package/dist/scripts/ux-review-extract-wires-real-extractor-check.js +0 -1
  426. package/dist/scripts/ux-review-imagegen-blackbox-check.js +0 -1
  427. package/dist/scripts/ux-review-patch-diff-recheck-check.js +0 -1
  428. package/dist/scripts/ux-review-real-imagegen-smoke-check.js +0 -1
  429. package/dist/scripts/ux-review-run-wires-imagegen-check.js +0 -1
  430. package/dist/scripts/write-build-manifest.js +0 -1
  431. package/dist/scripts/wrongness-fixture-check.js +0 -1
  432. package/dist/scripts/zellij-capability-check.js +0 -1
  433. package/dist/scripts/zellij-developer-controls-check.js +0 -1
  434. package/dist/scripts/zellij-doctor-readiness-check.js +0 -13
  435. package/dist/scripts/zellij-dynamic-pane-lifecycle-check.js +0 -1
  436. package/dist/scripts/zellij-fake-adapter-check.js +0 -1
  437. package/dist/scripts/zellij-initial-main-only-blackbox.js +0 -1
  438. package/dist/scripts/zellij-lane-renderer-check.js +0 -1
  439. package/dist/scripts/zellij-launch-command-truth-check.js +0 -12
  440. package/dist/scripts/zellij-layout-valid-check.js +0 -1
  441. package/dist/scripts/zellij-pane-creation-lock-metrics-check.js +0 -1
  442. package/dist/scripts/zellij-pane-lock-concurrency-blackbox.js +0 -1
  443. package/dist/scripts/zellij-pane-lock-does-not-block-worker-check.js +0 -1
  444. package/dist/scripts/zellij-pane-lock-open-worker-integration-blackbox.js +0 -1
  445. package/dist/scripts/zellij-pane-proof-check.js +0 -1
  446. package/dist/scripts/zellij-qa-app-handoff-status-check.js +0 -1
  447. package/dist/scripts/zellij-real-session-cleanup-check.js +0 -1
  448. package/dist/scripts/zellij-real-session-launch-check.js +0 -1
  449. package/dist/scripts/zellij-right-column-geometry-proof.js +0 -1
  450. package/dist/scripts/zellij-right-column-headless-overflow-check.js +0 -1
  451. package/dist/scripts/zellij-right-column-manager-check.js +0 -1
  452. package/dist/scripts/zellij-screen-proof-check.js +0 -1
  453. package/dist/scripts/zellij-slot-only-ui-check.js +0 -1
  454. package/dist/scripts/zellij-slot-pane-renderer-check.js +0 -1
  455. package/dist/scripts/zellij-slot-pane-stale-detection-check.js +0 -7
  456. package/dist/scripts/zellij-slot-telemetry-incremental-check.js +0 -1
  457. package/dist/scripts/zellij-slot-telemetry-live-flush-check.js +0 -1
  458. package/dist/scripts/zellij-slot-telemetry-performance-check.js +0 -1
  459. package/dist/scripts/zellij-stacked-capability-routing-check.js +0 -1
  460. package/dist/scripts/zellij-stacked-fallback-integration-blackbox.js +0 -1
  461. package/dist/scripts/zellij-stacked-version-matrix-check.js +0 -1
  462. package/dist/scripts/zellij-stacked-version-parser-check.js +0 -1
  463. package/dist/scripts/zellij-ui-design-check.js +0 -12
  464. package/dist/scripts/zellij-update-prompt-matrix-check.js +0 -1
  465. package/dist/scripts/zellij-update-prompt-mode-check.js +0 -1
  466. package/dist/scripts/zellij-update-prompt-safety-check.js +0 -1
  467. package/dist/scripts/zellij-worker-pane-real-ui-blackbox.js +0 -2
  468. package/package.json +1 -1
@@ -0,0 +1,1395 @@
1
+ import { sha256 } from '../fsx.js';
2
+ import { HOST_CAPABILITY_DESCRIPTORS, hostCapabilityDigest } from './agent-manifest.js';
3
+ import { HOST_CAPABILITY_MCP_SERVER, HOST_CAPABILITY_RUNTIME_SCHEMA, hostCapabilityRuntimeDigest } from './host-capability-policy.js';
4
+ export { HOST_CAPABILITY_MCP_SERVER, HOST_CAPABILITY_RUNTIME_SCHEMA, hostCapabilityCodexConfigArgs, inspectHostCapabilityRuntime, requestHostCapabilities } from './host-capability-policy.js';
5
+ export const HOST_CAPABILITY_EVIDENCE_SCHEMA = 'sks.host-capability-evidence.v1';
6
+ export const HOST_CAPABILITY_HOOK_RUNTIME_SCHEMA = 'sks.host-capability-hook-runtime.v1';
7
+ export const HOST_CAPABILITY_HOOK_PENDING_RUNTIME_SCHEMA = 'sks.host-capability-hook-pending-runtime.v1';
8
+ export const HOST_CAPABILITY_HOOK_OBSERVATIONS_SCHEMA = 'sks.host-capability-hook-observations.v1';
9
+ export const HOST_CAPABILITY_HOOK_RUNTIME_FILENAME = 'host-capability-runtime.json';
10
+ export const HOST_CAPABILITY_HOOK_PENDING_RUNTIME_FILENAME = 'host-capability-runtime-pending.json';
11
+ export const HOST_CAPABILITY_HOOK_OBSERVATIONS_FILENAME = 'host-capability-hook-observations.json';
12
+ export const HOST_CAPABILITY_HOOK_EVIDENCE_FILENAME = 'host-capability-evidence.json';
13
+ const MAX_EVENT_LINE_BYTES = 512 * 1024;
14
+ const MAX_MCP_TOOL_CALLS = 1024;
15
+ const MAX_PRE_TOOL_OBSERVATIONS = 2048;
16
+ const MAX_RECEIPT_JSON_STRING_BYTES = 64 * 1024;
17
+ const MAX_ARTIFACT_RECEIPTS = 64;
18
+ const MAX_ARTIFACT_PATH_CHARS = 512;
19
+ const MAX_SEMANTIC_RECEIPT_ITEMS = 10_000;
20
+ const SHA256_RECEIPT_PATTERN = /^sha256:[a-f0-9]{64}$/;
21
+ const XLSX_MEDIA_TYPE = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
22
+ const EXPLICIT_DENIAL_PATTERN = /(?:^|[_.:-])(?:slack|center|tenant|lease|connector|outbox|message|upload|send|post)(?:$|[_.:-])/i;
23
+ export function createHostCapabilityHookPendingRuntime(input) {
24
+ const missionId = boundedIdentity(input.missionId);
25
+ const workflowRunId = boundedIdentity(input.workflowRunId);
26
+ const launchNonce = boundedIdentity(input.launchNonce);
27
+ if (!missionId || !workflowRunId || !launchNonce || !isHostCapabilityRuntime(input.runtime)) {
28
+ throw new Error('host_capability_hook_pending_runtime_invalid');
29
+ }
30
+ return {
31
+ schema: HOST_CAPABILITY_HOOK_PENDING_RUNTIME_SCHEMA,
32
+ mission_id: missionId,
33
+ workflow_run_id: workflowRunId,
34
+ launch_nonce_sha256: `sha256:${sha256(launchNonce)}`,
35
+ runtime: input.runtime
36
+ };
37
+ }
38
+ export function resolveHostCapabilityHookPendingRuntime(value, input) {
39
+ if (!value)
40
+ return { pending: null, blocker: 'host_capability_hook_pending_runtime_missing' };
41
+ if (!isRecord(value)
42
+ || value.schema !== HOST_CAPABILITY_HOOK_PENDING_RUNTIME_SCHEMA
43
+ || !boundedIdentity(value.mission_id)
44
+ || !boundedIdentity(value.workflow_run_id)
45
+ || !SHA256_RECEIPT_PATTERN.test(String(value.launch_nonce_sha256 || ''))
46
+ || !isHostCapabilityRuntime(value.runtime)) {
47
+ return { pending: null, blocker: 'host_capability_hook_pending_runtime_invalid' };
48
+ }
49
+ const pending = value;
50
+ const launchNonce = boundedIdentity(input.launchNonce);
51
+ if (pending.mission_id !== boundedIdentity(input.missionId)
52
+ || pending.workflow_run_id !== boundedIdentity(input.workflowRunId)
53
+ || !launchNonce
54
+ || pending.launch_nonce_sha256 !== `sha256:${sha256(launchNonce)}`) {
55
+ return { pending: null, blocker: 'host_capability_hook_pending_runtime_scope_mismatch' };
56
+ }
57
+ if (input.request && !hostCapabilityRuntimeMatchesRequest(pending.runtime, input.request)) {
58
+ return { pending: null, blocker: 'host_capability_hook_pending_runtime_request_scope_mismatch' };
59
+ }
60
+ return { pending, blocker: '' };
61
+ }
62
+ export function createHostCapabilityHookRuntimeBinding(input) {
63
+ const missionId = boundedIdentity(input.missionId);
64
+ const workflowRunId = boundedIdentity(input.workflowRunId);
65
+ const sessionScope = boundedIdentity(input.sessionScope);
66
+ if (!missionId || !workflowRunId || !sessionScope) {
67
+ throw new Error('host_capability_hook_runtime_identity_missing');
68
+ }
69
+ return {
70
+ schema: HOST_CAPABILITY_HOOK_RUNTIME_SCHEMA,
71
+ mission_id: missionId,
72
+ workflow_run_id: workflowRunId,
73
+ session_scope: sessionScope,
74
+ runtime: input.runtime
75
+ };
76
+ }
77
+ export function normalizeHostCapabilityHookRuntimeBinding(value) {
78
+ if (!isRecord(value)
79
+ || value.schema !== HOST_CAPABILITY_HOOK_RUNTIME_SCHEMA
80
+ || !boundedIdentity(value.mission_id)
81
+ || !boundedIdentity(value.workflow_run_id)
82
+ || !boundedIdentity(value.session_scope)
83
+ || !isHostCapabilityRuntime(value.runtime))
84
+ return null;
85
+ return value;
86
+ }
87
+ export function hostCapabilityHookBindingMatches(binding, input) {
88
+ return binding.mission_id === boundedIdentity(input.missionId)
89
+ && binding.workflow_run_id === boundedIdentity(input.workflowRunId)
90
+ && binding.session_scope === boundedIdentity(input.sessionScope);
91
+ }
92
+ export function resolveHostCapabilityHookRuntimeBinding(value, input) {
93
+ if (!value)
94
+ return { binding: null, blocker: 'host_capability_hook_runtime_missing' };
95
+ const binding = normalizeHostCapabilityHookRuntimeBinding(value);
96
+ if (!binding)
97
+ return { binding: null, blocker: 'host_capability_hook_runtime_invalid' };
98
+ if (!hostCapabilityHookBindingMatches(binding, input)) {
99
+ return { binding: null, blocker: 'host_capability_hook_runtime_scope_mismatch' };
100
+ }
101
+ if (input.request && !hostCapabilityRuntimeMatchesRequest(binding.runtime, input.request)) {
102
+ return { binding: null, blocker: 'host_capability_hook_runtime_request_scope_mismatch' };
103
+ }
104
+ return { binding, blocker: '' };
105
+ }
106
+ export function acasHostToolName(value) {
107
+ const toolName = String(value || '').trim();
108
+ if (!toolName || toolName.length > 256 || /[\r\n\0]/.test(toolName))
109
+ return null;
110
+ const match = toolName.match(/^mcp__(?:acas-tools|acas_tools)__([A-Za-z][A-Za-z0-9_.:-]{0,127})$/);
111
+ return match?.[1] || null;
112
+ }
113
+ export function explicitlyDeniedHostCapabilityTool(value) {
114
+ return EXPLICIT_DENIAL_PATTERN.test(String(value || ''));
115
+ }
116
+ export function sanitizeHostCapabilityPreToolUse(runtime, payload) {
117
+ if (!isRecord(payload))
118
+ return null;
119
+ const tool = acasHostToolName(payload.tool_name);
120
+ const toolUseId = boundedIdentity(payload.tool_use_id);
121
+ if (!tool || !toolUseId)
122
+ return null;
123
+ const toolInput = isRecord(payload.tool_input) ? payload.tool_input : {};
124
+ const resourceKey = extractToolResourceKey({ arguments: payload.tool_input });
125
+ const datasource = tool === 'datasource_schema_context' || tool === 'datasource_query_readonly'
126
+ ? boundedIdentity(toolInput.datasource)
127
+ : null;
128
+ const schemaSnapshotId = tool === 'datasource_query_readonly'
129
+ ? boundedIdentity(toolInput.schema_snapshot_id)
130
+ : null;
131
+ const allowed = runtime.ok
132
+ && runtime.allowed_tool_names.includes(tool)
133
+ && !explicitlyDeniedHostCapabilityTool(tool);
134
+ const blocker = !runtime.ok
135
+ ? 'host_capability_runtime_unavailable'
136
+ : explicitlyDeniedHostCapabilityTool(tool)
137
+ ? `host_tool_call_explicitly_denied:${tool}`
138
+ : !runtime.allowed_tool_names.includes(tool)
139
+ ? `host_tool_call_not_allowed:${tool}`
140
+ : null;
141
+ return {
142
+ tool_use_id_sha256: `sha256:${sha256(toolUseId)}`,
143
+ tool,
144
+ resource_key: resourceKey,
145
+ datasource_sha256: datasource ? `sha256:${sha256(datasource)}` : null,
146
+ schema_snapshot_sha256: schemaSnapshotId ? `sha256:${sha256(schemaSnapshotId)}` : null,
147
+ decision: allowed ? 'allowed' : 'denied',
148
+ reservation_status: allowed ? 'pending' : 'denied',
149
+ blocker
150
+ };
151
+ }
152
+ export function sanitizeHostCapabilityPostToolUse(payload) {
153
+ if (!isRecord(payload))
154
+ return null;
155
+ const tool = acasHostToolName(payload.tool_name);
156
+ const toolUseId = boundedIdentity(payload.tool_use_id);
157
+ if (!tool || !toolUseId)
158
+ return null;
159
+ const response = structuredHostToolResponse(payload.tool_response);
160
+ const malformed = !response || Object.keys(response).length === 0;
161
+ const semantic = malformed
162
+ ? { receipt: null, blocker: `host_tool_response_malformed:${tool}` }
163
+ : normalizeHostToolSemanticReceipt(tool, payload.tool_input, response);
164
+ const status = hostToolResponseFailed(payload.tool_response)
165
+ || hostToolResponseFailed(response)
166
+ || malformed
167
+ || Boolean(semantic.blocker)
168
+ ? 'failed'
169
+ : 'passed';
170
+ const artifacts = status === 'passed'
171
+ ? extractArtifactReceipts(payload.tool_response)
172
+ : [];
173
+ const resourceKey = extractToolResourceKey({
174
+ arguments: payload.tool_input,
175
+ result: payload.tool_response
176
+ });
177
+ const toolUseIdSha256 = `sha256:${sha256(toolUseId)}`;
178
+ const eventSha256 = `sha256:${sha256(JSON.stringify({
179
+ server: HOST_CAPABILITY_MCP_SERVER,
180
+ tool,
181
+ status,
182
+ tool_use_id_sha256: toolUseIdSha256,
183
+ resource_key: resourceKey,
184
+ semantic_receipt: semantic.receipt,
185
+ validation_blocker: semantic.blocker,
186
+ artifacts
187
+ }))}`;
188
+ return {
189
+ sequence: 0,
190
+ tool_use_id_sha256: toolUseIdSha256,
191
+ tool,
192
+ status,
193
+ event_sha256: eventSha256,
194
+ resource_key: resourceKey,
195
+ semantic_receipt: semantic.receipt,
196
+ validation_blocker: semantic.blocker,
197
+ artifacts
198
+ };
199
+ }
200
+ export function mergeHostCapabilityPreToolObservation(input) {
201
+ return authorizeAndMergeHostCapabilityPreToolObservation(input).observations;
202
+ }
203
+ export function authorizeAndMergeHostCapabilityPreToolObservation(input) {
204
+ const current = normalizeHostCapabilityHookObservations(input.current, input.binding)
205
+ || emptyHookObservations(input.binding);
206
+ const existing = current.pre_tool_uses.find((row) => row.tool_use_id_sha256 === input.observation.tool_use_id_sha256);
207
+ if (existing) {
208
+ if (preToolReservationIdentityMatches(existing, input.observation)) {
209
+ if (existing.decision !== 'allowed' || existing.reservation_status !== 'pending') {
210
+ const observation = denyPreToolReservation(input.observation, `host_tool_reservation_replay_${existing.reservation_status}`);
211
+ return { observations: current, observation, decision: 'denied', blocker: observation.blocker };
212
+ }
213
+ return {
214
+ observations: current,
215
+ observation: existing,
216
+ decision: 'allowed',
217
+ blocker: null
218
+ };
219
+ }
220
+ const observation = denyPreToolReservation(input.observation, 'host_tool_reservation_identity_mismatch');
221
+ return { observations: current, observation, decision: 'denied', blocker: observation.blocker };
222
+ }
223
+ if (current.pre_tool_uses.length >= MAX_PRE_TOOL_OBSERVATIONS) {
224
+ const observation = denyPreToolReservation(input.observation, 'host_pre_tool_observations_too_many');
225
+ return { observations: current, observation, decision: 'denied', blocker: observation.blocker };
226
+ }
227
+ const observation = authorizePreToolReservation(input.binding.runtime, current, input.observation);
228
+ const observations = {
229
+ ...current,
230
+ pre_tool_uses: [...current.pre_tool_uses, observation]
231
+ };
232
+ return {
233
+ observations,
234
+ observation,
235
+ decision: observation.decision,
236
+ blocker: observation.blocker
237
+ };
238
+ }
239
+ function authorizePreToolReservation(runtime, current, observation) {
240
+ if (observation.decision === 'denied')
241
+ return denyPreToolReservation(observation, observation.blocker);
242
+ if (observation.tool === 'datasource_query_readonly') {
243
+ if (hasReservedOrObservedToolCall(current, observation.tool)) {
244
+ return denyPreToolReservation(observation, 'host_capability_readonly_query_already_reserved');
245
+ }
246
+ const schemaReceipts = completedPassedToolCalls(current, 'datasource_schema_context')
247
+ .map((call) => call.semantic_receipt?.kind === 'datasource_schema' ? call.semantic_receipt : null)
248
+ .filter(Boolean);
249
+ if (schemaReceipts.length === 0) {
250
+ return denyPreToolReservation(observation, 'host_capability_readonly_query_schema_not_completed');
251
+ }
252
+ const matchingDatasource = observation.datasource_sha256
253
+ ? schemaReceipts.filter((receipt) => receipt.datasource_sha256 === observation.datasource_sha256)
254
+ : [];
255
+ if (matchingDatasource.length === 0) {
256
+ return denyPreToolReservation(observation, 'host_capability_readonly_query_datasource_mismatch');
257
+ }
258
+ if (!observation.schema_snapshot_sha256
259
+ || !matchingDatasource.some((receipt) => (receipt.schema_snapshot_sha256 === observation.schema_snapshot_sha256))) {
260
+ return denyPreToolReservation(observation, 'host_capability_readonly_query_schema_mismatch');
261
+ }
262
+ }
263
+ if (observation.tool === 'spreadsheet_create'
264
+ && hasReservedOrObservedToolCall(current, observation.tool)) {
265
+ return denyPreToolReservation(observation, 'host_capability_spreadsheet_create_already_reserved');
266
+ }
267
+ if (observation.tool === 'spreadsheet_update') {
268
+ if (hasReservedOrObservedToolCall(current, observation.tool)) {
269
+ return denyPreToolReservation(observation, 'host_capability_spreadsheet_update_already_reserved');
270
+ }
271
+ let completedCreateSequence = null;
272
+ if (runtime.task_workflows.includes('spreadsheet_create')) {
273
+ const completedCreates = completedPassedToolCalls(current, 'spreadsheet_create');
274
+ if (completedCreates.length === 0) {
275
+ return denyPreToolReservation(observation, 'host_capability_spreadsheet_update_create_not_completed');
276
+ }
277
+ const matchingCreates = observation.resource_key
278
+ ? completedCreates.filter((call) => call.resource_key === observation.resource_key)
279
+ : [];
280
+ if (matchingCreates.length === 0) {
281
+ return denyPreToolReservation(observation, 'host_capability_spreadsheet_update_resource_mismatch');
282
+ }
283
+ completedCreateSequence = Math.max(...matchingCreates.map((call) => call.sequence));
284
+ }
285
+ const completedInspections = completedPassedToolCalls(current, 'spreadsheet_inspect');
286
+ if (completedInspections.length === 0) {
287
+ return denyPreToolReservation(observation, 'host_capability_spreadsheet_update_inspection_not_completed');
288
+ }
289
+ const matchingInspections = observation.resource_key
290
+ ? completedInspections.filter((call) => call.resource_key === observation.resource_key)
291
+ : [];
292
+ if (matchingInspections.length === 0) {
293
+ return denyPreToolReservation(observation, 'host_capability_spreadsheet_update_resource_mismatch');
294
+ }
295
+ if (completedCreateSequence !== null
296
+ && !matchingInspections.some((call) => call.sequence > completedCreateSequence)) {
297
+ return denyPreToolReservation(observation, 'host_capability_spreadsheet_update_inspection_not_completed');
298
+ }
299
+ }
300
+ return {
301
+ ...observation,
302
+ decision: 'allowed',
303
+ reservation_status: 'pending',
304
+ blocker: null
305
+ };
306
+ }
307
+ function hasReservedOrObservedToolCall(observations, tool) {
308
+ return observations.tool_calls.some((row) => row.tool === tool)
309
+ || observations.pre_tool_uses.some((row) => (row.tool === tool && row.reservation_status !== 'denied'));
310
+ }
311
+ function preToolReservationIdentityMatches(left, right) {
312
+ return left.tool === right.tool
313
+ && left.resource_key === right.resource_key
314
+ && left.datasource_sha256 === right.datasource_sha256
315
+ && left.schema_snapshot_sha256 === right.schema_snapshot_sha256;
316
+ }
317
+ function denyPreToolReservation(observation, blocker) {
318
+ return {
319
+ ...observation,
320
+ decision: 'denied',
321
+ reservation_status: 'denied',
322
+ blocker: blocker || 'host_tool_reservation_denied'
323
+ };
324
+ }
325
+ function completedPassedToolCalls(observations, tool) {
326
+ return observations.tool_calls.filter((call) => {
327
+ if (call.tool !== tool || call.status !== 'passed')
328
+ return false;
329
+ const reservation = observations.pre_tool_uses.find((row) => (row.tool_use_id_sha256 === call.tool_use_id_sha256
330
+ && row.tool === call.tool
331
+ && row.resource_key === call.resource_key));
332
+ return reservation?.reservation_status === 'completed';
333
+ });
334
+ }
335
+ export function mergeHostCapabilityPostToolObservation(input) {
336
+ const current = normalizeHostCapabilityHookObservations(input.current, input.binding)
337
+ || emptyHookObservations(input.binding);
338
+ if (current.tool_calls.some((row) => row.tool_use_id_sha256 === input.observation.tool_use_id_sha256)) {
339
+ return {
340
+ ...current,
341
+ blockers: uniqueStrings([
342
+ ...current.blockers,
343
+ `host_tool_call_post_replay:${input.observation.tool}`
344
+ ])
345
+ };
346
+ }
347
+ if (current.tool_calls.length >= MAX_MCP_TOOL_CALLS) {
348
+ return { ...current, blockers: uniqueStrings([...current.blockers, 'host_tool_call_receipts_too_many']) };
349
+ }
350
+ const existingArtifactCount = current.tool_calls.reduce((sum, row) => sum + row.artifacts.length, 0);
351
+ const remainingArtifactSlots = Math.max(0, MAX_ARTIFACT_RECEIPTS - existingArtifactCount);
352
+ const sequence = current.tool_calls.reduce((max, row) => Math.max(max, row.sequence), 0) + 1;
353
+ const observation = {
354
+ ...input.observation,
355
+ sequence,
356
+ artifacts: input.observation.artifacts.slice(0, remainingArtifactSlots)
357
+ };
358
+ const reservationById = current.pre_tool_uses.find((row) => (row.tool_use_id_sha256 === observation.tool_use_id_sha256));
359
+ const matchingReservation = reservationById
360
+ && reservationById.tool === observation.tool
361
+ && reservationById.resource_key === observation.resource_key
362
+ && semanticReceiptMatchesReservation(reservationById, observation)
363
+ ? reservationById
364
+ : null;
365
+ const preToolUses = matchingReservation && matchingReservation.decision === 'allowed'
366
+ ? current.pre_tool_uses.map((row) => row === matchingReservation
367
+ ? {
368
+ ...row,
369
+ reservation_status: observation.status === 'passed' ? 'completed' : 'failed'
370
+ }
371
+ : row)
372
+ : current.pre_tool_uses;
373
+ const reservationBlocker = reservationById && !matchingReservation
374
+ ? `host_tool_call_pre_use_identity_mismatch:${observation.tool}`
375
+ : matchingReservation?.decision === 'denied'
376
+ ? `host_tool_call_pre_use_denied:${observation.tool}`
377
+ : matchingReservation
378
+ ? null
379
+ : `host_tool_call_pre_use_missing:${observation.tool}`;
380
+ return {
381
+ ...current,
382
+ pre_tool_uses: preToolUses,
383
+ tool_calls: [...current.tool_calls, observation],
384
+ blockers: uniqueStrings([
385
+ ...current.blockers,
386
+ ...(input.observation.artifacts.length > remainingArtifactSlots ? ['host_artifact_receipts_too_many'] : []),
387
+ ...(reservationBlocker ? [reservationBlocker] : [])
388
+ ])
389
+ };
390
+ }
391
+ function semanticReceiptMatchesReservation(reservation, observation) {
392
+ if (observation.status !== 'passed')
393
+ return true;
394
+ if (observation.tool === 'datasource_schema_context') {
395
+ return observation.semantic_receipt?.kind === 'datasource_schema'
396
+ && (!reservation.datasource_sha256
397
+ || observation.semantic_receipt.datasource_sha256 === reservation.datasource_sha256);
398
+ }
399
+ if (observation.tool === 'datasource_query_readonly') {
400
+ return observation.semantic_receipt?.kind === 'datasource_query'
401
+ && observation.semantic_receipt.datasource_sha256 === reservation.datasource_sha256
402
+ && observation.semantic_receipt.schema_snapshot_sha256 === reservation.schema_snapshot_sha256;
403
+ }
404
+ return true;
405
+ }
406
+ export function normalizeHostCapabilityHookObservations(value, binding) {
407
+ if (!isRecord(value)
408
+ || value.schema !== HOST_CAPABILITY_HOOK_OBSERVATIONS_SCHEMA
409
+ || value.mission_id !== binding.mission_id
410
+ || value.workflow_run_id !== binding.workflow_run_id
411
+ || value.session_scope !== binding.session_scope
412
+ || value.allowlist_digest !== binding.runtime.allowlist_digest
413
+ || !Array.isArray(value.pre_tool_uses)
414
+ || !Array.isArray(value.tool_calls)
415
+ || !Array.isArray(value.blockers)
416
+ || value.pre_tool_uses.length > MAX_PRE_TOOL_OBSERVATIONS
417
+ || value.tool_calls.length > MAX_MCP_TOOL_CALLS
418
+ || value.blockers.length > 16
419
+ || value.blockers.some((blocker) => typeof blocker !== 'string' || blocker.length > 128))
420
+ return null;
421
+ let preToolUses = value.pre_tool_uses.map(normalizePreToolObservation).filter(Boolean);
422
+ const toolCalls = value.tool_calls.map(normalizePostToolObservation).filter(Boolean);
423
+ if (preToolUses.length !== value.pre_tool_uses.length || toolCalls.length !== value.tool_calls.length)
424
+ return null;
425
+ if (toolCalls.reduce((sum, row) => sum + row.artifacts.length, 0) > MAX_ARTIFACT_RECEIPTS)
426
+ return null;
427
+ preToolUses = preToolUses.map((row) => {
428
+ if (row.decision !== 'allowed')
429
+ return row;
430
+ const call = toolCalls.find((candidate) => (candidate.tool_use_id_sha256 === row.tool_use_id_sha256
431
+ && candidate.tool === row.tool
432
+ && candidate.resource_key === row.resource_key));
433
+ return call && semanticReceiptMatchesReservation(row, call)
434
+ ? { ...row, reservation_status: call.status === 'passed' ? 'completed' : 'failed' }
435
+ : row;
436
+ });
437
+ return {
438
+ schema: HOST_CAPABILITY_HOOK_OBSERVATIONS_SCHEMA,
439
+ mission_id: binding.mission_id,
440
+ workflow_run_id: binding.workflow_run_id,
441
+ session_scope: binding.session_scope,
442
+ allowlist_digest: binding.runtime.allowlist_digest,
443
+ pre_tool_uses: preToolUses,
444
+ tool_calls: [...toolCalls].sort((left, right) => left.sequence - right.sequence),
445
+ blockers: uniqueStrings(value.blockers)
446
+ };
447
+ }
448
+ export function buildHostCapabilityEvidenceFromHookObservations(input) {
449
+ const observations = normalizeHostCapabilityHookObservations(input.observations, input.binding)
450
+ || emptyHookObservations(input.binding);
451
+ const observationBlockers = [...observations.blockers];
452
+ const preToolUses = new Map(observations.pre_tool_uses.map((row) => [
453
+ `${row.tool_use_id_sha256}:${row.tool}`,
454
+ row
455
+ ]));
456
+ for (const row of observations.tool_calls) {
457
+ const preToolUse = preToolUses.get(`${row.tool_use_id_sha256}:${row.tool}`);
458
+ if (!preToolUse)
459
+ observationBlockers.push(`host_tool_call_pre_use_missing:${row.tool}`);
460
+ else if (preToolUse.decision !== 'allowed')
461
+ observationBlockers.push(`host_tool_call_pre_use_denied:${row.tool}`);
462
+ else if (preToolUse.resource_key !== row.resource_key)
463
+ observationBlockers.push(`host_tool_call_pre_use_identity_mismatch:${row.tool}`);
464
+ if (row.validation_blocker)
465
+ observationBlockers.push(row.validation_blocker);
466
+ }
467
+ for (const row of observations.pre_tool_uses) {
468
+ if (row.blocker)
469
+ observationBlockers.push(row.blocker);
470
+ if (row.reservation_status === 'pending')
471
+ observationBlockers.push(`host_tool_reservation_pending:${row.tool}`);
472
+ }
473
+ const calls = observations.tool_calls.map((row) => ({
474
+ server: HOST_CAPABILITY_MCP_SERVER,
475
+ tool: row.tool,
476
+ status: row.status,
477
+ event_sha256: row.event_sha256,
478
+ raw_hash: row.event_sha256,
479
+ index: row.sequence,
480
+ resource_key: row.resource_key,
481
+ semantic_receipt: row.semantic_receipt
482
+ }));
483
+ const artifacts = observations.tool_calls.flatMap((row) => row.artifacts.map((artifact) => ({
484
+ ...artifact,
485
+ source_tool: row.tool,
486
+ source_hash: row.event_sha256,
487
+ source_index: row.sequence
488
+ })));
489
+ return buildExecutionEvidence(input.binding.runtime, calls, artifacts, observationBlockers);
490
+ }
491
+ export function createHostCapabilityEventCollector(runtime) {
492
+ let buffer = '';
493
+ let parsedEvents = 0;
494
+ let callIndex = 0;
495
+ const internalCalls = [];
496
+ const observedArtifacts = [];
497
+ const blockers = [];
498
+ const parseLine = (line) => {
499
+ const trimmed = line.trim();
500
+ if (!trimmed)
501
+ return;
502
+ if (Buffer.byteLength(trimmed, 'utf8') > MAX_EVENT_LINE_BYTES) {
503
+ blockers.push('host_tool_event_line_too_large');
504
+ return;
505
+ }
506
+ let event;
507
+ try {
508
+ event = JSON.parse(trimmed);
509
+ }
510
+ catch {
511
+ return;
512
+ }
513
+ parsedEvents += 1;
514
+ const item = event?.type === 'item.completed' ? event.item : null;
515
+ if (!item || item.type !== 'mcp_tool_call')
516
+ return;
517
+ if (internalCalls.length >= MAX_MCP_TOOL_CALLS) {
518
+ blockers.push('host_tool_call_receipts_too_many');
519
+ return;
520
+ }
521
+ const server = String(item.server || '').trim();
522
+ const tool = String(item.tool || '').trim();
523
+ const declaredStatus = item.status === 'completed' ? 'passed' : item.status === 'failed' ? 'failed' : null;
524
+ const response = structuredHostToolResponse(item.result);
525
+ const malformed = !response || Object.keys(response).length === 0;
526
+ const semantic = malformed
527
+ ? { receipt: null, blocker: `host_tool_response_malformed:${tool}` }
528
+ : normalizeHostToolSemanticReceipt(tool, item.arguments, response);
529
+ const status = declaredStatus === 'passed' && (malformed || semantic.blocker)
530
+ ? 'failed'
531
+ : declaredStatus;
532
+ if (!server || !tool || !status)
533
+ return;
534
+ callIndex += 1;
535
+ if (server !== runtime.server)
536
+ return;
537
+ const rawHash = `sha256:${sha256(trimmed)}`;
538
+ internalCalls.push({
539
+ server,
540
+ tool,
541
+ status,
542
+ event_sha256: rawHash,
543
+ raw_hash: rawHash,
544
+ index: callIndex,
545
+ resource_key: extractToolResourceKey(item),
546
+ semantic_receipt: semantic.receipt
547
+ });
548
+ if (semantic.blocker)
549
+ blockers.push(semantic.blocker);
550
+ if (status === 'passed') {
551
+ for (const artifact of extractArtifactReceipts(item.result?.structured_content ?? item.result?.structuredContent ?? item.result)) {
552
+ observedArtifacts.push({ ...artifact, source_tool: tool, source_hash: rawHash, source_index: callIndex });
553
+ }
554
+ }
555
+ };
556
+ const push = (chunk) => {
557
+ buffer += String(chunk || '');
558
+ if (Buffer.byteLength(buffer, 'utf8') > MAX_EVENT_LINE_BYTES * 2 && !buffer.includes('\n')) {
559
+ blockers.push('host_tool_event_buffer_too_large');
560
+ buffer = '';
561
+ return;
562
+ }
563
+ const lines = buffer.split(/\r?\n/);
564
+ buffer = lines.pop() || '';
565
+ for (const line of lines)
566
+ parseLine(line);
567
+ };
568
+ const finish = (fallbackOutput = '') => {
569
+ if (parsedEvents === 0 && fallbackOutput)
570
+ push(fallbackOutput);
571
+ if (buffer.trim())
572
+ parseLine(buffer);
573
+ buffer = '';
574
+ return buildExecutionEvidence(runtime, internalCalls, observedArtifacts, blockers);
575
+ };
576
+ return { push, finish };
577
+ }
578
+ export function bindParentSummaryToHostCapabilityEvidence(value, evidence) {
579
+ const parsed = parseJsonObject(value);
580
+ const hostEvidenceRequired = evidence.runtime.requested_capability_ids.length > 0
581
+ || evidence.tool_calls.length > 0
582
+ || evidence.artifacts.length > 0;
583
+ if (!parsed) {
584
+ return {
585
+ value,
586
+ blockers: hostEvidenceRequired ? ['host_capability_parent_summary_not_structured'] : []
587
+ };
588
+ }
589
+ const blockers = [...evidence.blockers];
590
+ if (parsed.capabilities_used !== undefined
591
+ && JSON.stringify(parsed.capabilities_used) !== JSON.stringify(evidence.capabilities_used)) {
592
+ blockers.push('host_capability_parent_receipts_mismatch');
593
+ }
594
+ if (parsed.artifacts !== undefined
595
+ && JSON.stringify(parsed.artifacts) !== JSON.stringify(evidence.artifacts)) {
596
+ blockers.push('host_artifact_parent_receipts_mismatch');
597
+ }
598
+ const bindReceipts = hostEvidenceRequired
599
+ || parsed.capabilities_used !== undefined
600
+ || parsed.artifacts !== undefined;
601
+ const mergedBlockers = uniqueStrings([
602
+ ...arrayStrings(parsed.blockers),
603
+ ...blockers
604
+ ]);
605
+ const next = {
606
+ ...parsed,
607
+ ...(bindReceipts ? {
608
+ capabilities_used: evidence.capabilities_used,
609
+ artifacts: evidence.artifacts
610
+ } : {}),
611
+ ...(mergedBlockers.length > 0 ? { blockers: mergedBlockers } : {}),
612
+ ...(parsed.status === 'completed' && mergedBlockers.length > 0 ? { status: 'blocked' } : {})
613
+ };
614
+ return { value: next, blockers: uniqueStrings(blockers) };
615
+ }
616
+ function buildExecutionEvidence(runtime, calls, artifactRows, initialBlockers) {
617
+ const blockers = [...runtime.blockers, ...initialBlockers];
618
+ const requested = new Set(runtime.requested_capability_ids);
619
+ for (const call of calls) {
620
+ if (!runtime.allowed_tool_names.includes(call.tool))
621
+ blockers.push(`host_tool_call_not_allowed:${call.tool}`);
622
+ if (EXPLICIT_DENIAL_PATTERN.test(call.tool))
623
+ blockers.push(`host_tool_call_explicitly_denied:${call.tool}`);
624
+ if (call.status === 'failed')
625
+ blockers.push(`host_tool_call_failed:${call.tool}`);
626
+ }
627
+ const dedupedArtifactRows = dedupeObservedArtifacts(artifactRows);
628
+ if (dedupedArtifactRows.length > MAX_ARTIFACT_RECEIPTS)
629
+ blockers.push('host_artifact_receipts_too_many');
630
+ const receiptArtifactRows = dedupedArtifactRows.slice(0, MAX_ARTIFACT_RECEIPTS);
631
+ const artifacts = receiptArtifactRows.map(projectArtifactReceipt);
632
+ const artifactSources = receiptArtifactRows.map(projectArtifactSourceReceipt);
633
+ if (requested.size === 0 && calls.length > 0) {
634
+ for (const call of calls)
635
+ blockers.push(`host_tool_call_not_requested:${call.tool}`);
636
+ }
637
+ const capabilitiesUsed = [];
638
+ for (const descriptor of HOST_CAPABILITY_DESCRIPTORS) {
639
+ if (!requested.has(descriptor.id))
640
+ continue;
641
+ const relevantCalls = calls.filter((call) => descriptor.tool_names.includes(call.tool));
642
+ const capabilityBlockers = validateCapabilityWorkflow(runtime, descriptor, relevantCalls, calls, artifactRows);
643
+ blockers.push(...capabilityBlockers);
644
+ const status = capabilityBlockers.length === 0 && relevantCalls.every((call) => call.status === 'passed')
645
+ ? 'passed'
646
+ : 'failed';
647
+ const capabilityArtifactSources = descriptor.executable === false
648
+ ? artifactSources
649
+ : [];
650
+ const toolNames = uniqueStrings([
651
+ ...relevantCalls.map((call) => call.tool),
652
+ ...capabilityArtifactSources.map((source) => source.source_tool)
653
+ ]);
654
+ const receiptSha256 = `sha256:${sha256(JSON.stringify({
655
+ id: descriptor.id,
656
+ calls: relevantCalls.map((call) => call.raw_hash),
657
+ artifacts: capabilityArtifactSources.map((source) => source.source_event_sha256)
658
+ }))}`;
659
+ capabilitiesUsed.push({ id: descriptor.id, status, tool_names: toolNames, receipt_sha256: receiptSha256 });
660
+ }
661
+ const uniqueBlockersValue = uniqueStrings(blockers);
662
+ return {
663
+ schema: HOST_CAPABILITY_EVIDENCE_SCHEMA,
664
+ ok: uniqueBlockersValue.length === 0 && capabilitiesUsed.every((receipt) => receipt.status === 'passed'),
665
+ runtime,
666
+ tool_calls: calls.map(({ server, tool, status, event_sha256 }) => ({ server, tool, status, event_sha256 })),
667
+ capabilities_used: capabilitiesUsed,
668
+ artifacts,
669
+ artifact_sources: artifactSources,
670
+ blockers: uniqueBlockersValue
671
+ };
672
+ }
673
+ function validateCapabilityWorkflow(runtime, descriptor, calls, allCalls, artifacts) {
674
+ const blockers = [];
675
+ const passed = (tool) => calls.filter((call) => call.tool === tool && call.status === 'passed');
676
+ if (descriptor.executable !== false && calls.length === 0)
677
+ blockers.push(`host_capability_call_missing:${descriptor.id}`);
678
+ if (calls.some((call) => call.status !== 'passed'))
679
+ blockers.push(`host_capability_call_failed:${descriptor.id}`);
680
+ if (descriptor.id === 'host.datasource.schema.v1' && passed('datasource_schema_context').length === 0) {
681
+ blockers.push('host_capability_schema_call_missing');
682
+ }
683
+ if (descriptor.id === 'host.datasource.query.readonly.v1') {
684
+ const schemaCall = allCalls.find((call) => call.tool === 'datasource_schema_context' && call.status === 'passed') || null;
685
+ const queryCalls = passed('datasource_query_readonly');
686
+ const queryCall = queryCalls[0] || null;
687
+ const schemaIndex = schemaCall?.index ?? -1;
688
+ const queryIndex = queryCall?.index ?? -1;
689
+ if (queryIndex < 0)
690
+ blockers.push('host_capability_readonly_query_call_missing');
691
+ if (runtime.task_workflows.includes('datasource_query') && queryCalls.length !== 1) {
692
+ blockers.push('host_capability_readonly_query_count_invalid');
693
+ }
694
+ if (runtime.task_workflows.includes('datasource_query') && (schemaIndex < 0 || queryIndex <= schemaIndex)) {
695
+ blockers.push('host_capability_datasource_sequence_invalid');
696
+ }
697
+ const schemaReceipt = schemaCall?.semantic_receipt?.kind === 'datasource_schema'
698
+ ? schemaCall.semantic_receipt
699
+ : null;
700
+ const queryReceipts = queryCalls
701
+ .map((call) => call.semantic_receipt?.kind === 'datasource_query' ? call.semantic_receipt : null);
702
+ if (queryCalls.length > 0 && queryReceipts.some((receipt) => !receipt)) {
703
+ blockers.push('host_capability_readonly_query_receipt_invalid');
704
+ }
705
+ if (schemaCall && !schemaReceipt)
706
+ blockers.push('host_capability_schema_receipt_invalid');
707
+ if (schemaReceipt && queryReceipts.some((receipt) => receipt
708
+ && schemaReceipt.schema_snapshot_sha256 !== receipt.schema_snapshot_sha256)) {
709
+ blockers.push('host_capability_readonly_query_schema_mismatch');
710
+ }
711
+ if (schemaReceipt && queryReceipts.some((receipt) => receipt
712
+ && schemaReceipt.datasource_sha256 !== receipt.datasource_sha256)) {
713
+ blockers.push('host_capability_readonly_query_datasource_mismatch');
714
+ }
715
+ }
716
+ if (descriptor.id === 'host.spreadsheet.workbook.v1') {
717
+ const creates = passed('spreadsheet_create');
718
+ const updates = passed('spreadsheet_update');
719
+ const inspections = passed('spreadsheet_inspect');
720
+ const create = creates[0]?.index ?? -1;
721
+ const updateIndexes = updates.map((call) => call.index);
722
+ const inspectionIndexes = inspections.map((call) => call.index);
723
+ if (runtime.task_workflows.includes('spreadsheet_create')) {
724
+ if (creates.length !== 1)
725
+ blockers.push('host_capability_spreadsheet_create_sequence_invalid');
726
+ if (updates.length > 1)
727
+ blockers.push('host_capability_spreadsheet_create_update_count_invalid');
728
+ const update = updateIndexes[0] ?? -1;
729
+ const inspectedAfterCreate = inspectionIndexes.some((index) => index > create && (update < 0 || index < update));
730
+ const inspectedAfterMutation = update >= 0
731
+ ? inspectionIndexes.some((index) => index > update)
732
+ : inspectionIndexes.some((index) => index > create);
733
+ if (create < 0
734
+ || !inspectedAfterCreate
735
+ || !inspectedAfterMutation
736
+ || (update >= 0 && update <= create)) {
737
+ blockers.push('host_capability_spreadsheet_create_sequence_invalid');
738
+ }
739
+ }
740
+ if (runtime.task_workflows.includes('spreadsheet_edit')) {
741
+ const update = updateIndexes[0] ?? -1;
742
+ if (updates.length !== 1)
743
+ blockers.push('host_capability_spreadsheet_edit_update_count_invalid');
744
+ if (update < 0
745
+ || !inspectionIndexes.some((index) => index < update)
746
+ || !inspectionIndexes.some((index) => index > update)) {
747
+ blockers.push('host_capability_spreadsheet_edit_sequence_invalid');
748
+ }
749
+ }
750
+ if (runtime.task_workflows.includes('spreadsheet_create') || runtime.task_workflows.includes('spreadsheet_edit')) {
751
+ if (inspections.some((call) => call.semantic_receipt?.kind !== 'spreadsheet_inspection')) {
752
+ blockers.push('host_capability_spreadsheet_inspection_receipt_invalid');
753
+ }
754
+ const passedSpreadsheetCalls = calls.filter((call) => call.status === 'passed');
755
+ const resourceKeys = uniqueStrings(passedSpreadsheetCalls.map((call) => call.resource_key));
756
+ const lastMutation = [...creates, ...updates].sort((left, right) => right.index - left.index)[0] || null;
757
+ if (passedSpreadsheetCalls.some((call) => !call.resource_key)) {
758
+ blockers.push('host_capability_spreadsheet_resource_missing');
759
+ }
760
+ if (resourceKeys.length > 1)
761
+ blockers.push('host_capability_spreadsheet_resource_mismatch');
762
+ const finalMutationArtifacts = lastMutation
763
+ ? artifacts.filter((artifact) => (artifact.source_index === lastMutation.index
764
+ && artifact.source_tool === lastMutation.tool))
765
+ : [];
766
+ if (lastMutation && finalMutationArtifacts.some((artifact) => (isSpreadsheetDeliverable(artifact)
767
+ && !artifactMatchesResource(artifact, lastMutation.resource_key)))) {
768
+ blockers.push('host_capability_spreadsheet_resource_mismatch');
769
+ }
770
+ if (!lastMutation || !finalMutationArtifacts.some((artifact) => (isSpreadsheetDeliverable(artifact)
771
+ && artifactMatchesResource(artifact, lastMutation.resource_key)))) {
772
+ blockers.push('host_capability_spreadsheet_final_artifact_missing');
773
+ }
774
+ }
775
+ }
776
+ if (descriptor.id === 'host.document.render.v1' && runtime.task_workflows.includes('document_render')) {
777
+ const renderCalls = [...passed('html_to_pdf'), ...passed('html_to_screenshot')].sort((left, right) => left.index - right.index);
778
+ if (renderCalls.length === 0) {
779
+ blockers.push('host_capability_document_render_call_missing');
780
+ }
781
+ else {
782
+ const sourceWrite = allCalls.find((call) => (call.status === 'passed'
783
+ && (call.tool === 'write_file' || call.tool === 'edit_file')
784
+ && call.index < renderCalls[0].index));
785
+ if (!sourceWrite)
786
+ blockers.push('host_capability_document_source_sequence_invalid');
787
+ const finalRender = renderCalls.at(-1);
788
+ if (!artifacts.some((artifact) => (artifact.source_tool === finalRender.tool
789
+ && artifact.source_index === finalRender.index
790
+ && isDocumentRenderDeliverable(artifact, finalRender.tool)))) {
791
+ blockers.push('host_capability_document_render_artifact_missing');
792
+ }
793
+ }
794
+ }
795
+ if (descriptor.id === 'host.web.capture.v1'
796
+ && runtime.task_workflows.includes('web_capture')
797
+ && passed('capture_url_screenshot').length === 0) {
798
+ blockers.push('host_capability_web_capture_call_missing');
799
+ }
800
+ if (descriptor.id === 'host.artifact.receipt.v1' && artifacts.length === 0) {
801
+ blockers.push('host_capability_artifact_receipt_missing');
802
+ }
803
+ return uniqueStrings(blockers);
804
+ }
805
+ function extractToolResourceKey(item) {
806
+ if (!isRecord(item))
807
+ return null;
808
+ const queue = [
809
+ { value: item.arguments, depth: 0 },
810
+ { value: item.input, depth: 0 },
811
+ { value: item.result?.structured_content ?? item.result?.structuredContent ?? item.result, depth: 0 }
812
+ ];
813
+ let visited = 0;
814
+ while (queue.length > 0 && visited < 256) {
815
+ const current = queue.shift();
816
+ visited += 1;
817
+ if (current.depth > 5 || current.value === null || current.value === undefined)
818
+ continue;
819
+ if (Array.isArray(current.value)) {
820
+ for (const child of current.value)
821
+ queue.push({ value: child, depth: current.depth + 1 });
822
+ continue;
823
+ }
824
+ if (!isRecord(current.value))
825
+ continue;
826
+ for (const [key, value] of Object.entries(current.value)) {
827
+ if (/^(?:path|file_path|filepath|workbook_path|workbook|source_path|target_path|output_path)$/i.test(key)) {
828
+ const resourcePath = normalizeWorkspaceResourcePath(value);
829
+ if (resourcePath)
830
+ return `sha256:${sha256(resourcePath)}`;
831
+ }
832
+ queue.push({ value, depth: current.depth + 1 });
833
+ }
834
+ }
835
+ return null;
836
+ }
837
+ function normalizeWorkspaceResourcePath(value) {
838
+ if (typeof value !== 'string')
839
+ return null;
840
+ const original = value.trim();
841
+ if (!original
842
+ || original.length > MAX_ARTIFACT_PATH_CHARS
843
+ || /[\r\n\0\\]/.test(original)
844
+ || original.startsWith('/')
845
+ || /^[a-z]:/i.test(original))
846
+ return null;
847
+ const segments = original.split('/');
848
+ if (segments.length === 0 || segments.some((segment) => !segment || segment === '.' || segment === '..'))
849
+ return null;
850
+ return segments.join('/');
851
+ }
852
+ function isSpreadsheetDeliverable(artifact) {
853
+ const artifactPath = normalizeWorkspaceResourcePath(artifact.path);
854
+ return artifact.role === 'deliverable'
855
+ && (artifact.kind === 'xlsx' || artifact.kind === 'spreadsheet')
856
+ && artifact.media_type === XLSX_MEDIA_TYPE
857
+ && Boolean(artifactPath && /\.xlsx$/i.test(artifactPath));
858
+ }
859
+ function artifactMatchesResource(artifact, resourceKey) {
860
+ const artifactPath = normalizeWorkspaceResourcePath(artifact.path);
861
+ return Boolean(resourceKey && artifactPath && `sha256:${sha256(artifactPath)}` === resourceKey);
862
+ }
863
+ function isDocumentRenderDeliverable(artifact, tool) {
864
+ const artifactPath = normalizeWorkspaceResourcePath(artifact.path);
865
+ const pdf = tool === 'html_to_pdf';
866
+ return artifact.role === 'deliverable'
867
+ && artifact.kind === (pdf ? 'pdf' : 'png')
868
+ && artifact.media_type === (pdf ? 'application/pdf' : 'image/png')
869
+ && Boolean(artifactPath && (pdf ? /\.pdf$/i : /\.png$/i).test(artifactPath));
870
+ }
871
+ function extractArtifactReceipts(value) {
872
+ const result = [];
873
+ const queue = [{ value, depth: 0 }];
874
+ let visited = 0;
875
+ while (queue.length > 0 && visited < 512) {
876
+ const current = queue.shift();
877
+ visited += 1;
878
+ if (current.depth > 6 || current.value === null || current.value === undefined)
879
+ continue;
880
+ if (typeof current.value === 'string') {
881
+ const text = current.value.trim();
882
+ if (text && Buffer.byteLength(text, 'utf8') <= MAX_RECEIPT_JSON_STRING_BYTES && /^[{[]/.test(text)) {
883
+ try {
884
+ queue.push({ value: JSON.parse(text), depth: current.depth + 1 });
885
+ }
886
+ catch { }
887
+ }
888
+ continue;
889
+ }
890
+ if (Array.isArray(current.value)) {
891
+ for (const child of current.value)
892
+ queue.push({ value: child, depth: current.depth + 1 });
893
+ continue;
894
+ }
895
+ if (!isRecord(current.value))
896
+ continue;
897
+ const artifact = normalizeArtifactReceipt(current.value);
898
+ if (artifact)
899
+ result.push(artifact);
900
+ for (const child of Object.values(current.value))
901
+ queue.push({ value: child, depth: current.depth + 1 });
902
+ }
903
+ return dedupeArtifacts(result);
904
+ }
905
+ function normalizeArtifactReceipt(value) {
906
+ const artifactPath = normalizeWorkspaceResourcePath(value.path) || '';
907
+ const kind = typeof value.kind === 'string' ? value.kind.trim().toLowerCase() : '';
908
+ const mediaType = typeof value.media_type === 'string'
909
+ ? value.media_type.trim().toLowerCase()
910
+ : typeof value.mediaType === 'string' ? value.mediaType.trim().toLowerCase() : '';
911
+ const receiptHash = typeof value.sha256 === 'string' ? value.sha256.trim().toLowerCase() : '';
912
+ const bytes = typeof value.bytes === 'number' && Number.isSafeInteger(value.bytes) && value.bytes > 0 ? value.bytes : 0;
913
+ const role = typeof value.role === 'string' && ['deliverable', 'scratch', 'temp', 'log'].includes(value.role)
914
+ ? value.role
915
+ : null;
916
+ if (!artifactPath
917
+ || !kind
918
+ || kind.length > 64
919
+ || !mediaType
920
+ || mediaType.length > 160
921
+ || !SHA256_RECEIPT_PATTERN.test(receiptHash)
922
+ || !bytes
923
+ || !role)
924
+ return null;
925
+ return { path: artifactPath, kind, media_type: mediaType, sha256: receiptHash, bytes, role };
926
+ }
927
+ function dedupeArtifacts(values) {
928
+ const byPath = new Map(values.map((value) => [value.path, {
929
+ path: value.path,
930
+ kind: value.kind,
931
+ media_type: value.media_type,
932
+ sha256: value.sha256,
933
+ bytes: value.bytes,
934
+ role: value.role
935
+ }]));
936
+ return [...byPath.values()].sort((left, right) => left.path.localeCompare(right.path));
937
+ }
938
+ function dedupeObservedArtifacts(values) {
939
+ const byPath = new Map(values.map((value) => [value.path, value]));
940
+ return [...byPath.values()].sort((left, right) => left.path.localeCompare(right.path));
941
+ }
942
+ function projectArtifactReceipt(value) {
943
+ return {
944
+ path: value.path,
945
+ kind: value.kind,
946
+ media_type: value.media_type,
947
+ sha256: value.sha256,
948
+ bytes: value.bytes,
949
+ role: value.role
950
+ };
951
+ }
952
+ function projectArtifactSourceReceipt(value) {
953
+ return {
954
+ path: value.path,
955
+ source_tool: value.source_tool,
956
+ source_event_sha256: value.source_hash
957
+ };
958
+ }
959
+ function emptyHookObservations(binding) {
960
+ return {
961
+ schema: HOST_CAPABILITY_HOOK_OBSERVATIONS_SCHEMA,
962
+ mission_id: binding.mission_id,
963
+ workflow_run_id: binding.workflow_run_id,
964
+ session_scope: binding.session_scope,
965
+ allowlist_digest: binding.runtime.allowlist_digest,
966
+ pre_tool_uses: [],
967
+ tool_calls: [],
968
+ blockers: []
969
+ };
970
+ }
971
+ function normalizePreToolObservation(value) {
972
+ if (!isRecord(value)
973
+ || !SHA256_RECEIPT_PATTERN.test(String(value.tool_use_id_sha256 || ''))
974
+ || typeof value.tool !== 'string'
975
+ || value.tool.length === 0
976
+ || value.tool.length > 128
977
+ || (value.decision !== 'allowed' && value.decision !== 'denied'))
978
+ return null;
979
+ const resourceKey = value.resource_key === undefined || value.resource_key === null
980
+ ? null
981
+ : SHA256_RECEIPT_PATTERN.test(String(value.resource_key || ''))
982
+ ? String(value.resource_key)
983
+ : undefined;
984
+ if (resourceKey === undefined)
985
+ return null;
986
+ const datasourceSha256 = value.datasource_sha256 === undefined || value.datasource_sha256 === null
987
+ ? null
988
+ : SHA256_RECEIPT_PATTERN.test(String(value.datasource_sha256 || ''))
989
+ ? String(value.datasource_sha256)
990
+ : undefined;
991
+ const schemaSnapshotSha256 = value.schema_snapshot_sha256 === undefined || value.schema_snapshot_sha256 === null
992
+ ? null
993
+ : SHA256_RECEIPT_PATTERN.test(String(value.schema_snapshot_sha256 || ''))
994
+ ? String(value.schema_snapshot_sha256)
995
+ : undefined;
996
+ if (datasourceSha256 === undefined || schemaSnapshotSha256 === undefined)
997
+ return null;
998
+ const legacyStatus = value.decision === 'denied' ? 'denied' : 'pending';
999
+ const reservationStatus = value.reservation_status === undefined
1000
+ ? legacyStatus
1001
+ : ['pending', 'completed', 'failed', 'denied'].includes(String(value.reservation_status || ''))
1002
+ ? value.reservation_status
1003
+ : null;
1004
+ const blocker = value.blocker === undefined || value.blocker === null
1005
+ ? null
1006
+ : typeof value.blocker === 'string' && value.blocker.length > 0 && value.blocker.length <= 160
1007
+ ? value.blocker
1008
+ : undefined;
1009
+ if (!reservationStatus || blocker === undefined
1010
+ || (value.decision === 'denied' && reservationStatus !== 'denied')
1011
+ || (value.decision === 'allowed' && reservationStatus === 'denied'))
1012
+ return null;
1013
+ return {
1014
+ tool_use_id_sha256: value.tool_use_id_sha256,
1015
+ tool: value.tool,
1016
+ resource_key: resourceKey,
1017
+ datasource_sha256: datasourceSha256,
1018
+ schema_snapshot_sha256: schemaSnapshotSha256,
1019
+ decision: value.decision,
1020
+ reservation_status: reservationStatus,
1021
+ blocker
1022
+ };
1023
+ }
1024
+ function isPostToolObservation(value) {
1025
+ if (!isRecord(value)
1026
+ || !Number.isSafeInteger(value.sequence)
1027
+ || Number(value.sequence) < 1
1028
+ || !SHA256_RECEIPT_PATTERN.test(String(value.tool_use_id_sha256 || ''))
1029
+ || typeof value.tool !== 'string'
1030
+ || value.tool.length === 0
1031
+ || value.tool.length > 128
1032
+ || (value.status !== 'passed' && value.status !== 'failed')
1033
+ || !SHA256_RECEIPT_PATTERN.test(String(value.event_sha256 || ''))
1034
+ || (value.resource_key !== null && !SHA256_RECEIPT_PATTERN.test(String(value.resource_key || '')))
1035
+ || !isHostToolSemanticReceipt(value.semantic_receipt)
1036
+ || (value.validation_blocker !== null
1037
+ && (typeof value.validation_blocker !== 'string' || value.validation_blocker.length > 160))
1038
+ || !Array.isArray(value.artifacts))
1039
+ return false;
1040
+ return value.artifacts.length <= MAX_ARTIFACT_RECEIPTS
1041
+ && value.artifacts.every((artifact) => isRecord(artifact) && normalizeArtifactReceipt(artifact) !== null);
1042
+ }
1043
+ function normalizePostToolObservation(value) {
1044
+ if (!isPostToolObservation(value))
1045
+ return null;
1046
+ const semanticReceipt = normalizeStoredSemanticReceipt(value.semantic_receipt);
1047
+ if (value.semantic_receipt !== null && !semanticReceipt)
1048
+ return null;
1049
+ return {
1050
+ sequence: value.sequence,
1051
+ tool_use_id_sha256: value.tool_use_id_sha256,
1052
+ tool: value.tool,
1053
+ status: value.status,
1054
+ event_sha256: value.event_sha256,
1055
+ resource_key: value.resource_key,
1056
+ semantic_receipt: semanticReceipt,
1057
+ validation_blocker: value.validation_blocker,
1058
+ artifacts: value.artifacts.map((artifact) => normalizeArtifactReceipt(artifact))
1059
+ };
1060
+ }
1061
+ function isHostCapabilityRuntime(value) {
1062
+ if (!isRecord(value)
1063
+ || value.schema !== HOST_CAPABILITY_RUNTIME_SCHEMA
1064
+ || typeof value.ok !== 'boolean'
1065
+ || value.server !== HOST_CAPABILITY_MCP_SERVER
1066
+ || !Array.isArray(value.requested_capability_ids)
1067
+ || !Array.isArray(value.task_workflows)
1068
+ || !Array.isArray(value.requested_tool_names)
1069
+ || !Array.isArray(value.observed_tool_names)
1070
+ || !Array.isArray(value.allowed_tool_names)
1071
+ || !Array.isArray(value.denied_tool_names)
1072
+ || !Array.isArray(value.explicit_denied_tool_names)
1073
+ || !Array.isArray(value.capabilities)
1074
+ || !Array.isArray(value.blockers))
1075
+ return false;
1076
+ const knownIds = new Set(HOST_CAPABILITY_DESCRIPTORS.map((descriptor) => descriptor.id));
1077
+ const knownTools = new Set(HOST_CAPABILITY_DESCRIPTORS.flatMap((descriptor) => descriptor.tool_names));
1078
+ const requested = uniqueStrings(value.requested_capability_ids);
1079
+ const requestedTools = uniqueStrings(value.requested_tool_names);
1080
+ const observed = uniqueStrings(value.observed_tool_names);
1081
+ const allowed = uniqueStrings(value.allowed_tool_names);
1082
+ const denied = uniqueStrings(value.denied_tool_names);
1083
+ const blockers = uniqueStrings(value.blockers);
1084
+ if (requested.length !== value.requested_capability_ids.length
1085
+ || requested.some((id) => !knownIds.has(id))
1086
+ || requestedTools.length !== value.requested_tool_names.length
1087
+ || requestedTools.some((tool) => !knownTools.has(tool))
1088
+ || observed.length !== value.observed_tool_names.length
1089
+ || allowed.length !== value.allowed_tool_names.length
1090
+ || allowed.some((tool) => !knownTools.has(tool) || !observed.includes(tool) || EXPLICIT_DENIAL_PATTERN.test(tool))
1091
+ || denied.length !== value.denied_tool_names.length
1092
+ || JSON.stringify(denied) !== JSON.stringify(observed.filter((tool) => !allowed.includes(tool)))
1093
+ || blockers.length !== value.blockers.length
1094
+ || value.blockers.some((blocker) => typeof blocker !== 'string' || blocker.length > 256)
1095
+ || value.ok !== (blockers.length === 0)
1096
+ || JSON.stringify(uniqueWorkflows(value.task_workflows)) !== JSON.stringify(value.task_workflows)
1097
+ || value.capabilities.length !== HOST_CAPABILITY_DESCRIPTORS.length
1098
+ || JSON.stringify(value.capabilities.map((entry) => entry?.id))
1099
+ !== JSON.stringify(HOST_CAPABILITY_DESCRIPTORS.map((descriptor) => descriptor.id))
1100
+ || value.capabilities.some((entry) => !isHostCapabilityRuntimeEntry(entry, requested, observed, allowed))
1101
+ || typeof value.server_present !== 'boolean'
1102
+ || typeof value.server_enabled !== 'boolean'
1103
+ || value.server_scope !== (value.server_present ? 'project' : null)
1104
+ || (value.inventory_source !== null && !boundedRuntimeText(value.inventory_source, 512))
1105
+ || !boundedRuntimeText(value.health_status, 128))
1106
+ return false;
1107
+ const allowedFromEntries = uniqueStrings(value.capabilities.flatMap((entry) => entry.allowed_tool_names));
1108
+ if (JSON.stringify(allowedFromEntries) !== JSON.stringify(allowed))
1109
+ return false;
1110
+ const explicitDenied = denied.filter((tool) => EXPLICIT_DENIAL_PATTERN.test(tool));
1111
+ if (JSON.stringify(explicitDenied) !== JSON.stringify(value.explicit_denied_tool_names))
1112
+ return false;
1113
+ const expectedDigest = hostCapabilityRuntimeDigest(value);
1114
+ return value.allowlist_digest === expectedDigest
1115
+ && value.capability_digest === hostCapabilityDigest(HOST_CAPABILITY_DESCRIPTORS);
1116
+ }
1117
+ function isHostCapabilityRuntimeEntry(value, requested, observed, allowed) {
1118
+ if (!isRecord(value)
1119
+ || typeof value.id !== 'string'
1120
+ || typeof value.requested !== 'boolean'
1121
+ || !['available', 'missing', 'unhealthy', 'not_requested'].includes(String(value.state || ''))
1122
+ || !Array.isArray(value.expected_tool_names)
1123
+ || !Array.isArray(value.observed_tool_names)
1124
+ || !Array.isArray(value.allowed_tool_names)
1125
+ || !Array.isArray(value.blockers))
1126
+ return false;
1127
+ const descriptor = HOST_CAPABILITY_DESCRIPTORS.find((entry) => entry.id === value.id);
1128
+ if (!descriptor)
1129
+ return false;
1130
+ const expectedObserved = uniqueStrings(descriptor.tool_names.filter((tool) => observed.includes(tool)));
1131
+ const expectedAllowed = descriptor.executable !== false && requested.includes(value.id)
1132
+ ? uniqueStrings(descriptor.tool_names.filter((tool) => allowed.includes(tool)))
1133
+ : [];
1134
+ const entryBlockers = uniqueStrings(value.blockers);
1135
+ return value.requested === requested.includes(value.id)
1136
+ && JSON.stringify(value.expected_tool_names) === JSON.stringify(descriptor.tool_names)
1137
+ && JSON.stringify(value.allowed_tool_names) === JSON.stringify(expectedAllowed)
1138
+ && JSON.stringify(value.observed_tool_names) === JSON.stringify(expectedObserved)
1139
+ && JSON.stringify(value.blockers) === JSON.stringify(entryBlockers)
1140
+ && entryBlockers.every((blocker) => blocker.length <= 256)
1141
+ && (requested.includes(value.id) ? value.state !== 'not_requested' : value.state === 'not_requested');
1142
+ }
1143
+ function hostCapabilityRuntimeMatchesRequest(runtime, request) {
1144
+ return JSON.stringify(runtime.requested_capability_ids) === JSON.stringify(uniqueStrings(request.capability_ids))
1145
+ && JSON.stringify(runtime.task_workflows) === JSON.stringify(uniqueWorkflows(request.workflows))
1146
+ && JSON.stringify(runtime.requested_tool_names) === JSON.stringify(uniqueStrings(request.tool_names || []));
1147
+ }
1148
+ function structuredHostToolResponse(value) {
1149
+ if (!isRecord(value))
1150
+ return null;
1151
+ const nested = value.structured_content ?? value.structuredContent;
1152
+ if (nested !== undefined)
1153
+ return parseJsonObject(nested);
1154
+ return value;
1155
+ }
1156
+ function normalizeHostToolSemanticReceipt(tool, toolInput, response) {
1157
+ if (tool === 'datasource_schema_context') {
1158
+ const input = isRecord(toolInput) ? toolInput : {};
1159
+ const datasource = boundedIdentity(response.datasource);
1160
+ const inputDatasource = boundedIdentity(input.datasource);
1161
+ const snapshotId = boundedIdentity(response.schema_snapshot_id);
1162
+ return datasource && (!inputDatasource || datasource === inputDatasource) && snapshotId
1163
+ ? {
1164
+ receipt: {
1165
+ kind: 'datasource_schema',
1166
+ datasource_sha256: `sha256:${sha256(datasource)}`,
1167
+ schema_snapshot_sha256: `sha256:${sha256(snapshotId)}`
1168
+ },
1169
+ blocker: null
1170
+ }
1171
+ : {
1172
+ receipt: null,
1173
+ blocker: datasource && inputDatasource && datasource !== inputDatasource
1174
+ ? 'host_capability_schema_datasource_mismatch'
1175
+ : 'host_capability_schema_receipt_invalid'
1176
+ };
1177
+ }
1178
+ if (tool === 'datasource_query_readonly') {
1179
+ const input = isRecord(toolInput) ? toolInput : {};
1180
+ const datasource = boundedIdentity(response.datasource);
1181
+ const inputDatasource = boundedIdentity(input.datasource);
1182
+ const snapshotId = boundedIdentity(response.schema_snapshot_id);
1183
+ const inputSnapshotId = boundedIdentity(input.schema_snapshot_id);
1184
+ const query = boundedQueryText(input.query ?? input.sql);
1185
+ const querySha256 = typeof response.query_sha256 === 'string'
1186
+ ? response.query_sha256.trim().toLowerCase()
1187
+ : '';
1188
+ const rowCount = nonnegativeSafeInteger(response.row_count);
1189
+ const columnCount = nonnegativeSafeInteger(response.column_count);
1190
+ const status = String(response.status || '').trim().toLowerCase();
1191
+ if (!datasource) {
1192
+ return { receipt: null, blocker: 'host_capability_readonly_query_receipt_invalid' };
1193
+ }
1194
+ if (inputDatasource && datasource !== inputDatasource) {
1195
+ return { receipt: null, blocker: 'host_capability_readonly_query_datasource_mismatch' };
1196
+ }
1197
+ if (!snapshotId || !inputSnapshotId || snapshotId !== inputSnapshotId) {
1198
+ return { receipt: null, blocker: 'host_capability_readonly_query_schema_mismatch' };
1199
+ }
1200
+ if (!query || !SHA256_RECEIPT_PATTERN.test(querySha256)
1201
+ || querySha256 !== `sha256:${sha256(query)}`) {
1202
+ return { receipt: null, blocker: 'host_capability_readonly_query_hash_mismatch' };
1203
+ }
1204
+ if (rowCount === null || columnCount === null || typeof response.truncated !== 'boolean' || status !== 'passed') {
1205
+ return { receipt: null, blocker: 'host_capability_readonly_query_receipt_invalid' };
1206
+ }
1207
+ return {
1208
+ receipt: {
1209
+ kind: 'datasource_query',
1210
+ datasource_sha256: `sha256:${sha256(datasource)}`,
1211
+ schema_snapshot_sha256: `sha256:${sha256(snapshotId)}`,
1212
+ query_sha256: querySha256,
1213
+ row_count: rowCount,
1214
+ column_count: columnCount,
1215
+ truncated: response.truncated,
1216
+ status: 'passed'
1217
+ },
1218
+ blocker: null
1219
+ };
1220
+ }
1221
+ if (tool === 'spreadsheet_inspect') {
1222
+ const sheetNames = Array.isArray(response.sheet_names)
1223
+ ? response.sheet_names.map((value) => boundedIdentity(value)).filter(Boolean)
1224
+ : [];
1225
+ const rowCountKeys = isRecord(response.row_counts) ? Object.keys(response.row_counts).sort() : [];
1226
+ const rowCounts = isRecord(response.row_counts)
1227
+ ? Object.values(response.row_counts).map(nonnegativeSafeInteger)
1228
+ : [];
1229
+ const formulas = Array.isArray(response.formulas) ? response.formulas : null;
1230
+ const errorCells = Array.isArray(response.error_cells) ? response.error_cells : null;
1231
+ const successful = response.ok === true || response.success === true
1232
+ || ['passed', 'success', 'completed'].includes(String(response.status || '').trim().toLowerCase());
1233
+ if (!successful
1234
+ || sheetNames.length === 0
1235
+ || sheetNames.length > 256
1236
+ || uniqueStrings(sheetNames).length !== sheetNames.length
1237
+ || sheetNames.length !== response.sheet_names.length
1238
+ || rowCounts.length !== sheetNames.length
1239
+ || JSON.stringify(rowCountKeys) !== JSON.stringify([...sheetNames].sort())
1240
+ || rowCounts.some((count) => count === null)
1241
+ || formulas === null
1242
+ || formulas.length > MAX_SEMANTIC_RECEIPT_ITEMS
1243
+ || errorCells === null
1244
+ || errorCells.length > MAX_SEMANTIC_RECEIPT_ITEMS) {
1245
+ return { receipt: null, blocker: 'host_capability_spreadsheet_inspection_receipt_invalid' };
1246
+ }
1247
+ if (errorCells.length > 0) {
1248
+ return { receipt: null, blocker: 'host_capability_spreadsheet_error_cells_present' };
1249
+ }
1250
+ const totalRowCount = rowCounts.reduce((sum, count) => sum + count, 0);
1251
+ if (!Number.isSafeInteger(totalRowCount)) {
1252
+ return { receipt: null, blocker: 'host_capability_spreadsheet_inspection_receipt_invalid' };
1253
+ }
1254
+ return {
1255
+ receipt: {
1256
+ kind: 'spreadsheet_inspection',
1257
+ sheet_names_sha256: `sha256:${sha256(JSON.stringify(sheetNames))}`,
1258
+ sheet_count: sheetNames.length,
1259
+ row_count: totalRowCount,
1260
+ formula_count: formulas.length,
1261
+ error_cell_count: 0
1262
+ },
1263
+ blocker: null
1264
+ };
1265
+ }
1266
+ return { receipt: null, blocker: null };
1267
+ }
1268
+ function isHostToolSemanticReceipt(value) {
1269
+ if (value === null)
1270
+ return true;
1271
+ if (!isRecord(value))
1272
+ return false;
1273
+ if (value.kind === 'datasource_schema') {
1274
+ return SHA256_RECEIPT_PATTERN.test(String(value.datasource_sha256 || ''))
1275
+ && SHA256_RECEIPT_PATTERN.test(String(value.schema_snapshot_sha256 || ''));
1276
+ }
1277
+ if (value.kind === 'datasource_query') {
1278
+ return SHA256_RECEIPT_PATTERN.test(String(value.datasource_sha256 || ''))
1279
+ && SHA256_RECEIPT_PATTERN.test(String(value.schema_snapshot_sha256 || ''))
1280
+ && SHA256_RECEIPT_PATTERN.test(String(value.query_sha256 || ''))
1281
+ && nonnegativeSafeInteger(value.row_count) !== null
1282
+ && nonnegativeSafeInteger(value.column_count) !== null
1283
+ && typeof value.truncated === 'boolean'
1284
+ && value.status === 'passed';
1285
+ }
1286
+ if (value.kind === 'spreadsheet_inspection') {
1287
+ return SHA256_RECEIPT_PATTERN.test(String(value.sheet_names_sha256 || ''))
1288
+ && nonnegativeSafeInteger(value.sheet_count) !== null
1289
+ && nonnegativeSafeInteger(value.row_count) !== null
1290
+ && nonnegativeSafeInteger(value.formula_count) !== null
1291
+ && value.error_cell_count === 0;
1292
+ }
1293
+ return false;
1294
+ }
1295
+ function normalizeStoredSemanticReceipt(value) {
1296
+ if (value === null)
1297
+ return null;
1298
+ if (!isHostToolSemanticReceipt(value))
1299
+ return null;
1300
+ if (value.kind === 'datasource_schema') {
1301
+ return {
1302
+ kind: value.kind,
1303
+ datasource_sha256: value.datasource_sha256,
1304
+ schema_snapshot_sha256: value.schema_snapshot_sha256
1305
+ };
1306
+ }
1307
+ if (value.kind === 'datasource_query') {
1308
+ return {
1309
+ kind: value.kind,
1310
+ datasource_sha256: value.datasource_sha256,
1311
+ schema_snapshot_sha256: value.schema_snapshot_sha256,
1312
+ query_sha256: value.query_sha256,
1313
+ row_count: value.row_count,
1314
+ column_count: value.column_count,
1315
+ truncated: value.truncated,
1316
+ status: 'passed'
1317
+ };
1318
+ }
1319
+ return {
1320
+ kind: value.kind,
1321
+ sheet_names_sha256: value.sheet_names_sha256,
1322
+ sheet_count: value.sheet_count,
1323
+ row_count: value.row_count,
1324
+ formula_count: value.formula_count,
1325
+ error_cell_count: 0
1326
+ };
1327
+ }
1328
+ function nonnegativeSafeInteger(value) {
1329
+ return typeof value === 'number' && Number.isSafeInteger(value) && value >= 0 ? value : null;
1330
+ }
1331
+ function boundedRuntimeText(value, maxLength) {
1332
+ const text = typeof value === 'string' ? value.trim() : '';
1333
+ return text && text.length <= maxLength && !/[\r\n\0]/.test(text) ? text : null;
1334
+ }
1335
+ function boundedQueryText(value) {
1336
+ const text = typeof value === 'string' ? value : '';
1337
+ return text.trim()
1338
+ && Buffer.byteLength(text, 'utf8') <= MAX_RECEIPT_JSON_STRING_BYTES
1339
+ && !/[\0]/.test(text)
1340
+ ? text
1341
+ : null;
1342
+ }
1343
+ function hostToolResponseFailed(value) {
1344
+ if (!isRecord(value))
1345
+ return false;
1346
+ if (value.isError === true || value.is_error === true || value.ok === false || value.success === false)
1347
+ return true;
1348
+ const status = String(value.status || '').trim().toLowerCase();
1349
+ return status === 'failed' || status === 'error';
1350
+ }
1351
+ function boundedIdentity(value) {
1352
+ const text = typeof value === 'string' ? value.trim() : '';
1353
+ return text && text.length <= 256 && !/[\r\n\0]/.test(text) ? text : null;
1354
+ }
1355
+ function parseJsonObject(value) {
1356
+ if (isRecord(value))
1357
+ return value;
1358
+ if (typeof value !== 'string' || !value.trim())
1359
+ return null;
1360
+ const trimmed = value.trim();
1361
+ const fenced = /^```(?:json)?\s*([\s\S]*?)\s*```$/i.exec(trimmed)?.[1]?.trim();
1362
+ for (const candidate of [trimmed, ...(fenced ? [fenced] : [])]) {
1363
+ try {
1364
+ const parsed = JSON.parse(candidate);
1365
+ if (isRecord(parsed))
1366
+ return parsed;
1367
+ }
1368
+ catch { }
1369
+ }
1370
+ return null;
1371
+ }
1372
+ function uniqueStrings(values) {
1373
+ return [...new Set(values.map((value) => String(value || '').trim()).filter(Boolean))].sort();
1374
+ }
1375
+ function arrayStrings(value) {
1376
+ return Array.isArray(value)
1377
+ ? value.map((item) => String(item || '').trim()).filter(Boolean)
1378
+ : [];
1379
+ }
1380
+ function uniqueWorkflows(values) {
1381
+ const valid = new Set([
1382
+ 'datasource_sql_generation',
1383
+ 'datasource_query',
1384
+ 'spreadsheet_create',
1385
+ 'spreadsheet_edit',
1386
+ 'document_render',
1387
+ 'web_capture',
1388
+ 'workspace_files',
1389
+ 'artifact_delivery'
1390
+ ]);
1391
+ return uniqueStrings(values).filter((value) => valid.has(value));
1392
+ }
1393
+ function isRecord(value) {
1394
+ return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
1395
+ }