2sagaco48 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (365) hide show
  1. package/diagnostics.mjs +141 -0
  2. package/dist/compute.worker-j5ahIpF-.js +1 -0
  3. package/dist/graph.worker-DG6iGCB9.js +1 -0
  4. package/dist/index.html +2314 -0
  5. package/flatten-guide.md +248 -0
  6. package/index.html +12 -0
  7. package/package.json +38 -0
  8. package/src/App.orig.tsx +204 -0
  9. package/src/App.orig1.tsx +27 -0
  10. package/src/App.orig2.tsx +25 -0
  11. package/src/App.tsx +3 -0
  12. package/src/BaseApp.tsx +18 -0
  13. package/src/INTEGRATION_LEDGER.md +22 -0
  14. package/src/PERSIST_CANARY.orig.txt +1 -0
  15. package/src/PERSIST_CANARY.txt +1 -0
  16. package/src/REGRESSION_LEDGER.md +651 -0
  17. package/src/TEMPLATE_PIPELINE_AUDIT.md +208 -0
  18. package/src/WILLIAMS_PERSONA_GUIDE.md +62 -0
  19. package/src/chat/VeritasChat.tsx +69 -0
  20. package/src/chat/synthesis.ts +31 -0
  21. package/src/chat/tier.ts +45 -0
  22. package/src/components/AdaptersPage.orig.tsx +99 -0
  23. package/src/components/AdaptersPage.tsx +3 -0
  24. package/src/components/AdversarialPanel.tsx +136 -0
  25. package/src/components/AnchorBaselinePanel.tsx +75 -0
  26. package/src/components/AnswerPanel.tsx +60 -0
  27. package/src/components/ArtifactPanel.tsx +43 -0
  28. package/src/components/ChatApp.orig.tsx +1582 -0
  29. package/src/components/ChatApp.orig1.tsx +722 -0
  30. package/src/components/ChatApp.tsx +95 -0
  31. package/src/components/ChatAugmentPanels.tsx +73 -0
  32. package/src/components/CitationLedgerPanel.tsx +313 -0
  33. package/src/components/ComputeSandboxPanel.tsx +130 -0
  34. package/src/components/ConfigPanel.tsx +110 -0
  35. package/src/components/ControlPlanePage.tsx +195 -0
  36. package/src/components/CreativeTreeLifePage.tsx +234 -0
  37. package/src/components/CreativeTreeOfLifePanel.tsx +149 -0
  38. package/src/components/DebugTracePanel.tsx +137 -0
  39. package/src/components/DeepReasoningTrace.tsx +48 -0
  40. package/src/components/EntitySheetPanel.tsx +51 -0
  41. package/src/components/FailureModesPanel.tsx +104 -0
  42. package/src/components/GBSDashboard.tsx +239 -0
  43. package/src/components/GraphView.tsx +116 -0
  44. package/src/components/HUD.tsx +125 -0
  45. package/src/components/HypothesisPanel.tsx +67 -0
  46. package/src/components/InnovationGenomeEngine.tsx +792 -0
  47. package/src/components/InnovationPersonaGuide.tsx +348 -0
  48. package/src/components/InnovationPersonaPanel.tsx +289 -0
  49. package/src/components/LiveResourceHUD.tsx +109 -0
  50. package/src/components/LongWriterPanel.tsx +112 -0
  51. package/src/components/MainPipelineV10Bridge.tsx +72 -0
  52. package/src/components/MarkdownLite.tsx +63 -0
  53. package/src/components/MemoryInspector.tsx +38 -0
  54. package/src/components/MemoryMonitor.tsx +52 -0
  55. package/src/components/MemoryStressPanel.tsx +176 -0
  56. package/src/components/ModulesPage.tsx +171 -0
  57. package/src/components/PipelineDebugConsole.orig.tsx +1856 -0
  58. package/src/components/PipelineDebugConsole.tsx +3 -0
  59. package/src/components/PreFlightHUD.tsx +67 -0
  60. package/src/components/PrismaFetchTracePanel.tsx +87 -0
  61. package/src/components/ReportOSPanel.tsx +165 -0
  62. package/src/components/ResourceEstimatorPage.tsx +327 -0
  63. package/src/components/RichText.tsx +181 -0
  64. package/src/components/SagaOsPanel.tsx +605 -0
  65. package/src/components/SagaOsReference.tsx +421 -0
  66. package/src/components/SagaOsV2Panel.tsx +594 -0
  67. package/src/components/SagaStyleTab.tsx +382 -0
  68. package/src/components/SageBlueprintPanel.tsx +416 -0
  69. package/src/components/SharedChatInput.tsx +77 -0
  70. package/src/components/StatFinancePanel.tsx +190 -0
  71. package/src/components/StylePersonaPanel.tsx +128 -0
  72. package/src/components/TemplatesPage.tsx +300 -0
  73. package/src/components/TestPanel.tsx +63 -0
  74. package/src/components/TraceLog.tsx +89 -0
  75. package/src/components/V15CalibrationAugment.tsx +1134 -0
  76. package/src/components/V15CalibrationDialog.tsx +1871 -0
  77. package/src/components/V15Overlay.orig.tsx +120 -0
  78. package/src/components/V15Overlay.tsx +4 -0
  79. package/src/components/V15OverlayWrapper.tsx +362 -0
  80. package/src/components/V15Toggle.tsx +34 -0
  81. package/src/console/DiagnosticRecoveryPanel.tsx +358 -0
  82. package/src/console/EngineeringConsole.tsx +103 -0
  83. package/src/console/FictionSystemPanels.tsx +882 -0
  84. package/src/console/InspectorPanels.tsx +254 -0
  85. package/src/console/ManuscriptGraderPanel.tsx +182 -0
  86. package/src/console/RecursiveReviserPanel.tsx +245 -0
  87. package/src/console/SeedControlPanel.tsx +135 -0
  88. package/src/console/StoryControllerPanel.tsx +443 -0
  89. package/src/console/engineBridge.ts +258 -0
  90. package/src/console/gemini.ts +106 -0
  91. package/src/console/grading.ts +250 -0
  92. package/src/console/util.ts +45 -0
  93. package/src/fiction/continuity.ts +372 -0
  94. package/src/fiction/crash-protection.ts +111 -0
  95. package/src/fiction/diagnostics.ts +208 -0
  96. package/src/fiction/diff.ts +74 -0
  97. package/src/fiction/entity-state-machine.ts +214 -0
  98. package/src/fiction/nive-engine.ts +404 -0
  99. package/src/fiction/pipeline-selftest.ts +132 -0
  100. package/src/fiction/seed-control.ts +193 -0
  101. package/src/fiction/story-engine.ts +326 -0
  102. package/src/fiction/types.ts +68 -0
  103. package/src/flatten-guide.md +379 -0
  104. package/src/index.css +14 -0
  105. package/src/index.orig.css +13 -0
  106. package/src/lib/academic-sources.base.ts +188 -0
  107. package/src/lib/academic-sources.orig.ts +28 -0
  108. package/src/lib/academic-sources.ts +10 -0
  109. package/src/lib/advanced-math.ts +119 -0
  110. package/src/lib/adversarial-engine.base.ts +409 -0
  111. package/src/lib/adversarial-engine.ts +82 -0
  112. package/src/lib/ai-revision.ts +623 -0
  113. package/src/lib/app-state.tsx +426 -0
  114. package/src/lib/artifact-registry.ts +97 -0
  115. package/src/lib/artifacts.ts +180 -0
  116. package/src/lib/atlas-dr.ts +167 -0
  117. package/src/lib/browser-mtls.ts +127 -0
  118. package/src/lib/browser-queue.ts +221 -0
  119. package/src/lib/browser-search-scraper.base.ts +382 -0
  120. package/src/lib/browser-search-scraper.orig.ts +90 -0
  121. package/src/lib/browser-search-scraper.ts +10 -0
  122. package/src/lib/calc-interceptor.ts +82 -0
  123. package/src/lib/citation-lane-tap.ts +78 -0
  124. package/src/lib/citation-ledger-store.ts +369 -0
  125. package/src/lib/citation-ledger.ts +203 -0
  126. package/src/lib/compute-sandbox.ts +215 -0
  127. package/src/lib/compute.worker.ts +153 -0
  128. package/src/lib/connectors/gemini.ts +120 -0
  129. package/src/lib/connectors/jina.ts +233 -0
  130. package/src/lib/connectors/marketdata.ts +51 -0
  131. package/src/lib/connectors/prismafetch.base.ts +175 -0
  132. package/src/lib/connectors/prismafetch.ts +1 -0
  133. package/src/lib/connectors/serpapi.ts +65 -0
  134. package/src/lib/connectors/wikidata.ts +44 -0
  135. package/src/lib/constraints.ts +331 -0
  136. package/src/lib/continuation-detector.base.ts +153 -0
  137. package/src/lib/continuation-detector.ts +48 -0
  138. package/src/lib/contradraft.ts +168 -0
  139. package/src/lib/cors-proxy.ts +120 -0
  140. package/src/lib/coverage.ts +81 -0
  141. package/src/lib/debug/architecture-prescription.ts +556 -0
  142. package/src/lib/debug/covea-repair.ts +543 -0
  143. package/src/lib/debug/helios-ground.ts +319 -0
  144. package/src/lib/debug/intent-decomposer.ts +281 -0
  145. package/src/lib/debug/intent-lattice.ts +349 -0
  146. package/src/lib/debug/pipeline-diagnosis.ts +1149 -0
  147. package/src/lib/debug/pipeline-trace-bus.ts +424 -0
  148. package/src/lib/debug/prompt-forge.ts +678 -0
  149. package/src/lib/debug/repair-sites.ts +513 -0
  150. package/src/lib/debug/research-phase.ts +266 -0
  151. package/src/lib/debug/retrieval-context.ts +76 -0
  152. package/src/lib/debug/retrieval-hardener.ts +142 -0
  153. package/src/lib/debug/scraper-debug-runner.ts +576 -0
  154. package/src/lib/debug/scraper-forensics.ts +418 -0
  155. package/src/lib/debug/scraper-lane-roadmap.ts +136 -0
  156. package/src/lib/debug/self-test.ts +415 -0
  157. package/src/lib/debug/step-attribution.ts +211 -0
  158. package/src/lib/debug/template-rubric.ts +301 -0
  159. package/src/lib/debug/unified-innovation.ts +126 -0
  160. package/src/lib/debug/veritas-hybrid-scraper.ts +335 -0
  161. package/src/lib/defense-registry.ts +104 -0
  162. package/src/lib/defenses.ts +162 -0
  163. package/src/lib/deterministic-citation-ledger.ts +174 -0
  164. package/src/lib/elo-registry.base.ts +117 -0
  165. package/src/lib/elo-registry.ts +1 -0
  166. package/src/lib/entity-resolver.ts +291 -0
  167. package/src/lib/failure-modes.ts +267 -0
  168. package/src/lib/feature-registry.ts +69 -0
  169. package/src/lib/flaw-registry.ts +143 -0
  170. package/src/lib/flaws/_template.ts +52 -0
  171. package/src/lib/flaws/builtins.ts +63 -0
  172. package/src/lib/flaws/finance.ts +169 -0
  173. package/src/lib/flaws/fixers.ts +10 -0
  174. package/src/lib/flaws/index.ts +32 -0
  175. package/src/lib/flaws/legal.ts +157 -0
  176. package/src/lib/flaws/medical.ts +188 -0
  177. package/src/lib/flaws/original-defenses-pack.ts +81 -0
  178. package/src/lib/flaws/sample-declarative-pack.json +38 -0
  179. package/src/lib/flaws/selftest.ts +201 -0
  180. package/src/lib/flaws/software-extended.ts +125 -0
  181. package/src/lib/flaws/software-rn-webgl.ts +182 -0
  182. package/src/lib/flaws/statistics-advanced.ts +46 -0
  183. package/src/lib/flaws/statistics.ts +61 -0
  184. package/src/lib/gbse/config.ts +20 -0
  185. package/src/lib/gbse/engine.ts +226 -0
  186. package/src/lib/gbse/graph.ts +118 -0
  187. package/src/lib/gbse/graph.worker.ts +21 -0
  188. package/src/lib/gbse/tests.ts +117 -0
  189. package/src/lib/gbse/tiers.ts +65 -0
  190. package/src/lib/gbse/types.ts +94 -0
  191. package/src/lib/innovation-genome-engine-v2.orig.ts +1001 -0
  192. package/src/lib/innovation-genome-engine-v2.ts +3 -0
  193. package/src/lib/innovation-genome-engine.orig.ts +330 -0
  194. package/src/lib/innovation-genome-engine.ts +3 -0
  195. package/src/lib/innovation-genome-v10.orig.ts +314 -0
  196. package/src/lib/innovation-genome-v10.ts +2 -0
  197. package/src/lib/innovation-genome-v3.orig.ts +2015 -0
  198. package/src/lib/innovation-genome-v3.ts +2 -0
  199. package/src/lib/innovation-genome-v4.orig.ts +1959 -0
  200. package/src/lib/innovation-genome-v4.ts +2 -0
  201. package/src/lib/innovation-genome-v5.orig.ts +1210 -0
  202. package/src/lib/innovation-genome-v5.ts +2 -0
  203. package/src/lib/innovation-genome-v7.orig.ts +2549 -0
  204. package/src/lib/innovation-genome-v7.ts +2 -0
  205. package/src/lib/innovation-genome-v8.orig.ts +1485 -0
  206. package/src/lib/innovation-genome-v8.ts +2 -0
  207. package/src/lib/innovation-genome-v9.orig.ts +643 -0
  208. package/src/lib/innovation-genome-v9.ts +2 -0
  209. package/src/lib/jina.base.ts +293 -0
  210. package/src/lib/jina.ts +1 -0
  211. package/src/lib/live-telemetry.ts +61 -0
  212. package/src/lib/longwriter.ts +84 -0
  213. package/src/lib/manuscript-grade-v2.ts +298 -0
  214. package/src/lib/memory-governor.ts +173 -0
  215. package/src/lib/memory-stress-tests.ts +248 -0
  216. package/src/lib/model-intelligence.ts +48 -0
  217. package/src/lib/model-rotator.ts +75 -0
  218. package/src/lib/models.orig.ts +513 -0
  219. package/src/lib/models.ts +151 -0
  220. package/src/lib/n-deep.base.ts +592 -0
  221. package/src/lib/n-deep.ts +51 -0
  222. package/src/lib/nih-simulator.ts +56 -0
  223. package/src/lib/nih-vulnerability-fixes.ts +460 -0
  224. package/src/lib/omega-templates.base.ts +294 -0
  225. package/src/lib/omega-templates.ts +225 -0
  226. package/src/lib/omni-nexus.ts +64 -0
  227. package/src/lib/oracle-adapters.ts +67 -0
  228. package/src/lib/oracle-registry.ts +163 -0
  229. package/src/lib/orchestrator.ts +357 -0
  230. package/src/lib/output-boundary.ts +235 -0
  231. package/src/lib/overrides/vite-native-chaos-harness.ts +154 -0
  232. package/src/lib/overrides/vite-native-contract-plane.ts +245 -0
  233. package/src/lib/overrides/vite-native-doctor-plane.ts +208 -0
  234. package/src/lib/overrides/vite-native-knowledge-store.ts +267 -0
  235. package/src/lib/overrides/vite-native-policy-plane.ts +190 -0
  236. package/src/lib/overrides/vite-native-replay-plane.ts +197 -0
  237. package/src/lib/overrides/vite-native-runtime-plane.ts +106 -0
  238. package/src/lib/overrides/vite-native-scraper.ts +848 -0
  239. package/src/lib/overrides/vite-native-selftest-functional.ts +217 -0
  240. package/src/lib/overrides/vite-native-selftest.ts +183 -0
  241. package/src/lib/overrides/vite-native-snapshot-plane.ts +123 -0
  242. package/src/lib/philosophy-toolkit.ts +75 -0
  243. package/src/lib/pipeline.orig.ts +659 -0
  244. package/src/lib/pipeline.ts +42 -0
  245. package/src/lib/precache.ts +128 -0
  246. package/src/lib/py-sandbox.ts +205 -0
  247. package/src/lib/quality-score.ts +96 -0
  248. package/src/lib/quant-engine.ts +231 -0
  249. package/src/lib/quant-lib.ts +80 -0
  250. package/src/lib/reportos.ts +175 -0
  251. package/src/lib/research-os.ts +306 -0
  252. package/src/lib/resource-estimator.ts +114 -0
  253. package/src/lib/rpm-governor.ts +93 -0
  254. package/src/lib/runtime-estimator.ts +135 -0
  255. package/src/lib/sage/empty-space-v6.ts +560 -0
  256. package/src/lib/sage/empty-space-v7.ts +222 -0
  257. package/src/lib/sage/empty-space.ts +733 -0
  258. package/src/lib/sage/engine.ts +786 -0
  259. package/src/lib/sage/index.ts +17 -0
  260. package/src/lib/sage/judge.ts +246 -0
  261. package/src/lib/sage/prng.ts +53 -0
  262. package/src/lib/sage/reality-grounding.ts +380 -0
  263. package/src/lib/sage/repetition.ts +151 -0
  264. package/src/lib/sage/saga-os-v2-engines.ts +1870 -0
  265. package/src/lib/sage/saga-os-v2.ts +274 -0
  266. package/src/lib/sage/saga-os-v3-core.ts +1491 -0
  267. package/src/lib/sage/saga-os-v3-release.ts +739 -0
  268. package/src/lib/sage/saga-os-v4-aureate.ts +1161 -0
  269. package/src/lib/sage/saga-os-v4.ts +212 -0
  270. package/src/lib/sage/saga-os-v5.ts +205 -0
  271. package/src/lib/sage/saga-os-v6.ts +346 -0
  272. package/src/lib/sage/saga-os-v7.ts +314 -0
  273. package/src/lib/sage/saga-os-v8.ts +505 -0
  274. package/src/lib/sage/saga-os.ts +329 -0
  275. package/src/lib/sage/taxonomy.ts +403 -0
  276. package/src/lib/sage/unified-roll.ts +524 -0
  277. package/src/lib/sage/worked-sketches.ts +44 -0
  278. package/src/lib/sage.ts +166 -0
  279. package/src/lib/scraper-debug-bus.ts +53 -0
  280. package/src/lib/scraper-enhanced.orig.ts +153 -0
  281. package/src/lib/scraper-enhanced.ts +10 -0
  282. package/src/lib/scraper-hardener.base.orig.ts +155 -0
  283. package/src/lib/scraper-hardener.base.ts +317 -0
  284. package/src/lib/scraper-hardener.ts +1 -0
  285. package/src/lib/scraper-palisade/palisade-adjudicator.orig.ts +419 -0
  286. package/src/lib/scraper-palisade/palisade-adjudicator.ts +13 -0
  287. package/src/lib/scraper-vnext/arbiter-omega.orig.ts +688 -0
  288. package/src/lib/scraper-vnext/arbiter-omega.ts +13 -0
  289. package/src/lib/scraper-vnext/canonical-portfolio-augments.ts +479 -0
  290. package/src/lib/scraper-vnext/canonical-portfolio-orchestrator.orig.ts +1529 -0
  291. package/src/lib/scraper-vnext/canonical-portfolio-orchestrator.ts +13 -0
  292. package/src/lib/scraper-vnext/conclave-omega.ts +1830 -0
  293. package/src/lib/scraper-vnext/content-extractor-v2.ts +226 -0
  294. package/src/lib/scraper-vnext/diagnostics-suite.ts +36 -0
  295. package/src/lib/scraper-vnext/epistemic-packer.ts +97 -0
  296. package/src/lib/scraper-vnext/fusion-v2.ts +65 -0
  297. package/src/lib/scraper-vnext/hydra-reader.orig.ts +1216 -0
  298. package/src/lib/scraper-vnext/hydra-reader.ts +13 -0
  299. package/src/lib/scraper-vnext/native-scraper-browser-vnext.orig.ts +91 -0
  300. package/src/lib/scraper-vnext/native-scraper-browser-vnext.ts +13 -0
  301. package/src/lib/scraper-vnext/nexus-consensus.orig.ts +905 -0
  302. package/src/lib/scraper-vnext/nexus-consensus.ts +13 -0
  303. package/src/lib/scraper-vnext/portfolio-consensus-adjudicator.ts +804 -0
  304. package/src/lib/scraper-vnext/portfolio-consensus-memory.ts +377 -0
  305. package/src/lib/scraper-vnext/portfolio-terminal-governor.ts +548 -0
  306. package/src/lib/scraper-vnext/query-strategist.orig.ts +224 -0
  307. package/src/lib/scraper-vnext/query-strategist.ts +423 -0
  308. package/src/lib/scraper-vnext/retrieval-accelerator.ts +708 -0
  309. package/src/lib/scraper-vnext/retrieval-audit-augments.ts +477 -0
  310. package/src/lib/scraper-vnext/retrieval-control-plane.ts +904 -0
  311. package/src/lib/scraper-vnext/retrieval-policy-augments.ts +358 -0
  312. package/src/lib/scraper-vnext/safe-fetch-v2.ts +157 -0
  313. package/src/lib/scraper-vnext/sentinel-omega.ts +56 -0
  314. package/src/lib/scraper-vnext/sentinel-orchestrator.ts +69 -0
  315. package/src/lib/scraper-vnext/sibyl-oracle.orig.ts +413 -0
  316. package/src/lib/scraper-vnext/sibyl-oracle.ts +13 -0
  317. package/src/lib/scraper-vnext/smart-read-v2.ts +55 -0
  318. package/src/lib/scraper-vnext/spa-rescue-bridge.ts +608 -0
  319. package/src/lib/scraper-vnext/strata-engine.orig.ts +2666 -0
  320. package/src/lib/scraper-vnext/strata-engine.ts +13 -0
  321. package/src/lib/scraper-vnext/structured-source-adapter.orig.ts +369 -0
  322. package/src/lib/scraper-vnext/structured-source-adapter.ts +34 -0
  323. package/src/lib/scraper-vnext/terminal-complete.ts +224 -0
  324. package/src/lib/scraper-vnext/terminal-final.ts +277 -0
  325. package/src/lib/scraper-vnext/terminal-saturation.ts +345 -0
  326. package/src/lib/scraper-vnext/terminal-wire.ts +425 -0
  327. package/src/lib/scraper-vnext/vanguard-titanium.orig.ts +467 -0
  328. package/src/lib/scraper-vnext/vanguard-titanium.ts +17 -0
  329. package/src/lib/search-cache.ts +138 -0
  330. package/src/lib/sloop-runner.base.ts +223 -0
  331. package/src/lib/sloop-runner.ts +104 -0
  332. package/src/lib/sloop.ts +114 -0
  333. package/src/lib/small-model-adapters.ts +82 -0
  334. package/src/lib/sscp.ts +86 -0
  335. package/src/lib/system-map.ts +54 -0
  336. package/src/lib/uni-node.ts +86 -0
  337. package/src/lib/universal-rigor-guard.ts +433 -0
  338. package/src/lib/v15-gate-testbed.ts +274 -0
  339. package/src/lib/v15-gemini.base.ts +89 -0
  340. package/src/lib/v15-gemini.ts +1 -0
  341. package/src/lib/v15-grounding.orig.ts +241 -0
  342. package/src/lib/v15-grounding.ts +79 -0
  343. package/src/lib/v15-pipeline.base.ts +769 -0
  344. package/src/lib/v15-pipeline.orig.ts +1154 -0
  345. package/src/lib/v15-pipeline.ts +674 -0
  346. package/src/lib/v15-questions.ts +64 -0
  347. package/src/lib/v15-rate-limiter.orig.ts +91 -0
  348. package/src/lib/v15-rate-limiter.ts +48 -0
  349. package/src/lib/v15-state.base.ts +87 -0
  350. package/src/lib/v15-state.ts +28 -0
  351. package/src/lib/visual-table-generator.tsx +207 -0
  352. package/src/lib/wasm-runtime.ts +133 -0
  353. package/src/lib/williams-persona-guide.ts +265 -0
  354. package/src/lib/williams-style.base.ts +464 -0
  355. package/src/lib/williams-style.ts +59 -0
  356. package/src/lib/worker-pool.ts +96 -0
  357. package/src/lib/writing-tiers.ts +125 -0
  358. package/src/main.orig.tsx +10 -0
  359. package/src/main.tsx +10 -0
  360. package/src/utils/cn.orig.ts +6 -0
  361. package/src/utils/cn.ts +6 -0
  362. package/src/vite-env.d.ts +1 -0
  363. package/tsconfig.json +31 -0
  364. package/unify.mjs +537 -0
  365. package/vite.config.ts +18 -0
@@ -0,0 +1,1210 @@
1
+ /**
2
+ * innovation-genome-v5.ts — Production Assurance Plane for V1/V2/V3/V4.
3
+ * ============================================================================
4
+ * Additive only. Imports V4 and adds:
5
+ * 1. Policy-as-code governance over runtime actions.
6
+ * 2. OpenTelemetry-inspired trace/span observability.
7
+ * 3. Canary leakage detection and taint labels.
8
+ * 4. Sealed challenge-suite commitments.
9
+ * 5. Standardized verifier adapter protocol.
10
+ * 6. Replay manifests and deterministic replay matrix.
11
+ * 7. Dynamic tool-inventory drift detection.
12
+ * 8. Operational SLO / health gates.
13
+ * 9. Promotion-time assurance gate (V4 audit + V5 policies).
14
+ * 10. Fail-closed audit / policy-check / replay-check / health-check entries.
15
+ *
16
+ * RUNTIME HONESTY: no Python interpreter, no SQLite, no browser in this
17
+ * session. This is a structural/semantic port verified by side-by-side
18
+ * reading of the pasted Python V5, not by execute-and-diff. SQLite tables
19
+ * become in-memory typed collections on the V4 store (same disclosure as
20
+ * V3/V4). Every class, field, rule id, threshold and predicate name below
21
+ * matches the Python source.
22
+ */
23
+
24
+ import type { RiskTier } from '@/lib/innovation-genome-engine-v2';
25
+ import {
26
+ Candidate,
27
+ ToolRegistry,
28
+ canonicalJson,
29
+ sha256Text,
30
+ utcNow,
31
+ } from "@/lib/innovation-genome-v3";
32
+ import {
33
+ AtomicGovernanceStore,
34
+ auditRuntime,
35
+ type EvidenceKind,
36
+ type EvidenceMaterial,
37
+ type PromotionRecord,
38
+ } from "@/lib/innovation-genome-v4";
39
+
40
+ export const ZERO_HASH = "0".repeat(64);
41
+
42
+ // ═══════════════════════════════════════════════════════════════════════
43
+ // 1. V5 store (extends V4's AtomicGovernanceStore)
44
+ // ═══════════════════════════════════════════════════════════════════════
45
+
46
+ export interface PolicyDecisionRow {
47
+ decisionId: string;
48
+ runId: string;
49
+ createdUtc: string;
50
+ subject: string;
51
+ action: string;
52
+ allowed: boolean;
53
+ violationsJson: string;
54
+ inputHash: string;
55
+ }
56
+
57
+ export interface SpanRow {
58
+ spanId: string;
59
+ runId: string;
60
+ traceId: string;
61
+ parentSpanId: string;
62
+ name: string;
63
+ kind: string;
64
+ startUtc: string;
65
+ endUtc: string;
66
+ durationMs: number;
67
+ status: string;
68
+ attributesJson: string;
69
+ }
70
+
71
+ export interface CanaryRow {
72
+ canaryId: string;
73
+ runId: string;
74
+ label: string;
75
+ tokenHash: string;
76
+ taint: string;
77
+ createdUtc: string;
78
+ }
79
+
80
+ export interface CanaryHitRow {
81
+ hitId: string;
82
+ runId: string;
83
+ canaryId: string;
84
+ candidateId: string;
85
+ location: string;
86
+ severity: string;
87
+ createdUtc: string;
88
+ }
89
+
90
+ export interface ChallengeSuiteRow {
91
+ suiteId: string;
92
+ runId: string;
93
+ name: string;
94
+ tier: string;
95
+ commitmentHash: string;
96
+ diagnosticRelease: string;
97
+ createdUtc: string;
98
+ }
99
+
100
+ export interface VerifierRunRow {
101
+ verifierRunId: string;
102
+ runId: string;
103
+ candidateId: string;
104
+ verifierName: string;
105
+ verifierVersion: string;
106
+ jobHash: string;
107
+ verdict: string;
108
+ resultJson: string;
109
+ resultHash: string;
110
+ createdUtc: string;
111
+ }
112
+
113
+ export interface ReplayManifestRow {
114
+ manifestId: string;
115
+ runId: string;
116
+ subjectId: string;
117
+ manifestJson: string;
118
+ manifestHash: string;
119
+ createdUtc: string;
120
+ }
121
+
122
+ export interface ReplayResultRow {
123
+ replayId: string;
124
+ runId: string;
125
+ manifestId: string;
126
+ success: boolean;
127
+ resultJson: string;
128
+ resultHash: string;
129
+ createdUtc: string;
130
+ }
131
+
132
+ export interface ToolInventoryRow {
133
+ runId: string;
134
+ snapshotId: string;
135
+ inventoryHash: string;
136
+ inventoryJson: string;
137
+ createdUtc: string;
138
+ }
139
+
140
+ export interface HealthReportRow {
141
+ reportId: string;
142
+ runId: string;
143
+ status: string;
144
+ reportJson: string;
145
+ reportHash: string;
146
+ createdUtc: string;
147
+ }
148
+
149
+ /** Extends V4's AtomicGovernanceStore. Does not alter V1-V4 behavior. */
150
+ export class V5AssuranceStore extends AtomicGovernanceStore {
151
+ protected policyDecisions = new Map<string, PolicyDecisionRow>();
152
+ protected spans: SpanRow[] = [];
153
+ protected canaryRows = new Map<string, CanaryRow>();
154
+ protected canaryHits = new Map<string, CanaryHitRow>();
155
+ protected challengeSuites = new Map<string, ChallengeSuiteRow>();
156
+ protected verifierRuns = new Map<string, VerifierRunRow>();
157
+ protected replayManifests = new Map<string, ReplayManifestRow>();
158
+ protected replayResults = new Map<string, ReplayResultRow>();
159
+ protected toolInventory = new Map<string, ToolInventoryRow>();
160
+ protected healthReports = new Map<string, HealthReportRow>();
161
+
162
+ _putPolicyDecision(row: PolicyDecisionRow): void {
163
+ this.policyDecisions.set(row.decisionId, row);
164
+ }
165
+ _countPolicyDenials(runId: string): number {
166
+ let n = 0;
167
+ for (const row of this.policyDecisions.values()) {
168
+ if (row.runId === runId && !row.allowed) n += 1;
169
+ }
170
+ return n;
171
+ }
172
+
173
+ _putSpan(row: SpanRow): void {
174
+ this.spans.push(row);
175
+ }
176
+ _getSpans(runId: string): SpanRow[] {
177
+ return this.spans.filter((s) => s.runId === runId);
178
+ }
179
+
180
+ _putCanary(row: CanaryRow): void {
181
+ this.canaryRows.set(row.canaryId, row);
182
+ }
183
+ /** Public accessor so the "plaintext token is never persisted" property is
184
+ * testable without reaching into a protected field (which a property-mangling
185
+ * minifier could rename, turning the test into a vacuous pass). */
186
+ _getCanaryRows(runId: string): CanaryRow[] {
187
+ return [...this.canaryRows.values()].filter((r) => r.runId === runId);
188
+ }
189
+ _putCanaryHit(row: CanaryHitRow): void {
190
+ this.canaryHits.set(row.hitId, row);
191
+ }
192
+ _countCanaryHits(runId: string, candidateId: string): number {
193
+ let n = 0;
194
+ for (const hit of this.canaryHits.values()) {
195
+ if (hit.runId === runId && hit.candidateId === candidateId) n += 1;
196
+ }
197
+ return n;
198
+ }
199
+
200
+ _putChallengeSuite(row: ChallengeSuiteRow): void {
201
+ this.challengeSuites.set(row.suiteId, row);
202
+ }
203
+ _getChallengeSuite(suiteId: string): ChallengeSuiteRow | undefined {
204
+ return this.challengeSuites.get(suiteId);
205
+ }
206
+
207
+ _putVerifierRun(row: VerifierRunRow): void {
208
+ this.verifierRuns.set(row.verifierRunId, row);
209
+ }
210
+ _getVerifierRuns(runId: string, candidateId: string): VerifierRunRow[] {
211
+ return [...this.verifierRuns.values()]
212
+ .filter((r) => r.runId === runId && r.candidateId === candidateId)
213
+ .sort((a, b) => a.createdUtc.localeCompare(b.createdUtc));
214
+ }
215
+
216
+ _putReplayManifest(row: ReplayManifestRow): void {
217
+ this.replayManifests.set(row.manifestId, row);
218
+ }
219
+ _putReplayResult(row: ReplayResultRow): void {
220
+ this.replayResults.set(row.replayId, row);
221
+ }
222
+ _getReplayResult(runId: string, replayId: string): ReplayResultRow | undefined {
223
+ const row = this.replayResults.get(replayId);
224
+ return row && row.runId === runId ? row : undefined;
225
+ }
226
+
227
+ _putToolInventory(row: ToolInventoryRow): void {
228
+ this.toolInventory.set(`${row.runId}:${row.snapshotId}`, row);
229
+ }
230
+ _getToolInventory(runId: string, snapshotId: string): ToolInventoryRow | undefined {
231
+ return this.toolInventory.get(`${runId}:${snapshotId}`);
232
+ }
233
+
234
+ _putHealthReport(row: HealthReportRow): void {
235
+ this.healthReports.set(row.reportId, row);
236
+ }
237
+ }
238
+
239
+ // ═══════════════════════════════════════════════════════════════════════
240
+ // 2. Policy-as-code
241
+ // ═══════════════════════════════════════════════════════════════════════
242
+
243
+ export type PolicySeverity = "info" | "warning" | "error" | "fatal";
244
+
245
+ export interface PolicyViolation {
246
+ ruleId: string;
247
+ severity: PolicySeverity;
248
+ message: string;
249
+ location?: string;
250
+ }
251
+
252
+ export interface PolicyInput {
253
+ runId: string;
254
+ subject: string;
255
+ action: string;
256
+ resource: string;
257
+ risk: string;
258
+ payload: Record<string, unknown>;
259
+ capabilities?: Record<string, unknown>;
260
+ }
261
+
262
+ export class PolicyDecision {
263
+ constructor(
264
+ public readonly allowed: boolean,
265
+ public readonly subject: string,
266
+ public readonly action: string,
267
+ public readonly violations: readonly PolicyViolation[],
268
+ public readonly inputHash: string,
269
+ ) {}
270
+
271
+ toDict(): Record<string, unknown> {
272
+ return {
273
+ allowed: this.allowed,
274
+ subject: this.subject,
275
+ action: this.action,
276
+ violations: this.violations.map((v) => ({ ...v })),
277
+ input_hash: this.inputHash,
278
+ };
279
+ }
280
+ }
281
+
282
+ export interface PolicyRule {
283
+ ruleId: string;
284
+ description: string;
285
+ severity: PolicySeverity;
286
+ predicate: (input: PolicyInput) => string | null;
287
+ }
288
+
289
+ export class PolicyEngine {
290
+ readonly rules: readonly PolicyRule[];
291
+
292
+ constructor(rules: readonly PolicyRule[]) {
293
+ this.rules = rules;
294
+ }
295
+
296
+ evaluate(policyInput: PolicyInput): PolicyDecision {
297
+ const violations: PolicyViolation[] = [];
298
+
299
+ for (const rule of this.rules) {
300
+ const message = rule.predicate(policyInput);
301
+ if (message) {
302
+ violations.push({
303
+ ruleId: rule.ruleId,
304
+ severity: rule.severity,
305
+ message,
306
+ location: policyInput.resource,
307
+ });
308
+ }
309
+ }
310
+
311
+ const fatal = violations.some(
312
+ (v) => v.severity === "error" || v.severity === "fatal",
313
+ );
314
+
315
+ return new PolicyDecision(
316
+ !fatal,
317
+ policyInput.subject,
318
+ policyInput.action,
319
+ violations,
320
+ sha256Text(canonicalJson(policyInput as unknown as Record<string, unknown>)),
321
+ );
322
+ }
323
+
324
+ /** Persists the decision, emits the event, and THROWS when denied (fail-closed). */
325
+ enforce(store: V5AssuranceStore, decision: PolicyDecision, runId: string): void {
326
+ const decisionId =
327
+ "policy-" +
328
+ sha256Text(
329
+ canonicalJson({
330
+ run_id: runId,
331
+ subject: decision.subject,
332
+ action: decision.action,
333
+ input_hash: decision.inputHash,
334
+ violations: decision.violations.map((v) => ({ ...v })),
335
+ }),
336
+ ).slice(0, 32);
337
+
338
+ store._putPolicyDecision({
339
+ decisionId,
340
+ runId,
341
+ createdUtc: utcNow(),
342
+ subject: decision.subject,
343
+ action: decision.action,
344
+ allowed: decision.allowed,
345
+ violationsJson: canonicalJson(decision.violations.map((v) => ({ ...v }))),
346
+ inputHash: decision.inputHash,
347
+ });
348
+
349
+ store.appendEvent(runId, "policy_decision_v5", {
350
+ decision_id: decisionId,
351
+ allowed: decision.allowed,
352
+ subject: decision.subject,
353
+ action: decision.action,
354
+ input_hash: decision.inputHash,
355
+ });
356
+
357
+ if (!decision.allowed) {
358
+ throw new Error(decision.violations.map((v) => v.message).join("; "));
359
+ }
360
+ }
361
+ }
362
+
363
+ export function defaultPolicyRules(): readonly PolicyRule[] {
364
+ const highStakesNeedsHuman = (input: PolicyInput): string | null => {
365
+ if (input.risk === "high" || input.risk === "critical") {
366
+ const approvals = (input.payload.human_approvals ?? []) as unknown[];
367
+ if (!approvals || approvals.length === 0) {
368
+ return "High-stakes action lacks human approval";
369
+ }
370
+ }
371
+ return null;
372
+ };
373
+
374
+ const worldActionNeedsScope = (input: PolicyInput): string | null => {
375
+ if (input.action === "tool_call" && input.payload.world_action) {
376
+ const scopes = new Set((input.payload.grant_scopes ?? []) as string[]);
377
+ if (!scopes.has("world:action") && !scopes.has("*")) {
378
+ return "World action lacks world:action scope";
379
+ }
380
+ }
381
+ return null;
382
+ };
383
+
384
+ const noUndeclaredTool = (input: PolicyInput): string | null => {
385
+ if (input.action === "tool_call") {
386
+ const tool = input.payload.tool_name as string | undefined;
387
+ const declared = new Set(
388
+ ((input.capabilities?.declared_tools ?? []) as string[]),
389
+ );
390
+ if (!tool || !declared.has(tool)) {
391
+ return `Tool ${JSON.stringify(tool)} is not declared`;
392
+ }
393
+ }
394
+ return null;
395
+ };
396
+
397
+ const promotionRequiresEvidence = (input: PolicyInput): string | null => {
398
+ if (input.action === "promote_candidate") {
399
+ if (!input.payload.evidence_closed) {
400
+ return "Promotion attempted without evidence closure";
401
+ }
402
+ }
403
+ return null;
404
+ };
405
+
406
+ const canaryLeakBlocks = (input: PolicyInput): string | null => {
407
+ if (((input.payload.canary_hits as number) ?? 0) > 0) {
408
+ return "Canary leakage detected";
409
+ }
410
+ return null;
411
+ };
412
+
413
+ return [
414
+ {
415
+ ruleId: "V5-POL-001",
416
+ description: "High-stakes actions require human approval.",
417
+ severity: "error",
418
+ predicate: highStakesNeedsHuman,
419
+ },
420
+ {
421
+ ruleId: "V5-POL-002",
422
+ description: "World actions require explicit world:action scope.",
423
+ severity: "error",
424
+ predicate: worldActionNeedsScope,
425
+ },
426
+ {
427
+ ruleId: "V5-POL-003",
428
+ description: "Tool calls must use declared tools.",
429
+ severity: "error",
430
+ predicate: noUndeclaredTool,
431
+ },
432
+ {
433
+ ruleId: "V5-POL-004",
434
+ description: "Promotion requires claim evidence closure.",
435
+ severity: "error",
436
+ predicate: promotionRequiresEvidence,
437
+ },
438
+ {
439
+ ruleId: "V5-POL-005",
440
+ description: "Canary leakage blocks promotion or external action.",
441
+ severity: "fatal",
442
+ predicate: canaryLeakBlocks,
443
+ },
444
+ ];
445
+ }
446
+
447
+ // ═══════════════════════════════════════════════════════════════════════
448
+ // 3. Telemetry spans
449
+ // ═══════════════════════════════════════════════════════════════════════
450
+
451
+ export interface SpanContext {
452
+ traceId: string;
453
+ spanId: string;
454
+ parentSpanId: string;
455
+ }
456
+
457
+ function randomHex(bytes: number): string {
458
+ const out = new Uint8Array(bytes);
459
+ if (typeof crypto !== "undefined" && crypto.getRandomValues) {
460
+ crypto.getRandomValues(out);
461
+ } else {
462
+ for (let i = 0; i < bytes; i++) out[i] = Math.floor(Math.random() * 256);
463
+ }
464
+ return Array.from(out).map((b) => b.toString(16).padStart(2, "0")).join("");
465
+ }
466
+
467
+ export class TelemetryRecorder {
468
+ constructor(
469
+ protected readonly store: V5AssuranceStore,
470
+ protected readonly runId: string,
471
+ ) {}
472
+
473
+ startSpan(
474
+ _name: string,
475
+ _kind: string,
476
+ parent?: SpanContext,
477
+ ): { context: SpanContext; startMonotonic: number; startUtc: string } {
478
+ const traceId = parent ? parent.traceId : randomHex(16);
479
+ const spanId = randomHex(8);
480
+ const parentSpanId = parent ? parent.spanId : "";
481
+ const startMonotonic =
482
+ typeof performance !== "undefined" ? performance.now() : Date.now();
483
+ return {
484
+ context: { traceId, spanId, parentSpanId },
485
+ startMonotonic,
486
+ startUtc: utcNow(),
487
+ };
488
+ }
489
+
490
+ endSpan(
491
+ context: SpanContext,
492
+ name: string,
493
+ kind: string,
494
+ startMonotonic: number,
495
+ startUtc: string,
496
+ status: string,
497
+ attributes: Record<string, unknown>,
498
+ ): void {
499
+ const nowMonotonic =
500
+ typeof performance !== "undefined" ? performance.now() : Date.now();
501
+ const durationMs = Math.max(0, Math.round(nowMonotonic - startMonotonic));
502
+
503
+ this.store._putSpan({
504
+ spanId: context.spanId,
505
+ runId: this.runId,
506
+ traceId: context.traceId,
507
+ parentSpanId: context.parentSpanId,
508
+ name,
509
+ kind,
510
+ startUtc,
511
+ endUtc: utcNow(),
512
+ durationMs,
513
+ status,
514
+ attributesJson: canonicalJson(attributes),
515
+ });
516
+
517
+ this.store.appendEvent(this.runId, "span_recorded_v5", {
518
+ trace_id: context.traceId,
519
+ span_id: context.spanId,
520
+ parent_span_id: context.parentSpanId,
521
+ name,
522
+ kind,
523
+ status,
524
+ duration_ms: durationMs,
525
+ });
526
+ }
527
+ }
528
+
529
+ // ═══════════════════════════════════════════════════════════════════════
530
+ // 4. Canary leakage and taint labels
531
+ // ═══════════════════════════════════════════════════════════════════════
532
+
533
+ export type CanarySeverity = "low" | "medium" | "high" | "critical";
534
+
535
+ export interface Canary {
536
+ canaryId: string;
537
+ label: string;
538
+ token: string;
539
+ taint: string;
540
+ severity: CanarySeverity;
541
+ tokenHash: string;
542
+ }
543
+
544
+ export interface CanaryHit {
545
+ canaryId: string;
546
+ label: string;
547
+ candidateId: string;
548
+ location: string;
549
+ severity: CanarySeverity;
550
+ }
551
+
552
+ /** Keeps canary plaintext in memory; persists only hashes. */
553
+ export class CanaryRegistry {
554
+ private readonly canaries = new Map<string, Canary>();
555
+
556
+ constructor(
557
+ private readonly store: V5AssuranceStore,
558
+ private readonly runId: string,
559
+ ) {}
560
+
561
+ register(
562
+ label: string,
563
+ token: string,
564
+ taint: string,
565
+ severity: CanarySeverity = "high",
566
+ ): Canary {
567
+ if (!token) throw new Error("Canary token cannot be empty");
568
+
569
+ const tokenHash = sha256Text(token);
570
+ const canaryId =
571
+ "canary-" +
572
+ sha256Text(
573
+ canonicalJson({ run_id: this.runId, label, token_hash: tokenHash }),
574
+ ).slice(0, 32);
575
+
576
+ const canary: Canary = { canaryId, label, token, taint, severity, tokenHash };
577
+ this.canaries.set(canaryId, canary);
578
+
579
+ this.store._putCanary({
580
+ canaryId,
581
+ runId: this.runId,
582
+ label,
583
+ tokenHash,
584
+ taint,
585
+ createdUtc: utcNow(),
586
+ });
587
+
588
+ this.store.appendEvent(this.runId, "canary_registered_v5", {
589
+ canary_id: canaryId,
590
+ label,
591
+ token_hash: tokenHash,
592
+ taint,
593
+ severity,
594
+ });
595
+
596
+ return canary;
597
+ }
598
+
599
+ scan(candidateId: string, text: string, location: string): CanaryHit[] {
600
+ const hits: CanaryHit[] = [];
601
+
602
+ for (const canary of this.canaries.values()) {
603
+ if (!text.includes(canary.token)) continue;
604
+
605
+ hits.push({
606
+ canaryId: canary.canaryId,
607
+ label: canary.label,
608
+ candidateId,
609
+ location,
610
+ severity: canary.severity,
611
+ });
612
+
613
+ const hitId =
614
+ "hit-" +
615
+ sha256Text(
616
+ canonicalJson({
617
+ candidate_id: candidateId,
618
+ canary_id: canary.canaryId,
619
+ location,
620
+ }),
621
+ ).slice(0, 32);
622
+
623
+ this.store._putCanaryHit({
624
+ hitId,
625
+ runId: this.runId,
626
+ canaryId: canary.canaryId,
627
+ candidateId,
628
+ location,
629
+ severity: canary.severity,
630
+ createdUtc: utcNow(),
631
+ });
632
+
633
+ this.store.appendEvent(this.runId, "canary_hit_v5", {
634
+ hit_id: hitId,
635
+ canary_id: canary.canaryId,
636
+ candidate_id: candidateId,
637
+ location,
638
+ severity: canary.severity,
639
+ });
640
+ }
641
+
642
+ return hits;
643
+ }
644
+
645
+ hitCount(candidateId: string): number {
646
+ return this.store._countCanaryHits(this.runId, candidateId);
647
+ }
648
+ }
649
+
650
+ // ═══════════════════════════════════════════════════════════════════════
651
+ // 5. Sealed challenge suite commitments
652
+ // ═══════════════════════════════════════════════════════════════════════
653
+
654
+ export type DiagnosticRelease = "full" | "summary" | "none";
655
+
656
+ export interface ChallengeCase {
657
+ caseId: string;
658
+ inputDigest: string;
659
+ expectedDigest: string;
660
+ metadata?: Record<string, unknown>;
661
+ }
662
+
663
+ export class ChallengeSuite {
664
+ constructor(
665
+ public readonly suiteId: string,
666
+ public readonly name: string,
667
+ public readonly tier: string,
668
+ public readonly cases: readonly ChallengeCase[],
669
+ public readonly diagnosticRelease: DiagnosticRelease,
670
+ ) {}
671
+
672
+ get commitmentHash(): string {
673
+ return sha256Text(
674
+ canonicalJson({
675
+ suite_id: this.suiteId,
676
+ name: this.name,
677
+ tier: this.tier,
678
+ cases: this.cases.map((c) => ({ ...c })),
679
+ diagnostic_release: this.diagnosticRelease,
680
+ }),
681
+ );
682
+ }
683
+ }
684
+
685
+ export class ChallengeSuiteRegistry {
686
+ constructor(
687
+ private readonly store: V5AssuranceStore,
688
+ private readonly runId: string,
689
+ ) {}
690
+
691
+ register(suite: ChallengeSuite): void {
692
+ this.store._putChallengeSuite({
693
+ suiteId: suite.suiteId,
694
+ runId: this.runId,
695
+ name: suite.name,
696
+ tier: suite.tier,
697
+ commitmentHash: suite.commitmentHash,
698
+ diagnosticRelease: suite.diagnosticRelease,
699
+ createdUtc: utcNow(),
700
+ });
701
+
702
+ this.store.appendEvent(this.runId, "challenge_suite_registered_v5", {
703
+ suite_id: suite.suiteId,
704
+ tier: suite.tier,
705
+ commitment_hash: suite.commitmentHash,
706
+ diagnostic_release: suite.diagnosticRelease,
707
+ });
708
+ }
709
+ }
710
+
711
+ // ═══════════════════════════════════════════════════════════════════════
712
+ // 6. Verifier protocol
713
+ // ═══════════════════════════════════════════════════════════════════════
714
+
715
+ export type VerificationVerdict = "pass" | "fail" | "inconclusive" | "error";
716
+
717
+ export interface VerificationJob {
718
+ candidateId: string;
719
+ artifactDigest: string;
720
+ artifactMediaType: string;
721
+ goalHash: string;
722
+ evaluatorHash: string;
723
+ verifierScope: string;
724
+ arguments?: Record<string, unknown>;
725
+ }
726
+
727
+ export class VerificationResult {
728
+ constructor(
729
+ public readonly verifierName: string,
730
+ public readonly verifierVersion: string,
731
+ public readonly verdict: VerificationVerdict,
732
+ public readonly evidence: readonly EvidenceMaterial[],
733
+ public readonly witness: string = "",
734
+ public readonly counterexample: string = "",
735
+ public readonly diagnostics: readonly string[] = [],
736
+ ) {}
737
+
738
+ toDict(): Record<string, unknown> {
739
+ return {
740
+ verifier_name: this.verifierName,
741
+ verifier_version: this.verifierVersion,
742
+ verdict: this.verdict,
743
+ evidence: this.evidence.map((ev) => ({
744
+ evidence_id: ev.evidenceId,
745
+ kind: ev.kind as EvidenceKind,
746
+ content_hash: sha256Text(ev.content),
747
+ media_type: ev.mediaType ?? "text/plain",
748
+ locator: ev.locator ?? "",
749
+ })),
750
+ witness_hash: sha256Text(this.witness),
751
+ counterexample_hash: sha256Text(this.counterexample),
752
+ diagnostics: this.diagnostics,
753
+ };
754
+ }
755
+ }
756
+
757
+ export interface VerifierAdapter {
758
+ name: string;
759
+ version: string;
760
+ verify(job: VerificationJob): VerificationResult | Promise<VerificationResult>;
761
+ }
762
+
763
+ export class FunctionVerifier implements VerifierAdapter {
764
+ constructor(
765
+ public readonly name: string,
766
+ public readonly version: string,
767
+ private readonly fn: (job: VerificationJob) => VerificationResult | Promise<VerificationResult>,
768
+ ) {}
769
+ verify(job: VerificationJob) {
770
+ return this.fn(job);
771
+ }
772
+ }
773
+
774
+ export class VerifierOrchestrator {
775
+ readonly verifiers: readonly VerifierAdapter[];
776
+
777
+ constructor(
778
+ private readonly store: V5AssuranceStore,
779
+ private readonly runId: string,
780
+ verifiers: readonly VerifierAdapter[],
781
+ ) {
782
+ if (verifiers.length === 0) throw new Error("At least one verifier is required");
783
+ this.verifiers = verifiers;
784
+ }
785
+
786
+ async run(job: VerificationJob): Promise<VerificationResult[]> {
787
+ const jobHash = sha256Text(canonicalJson(job as unknown as Record<string, unknown>));
788
+ const results: VerificationResult[] = [];
789
+
790
+ for (const verifier of this.verifiers) {
791
+ let result: VerificationResult;
792
+ try {
793
+ result = await verifier.verify(job);
794
+ } catch (exc) {
795
+ result = new VerificationResult(
796
+ verifier.name,
797
+ verifier.version,
798
+ "error",
799
+ [],
800
+ "",
801
+ "",
802
+ [`${exc instanceof Error ? exc.constructor.name : "Error"}: ${exc instanceof Error ? exc.message : String(exc)}`],
803
+ );
804
+ }
805
+
806
+ const resultJson = canonicalJson(result.toDict());
807
+ const resultHash = sha256Text(resultJson);
808
+ const verifierRunId =
809
+ "verifier-" +
810
+ sha256Text(
811
+ canonicalJson({
812
+ run_id: this.runId,
813
+ candidate_id: job.candidateId,
814
+ verifier: verifier.name,
815
+ job_hash: jobHash,
816
+ result_hash: resultHash,
817
+ }),
818
+ ).slice(0, 32);
819
+
820
+ this.store._putVerifierRun({
821
+ verifierRunId,
822
+ runId: this.runId,
823
+ candidateId: job.candidateId,
824
+ verifierName: verifier.name,
825
+ verifierVersion: verifier.version,
826
+ jobHash,
827
+ verdict: result.verdict,
828
+ resultJson,
829
+ resultHash,
830
+ createdUtc: utcNow(),
831
+ });
832
+
833
+ this.store.appendEvent(this.runId, "verifier_run_v5", {
834
+ verifier_run_id: verifierRunId,
835
+ candidate_id: job.candidateId,
836
+ verifier: verifier.name,
837
+ verdict: result.verdict,
838
+ job_hash: jobHash,
839
+ result_hash: resultHash,
840
+ });
841
+
842
+ results.push(result);
843
+ }
844
+
845
+ return results;
846
+ }
847
+
848
+ /**
849
+ * NOTE (carried forward verbatim from the Python V5): this returns true when
850
+ * ALL PRESENT rows pass. V7's VerifierClosureGate replaces it with an exact
851
+ * required-set check, because a missing required verifier passes here.
852
+ */
853
+ allRequiredPassed(candidateId: string): boolean {
854
+ const rows = this.store._getVerifierRuns(this.runId, candidateId);
855
+ return rows.length > 0 && rows.every((r) => r.verdict === "pass");
856
+ }
857
+ }
858
+
859
+ // ═══════════════════════════════════════════════════════════════════════
860
+ // 7. Replay manifests
861
+ // ═══════════════════════════════════════════════════════════════════════
862
+
863
+ export interface ReplayStep {
864
+ name: string;
865
+ inputHash: string;
866
+ expectedOutputHash: string;
867
+ toolReceipts?: readonly string[];
868
+ }
869
+
870
+ export class ReplayManifest {
871
+ constructor(
872
+ public readonly subjectId: string,
873
+ public readonly environment: Record<string, unknown>,
874
+ public readonly steps: readonly ReplayStep[],
875
+ ) {}
876
+
877
+ get manifestHash(): string {
878
+ return sha256Text(
879
+ canonicalJson({
880
+ subject_id: this.subjectId,
881
+ environment: this.environment,
882
+ steps: this.steps.map((s) => ({ ...s })),
883
+ }),
884
+ );
885
+ }
886
+ }
887
+
888
+ export interface ReplayRunner {
889
+ runStep(step: ReplayStep): string | Promise<string>;
890
+ }
891
+
892
+ export class ReplayMatrix {
893
+ constructor(
894
+ private readonly store: V5AssuranceStore,
895
+ private readonly runId: string,
896
+ ) {}
897
+
898
+ saveManifest(manifest: ReplayManifest): string {
899
+ const manifestId = "replay-manifest-" + manifest.manifestHash.slice(0, 32);
900
+ const manifestJson = canonicalJson({
901
+ subject_id: manifest.subjectId,
902
+ environment: manifest.environment,
903
+ steps: manifest.steps.map((s) => ({ ...s })),
904
+ });
905
+
906
+ this.store._putReplayManifest({
907
+ manifestId,
908
+ runId: this.runId,
909
+ subjectId: manifest.subjectId,
910
+ manifestJson,
911
+ manifestHash: manifest.manifestHash,
912
+ createdUtc: utcNow(),
913
+ });
914
+
915
+ this.store.appendEvent(this.runId, "replay_manifest_saved_v5", {
916
+ manifest_id: manifestId,
917
+ subject_id: manifest.subjectId,
918
+ manifest_hash: manifest.manifestHash,
919
+ });
920
+
921
+ return manifestId;
922
+ }
923
+
924
+ async run(manifest: ReplayManifest, runner: ReplayRunner): Promise<boolean> {
925
+ const manifestId = this.saveManifest(manifest);
926
+ const stepResults: Array<Record<string, unknown>> = [];
927
+ let success = true;
928
+
929
+ for (const step of manifest.steps) {
930
+ const actualHash = await runner.runStep(step);
931
+ const ok = actualHash === step.expectedOutputHash;
932
+ success = success && ok;
933
+ stepResults.push({
934
+ name: step.name,
935
+ expected_output_hash: step.expectedOutputHash,
936
+ actual_output_hash: actualHash,
937
+ ok,
938
+ });
939
+ }
940
+
941
+ const result = {
942
+ manifest_id: manifestId,
943
+ subject_id: manifest.subjectId,
944
+ steps: stepResults,
945
+ success,
946
+ };
947
+ const resultJson = canonicalJson(result);
948
+ const replayId = "replay-" + sha256Text(resultJson).slice(0, 32);
949
+
950
+ this.store._putReplayResult({
951
+ replayId,
952
+ runId: this.runId,
953
+ manifestId,
954
+ success,
955
+ resultJson,
956
+ resultHash: sha256Text(resultJson),
957
+ createdUtc: utcNow(),
958
+ });
959
+
960
+ this.store.appendEvent(this.runId, "replay_run_v5", {
961
+ replay_id: replayId,
962
+ manifest_id: manifestId,
963
+ success,
964
+ });
965
+
966
+ return success;
967
+ }
968
+ }
969
+
970
+ // ═══════════════════════════════════════════════════════════════════════
971
+ // 8. Tool inventory drift
972
+ // ═══════════════════════════════════════════════════════════════════════
973
+
974
+ export class ToolInventoryMonitor {
975
+ constructor(
976
+ private readonly store: V5AssuranceStore,
977
+ private readonly runId: string,
978
+ ) {}
979
+
980
+ static snapshot(registry: ToolRegistry): Record<string, unknown> {
981
+ // V3's ToolRegistry exposes an allowlist of name → function. There is no
982
+ // version/side_effects metadata in the browser port, so the snapshot keys
983
+ // on the sorted tool names and a stable descriptor. Disclosed difference
984
+ // from the Python (which reads adapter.version / adapter.side_effects).
985
+ const names = (registry as unknown as { allowlist?: Map<string, unknown> }).allowlist;
986
+ const entries: Record<string, unknown> = {};
987
+ if (names instanceof Map) {
988
+ for (const name of [...names.keys()].sort()) {
989
+ entries[name] = { version: "1", side_effects: false };
990
+ }
991
+ }
992
+ return entries;
993
+ }
994
+
995
+ record(registry: ToolRegistry, snapshotId: string): string {
996
+ const inventory = ToolInventoryMonitor.snapshot(registry);
997
+ const inventoryJson = canonicalJson(inventory);
998
+ const inventoryHash = sha256Text(inventoryJson);
999
+
1000
+ this.store._putToolInventory({
1001
+ runId: this.runId,
1002
+ snapshotId,
1003
+ inventoryHash,
1004
+ inventoryJson,
1005
+ createdUtc: utcNow(),
1006
+ });
1007
+
1008
+ this.store.appendEvent(this.runId, "tool_inventory_recorded_v5", {
1009
+ snapshot_id: snapshotId,
1010
+ inventory_hash: inventoryHash,
1011
+ });
1012
+
1013
+ return inventoryHash;
1014
+ }
1015
+
1016
+ drifted(beforeId: string, afterId: string): boolean {
1017
+ const before = this.store._getToolInventory(this.runId, beforeId);
1018
+ const after = this.store._getToolInventory(this.runId, afterId);
1019
+ if (!before || !after) throw new Error("Missing inventory snapshot");
1020
+ return before.inventoryHash !== after.inventoryHash;
1021
+ }
1022
+ }
1023
+
1024
+ // ═══════════════════════════════════════════════════════════════════════
1025
+ // 9. Health monitor and assurance gateway
1026
+ // ═══════════════════════════════════════════════════════════════════════
1027
+
1028
+ export interface HealthThresholdsOptions {
1029
+ maxErrorRate?: number;
1030
+ maxP95LatencyMs?: number;
1031
+ maxPolicyDenials?: number;
1032
+ requireSemanticChain?: boolean;
1033
+ requireBlobIntegrity?: boolean;
1034
+ }
1035
+
1036
+ export class HealthThresholds {
1037
+ readonly maxErrorRate: number;
1038
+ readonly maxP95LatencyMs: number;
1039
+ readonly maxPolicyDenials: number;
1040
+ readonly requireSemanticChain: boolean;
1041
+ readonly requireBlobIntegrity: boolean;
1042
+
1043
+ constructor(options: HealthThresholdsOptions = {}) {
1044
+ this.maxErrorRate = options.maxErrorRate ?? 0.05;
1045
+ this.maxP95LatencyMs = options.maxP95LatencyMs ?? 60_000;
1046
+ this.maxPolicyDenials = options.maxPolicyDenials ?? 0;
1047
+ this.requireSemanticChain = options.requireSemanticChain ?? true;
1048
+ this.requireBlobIntegrity = options.requireBlobIntegrity ?? true;
1049
+ }
1050
+ }
1051
+
1052
+ export class RunHealthMonitor {
1053
+ constructor(
1054
+ private readonly store: V5AssuranceStore,
1055
+ private readonly runId: string,
1056
+ private readonly thresholds: HealthThresholds,
1057
+ ) {}
1058
+
1059
+ report(): Record<string, unknown> {
1060
+ const spans = this.store._getSpans(this.runId);
1061
+ const durations = spans.map((s) => s.durationMs);
1062
+ const errors = spans.filter((s) => s.status !== "ok");
1063
+
1064
+ let p95 = 0;
1065
+ if (durations.length > 0) {
1066
+ const ordered = [...durations].sort((a, b) => a - b);
1067
+ const index = Math.min(ordered.length - 1, Math.floor(0.95 * ordered.length));
1068
+ p95 = ordered[index];
1069
+ }
1070
+
1071
+ const errorRate = errors.length / Math.max(1, spans.length);
1072
+ const denials = this.store._countPolicyDenials(this.runId);
1073
+ const baseAudit = auditRuntime(this.store, this.runId);
1074
+
1075
+ let status = "ok";
1076
+ const reasons: string[] = [];
1077
+
1078
+ if (errorRate > this.thresholds.maxErrorRate) {
1079
+ status = "fail";
1080
+ reasons.push("span error rate exceeds threshold");
1081
+ }
1082
+ if (p95 > this.thresholds.maxP95LatencyMs) {
1083
+ status = "fail";
1084
+ reasons.push("p95 latency exceeds threshold");
1085
+ }
1086
+ if (denials > this.thresholds.maxPolicyDenials) {
1087
+ status = "fail";
1088
+ reasons.push("policy denials exceed threshold");
1089
+ }
1090
+ if (this.thresholds.requireSemanticChain && !baseAudit.v4_semantic_chain_valid) {
1091
+ status = "fail";
1092
+ reasons.push("semantic chain invalid");
1093
+ }
1094
+ if (this.thresholds.requireBlobIntegrity && !baseAudit.blob_integrity_valid) {
1095
+ status = "fail";
1096
+ reasons.push("blob integrity invalid");
1097
+ }
1098
+
1099
+ const report: Record<string, unknown> = {
1100
+ run_id: this.runId,
1101
+ status,
1102
+ reasons,
1103
+ span_count: spans.length,
1104
+ error_rate: Math.round(errorRate * 10000) / 10000,
1105
+ p95_latency_ms: p95,
1106
+ policy_denials: denials,
1107
+ base_audit: baseAudit,
1108
+ };
1109
+
1110
+ const reportJson = canonicalJson(report);
1111
+ const reportId = "health-" + sha256Text(reportJson).slice(0, 32);
1112
+
1113
+ this.store._putHealthReport({
1114
+ reportId,
1115
+ runId: this.runId,
1116
+ status,
1117
+ reportJson,
1118
+ reportHash: sha256Text(reportJson),
1119
+ createdUtc: utcNow(),
1120
+ });
1121
+
1122
+ this.store.appendEvent(this.runId, "health_report_v5", {
1123
+ report_id: reportId,
1124
+ status,
1125
+ report_hash: sha256Text(reportJson),
1126
+ });
1127
+
1128
+ return report;
1129
+ }
1130
+ }
1131
+
1132
+ /**
1133
+ * Final promotion-time assurance. V4 decides candidate promotion; V5 decides
1134
+ * whether promotion is operationally releasable.
1135
+ */
1136
+ export class AssuranceGateway {
1137
+ constructor(
1138
+ private readonly store: V5AssuranceStore,
1139
+ private readonly runId: string,
1140
+ private readonly policy: PolicyEngine,
1141
+ private readonly health: RunHealthMonitor,
1142
+ private readonly canaries: CanaryRegistry,
1143
+ private readonly verifier?: VerifierOrchestrator,
1144
+ ) {}
1145
+
1146
+ releasable(
1147
+ candidate: Candidate,
1148
+ promotion: PromotionRecord,
1149
+ risk: RiskTier,
1150
+ humanApprovals: readonly string[] = [],
1151
+ ): boolean {
1152
+ const canaryHits = this.canaries.hitCount(candidate.candidateId);
1153
+
1154
+ const decision = this.policy.evaluate({
1155
+ runId: this.runId,
1156
+ subject: candidate.candidateId,
1157
+ action: "promote_candidate",
1158
+ resource: "candidate",
1159
+ risk,
1160
+ payload: {
1161
+ evidence_closed: promotion.evidenceClosed,
1162
+ canary_hits: canaryHits,
1163
+ human_approvals: humanApprovals,
1164
+ },
1165
+ });
1166
+ this.policy.enforce(this.store, decision, this.runId);
1167
+
1168
+ if (this.verifier && !this.verifier.allRequiredPassed(candidate.candidateId)) {
1169
+ return false;
1170
+ }
1171
+
1172
+ const health = this.health.report();
1173
+ return (
1174
+ promotion.promoted &&
1175
+ promotion.evidenceClosed &&
1176
+ canaryHits === 0 &&
1177
+ health.status === "ok"
1178
+ );
1179
+ }
1180
+ }
1181
+
1182
+ // ═══════════════════════════════════════════════════════════════════════
1183
+ // 10. Fail-closed command entry points (CLI equivalents)
1184
+ // ═══════════════════════════════════════════════════════════════════════
1185
+
1186
+ export function cliHealthCheck(store: V5AssuranceStore, runId: string): {
1187
+ exitCode: number;
1188
+ report: Record<string, unknown>;
1189
+ } {
1190
+ const report = new RunHealthMonitor(store, runId, new HealthThresholds()).report();
1191
+ return { exitCode: report.status === "ok" ? 0 : 1, report };
1192
+ }
1193
+
1194
+ export function cliPolicyCheck(input: PolicyInput): {
1195
+ exitCode: number;
1196
+ decision: Record<string, unknown>;
1197
+ } {
1198
+ const decision = new PolicyEngine(defaultPolicyRules()).evaluate(input);
1199
+ return { exitCode: decision.allowed ? 0 : 1, decision: decision.toDict() };
1200
+ }
1201
+
1202
+ export function cliReplayResult(
1203
+ store: V5AssuranceStore,
1204
+ runId: string,
1205
+ replayId: string,
1206
+ ): { exitCode: number; result: Record<string, unknown> } {
1207
+ const row = store._getReplayResult(runId, replayId);
1208
+ if (!row) return { exitCode: 2, result: { error: "replay_id not found" } };
1209
+ return { exitCode: row.success ? 0 : 1, result: JSON.parse(row.resultJson) };
1210
+ }