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,804 @@
1
+ /**
2
+ * portfolio-consensus-adjudicator.ts
3
+ * ============================================================================
4
+ * ADDITIVE layer over the canonical canonical-portfolio-orchestrator.ts.
5
+ *
6
+ * WHAT THE CANONICAL PORTFOLIO LEAVES ON THE TABLE (verified by hand-trace):
7
+ * groundWithCanonicalPortfolio() computes an `agreement` matrix across all
8
+ * completed engine lanes, but chooseBest() never consults it. The winner is
9
+ * selected on a 7-field quality vector and final ties break on static
10
+ * `priority`. Cross-engine corroboration — a genuine reliability signal — is
11
+ * discarded.
12
+ *
13
+ * WHAT THIS ADDS (nothing else touched):
14
+ * 1. FAMILY-AWARE CORROBORATION
15
+ * Portfolio lanes are NOT all independent. terminal-wire /
16
+ * sentinel-orchestrator / vanguard-packer share the conclave-core
17
+ * internals; sentinel-omega and omni-nexus are self-contained;
18
+ * structured-search is API-only. Only agreement ACROSS distinct
19
+ * architectural families is counted as independent corroboration.
20
+ *
21
+ * 2. TWO CORROBORATION SIGNALS, HONESTLY LABELED
22
+ * - Block-level token Jaccard (already in portfolio.agreement) — noted as
23
+ * inflated by shared security-boundary boilerplate.
24
+ * - Claim-level echo: does another family's raw result contain a claim
25
+ * whose text matches a winner claim above a similarity floor. This is
26
+ * the STRONGER signal because it compares claim texts, not whole blocks.
27
+ * A non-winner family counts as an independent corroborator if EITHER
28
+ * signal fires.
29
+ *
30
+ * 3. STRICTLY-DOMINANT TIE-BREAK (opt-in)
31
+ * selection:"consensus" appends independent-corroboration count as an
32
+ * 8th, LOWEST-priority dimension. The first 7 dimensions are byte-for-byte
33
+ * the canonical quality vector, so the winner can only differ from the
34
+ * canonical winner when two lanes are EXACTLY equal on every hard trust
35
+ * dimension — in which case preferring the more-corroborated one is a
36
+ * strict reliability gain with zero loss. Default selection:"canonical"
37
+ * reproduces the canonical winner EXACTLY (no regression).
38
+ *
39
+ * 4. AUDITABLE DECISION LEDGER + CONSENSUS CONFIDENCE BAND
40
+ * Records which dimension decided each pairwise comparison and reports a
41
+ * strong/moderate/solo confidence label derived from the number of
42
+ * distinct independent families corroborating the winner.
43
+ *
44
+ * HONEST CEILING:
45
+ * Cross-engine textual agreement is surface corroboration, not factual
46
+ * verification. Several engines share internal components, so agreement is
47
+ * only meaningful across families and is used solely as a tie-break and an
48
+ * advisory confidence readout — never as a trust multiplier.
49
+ *
50
+ * ADDITIVE ONLY. No canonical file modified. No new npm dependency.
51
+ * NOT EXECUTED in this environment.
52
+ * ============================================================================ */
53
+
54
+ import {
55
+ groundWithCanonicalPortfolio,
56
+ type CanonicalLaneId,
57
+ type PortfolioOptions,
58
+ type LaneExecution,
59
+ type AgreementCell,
60
+ type StandardSource,
61
+ } from "./canonical-portfolio-orchestrator";
62
+
63
+ export type { CanonicalLaneId } from "./canonical-portfolio-orchestrator";
64
+
65
+ // ═══════════════════════════════════════════════════════════════════════════
66
+ // Engine families (which lanes share internal machinery)
67
+ // ═══════════════════════════════════════════════════════════════════════════
68
+
69
+ /**
70
+ * Architectural family of each canonical lane. Lanes in the same family are
71
+ * NOT independent witnesses because they wrap the same internal engines.
72
+ */
73
+ export const ENGINE_FAMILY: Record<CanonicalLaneId, string> = {
74
+ "terminal-wire": "conclave-core",
75
+ "sentinel-orchestrator": "conclave-core",
76
+ "vanguard-packer": "conclave-core",
77
+ "sentinel-omega": "omega-standalone",
78
+ "omni-nexus": "omni-standalone",
79
+ "structured-search": "structured-apis",
80
+ };
81
+
82
+ export function familyOf(id: CanonicalLaneId): string {
83
+ return ENGINE_FAMILY[id] ?? "unknown";
84
+ }
85
+
86
+ // ═══════════════════════════════════════════════════════════════════════════
87
+ // Public types
88
+ // ═══════════════════════════════════════════════════════════════════════════
89
+
90
+ export type ConsensusSelection = "canonical" | "consensus";
91
+
92
+ export interface PortfolioConsensusOptions
93
+ extends Omit<PortfolioOptions, "mode"> {
94
+ /** "canonical" = identical to canonical winner (default). */
95
+ selection?: ConsensusSelection;
96
+ /** Block-level Jaccard floor for corroboration. Default 0.30. */
97
+ blockCorroborationThreshold?: number;
98
+ /** Claim-text Jaccard floor for echo. Default 0.60. */
99
+ claimCorroborationSim?: number;
100
+ /** How many of the winner's claims to check for echo. Default 8. */
101
+ topClaims?: number;
102
+ }
103
+
104
+ export interface LaneConsensus {
105
+ laneId: CanonicalLaneId;
106
+ family: string;
107
+ acceptable: boolean;
108
+ blockMeanJaccard: number;
109
+ blockCorroborators: CanonicalLaneId[];
110
+ independentFamilies: string[];
111
+ independentCorroborationCount: number;
112
+ augmentedQuality: number[];
113
+ }
114
+
115
+ export interface ClaimCorroboration {
116
+ claimText: string;
117
+ winnerLane: CanonicalLaneId;
118
+ echoedByLanes: CanonicalLaneId[];
119
+ echoedByFamilies: string[];
120
+ independentEchoCount: number;
121
+ }
122
+
123
+ export interface DecisionLedgerEntry {
124
+ winner: CanonicalLaneId;
125
+ challenger: CanonicalLaneId;
126
+ decidedBy: string;
127
+ winnerValue: number;
128
+ challengerValue: number;
129
+ }
130
+
131
+ export type ConsensusConfidence =
132
+ | "strong"
133
+ | "moderate"
134
+ | "solo"
135
+ | "none";
136
+
137
+ export interface PortfolioConsensusResult {
138
+ ok: boolean;
139
+ provider: string;
140
+ selection: ConsensusSelection;
141
+
142
+ canonicalWinnerLane?: CanonicalLaneId;
143
+ consensusWinnerLane?: CanonicalLaneId;
144
+ winnerLane?: CanonicalLaneId;
145
+
146
+ count: number;
147
+ sources: StandardSource[];
148
+ evidenceBlock: string;
149
+
150
+ consensusConfidence: ConsensusConfidence;
151
+ consensusCaveat: string;
152
+
153
+ laneConsensus: LaneConsensus[];
154
+ claimCorroboration: ClaimCorroboration[];
155
+ decisionLedger: DecisionLedgerEntry[];
156
+
157
+ agreement: AgreementCell[];
158
+ laneResults: LaneExecution[];
159
+ winnerRaw?: unknown;
160
+ }
161
+
162
+ // ═══════════════════════════════════════════════════════════════════════════
163
+ // Helpers (pure, hand-traceable)
164
+ // ═══════════════════════════════════════════════════════════════════════════
165
+
166
+ const DIMENSION_NAMES = [
167
+ "acceptable",
168
+ "proofRank",
169
+ "attested",
170
+ "supported",
171
+ "claims",
172
+ "sources",
173
+ "blockLength",
174
+ "independentCorroboration",
175
+ ] as const;
176
+
177
+ const CONSENSUS_CAVEAT =
178
+ "Cross-engine corroboration is SURFACE textual agreement, not factual " +
179
+ "verification. Several portfolio engines share internal components " +
180
+ "(conclave-core family); only cross-family agreement is counted as " +
181
+ "independent, and block-level Jaccard is inflated by shared security " +
182
+ "boundary boilerplate. Claim-level echo is the stronger of the two signals.";
183
+
184
+ function isRecord(
185
+ value: unknown,
186
+ ): value is Record<string, unknown> {
187
+ return (
188
+ typeof value === "object" &&
189
+ value !== null &&
190
+ !Array.isArray(value)
191
+ );
192
+ }
193
+
194
+ function asString(value: unknown): string {
195
+ return typeof value === "string" ? value : "";
196
+ }
197
+
198
+ export function tokenSet(text: string): Set<string> {
199
+ let tokens: string[];
200
+ try {
201
+ tokens = text.toLowerCase().match(/[\p{L}\p{N}]+/gu) ?? [];
202
+ } catch {
203
+ tokens = text.toLowerCase().match(/[a-z0-9]+/g) ?? [];
204
+ }
205
+ return new Set(tokens.filter((t) => t.length > 2));
206
+ }
207
+
208
+ export function tokenJaccard(left: string, right: string): number {
209
+ const a = tokenSet(left);
210
+ const b = tokenSet(right);
211
+ if (a.size === 0 || b.size === 0) return 0;
212
+ let inter = 0;
213
+ for (const t of a) if (b.has(t)) inter += 1;
214
+ const union = a.size + b.size - inter;
215
+ return union > 0 ? inter / union : 0;
216
+ }
217
+
218
+ /** Extract claim texts from an arbitrary engine's raw result, defensively. */
219
+ export function extractClaimTexts(raw: unknown): string[] {
220
+ if (!isRecord(raw)) return [];
221
+ const arr = Array.isArray(raw.claims) ? raw.claims : [];
222
+ const out: string[] = [];
223
+ for (const claim of arr) {
224
+ if (typeof claim === "string") {
225
+ if (claim.trim()) out.push(claim.trim());
226
+ continue;
227
+ }
228
+ if (isRecord(claim)) {
229
+ const text =
230
+ asString(claim.text) ||
231
+ asString(claim.representativeText) ||
232
+ asString(claim.canonicalText) ||
233
+ asString(claim.claim);
234
+ if (text.trim()) out.push(text.trim());
235
+ }
236
+ }
237
+ return out;
238
+ }
239
+
240
+ function jaccardBetween(
241
+ a: CanonicalLaneId,
242
+ b: CanonicalLaneId,
243
+ agreement: AgreementCell[],
244
+ ): number | undefined {
245
+ for (const cell of agreement) {
246
+ if (
247
+ (cell.left === a && cell.right === b) ||
248
+ (cell.left === b && cell.right === a)
249
+ ) {
250
+ return cell.tokenJaccard;
251
+ }
252
+ }
253
+ return undefined;
254
+ }
255
+
256
+ function completedEligible(
257
+ lanes: LaneExecution[],
258
+ ): Array<
259
+ LaneExecution & {
260
+ normalized: NonNullable<LaneExecution["normalized"]>;
261
+ }
262
+ > {
263
+ return lanes.filter(
264
+ (
265
+ lane,
266
+ ): lane is LaneExecution & {
267
+ normalized: NonNullable<LaneExecution["normalized"]>;
268
+ } =>
269
+ lane.status === "fulfilled" &&
270
+ lane.normalized !== undefined &&
271
+ lane.normalized.eligibleForWinner,
272
+ );
273
+ }
274
+
275
+ function compareAugmented(
276
+ a: readonly number[],
277
+ b: readonly number[],
278
+ ): number {
279
+ const n = Math.max(a.length, b.length);
280
+ for (let i = 0; i < n; i += 1) {
281
+ const delta = (a[i] ?? 0) - (b[i] ?? 0);
282
+ if (delta !== 0) return delta;
283
+ }
284
+ return 0;
285
+ }
286
+
287
+ // ═══════════════════════════════════════════════════════════════════════════
288
+ // Core corroboration computation
289
+ // ═══════════════════════════════════════════════════════════════════════════
290
+
291
+ interface WorkingLane {
292
+ id: CanonicalLaneId;
293
+ family: string;
294
+ priority: number;
295
+ acceptable: boolean;
296
+ qualityVector: readonly number[];
297
+ evidenceBlock: string;
298
+ sources: StandardSource[];
299
+ claims: string[];
300
+ raw: unknown;
301
+ }
302
+
303
+ function toWorkingLane(
304
+ lane: LaneExecution & {
305
+ normalized: NonNullable<LaneExecution["normalized"]>;
306
+ },
307
+ ): WorkingLane {
308
+ return {
309
+ id: lane.id,
310
+ family: familyOf(lane.id),
311
+ priority: lane.priority,
312
+ acceptable: lane.normalized.acceptable,
313
+ qualityVector: lane.normalized.qualityVector,
314
+ evidenceBlock: lane.normalized.evidenceBlock,
315
+ sources: lane.normalized.sources,
316
+ claims: extractClaimTexts(lane.raw),
317
+ raw: lane.raw,
318
+ };
319
+ }
320
+
321
+ /**
322
+ * Compute, for `target`, the set of DISTINCT non-family families that
323
+ * corroborate it via block-level Jaccard OR claim-level echo.
324
+ */
325
+ function independentCorroboration(
326
+ target: WorkingLane,
327
+ others: WorkingLane[],
328
+ agreement: AgreementCell[],
329
+ blockThreshold: number,
330
+ claimSim: number,
331
+ topClaims: number,
332
+ ): {
333
+ independentFamilies: string[];
334
+ blockCorroborators: CanonicalLaneId[];
335
+ blockMeanJaccard: number;
336
+ } {
337
+ const winnerClaims = target.claims.slice(0, topClaims);
338
+ const families = new Set<string>();
339
+ const blockCorroborators: CanonicalLaneId[] = [];
340
+
341
+ let jaccardSum = 0;
342
+ let jaccardCount = 0;
343
+
344
+ for (const other of others) {
345
+ if (other.id === target.id) continue;
346
+
347
+ const j = jaccardBetween(target.id, other.id, agreement);
348
+ if (j !== undefined) {
349
+ jaccardSum += j;
350
+ jaccardCount += 1;
351
+ }
352
+
353
+ const blockOk = j !== undefined && j >= blockThreshold;
354
+ if (blockOk) blockCorroborators.push(other.id);
355
+
356
+ const claimOk =
357
+ winnerClaims.length > 0 &&
358
+ other.claims.length > 0 &&
359
+ winnerClaims.some((wc) =>
360
+ other.claims.some(
361
+ (oc) => tokenJaccard(wc, oc) >= claimSim,
362
+ ),
363
+ );
364
+
365
+ if ((blockOk || claimOk) && other.family !== target.family) {
366
+ families.add(other.family);
367
+ }
368
+ }
369
+
370
+ return {
371
+ independentFamilies: Array.from(families).sort(),
372
+ blockCorroborators,
373
+ blockMeanJaccard:
374
+ jaccardCount > 0 ? jaccardSum / jaccardCount : 0,
375
+ };
376
+ }
377
+
378
+ function confidenceFor(
379
+ independentFamilyCount: number,
380
+ acceptable: boolean,
381
+ ): ConsensusConfidence {
382
+ if (!acceptable) return "none";
383
+ if (independentFamilyCount >= 2) return "strong";
384
+ if (independentFamilyCount === 1) return "moderate";
385
+ return "solo";
386
+ }
387
+
388
+ function buildDecisionLedger(
389
+ winner: {
390
+ id: CanonicalLaneId;
391
+ augmented: number[];
392
+ priority: number;
393
+ },
394
+ challengers: Array<{
395
+ id: CanonicalLaneId;
396
+ augmented: number[];
397
+ priority: number;
398
+ }>,
399
+ ): DecisionLedgerEntry[] {
400
+ const ledger: DecisionLedgerEntry[] = [];
401
+ for (const challenger of challengers) {
402
+ if (challenger.id === winner.id) continue;
403
+ let decidedBy = "priority";
404
+ let winnerValue = winner.priority;
405
+ let challengerValue = challenger.priority;
406
+
407
+ const n = Math.max(
408
+ winner.augmented.length,
409
+ challenger.augmented.length,
410
+ );
411
+ for (let i = 0; i < n; i += 1) {
412
+ const w = winner.augmented[i] ?? 0;
413
+ const c = challenger.augmented[i] ?? 0;
414
+ if (w !== c) {
415
+ decidedBy = DIMENSION_NAMES[i] ?? `dim${i}`;
416
+ winnerValue = w;
417
+ challengerValue = c;
418
+ break;
419
+ }
420
+ }
421
+
422
+ ledger.push({
423
+ winner: winner.id,
424
+ challenger: challenger.id,
425
+ decidedBy,
426
+ winnerValue,
427
+ challengerValue,
428
+ });
429
+ }
430
+ return ledger;
431
+ }
432
+
433
+ // ═══════════════════════════════════════════════════════════════════════════
434
+ // Public entry point
435
+ // ═══════════════════════════════════════════════════════════════════════════
436
+
437
+ export async function groundWithPortfolioConsensus(
438
+ question: string,
439
+ options: PortfolioConsensusOptions = {},
440
+ ): Promise<PortfolioConsensusResult> {
441
+ const selection: ConsensusSelection =
442
+ options.selection ?? "canonical";
443
+ const blockThreshold =
444
+ options.blockCorroborationThreshold ?? 0.3;
445
+ const claimSim = options.claimCorroborationSim ?? 0.6;
446
+ const topClaims = Math.max(
447
+ 1,
448
+ Math.min(32, Math.floor(options.topClaims ?? 8)),
449
+ );
450
+
451
+ // Consensus needs multiple completed engines → force audit-all.
452
+ const portfolio = await groundWithCanonicalPortfolio(question, {
453
+ ...options,
454
+ mode: "audit-all",
455
+ });
456
+
457
+ const eligible = completedEligible(portfolio.laneResults);
458
+
459
+ const emptyReturn = (): PortfolioConsensusResult => ({
460
+ ok: portfolio.ok,
461
+ provider: `portfolio-consensus(${selection}:${portfolio.provider})`,
462
+ selection,
463
+ canonicalWinnerLane: portfolio.winnerLane,
464
+ consensusWinnerLane: portfolio.winnerLane,
465
+ winnerLane: portfolio.winnerLane,
466
+ count: portfolio.count,
467
+ sources: portfolio.sources,
468
+ evidenceBlock: portfolio.evidenceBlock,
469
+ consensusConfidence: "none",
470
+ consensusCaveat: CONSENSUS_CAVEAT,
471
+ laneConsensus: [],
472
+ claimCorroboration: [],
473
+ decisionLedger: [],
474
+ agreement: portfolio.agreement,
475
+ laneResults: portfolio.laneResults,
476
+ winnerRaw: portfolio.winnerRaw,
477
+ });
478
+
479
+ if (eligible.length === 0) return emptyReturn();
480
+
481
+ const working = eligible.map(toWorkingLane);
482
+
483
+ // Per-lane corroboration + augmented quality vector.
484
+ const laneConsensus: LaneConsensus[] = [];
485
+ const augmentedById = new Map<CanonicalLaneId, number[]>();
486
+
487
+ for (const lane of working) {
488
+ const corr = independentCorroboration(
489
+ lane,
490
+ working,
491
+ portfolio.agreement,
492
+ blockThreshold,
493
+ claimSim,
494
+ topClaims,
495
+ );
496
+ const augmented = [
497
+ ...lane.qualityVector,
498
+ corr.independentFamilies.length,
499
+ ];
500
+ augmentedById.set(lane.id, augmented);
501
+
502
+ laneConsensus.push({
503
+ laneId: lane.id,
504
+ family: lane.family,
505
+ acceptable: lane.acceptable,
506
+ blockMeanJaccard: corr.blockMeanJaccard,
507
+ blockCorroborators: corr.blockCorroborators,
508
+ independentFamilies: corr.independentFamilies,
509
+ independentCorroborationCount:
510
+ corr.independentFamilies.length,
511
+ augmentedQuality: augmented,
512
+ });
513
+ }
514
+
515
+ const acceptableLanes = working.filter((l) => l.acceptable);
516
+
517
+ // ── Canonical winner: exactly what the canonical portfolio chose ────────
518
+ const canonicalWinnerId = portfolio.winnerLane;
519
+
520
+ // ── Consensus winner: augmented lexicographic (7 hard dims + corroboration)
521
+ let consensusWinner: WorkingLane | undefined;
522
+ for (const lane of acceptableLanes) {
523
+ if (!consensusWinner) {
524
+ consensusWinner = lane;
525
+ continue;
526
+ }
527
+ const cmp = compareAugmented(
528
+ augmentedById.get(lane.id) ?? [],
529
+ augmentedById.get(consensusWinner.id) ?? [],
530
+ );
531
+ if (cmp > 0 || (cmp === 0 && lane.priority > consensusWinner.priority)) {
532
+ consensusWinner = lane;
533
+ }
534
+ }
535
+ const consensusWinnerId = consensusWinner?.id;
536
+
537
+ // ── Choose the lane whose output we actually surface ────────────────────
538
+ const finalWinnerId =
539
+ selection === "consensus"
540
+ ? consensusWinnerId ?? canonicalWinnerId
541
+ : canonicalWinnerId;
542
+
543
+ const finalWorking = working.find((l) => l.id === finalWinnerId);
544
+ const finalNormalizedLane = eligible.find(
545
+ (l) => l.id === finalWinnerId,
546
+ );
547
+
548
+ // If default (canonical) selection, preserve canonical output byte-for-byte.
549
+ const surfacedEvidence =
550
+ selection === "canonical"
551
+ ? portfolio.evidenceBlock
552
+ : finalNormalizedLane?.normalized.evidenceBlock ??
553
+ portfolio.evidenceBlock;
554
+
555
+ const surfacedSources =
556
+ selection === "canonical"
557
+ ? portfolio.sources
558
+ : finalNormalizedLane?.normalized.sources ??
559
+ portfolio.sources;
560
+
561
+ const surfacedCount =
562
+ selection === "canonical"
563
+ ? portfolio.count
564
+ : finalNormalizedLane?.normalized.sourceCount ??
565
+ portfolio.count;
566
+
567
+ const surfacedRaw =
568
+ selection === "canonical"
569
+ ? portfolio.winnerRaw
570
+ : finalNormalizedLane?.raw ?? portfolio.winnerRaw;
571
+
572
+ // ── Confidence + claim corroboration for the surfaced winner ────────────
573
+ const finalConsensus = laneConsensus.find(
574
+ (c) => c.laneId === finalWinnerId,
575
+ );
576
+ const confidence = confidenceFor(
577
+ finalConsensus?.independentCorroborationCount ?? 0,
578
+ finalConsensus?.acceptable ?? false,
579
+ );
580
+
581
+ const claimCorroboration: ClaimCorroboration[] = [];
582
+ if (finalWorking) {
583
+ const others = working.filter((l) => l.id !== finalWorking.id);
584
+ for (const claimText of finalWorking.claims.slice(0, topClaims)) {
585
+ const echoedByLanes: CanonicalLaneId[] = [];
586
+ const echoedByFamilies = new Set<string>();
587
+ for (const other of others) {
588
+ const echoed = other.claims.some(
589
+ (oc) => tokenJaccard(claimText, oc) >= claimSim,
590
+ );
591
+ if (echoed) {
592
+ echoedByLanes.push(other.id);
593
+ if (other.family !== finalWorking.family) {
594
+ echoedByFamilies.add(other.family);
595
+ }
596
+ }
597
+ }
598
+ if (echoedByLanes.length > 0) {
599
+ claimCorroboration.push({
600
+ claimText: claimText.slice(0, 200),
601
+ winnerLane: finalWorking.id,
602
+ echoedByLanes,
603
+ echoedByFamilies: Array.from(echoedByFamilies).sort(),
604
+ independentEchoCount: echoedByFamilies.size,
605
+ });
606
+ }
607
+ }
608
+ }
609
+
610
+ // ── Decision ledger for the surfaced winner ─────────────────────────────
611
+ const decisionLedger = finalWinnerId
612
+ ? buildDecisionLedger(
613
+ {
614
+ id: finalWinnerId,
615
+ augmented: augmentedById.get(finalWinnerId) ?? [],
616
+ priority:
617
+ eligible.find((l) => l.id === finalWinnerId)?.priority ?? 0,
618
+ },
619
+ acceptableLanes.map((l) => ({
620
+ id: l.id,
621
+ augmented: augmentedById.get(l.id) ?? [],
622
+ priority: l.priority,
623
+ })),
624
+ )
625
+ : [];
626
+
627
+ return {
628
+ ok: portfolio.ok && finalWinnerId !== undefined,
629
+ provider: `portfolio-consensus(${selection}:${finalWinnerId ?? "none"}→conf=${confidence})`,
630
+ selection,
631
+ canonicalWinnerLane: canonicalWinnerId,
632
+ consensusWinnerLane: consensusWinnerId,
633
+ winnerLane: finalWinnerId,
634
+ count: surfacedCount,
635
+ sources: surfacedSources,
636
+ evidenceBlock: surfacedEvidence,
637
+ consensusConfidence: confidence,
638
+ consensusCaveat: CONSENSUS_CAVEAT,
639
+ laneConsensus,
640
+ claimCorroboration,
641
+ decisionLedger,
642
+ agreement: portfolio.agreement,
643
+ laneResults: portfolio.laneResults,
644
+ winnerRaw: surfacedRaw,
645
+ };
646
+ }
647
+
648
+ // ═══════════════════════════════════════════════════════════════════════════
649
+ // Diagnostics — pure, synchronous, no network, fully awaited by construction
650
+ // ═══════════════════════════════════════════════════════════════════════════
651
+
652
+ export function runPortfolioConsensusDiagnostics(): {
653
+ ok: boolean;
654
+ checks: Array<{ id: string; passed: boolean; detail: string }>;
655
+ } {
656
+ const checks: Array<{ id: string; passed: boolean; detail: string }> = [];
657
+ const add = (id: string, passed: boolean, detail: string) =>
658
+ checks.push({ id, passed, detail });
659
+
660
+ // 1. tokenJaccard bounds
661
+ add(
662
+ "jaccard-identical",
663
+ tokenJaccard("alpha beta gamma", "alpha beta gamma") === 1,
664
+ "identical=1",
665
+ );
666
+ add(
667
+ "jaccard-disjoint",
668
+ tokenJaccard("alpha beta gamma", "quartz violin nebula") === 0,
669
+ "disjoint=0",
670
+ );
671
+
672
+ // 2. family map
673
+ add(
674
+ "family-conclave-core",
675
+ familyOf("terminal-wire") === "conclave-core" &&
676
+ familyOf("vanguard-packer") === "conclave-core",
677
+ "shared-core grouped",
678
+ );
679
+ add(
680
+ "family-standalone-distinct",
681
+ familyOf("sentinel-omega") !== familyOf("omni-nexus") &&
682
+ familyOf("sentinel-omega") !== familyOf("terminal-wire"),
683
+ "standalone families separate",
684
+ );
685
+
686
+ // 3. claim extraction duck-typing
687
+ const claims = extractClaimTexts({
688
+ claims: [
689
+ "a plain string claim",
690
+ { text: "text-field claim" },
691
+ { representativeText: "rep-field claim" },
692
+ { canonicalText: "canonical-field claim" },
693
+ { irrelevant: "ignored" },
694
+ ],
695
+ });
696
+ add(
697
+ "extract-claims-shapes",
698
+ claims.length === 4 &&
699
+ claims.includes("a plain string claim") &&
700
+ claims.includes("rep-field claim"),
701
+ `n=${claims.length}`,
702
+ );
703
+ add(
704
+ "extract-claims-nonrecord",
705
+ extractClaimTexts("not an object").length === 0,
706
+ "non-record → []",
707
+ );
708
+
709
+ // 4. augmented comparison: equal 7 dims, higher corroboration wins
710
+ const base = [1, 4, 2, 1, 3, 3, 500] as const;
711
+ add(
712
+ "augmented-corroboration-tiebreak",
713
+ compareAugmented([...base, 2], [...base, 1]) > 0 &&
714
+ compareAugmented([...base, 0], [...base, 2]) < 0,
715
+ "dim8 breaks exact tie",
716
+ );
717
+ add(
718
+ "augmented-hard-dim-dominates",
719
+ // higher attested (dim2) beats higher corroboration (dim8)
720
+ compareAugmented([1, 4, 9, 1, 3, 3, 500, 0], [1, 4, 2, 1, 3, 3, 500, 9]) > 0,
721
+ "hard trust dimension dominates corroboration",
722
+ );
723
+
724
+ // 5. jaccardBetween lookup (order-independent)
725
+ const agreement: AgreementCell[] = [
726
+ { left: "terminal-wire", right: "omni-nexus", tokenJaccard: 0.5 },
727
+ { left: "sentinel-omega", right: "terminal-wire", tokenJaccard: 0.2 },
728
+ ];
729
+ add(
730
+ "agreement-lookup-symmetric",
731
+ jaccardBetween("omni-nexus", "terminal-wire", agreement) === 0.5 &&
732
+ jaccardBetween("terminal-wire", "sentinel-omega", agreement) === 0.2 &&
733
+ jaccardBetween("terminal-wire", "vanguard-packer", agreement) === undefined,
734
+ "symmetric lookup + undefined for absent",
735
+ );
736
+
737
+ // 6. independentCorroboration: cross-family counts, same-family excluded
738
+ const mkLane = (
739
+ id: CanonicalLaneId,
740
+ claimsArr: string[],
741
+ ): WorkingLane => ({
742
+ id,
743
+ family: familyOf(id),
744
+ priority: 0,
745
+ acceptable: true,
746
+ qualityVector: base,
747
+ evidenceBlock: "",
748
+ sources: [],
749
+ claims: claimsArr,
750
+ raw: {},
751
+ });
752
+
753
+ const winner = mkLane("terminal-wire", [
754
+ "the widget market grew twelve percent in the third quarter",
755
+ ]);
756
+ const sameFamily = mkLane("sentinel-orchestrator", [
757
+ "the widget market grew twelve percent in the third quarter",
758
+ ]);
759
+ const crossFamily = mkLane("omni-nexus", [
760
+ "the widget market grew twelve percent in the third quarter",
761
+ ]);
762
+
763
+ const corr = independentCorroboration(
764
+ winner,
765
+ [winner, sameFamily, crossFamily],
766
+ [],
767
+ 0.3,
768
+ 0.6,
769
+ 8,
770
+ );
771
+ add(
772
+ "corroboration-cross-family-only",
773
+ corr.independentFamilies.length === 1 &&
774
+ corr.independentFamilies[0] === "omni-standalone",
775
+ `families=${JSON.stringify(corr.independentFamilies)}`,
776
+ );
777
+
778
+ // 7. confidence bands
779
+ add(
780
+ "confidence-strong",
781
+ confidenceFor(2, true) === "strong" &&
782
+ confidenceFor(1, true) === "moderate" &&
783
+ confidenceFor(0, true) === "solo" &&
784
+ confidenceFor(2, false) === "none",
785
+ "band thresholds",
786
+ );
787
+
788
+ // 8. decision ledger names the deciding dimension
789
+ const ledger = buildDecisionLedger(
790
+ { id: "terminal-wire", augmented: [1, 4, 5, 0, 0, 0, 0, 0], priority: 100 },
791
+ [
792
+ { id: "omni-nexus", augmented: [1, 4, 2, 0, 0, 0, 0, 0], priority: 60 },
793
+ ],
794
+ );
795
+ add(
796
+ "ledger-decides-on-attested",
797
+ ledger.length === 1 &&
798
+ ledger[0].decidedBy === "attested" &&
799
+ ledger[0].winnerValue === 5,
800
+ `decidedBy=${ledger[0]?.decidedBy}`,
801
+ );
802
+
803
+ return { ok: checks.every((c) => c.passed), checks };
804
+ }