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
@@ -1,9 +1,13 @@
1
+ import { constants as fsConstants } from 'node:fs';
1
2
  import fsp from 'node:fs/promises';
2
3
  import path from 'node:path';
4
+ import { createHash } from 'node:crypto';
3
5
  import { sha256 } from '../fsx.js';
4
- import { SUBAGENT_EVIDENCE_FILENAME, SUBAGENT_EVENT_LOG_FILENAME, SUBAGENT_PARENT_SUMMARY_FILENAME, buildSubagentEvidence, normalizeSubagentEvent, normalizeSubagentParentSummary } from './subagent-evidence.js';
6
+ import { SUBAGENT_EVIDENCE_FILENAME, SUBAGENT_EVENT_LOG_FILENAME, SUBAGENT_PARENT_SUMMARY_FILENAME, buildSubagentEvidence, normalizeSubagentEvent, normalizeSubagentParentSummary, trustedHostCapabilityReceiptBindingBlockers } from './subagent-evidence.js';
5
7
  import { NARUTO_GATE_FILENAME, NARUTO_RESULT_SCHEMA, NARUTO_SUMMARY_FILENAME, SUBAGENT_PLAN_FILENAME } from './official-subagent-preparation.js';
6
8
  import { effectiveSubagentTarget, normalizeLegacySubagentCountFields, subagentCountContractBlockers } from './wave-lifecycle.js';
9
+ import { HOST_CAPABILITY_DESCRIPTORS, hostCapabilityDigest } from '../agent-bridge/agent-manifest.js';
10
+ import { HOST_CAPABILITY_EVIDENCE_SCHEMA, HOST_CAPABILITY_RUNTIME_SCHEMA } from '../agent-bridge/host-capability-runtime.js';
7
11
  export const NARUTO_PROOF_ARTIFACT_FILENAMES = Object.freeze([
8
12
  SUBAGENT_PLAN_FILENAME,
9
13
  SUBAGENT_EVENT_LOG_FILENAME,
@@ -17,6 +21,25 @@ const MAX_CHANGED_FILES = 256;
17
21
  const MAX_CHANGED_FILE_CHARS = 512;
18
22
  const MAX_VERIFICATION_ROWS = 32;
19
23
  const MAX_VERIFICATION_NAME_CHARS = 240;
24
+ const MAX_ARTIFACTS = 64;
25
+ const MAX_ARTIFACT_PATH_CHARS = 512;
26
+ const MAX_ARTIFACT_KIND_CHARS = 64;
27
+ const MAX_MEDIA_TYPE_CHARS = 160;
28
+ const MAX_CAPABILITY_USES = 64;
29
+ const MAX_CAPABILITY_ID_CHARS = 160;
30
+ const MAX_CAPABILITY_TOOL_NAMES = 64;
31
+ const MAX_CAPABILITY_TOOL_NAME_CHARS = 128;
32
+ const MAX_CANONICAL_PROOF_ARTIFACT_BYTES = 4 * 1024 * 1024;
33
+ const MAX_CANONICAL_PROOF_AGGREGATE_BYTES = 16 * 1024 * 1024;
34
+ const MAX_DELIVERABLE_ARTIFACT_BYTES = 128 * 1024 * 1024;
35
+ const MAX_DELIVERABLE_ARTIFACT_AGGREGATE_BYTES = 512 * 1024 * 1024;
36
+ const SHA256_RECEIPT_PATTERN = /^sha256:[a-f0-9]{64}$/;
37
+ const ARTIFACT_ROLES = new Set(['deliverable', 'scratch', 'temp', 'log']);
38
+ const NON_DELIVERABLE_ARTIFACT_KINDS = new Set(['scratch', 'temp', 'tmp', 'log']);
39
+ const NON_DELIVERABLE_PATH_SEGMENTS = new Set(['scratch', 'temp', 'tmp', 'log', 'logs']);
40
+ const ARTIFACT_RECEIPT_KEYS = new Set(['path', 'kind', 'media_type', 'sha256', 'bytes', 'role']);
41
+ const CAPABILITY_USE_KEYS = new Set(['id', 'status', 'tool_names', 'receipt_sha256']);
42
+ const HOST_CAPABILITY_BY_ID = new Map(HOST_CAPABILITY_DESCRIPTORS.map((descriptor) => [descriptor.id, descriptor]));
20
43
  const INCOMPLETE_BLOCKER_PATTERNS = [
21
44
  /^proof_artifact_missing:/,
22
45
  /^requested_subagent_(?:starts|completions)_incomplete:/,
@@ -28,7 +51,14 @@ const INCOMPLETE_BLOCKER_PATTERNS = [
28
51
  export async function readNarutoProofArtifactSnapshot(artifactDir) {
29
52
  const rows = await Promise.all(NARUTO_PROOF_ARTIFACT_FILENAMES.map(async (filename) => {
30
53
  try {
31
- return { filename, bytes: await fsp.readFile(path.join(artifactDir, filename)), blocker: null };
54
+ const file = path.join(artifactDir, filename);
55
+ const stat = await fsp.stat(file);
56
+ if (!stat.isFile())
57
+ return { filename, bytes: null, blocker: `proof_artifact_unreadable:${filename}` };
58
+ if (stat.size > MAX_CANONICAL_PROOF_ARTIFACT_BYTES) {
59
+ return { filename, bytes: null, blocker: `proof_artifact_too_large:${filename}` };
60
+ }
61
+ return { filename, bytes: await fsp.readFile(file), blocker: null };
32
62
  }
33
63
  catch (error) {
34
64
  const code = errorCode(error);
@@ -44,24 +74,54 @@ export async function readNarutoProofArtifactSnapshot(artifactDir) {
44
74
  const bytes = {};
45
75
  const byteHashes = {};
46
76
  const blockers = [];
77
+ let aggregateBytes = 0;
47
78
  for (const row of rows) {
48
79
  bytes[row.filename] = row.bytes;
49
80
  byteHashes[row.filename] = row.bytes ? `sha256:${sha256(row.bytes)}` : null;
81
+ aggregateBytes += row.bytes?.length || 0;
50
82
  if (row.blocker)
51
83
  blockers.push(row.blocker);
52
84
  }
85
+ if (aggregateBytes > MAX_CANONICAL_PROOF_AGGREGATE_BYTES)
86
+ blockers.push('proof_artifacts_aggregate_too_large');
53
87
  return { bytes, byte_hashes: byteHashes, read_blockers: blockers };
54
88
  }
55
89
  export async function buildNarutoProofProjection(input) {
56
90
  const snapshot = await readNarutoProofArtifactSnapshot(input.artifactDir);
57
- return projectNarutoProofSnapshot({ snapshot, missionId: input.missionId });
91
+ const projected = projectNarutoProofSnapshot({ snapshot, missionId: input.missionId });
92
+ if (!projected.result.artifacts?.length)
93
+ return projected;
94
+ const artifactBlockers = await verifyProjectedArtifactFiles({
95
+ artifacts: projected.result.artifacts,
96
+ artifactDir: input.artifactDir,
97
+ workspaceRoot: input.workspaceRoot
98
+ });
99
+ if (artifactBlockers.length === 0)
100
+ return projected;
101
+ return projectNarutoProofSnapshot({
102
+ snapshot: {
103
+ ...snapshot,
104
+ read_blockers: [...snapshot.read_blockers, ...artifactBlockers]
105
+ },
106
+ missionId: input.missionId
107
+ });
58
108
  }
59
109
  export function projectNarutoProofSnapshot(input) {
60
110
  const missionId = String(input.missionId || '').trim();
61
- const blockers = [...input.snapshot.read_blockers];
111
+ const readBlockers = input.snapshot.read_blockers;
112
+ const blockers = Array.isArray(readBlockers)
113
+ ? readBlockers.filter((blocker) => typeof blocker === 'string')
114
+ : ['proof_read_blockers_invalid'];
115
+ if (Array.isArray(readBlockers) && blockers.length !== readBlockers.length)
116
+ blockers.push('proof_read_blockers_invalid');
62
117
  const plan = parseJsonArtifact(input.snapshot, SUBAGENT_PLAN_FILENAME, blockers);
63
118
  const parentSummaryValue = parseJsonArtifact(input.snapshot, SUBAGENT_PARENT_SUMMARY_FILENAME, blockers);
64
119
  const persistedEvidence = normalizeLegacySubagentCountFields(parseJsonArtifact(input.snapshot, SUBAGENT_EVIDENCE_FILENAME, blockers), isRecord(plan) ? plan : null);
120
+ const receiptProjectedPersistedEvidence = projectReceiptAdditiveFields(SUBAGENT_EVIDENCE_FILENAME, persistedEvidence);
121
+ const trustedHostCapabilityEvidence = projectTrustedHostCapabilityEvidence(recordValue(receiptProjectedPersistedEvidence, 'host_capability_evidence'), blockers);
122
+ const projectedPersistedEvidence = isRecord(receiptProjectedPersistedEvidence) && trustedHostCapabilityEvidence
123
+ ? { ...receiptProjectedPersistedEvidence, host_capability_evidence: trustedHostCapabilityEvidence }
124
+ : receiptProjectedPersistedEvidence;
65
125
  const summary = normalizeLegacySubagentCountFields(parseJsonArtifact(input.snapshot, NARUTO_SUMMARY_FILENAME, blockers), isRecord(plan) ? plan : null);
66
126
  const gate = normalizeLegacySubagentCountFields(parseJsonArtifact(input.snapshot, NARUTO_GATE_FILENAME, blockers), isRecord(plan) ? plan : null);
67
127
  const events = parseJsonlArtifact(input.snapshot, blockers);
@@ -100,6 +160,7 @@ export function projectNarutoProofSnapshot(input) {
100
160
  workflowStatus: firstText(recordValue(summary, 'status')),
101
161
  preparationOnly: recordValue(persistedEvidence, 'preparation_only') === true,
102
162
  runId: workflowRunId,
163
+ ...(trustedHostCapabilityEvidence ? { hostCapabilityEvidence: trustedHostCapabilityEvidence } : {}),
103
164
  additionalBlockers: subagentCountContractBlockers(isRecord(plan) ? plan : null, observedStarts)
104
165
  });
105
166
  if (planRequestedSubagents === null && plan !== null)
@@ -108,9 +169,42 @@ export function projectNarutoProofSnapshot(input) {
108
169
  && input.snapshot.bytes[SUBAGENT_EVENT_LOG_FILENAME] !== null
109
170
  && input.snapshot.bytes[SUBAGENT_PARENT_SUMMARY_FILENAME] !== null;
110
171
  if (evidenceInputsPresent)
111
- validatePersistedEvidence(persistedEvidence, rebuiltEvidence, blockers);
172
+ validatePersistedEvidence(projectedPersistedEvidence, rebuiltEvidence, blockers);
112
173
  const changedFiles = projectChangedFiles(normalizedParentSummary.raw?.changed_files, blockers);
113
174
  const verification = projectVerification(normalizedParentSummary.raw?.verification, blockers);
175
+ const parentArtifacts = projectArtifacts(recordValue(parentSummaryValue, 'artifacts'), blockers);
176
+ const parentCapabilitiesUsed = projectCapabilityUses(recordValue(parentSummaryValue, 'capabilities_used'), blockers);
177
+ const trustedArtifacts = trustedHostCapabilityEvidence
178
+ ? projectArtifacts(trustedHostCapabilityEvidence.artifacts, blockers) || []
179
+ : undefined;
180
+ const trustedCapabilitiesUsed = trustedHostCapabilityEvidence
181
+ ? projectCapabilityUses(trustedHostCapabilityEvidence.capabilities_used, blockers) || []
182
+ : undefined;
183
+ const rawParentArtifacts = recordValue(parentSummaryValue, 'artifacts');
184
+ const rawParentCapabilitiesUsed = recordValue(parentSummaryValue, 'capabilities_used');
185
+ const parentHostClaimsPresent = hasNonEmptyHostCapabilityClaim(rawParentArtifacts)
186
+ || hasNonEmptyHostCapabilityClaim(rawParentCapabilitiesUsed);
187
+ const trustedHostBindingRequired = Boolean(trustedHostCapabilityEvidence && (trustedHostCapabilityEvidence.runtime.requested_capability_ids.length > 0
188
+ || trustedHostCapabilityEvidence.tool_calls.length > 0
189
+ || trustedHostCapabilityEvidence.artifacts.length > 0
190
+ || parentHostClaimsPresent));
191
+ if (trustedHostCapabilityEvidence) {
192
+ if (trustedHostBindingRequired && JSON.stringify(parentArtifacts || []) !== JSON.stringify(trustedArtifacts || [])) {
193
+ blockers.push('proof_parent_host_artifacts_mismatch');
194
+ }
195
+ if (trustedHostBindingRequired && JSON.stringify(parentCapabilitiesUsed || []) !== JSON.stringify(trustedCapabilitiesUsed || [])) {
196
+ blockers.push('proof_parent_host_capabilities_mismatch');
197
+ }
198
+ }
199
+ else if (parentHostClaimsPresent) {
200
+ blockers.push('proof_host_capability_evidence_missing');
201
+ }
202
+ const artifacts = trustedHostBindingRequired ? trustedArtifacts : parentArtifacts;
203
+ const capabilitiesUsed = trustedHostBindingRequired ? trustedCapabilitiesUsed : parentCapabilitiesUsed;
204
+ for (const receipt of capabilitiesUsed || []) {
205
+ if (receipt.status !== 'passed')
206
+ blockers.push(`proof_capability_use_not_passed:${receipt.id}`);
207
+ }
114
208
  const parentText = normalizedParentSummary.summary || '';
115
209
  if (parentText.length > MAX_RESULT_SUMMARY_CHARS)
116
210
  blockers.push('proof_result_summary_too_large');
@@ -123,11 +217,13 @@ export function projectNarutoProofSnapshot(input) {
123
217
  ? parentText
124
218
  : '',
125
219
  changed_files: changedFiles,
126
- verification
220
+ verification,
221
+ ...(artifacts === undefined ? {} : { artifacts }),
222
+ ...(capabilitiesUsed === undefined ? {} : { capabilities_used: capabilitiesUsed })
127
223
  };
128
224
  const completed = gatePassed(gate)
129
- && recordValue(persistedEvidence, 'ok') === true
130
- && firstText(recordValue(persistedEvidence, 'status')).toLowerCase() === 'completed'
225
+ && recordValue(projectedPersistedEvidence, 'ok') === true
226
+ && firstText(recordValue(projectedPersistedEvidence, 'status')).toLowerCase() === 'completed'
131
227
  && rebuiltEvidence?.ok === true
132
228
  && normalizedParentSummary.trustworthy
133
229
  && normalizedParentSummary.status === 'completed'
@@ -138,8 +234,8 @@ export function projectNarutoProofSnapshot(input) {
138
234
  const explicitBlocked = !completed && isExplicitlyBlocked({
139
235
  blockers,
140
236
  parentStatus: normalizedParentSummary.status,
141
- evidenceStatus: firstText(recordValue(persistedEvidence, 'status')),
142
- failedThreads: Number(recordValue(persistedEvidence, 'failed_threads') || 0),
237
+ evidenceStatus: firstText(recordValue(projectedPersistedEvidence, 'status')),
238
+ failedThreads: Number(recordValue(projectedPersistedEvidence, 'failed_threads') || 0),
143
239
  summaryStatus: firstText(recordValue(summary, 'status')),
144
240
  gate
145
241
  });
@@ -151,7 +247,7 @@ export function projectNarutoProofSnapshot(input) {
151
247
  status,
152
248
  missionId,
153
249
  workflowRunId,
154
- artifactHashes: input.snapshot.byte_hashes,
250
+ artifactHashes: projectFingerprintArtifactHashes(input.snapshot),
155
251
  result
156
252
  });
157
253
  return {
@@ -163,13 +259,16 @@ export function projectNarutoProofSnapshot(input) {
163
259
  workflow: 'official_codex_subagent',
164
260
  workflow_run_id: workflowRunId,
165
261
  blockers: uniqueBlockers,
166
- evidence: persistedEvidence,
262
+ evidence: projectedPersistedEvidence,
167
263
  summary,
168
264
  gate,
169
265
  result,
170
266
  proof_fingerprint: proofFingerprint
171
267
  };
172
268
  }
269
+ function hasNonEmptyHostCapabilityClaim(value) {
270
+ return Array.isArray(value) ? value.length > 0 : value !== undefined;
271
+ }
173
272
  export function validateNarutoProofStatus(value) {
174
273
  const status = String(value.status || '').trim();
175
274
  if (status !== 'completed' && status !== 'blocked' && status !== 'incomplete') {
@@ -177,6 +276,202 @@ export function validateNarutoProofStatus(value) {
177
276
  }
178
277
  return value.ok === (status === 'completed') ? [] : ['proof_status_ok_inconsistent'];
179
278
  }
279
+ function projectTrustedHostCapabilityEvidence(value, blockers) {
280
+ if (value === undefined || value === null)
281
+ return null;
282
+ if (!isRecord(value)
283
+ || value.schema !== HOST_CAPABILITY_EVIDENCE_SCHEMA
284
+ || typeof value.ok !== 'boolean'
285
+ || !isRecord(value.runtime)
286
+ || value.runtime.schema !== HOST_CAPABILITY_RUNTIME_SCHEMA
287
+ || value.runtime.server !== 'acas-tools'
288
+ || value.runtime.capability_digest !== hostCapabilityDigest(HOST_CAPABILITY_DESCRIPTORS)
289
+ || !Array.isArray(value.runtime.requested_capability_ids)
290
+ || !Array.isArray(value.runtime.blockers)
291
+ || !Array.isArray(value.tool_calls)
292
+ || !Array.isArray(value.capabilities_used)
293
+ || !Array.isArray(value.artifacts)
294
+ || !Array.isArray(value.blockers)) {
295
+ blockers.push('proof_host_capability_evidence_invalid');
296
+ return null;
297
+ }
298
+ const requestedIds = value.runtime.requested_capability_ids.map((id) => String(id || '').trim());
299
+ if (requestedIds.some((id) => !HOST_CAPABILITY_BY_ID.has(id))
300
+ || new Set(requestedIds).size !== requestedIds.length
301
+ || value.runtime.blockers.some((blocker) => !isBoundedBlockerCode(blocker))
302
+ || value.blockers.some((blocker) => !isBoundedBlockerCode(blocker))) {
303
+ blockers.push('proof_host_capability_runtime_invalid');
304
+ return null;
305
+ }
306
+ const knownTools = new Set(HOST_CAPABILITY_DESCRIPTORS.flatMap((descriptor) => descriptor.tool_names));
307
+ if (value.tool_calls.length > 1024 || value.tool_calls.some((row) => {
308
+ if (!isRecord(row))
309
+ return true;
310
+ return row.server !== 'acas-tools'
311
+ || typeof row.tool !== 'string'
312
+ || !knownTools.has(row.tool)
313
+ || (row.status !== 'passed' && row.status !== 'failed')
314
+ || typeof row.event_sha256 !== 'string'
315
+ || !SHA256_RECEIPT_PATTERN.test(row.event_sha256);
316
+ })) {
317
+ blockers.push('proof_host_capability_tool_calls_invalid');
318
+ return null;
319
+ }
320
+ const receiptBlockers = [];
321
+ const capabilities = projectCapabilityUses(value.capabilities_used, receiptBlockers);
322
+ const artifacts = projectArtifacts(value.artifacts, receiptBlockers);
323
+ if (!capabilities || !artifacts || receiptBlockers.length > 0
324
+ || capabilities.length !== value.capabilities_used.length
325
+ || artifacts.length !== value.artifacts.length) {
326
+ blockers.push(...receiptBlockers, 'proof_host_capability_receipts_invalid');
327
+ return null;
328
+ }
329
+ const observedIds = capabilities.map((receipt) => receipt.id);
330
+ if (JSON.stringify([...observedIds].sort()) !== JSON.stringify([...requestedIds].sort())) {
331
+ blockers.push('proof_host_capability_requested_receipts_mismatch');
332
+ }
333
+ const expectedOk = value.blockers.length === 0 && capabilities.every((receipt) => receipt.status === 'passed');
334
+ if (value.ok !== expectedOk)
335
+ blockers.push('proof_host_capability_evidence_status_inconsistent');
336
+ const bindingBlockers = trustedHostCapabilityReceiptBindingBlockers({
337
+ ...value,
338
+ capabilities_used: capabilities,
339
+ artifacts
340
+ });
341
+ blockers.push(...bindingBlockers.map((blocker) => `proof_${blocker}`));
342
+ blockers.push(...value.blockers);
343
+ return {
344
+ ...value,
345
+ capabilities_used: capabilities,
346
+ artifacts
347
+ };
348
+ }
349
+ async function verifyProjectedArtifactFiles(input) {
350
+ const workspaceRoot = await resolveArtifactWorkspaceRoot(input.artifactDir, input.workspaceRoot);
351
+ if (!workspaceRoot)
352
+ return ['proof_artifact_workspace_root_missing'];
353
+ const blockers = [];
354
+ for (const artifact of input.artifacts) {
355
+ blockers.push(...await verifyProjectedArtifactFile(workspaceRoot, artifact));
356
+ }
357
+ return uniqueStrings(blockers);
358
+ }
359
+ async function resolveArtifactWorkspaceRoot(artifactDir, explicitRoot) {
360
+ let candidate = explicitRoot ? path.resolve(explicitRoot) : '';
361
+ if (!candidate) {
362
+ let cursor = path.resolve(artifactDir);
363
+ while (true) {
364
+ if (path.basename(cursor) === '.sneakoscope') {
365
+ candidate = path.dirname(cursor);
366
+ break;
367
+ }
368
+ const parent = path.dirname(cursor);
369
+ if (parent === cursor)
370
+ break;
371
+ cursor = parent;
372
+ }
373
+ }
374
+ if (!candidate)
375
+ return null;
376
+ try {
377
+ const realRoot = await fsp.realpath(candidate);
378
+ return (await fsp.stat(realRoot)).isDirectory() ? realRoot : null;
379
+ }
380
+ catch {
381
+ return null;
382
+ }
383
+ }
384
+ async function verifyProjectedArtifactFile(workspaceRoot, artifact) {
385
+ if (artifact.bytes > MAX_DELIVERABLE_ARTIFACT_BYTES)
386
+ return ['proof_artifact_file_too_large'];
387
+ const segments = artifact.path.split('/');
388
+ const candidate = path.join(workspaceRoot, ...segments);
389
+ if (!pathWithinRoot(workspaceRoot, candidate))
390
+ return ['proof_artifact_file_escape'];
391
+ let cursor = workspaceRoot;
392
+ for (let index = 0; index < segments.length; index += 1) {
393
+ cursor = path.join(cursor, segments[index]);
394
+ try {
395
+ const stat = await fsp.lstat(cursor);
396
+ if (stat.isSymbolicLink())
397
+ return ['proof_artifact_file_symlink'];
398
+ if (index < segments.length - 1 && !stat.isDirectory())
399
+ return ['proof_artifact_file_not_regular'];
400
+ if (index === segments.length - 1 && !stat.isFile())
401
+ return ['proof_artifact_file_not_regular'];
402
+ }
403
+ catch (error) {
404
+ return [errorCode(error) === 'ENOENT' ? 'proof_artifact_file_missing' : 'proof_artifact_file_unreadable'];
405
+ }
406
+ }
407
+ try {
408
+ const realCandidate = await fsp.realpath(candidate);
409
+ if (!pathWithinRoot(workspaceRoot, realCandidate))
410
+ return ['proof_artifact_file_escape'];
411
+ const expected = await fsp.stat(realCandidate);
412
+ if (expected.size > MAX_DELIVERABLE_ARTIFACT_BYTES)
413
+ return ['proof_artifact_file_too_large'];
414
+ const handle = await fsp.open(candidate, fsConstants.O_RDONLY | fsConstants.O_NOFOLLOW);
415
+ try {
416
+ const before = await handle.stat();
417
+ if (!before.isFile())
418
+ return ['proof_artifact_file_not_regular'];
419
+ if (before.dev !== expected.dev || before.ino !== expected.ino) {
420
+ return ['proof_artifact_file_changed_during_hash'];
421
+ }
422
+ const header = Buffer.alloc(8);
423
+ const headerRead = await handle.read(header, 0, header.length, 0);
424
+ const digest = createHash('sha256');
425
+ for await (const chunk of handle.createReadStream({ autoClose: false, start: 0 }))
426
+ digest.update(chunk);
427
+ const after = await handle.stat();
428
+ const finalPathStat = await fsp.lstat(candidate);
429
+ if (finalPathStat.isSymbolicLink())
430
+ return ['proof_artifact_file_symlink'];
431
+ if (before.dev !== after.dev
432
+ || before.ino !== after.ino
433
+ || before.size !== after.size
434
+ || before.mtimeMs !== after.mtimeMs
435
+ || finalPathStat.dev !== after.dev
436
+ || finalPathStat.ino !== after.ino) {
437
+ return ['proof_artifact_file_changed_during_hash'];
438
+ }
439
+ const blockers = [];
440
+ if (after.size !== artifact.bytes)
441
+ blockers.push('proof_artifact_file_bytes_mismatch');
442
+ if (`sha256:${digest.digest('hex')}` !== artifact.sha256)
443
+ blockers.push('proof_artifact_file_sha256_mismatch');
444
+ blockers.push(...artifactSignatureBlockers(artifact, header.subarray(0, headerRead.bytesRead)));
445
+ return blockers;
446
+ }
447
+ finally {
448
+ await handle.close();
449
+ }
450
+ }
451
+ catch (error) {
452
+ return [errorCode(error) === 'ELOOP' ? 'proof_artifact_file_symlink' : 'proof_artifact_file_unreadable'];
453
+ }
454
+ }
455
+ function artifactSignatureBlockers(artifact, header) {
456
+ if (artifact.media_type === 'application/pdf') {
457
+ return header.subarray(0, 5).equals(Buffer.from('%PDF-')) ? [] : ['proof_artifact_pdf_signature_invalid'];
458
+ }
459
+ if (artifact.media_type === 'image/png') {
460
+ const png = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
461
+ return header.subarray(0, png.length).equals(png) ? [] : ['proof_artifact_png_signature_invalid'];
462
+ }
463
+ if (artifact.media_type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') {
464
+ const zipLocalHeader = Buffer.from([0x50, 0x4b, 0x03, 0x04]);
465
+ return header.subarray(0, zipLocalHeader.length).equals(zipLocalHeader)
466
+ ? []
467
+ : ['proof_artifact_xlsx_signature_invalid'];
468
+ }
469
+ return [];
470
+ }
471
+ function pathWithinRoot(root, candidate) {
472
+ const relative = path.relative(root, candidate);
473
+ return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));
474
+ }
180
475
  function parseJsonArtifact(snapshot, filename, blockers) {
181
476
  const bytes = snapshot.bytes[filename];
182
477
  if (!bytes)
@@ -275,6 +570,9 @@ function validatePersistedEvidence(persisted, rebuilt, blockers) {
275
570
  blockers.push(`proof_evidence_rebuild_mismatch:${key}`);
276
571
  }
277
572
  }
573
+ if (JSON.stringify(persisted.host_capability_evidence) !== JSON.stringify(rebuilt.host_capability_evidence)) {
574
+ blockers.push('proof_evidence_rebuild_mismatch:host_capability_evidence');
575
+ }
278
576
  }
279
577
  function validateCountContractArtifacts(input, blockers) {
280
578
  for (const [label, value] of [
@@ -361,6 +659,210 @@ function projectVerificationRow(value) {
361
659
  const rawStatus = isRecord(value) ? firstText(value.status) : '';
362
660
  return { name, status: normalizeVerificationStatus(rawStatus, name) };
363
661
  }
662
+ function projectArtifacts(value, blockers) {
663
+ if (value === undefined)
664
+ return undefined;
665
+ if (!Array.isArray(value)) {
666
+ blockers.push('proof_artifacts_invalid');
667
+ return [];
668
+ }
669
+ if (value.length > MAX_ARTIFACTS)
670
+ blockers.push('proof_artifacts_too_many');
671
+ const result = [];
672
+ const seenPaths = new Set();
673
+ let aggregateBytes = 0;
674
+ for (const row of value.slice(0, MAX_ARTIFACTS)) {
675
+ if (!isRecord(row)) {
676
+ blockers.push('proof_artifact_invalid');
677
+ continue;
678
+ }
679
+ const artifactPath = normalizeArtifactPath(row.path, blockers);
680
+ const kind = boundedToken(row.kind, MAX_ARTIFACT_KIND_CHARS, /^[a-z][a-z0-9_-]*$/);
681
+ const mediaType = boundedToken(row.media_type, MAX_MEDIA_TYPE_CHARS, /^[a-z0-9][a-z0-9!#$&^_.+-]*\/[a-z0-9][a-z0-9!#$&^_.+-]*$/i);
682
+ const artifactSha256 = typeof row.sha256 === 'string' && SHA256_RECEIPT_PATTERN.test(row.sha256)
683
+ ? row.sha256
684
+ : null;
685
+ const bytes = typeof row.bytes === 'number' && Number.isSafeInteger(row.bytes) && row.bytes > 0
686
+ ? row.bytes
687
+ : null;
688
+ const role = typeof row.role === 'string' && ARTIFACT_ROLES.has(row.role)
689
+ ? row.role
690
+ : null;
691
+ if (!kind)
692
+ blockers.push('proof_artifact_kind_invalid');
693
+ if (!mediaType)
694
+ blockers.push('proof_artifact_media_type_invalid');
695
+ if (!artifactSha256)
696
+ blockers.push('proof_artifact_sha256_invalid');
697
+ if (bytes === null)
698
+ blockers.push('proof_artifact_bytes_invalid');
699
+ if (bytes !== null && bytes > MAX_DELIVERABLE_ARTIFACT_BYTES)
700
+ blockers.push('proof_artifact_bytes_too_large');
701
+ if (!role)
702
+ blockers.push('proof_artifact_role_invalid');
703
+ if (!artifactPath || !kind || !mediaType || !artifactSha256 || bytes === null || !role)
704
+ continue;
705
+ if (seenPaths.has(artifactPath)) {
706
+ blockers.push('proof_artifact_path_duplicate');
707
+ continue;
708
+ }
709
+ if (role === 'deliverable' && isNonDeliverableArtifact(artifactPath, kind)) {
710
+ blockers.push('proof_artifact_deliverable_role_invalid');
711
+ continue;
712
+ }
713
+ blockers.push(...artifactMediaConsistencyBlockers(artifactPath, mediaType));
714
+ seenPaths.add(artifactPath);
715
+ aggregateBytes += bytes;
716
+ result.push({ path: artifactPath, kind, media_type: mediaType, sha256: artifactSha256, bytes, role });
717
+ }
718
+ if (aggregateBytes > MAX_DELIVERABLE_ARTIFACT_AGGREGATE_BYTES)
719
+ blockers.push('proof_artifact_bytes_aggregate_too_large');
720
+ return result;
721
+ }
722
+ function normalizeArtifactPath(value, blockers) {
723
+ if (typeof value !== 'string') {
724
+ blockers.push('proof_artifact_path_invalid');
725
+ return null;
726
+ }
727
+ const original = value.trim();
728
+ if (!original || original.length > MAX_ARTIFACT_PATH_CHARS || /[\r\n\0]/.test(original)) {
729
+ blockers.push('proof_artifact_path_invalid');
730
+ return null;
731
+ }
732
+ if (original.includes('\\')) {
733
+ blockers.push('proof_artifact_path_not_posix');
734
+ return null;
735
+ }
736
+ if (path.posix.isAbsolute(original) || path.win32.isAbsolute(original)) {
737
+ blockers.push('proof_artifact_path_absolute');
738
+ return null;
739
+ }
740
+ const normalized = path.posix.normalize(original).replace(/^\.\//, '');
741
+ if (!normalized || normalized === '.' || normalized === '..' || normalized.startsWith('../')) {
742
+ blockers.push('proof_artifact_path_escape');
743
+ return null;
744
+ }
745
+ if (normalized.length > MAX_ARTIFACT_PATH_CHARS) {
746
+ blockers.push('proof_artifact_path_invalid');
747
+ return null;
748
+ }
749
+ return normalized;
750
+ }
751
+ function isNonDeliverableArtifact(artifactPath, kind) {
752
+ if (NON_DELIVERABLE_ARTIFACT_KINDS.has(kind.toLowerCase()))
753
+ return true;
754
+ const segments = artifactPath.toLowerCase().split('/');
755
+ return segments.some((segment) => NON_DELIVERABLE_PATH_SEGMENTS.has(segment))
756
+ || artifactPath.toLowerCase().endsWith('.log');
757
+ }
758
+ function artifactMediaConsistencyBlockers(artifactPath, mediaType) {
759
+ const extension = path.posix.extname(artifactPath).toLowerCase();
760
+ const expectedByExtension = {
761
+ '.csv': 'text/csv',
762
+ '.pdf': 'application/pdf',
763
+ '.png': 'image/png',
764
+ '.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
765
+ };
766
+ const expectedExtensionsByMedia = {
767
+ 'text/csv': ['.csv'],
768
+ 'application/pdf': ['.pdf'],
769
+ 'image/png': ['.png'],
770
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': ['.xlsx']
771
+ };
772
+ const blockers = [];
773
+ const expectedMedia = expectedByExtension[extension];
774
+ if (expectedMedia && mediaType !== expectedMedia)
775
+ blockers.push('proof_artifact_media_extension_mismatch');
776
+ const expectedExtensions = expectedExtensionsByMedia[mediaType];
777
+ if (expectedExtensions && !expectedExtensions.includes(extension))
778
+ blockers.push('proof_artifact_extension_media_mismatch');
779
+ return blockers;
780
+ }
781
+ function projectCapabilityUses(value, blockers) {
782
+ if (value === undefined)
783
+ return undefined;
784
+ if (!Array.isArray(value)) {
785
+ blockers.push('proof_capabilities_used_invalid');
786
+ return [];
787
+ }
788
+ if (value.length > MAX_CAPABILITY_USES)
789
+ blockers.push('proof_capabilities_used_too_many');
790
+ const result = [];
791
+ const seenIds = new Set();
792
+ for (const row of value.slice(0, MAX_CAPABILITY_USES)) {
793
+ if (!isRecord(row)) {
794
+ blockers.push('proof_capability_use_invalid');
795
+ continue;
796
+ }
797
+ const id = boundedToken(row.id, MAX_CAPABILITY_ID_CHARS, /^[a-z][a-z0-9._-]*$/);
798
+ const descriptor = id ? HOST_CAPABILITY_BY_ID.get(id) : undefined;
799
+ const status = normalizeCapabilityStatus(row.status);
800
+ const toolNames = projectCapabilityToolNames(row.tool_names, descriptor?.tool_names || [], status, blockers);
801
+ const receiptSha256 = typeof row.receipt_sha256 === 'string' && SHA256_RECEIPT_PATTERN.test(row.receipt_sha256)
802
+ ? row.receipt_sha256
803
+ : null;
804
+ if (!id)
805
+ blockers.push('proof_capability_use_id_invalid');
806
+ else if (!descriptor)
807
+ blockers.push('proof_capability_use_unknown_id');
808
+ if (!status)
809
+ blockers.push('proof_capability_use_status_invalid');
810
+ if (!receiptSha256)
811
+ blockers.push('proof_capability_use_receipt_sha256_invalid');
812
+ if (!id || !descriptor || !status || !toolNames || !receiptSha256)
813
+ continue;
814
+ if (seenIds.has(id)) {
815
+ blockers.push('proof_capability_use_duplicate');
816
+ continue;
817
+ }
818
+ seenIds.add(id);
819
+ result.push({ id, status, tool_names: toolNames, receipt_sha256: receiptSha256 });
820
+ }
821
+ return result;
822
+ }
823
+ function projectCapabilityToolNames(value, allowedToolNames, status, blockers) {
824
+ if (!Array.isArray(value) || (status === 'passed' && value.length === 0)) {
825
+ blockers.push('proof_capability_use_tool_names_invalid');
826
+ return null;
827
+ }
828
+ if (value.length > MAX_CAPABILITY_TOOL_NAMES) {
829
+ blockers.push('proof_capability_use_tool_names_too_many');
830
+ return null;
831
+ }
832
+ const result = [];
833
+ const seen = new Set();
834
+ const allowed = new Set(allowedToolNames);
835
+ for (const valueItem of value) {
836
+ const toolName = boundedToken(valueItem, MAX_CAPABILITY_TOOL_NAME_CHARS, /^[A-Za-z][A-Za-z0-9_.:-]*$/);
837
+ if (!toolName) {
838
+ blockers.push('proof_capability_use_tool_name_invalid');
839
+ return null;
840
+ }
841
+ if (seen.has(toolName)) {
842
+ blockers.push('proof_capability_use_tool_name_duplicate');
843
+ return null;
844
+ }
845
+ if (!allowed.has(toolName)) {
846
+ blockers.push('proof_capability_use_tool_name_not_declared');
847
+ return null;
848
+ }
849
+ seen.add(toolName);
850
+ result.push(toolName);
851
+ }
852
+ return result;
853
+ }
854
+ function normalizeCapabilityStatus(value) {
855
+ const status = typeof value === 'string' ? value.trim().toLowerCase() : '';
856
+ return status === 'passed' || status === 'failed' ? status : null;
857
+ }
858
+ function boundedToken(value, maxChars, pattern) {
859
+ if (typeof value !== 'string')
860
+ return null;
861
+ const text = value.trim();
862
+ if (!text || text.length > maxChars || containsLeakageMarker(text) || !pattern.test(text))
863
+ return null;
864
+ return text;
865
+ }
364
866
  function normalizeVerificationStatus(value, name) {
365
867
  const normalized = value.trim().toLowerCase();
366
868
  if (normalized === 'passed' || normalized === 'pass' || normalized === 'ok' || normalized === 'verified')
@@ -391,6 +893,12 @@ function containsLeakageMarker(value) {
391
893
  return /(?:^|\s)(?:prompt|system_prompt|user_prompt|stdout|stderr|environment|env_dump)\s*[:=]/i.test(value)
392
894
  || /\b(?:api[_-]?key|access[_-]?token|secret|password)\s*[:=]/i.test(value);
393
895
  }
896
+ function isBoundedBlockerCode(value) {
897
+ return typeof value === 'string'
898
+ && value.length > 0
899
+ && value.length <= 240
900
+ && /^[A-Za-z0-9_.:-]+$/.test(value);
901
+ }
394
902
  function isExplicitlyBlocked(input) {
395
903
  if (input.parentStatus === 'blocked' || input.parentStatus === 'failed' || input.failedThreads > 0)
396
904
  return true;
@@ -420,6 +928,66 @@ function fingerprintProof(input) {
420
928
  };
421
929
  return `sha256:${sha256(JSON.stringify(stableInput))}`;
422
930
  }
931
+ function projectFingerprintArtifactHashes(snapshot) {
932
+ const hashes = { ...snapshot.byte_hashes };
933
+ for (const filename of [SUBAGENT_PARENT_SUMMARY_FILENAME, SUBAGENT_EVIDENCE_FILENAME]) {
934
+ const bytes = snapshot.bytes[filename];
935
+ if (!bytes)
936
+ continue;
937
+ let parsed;
938
+ try {
939
+ parsed = JSON.parse(bytes.toString('utf8'));
940
+ }
941
+ catch {
942
+ continue;
943
+ }
944
+ const projected = projectReceiptAdditiveFields(filename, parsed);
945
+ if (projected === parsed)
946
+ continue;
947
+ hashes[filename] = `sha256:${sha256(`${JSON.stringify(projected, null, 2)}\n`)}`;
948
+ }
949
+ return hashes;
950
+ }
951
+ function projectReceiptAdditiveFields(filename, value) {
952
+ if (!isRecord(value))
953
+ return value;
954
+ if (filename === SUBAGENT_PARENT_SUMMARY_FILENAME) {
955
+ return projectReceiptContainerAdditiveFields(value);
956
+ }
957
+ const hostEvidence = recordValue(value, 'host_capability_evidence');
958
+ if (!isRecord(hostEvidence))
959
+ return value;
960
+ const projectedHostEvidence = projectReceiptContainerAdditiveFields(hostEvidence);
961
+ return projectedHostEvidence === hostEvidence
962
+ ? value
963
+ : { ...value, host_capability_evidence: projectedHostEvidence };
964
+ }
965
+ function projectReceiptContainerAdditiveFields(value) {
966
+ const artifacts = projectReceiptRowsAdditiveFields(value.artifacts, ARTIFACT_RECEIPT_KEYS);
967
+ const capabilitiesUsed = projectReceiptRowsAdditiveFields(value.capabilities_used, CAPABILITY_USE_KEYS);
968
+ if (artifacts === value.artifacts && capabilitiesUsed === value.capabilities_used)
969
+ return value;
970
+ return {
971
+ ...value,
972
+ ...(artifacts === value.artifacts ? {} : { artifacts }),
973
+ ...(capabilitiesUsed === value.capabilities_used ? {} : { capabilities_used: capabilitiesUsed })
974
+ };
975
+ }
976
+ function projectReceiptRowsAdditiveFields(value, allowedKeys) {
977
+ if (!Array.isArray(value))
978
+ return value;
979
+ let changed = false;
980
+ const projected = value.map((row) => {
981
+ if (!isRecord(row))
982
+ return row;
983
+ const unknownKeys = Object.keys(row).filter((key) => !allowedKeys.has(key));
984
+ if (unknownKeys.length === 0)
985
+ return row;
986
+ changed = true;
987
+ return Object.fromEntries(Object.entries(row).filter(([key]) => allowedKeys.has(key)));
988
+ });
989
+ return changed ? projected : value;
990
+ }
423
991
  function recordValue(value, key) {
424
992
  return isRecord(value) ? value[key] : undefined;
425
993
  }