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,277 @@
1
+ /**
2
+ * terminal-final.ts
3
+ * ============================================================================
4
+ * TRUE TERMINAL — chains the corrected governor with structured pre-fetch,
5
+ * real-time independence, marginal gain, and a unified diagnostic hub.
6
+ *
7
+ * ADDITIVE ONLY. No canonical file modified. Browser/static-build compatible.
8
+ * ============================================================================ */
9
+
10
+ import {
11
+ ENGINE_FAMILY,
12
+ familyOf,
13
+ groundWithTerminalPortfolioGovernor,
14
+ runPortfolioTerminalGovernorDiagnostics,
15
+ type TerminalGovernorOptions,
16
+ type TerminalGovernorResult,
17
+ } from "./portfolio-terminal-governor";
18
+ import {
19
+ runPortfolioConsensusDiagnostics,
20
+ } from "./portfolio-consensus-adjudicator";
21
+ import {
22
+ runCanonicalPortfolioDiagnostics,
23
+ type CanonicalLaneId,
24
+ type LaneExecution,
25
+ type StandardSource,
26
+ } from "./canonical-portfolio-orchestrator";
27
+ import { runSpaRescueBridgeDiagnostics } from "./spa-rescue-bridge";
28
+ import {
29
+ structuredSearch,
30
+ type StructuredAdapterOptions,
31
+ type StructuredItem,
32
+ } from "./structured-source-adapter";
33
+ import { cachedValue } from "./retrieval-accelerator";
34
+
35
+ export interface TerminalFinalOptions extends TerminalGovernorOptions {
36
+ structuredPreFetch?: boolean;
37
+ openAlexApiKey?: string;
38
+ }
39
+
40
+ export interface TerminalIndependence {
41
+ distinctFamilies: number;
42
+ fulfilledFamilies: string[];
43
+ effectiveWitnessCount: number;
44
+ }
45
+
46
+ export interface TerminalMarginalGain {
47
+ fulfilledCount: number;
48
+ failedCount: number;
49
+ extraLanesChangedWinner: boolean;
50
+ attestedDelta: number;
51
+ assessment: "high-value" | "moderate-value" | "low-value" | "single-lane-only";
52
+ }
53
+
54
+ export interface TerminalFinalResult extends TerminalGovernorResult {
55
+ structuredItems: StructuredItem[];
56
+ portfolioIndependence: TerminalIndependence;
57
+ marginalGain: TerminalMarginalGain;
58
+ }
59
+
60
+ function computeIndependence(lanes: LaneExecution[]): TerminalIndependence {
61
+ const families = new Set<string>();
62
+ for (const lane of lanes) {
63
+ if (lane.status === "fulfilled") families.add(familyOf(lane.id));
64
+ }
65
+ const fulfilledFamilies = Array.from(families).sort();
66
+ return {
67
+ distinctFamilies: fulfilledFamilies.length,
68
+ fulfilledFamilies,
69
+ effectiveWitnessCount: fulfilledFamilies.length,
70
+ };
71
+ }
72
+
73
+ function computeMarginalGain(
74
+ lanes: LaneExecution[],
75
+ canonicalWinner: CanonicalLaneId | undefined,
76
+ consensusWinner: CanonicalLaneId | undefined,
77
+ ): TerminalMarginalGain {
78
+ const fulfilled = lanes.filter((lane) => lane.status === "fulfilled");
79
+ const failedCount = lanes.length - fulfilled.length;
80
+ if (fulfilled.length <= 1) {
81
+ return { fulfilledCount: fulfilled.length, failedCount, extraLanesChangedWinner: false, attestedDelta: 0, assessment: "single-lane-only" };
82
+ }
83
+ const extraLanesChangedWinner = canonicalWinner !== undefined && consensusWinner !== undefined && canonicalWinner !== consensusWinner;
84
+ const winnerId = consensusWinner ?? canonicalWinner;
85
+ const winnerAttested = fulfilled.find((lane) => lane.id === winnerId)?.normalized?.attestedCount ?? 0;
86
+ const bestOther = Math.max(0, ...fulfilled.filter((lane) => lane.id !== winnerId).map((lane) => lane.normalized?.attestedCount ?? 0));
87
+ const attestedDelta = winnerAttested - bestOther;
88
+ const assessment = extraLanesChangedWinner || attestedDelta >= 2
89
+ ? "high-value"
90
+ : attestedDelta >= 1 || fulfilled.length >= 3
91
+ ? "moderate-value"
92
+ : "low-value";
93
+ return { fulfilledCount: fulfilled.length, failedCount, extraLanesChangedWinner, attestedDelta, assessment };
94
+ }
95
+
96
+ // RFC 9309 strict helper: 4xx robots responses allow crawling, while network
97
+ // errors and 5xx responses deny. It is available to crawl callers without
98
+ // changing the package policy module.
99
+ const ROBOTS_TTL_MS = 24 * 60 * 60_000;
100
+
101
+ function parseRobotsStarRules(text: string): Array<{ allow: boolean; path: string }> {
102
+ const rules: Array<{ allow: boolean; path: string }> = [];
103
+ let inStarGroup = false;
104
+ let sawUserAgent = false;
105
+ for (const rawLine of text.split(/\r?\n/)) {
106
+ const line = rawLine.replace(/#.*$/, "").trim();
107
+ const separator = line.indexOf(":");
108
+ if (!line || separator < 0) continue;
109
+ const key = line.slice(0, separator).trim().toLowerCase();
110
+ const value = line.slice(separator + 1).trim();
111
+ if (key === "user-agent") {
112
+ sawUserAgent = true;
113
+ inStarGroup = value === "*";
114
+ } else if (sawUserAgent && inStarGroup && value && (key === "allow" || key === "disallow")) {
115
+ rules.push({ allow: key === "allow", path: value });
116
+ }
117
+ }
118
+ return rules;
119
+ }
120
+
121
+ function robotsPathMatches(path: string, rulePath: string): boolean {
122
+ if (!rulePath) return false;
123
+ if (rulePath.endsWith("$")) return path === rulePath.slice(0, -1);
124
+ return path.startsWith(rulePath);
125
+ }
126
+
127
+ export function makeRfc9309RobotsDecision(): (url: string, signal?: AbortSignal) => Promise<"allow" | "deny" | "unknown"> {
128
+ return async (url, signal) => {
129
+ let origin = "";
130
+ let path = "";
131
+ try {
132
+ const parsed = new URL(url);
133
+ origin = parsed.origin;
134
+ path = `${parsed.pathname}${parsed.search}`;
135
+ } catch {
136
+ return "unknown";
137
+ }
138
+ const cached = await cachedValue(`terminal-rfc9309\u0000${origin}`, ROBOTS_TTL_MS, async () => {
139
+ try {
140
+ const controller = new AbortController();
141
+ const timeout = setTimeout(() => controller.abort(), 4_000);
142
+ signal?.addEventListener("abort", () => controller.abort(), { once: true });
143
+ const response = await fetch(`${origin}/robots.txt`, {
144
+ signal: controller.signal,
145
+ credentials: "omit",
146
+ referrerPolicy: "no-referrer",
147
+ });
148
+ clearTimeout(timeout);
149
+ if (response.status >= 500) return { kind: "unreachable" as const, rules: [] };
150
+ if (!response.ok) return { kind: "unavailable" as const, rules: [] };
151
+ return { kind: "ok" as const, rules: parseRobotsStarRules((await response.text()).slice(0, 512 * 1024)) };
152
+ } catch {
153
+ return { kind: "unreachable" as const, rules: [] };
154
+ }
155
+ });
156
+ if (cached.value.kind === "unreachable") return "deny";
157
+ if (cached.value.kind === "unavailable") return "allow";
158
+ let best: { allow: boolean; path: string } | undefined;
159
+ for (const rule of cached.value.rules) {
160
+ if (robotsPathMatches(path, rule.path) && (!best || rule.path.length > best.path.length)) best = rule;
161
+ }
162
+ return best?.allow === false ? "deny" : "allow";
163
+ };
164
+ }
165
+
166
+ export async function groundTerminalFinal(
167
+ question: string,
168
+ opts?: TerminalFinalOptions,
169
+ ): Promise<TerminalFinalResult> {
170
+ const dbg = opts?.onDebug ?? (() => {});
171
+ const normalized = (question ?? "").replace(/\s+/g, " ").trim();
172
+ const doStructured = opts?.structuredPreFetch !== false;
173
+
174
+ const structuredPromise = doStructured && normalized
175
+ ? structuredSearch(normalized, {
176
+ signal: opts?.signal,
177
+ limitPerSource: 6,
178
+ openAlexApiKey: opts?.openAlexApiKey,
179
+ } satisfies StructuredAdapterOptions).catch(() => ({
180
+ items: [] as StructuredItem[],
181
+ queriedSources: [] as string[],
182
+ totalFound: 0,
183
+ }))
184
+ : Promise.resolve({ items: [] as StructuredItem[], queriedSources: [] as string[], totalFound: 0 });
185
+
186
+ dbg("terminal-final: groundWithTerminalPortfolioGovernor");
187
+ const governorResult = await groundWithTerminalPortfolioGovernor(normalized, {
188
+ ...opts,
189
+ onDebug: (message) => dbg(`[governor] ${message}`),
190
+ });
191
+ const structured = await structuredPromise;
192
+ const portfolioIndependence = computeIndependence(governorResult.laneResults);
193
+ const marginalGain = computeMarginalGain(
194
+ governorResult.laneResults,
195
+ governorResult.canonicalWinnerLane,
196
+ governorResult.consensusWinnerLane,
197
+ );
198
+
199
+ const seenUrls = new Set(governorResult.sources.map((source) => source.url));
200
+ const extraSources: StandardSource[] = [];
201
+ for (const item of structured.items) {
202
+ const url = item.externalUrl ?? (item.doi ? `https://doi.org/${item.doi}` : undefined) ?? `structured:${item.kind}:${item.title.slice(0, 40)}`;
203
+ if (!url || seenUrls.has(url)) continue;
204
+ seenUrls.add(url);
205
+ extraSources.push({
206
+ title: item.title || "Structured Item",
207
+ url,
208
+ content: (item.pageContent || item.abstract || "").slice(0, 1800),
209
+ });
210
+ }
211
+
212
+ let evidenceBlock = governorResult.evidenceBlock;
213
+ if (structured.items.length > 0 && evidenceBlock.length > 0) {
214
+ const items = structured.items.slice(0, 6).map((item, index) =>
215
+ `[STRUCTURED:${item.kind.toUpperCase()}:${index + 1}] ${item.title}\n${(item.pageContent || "").slice(0, 360)}`,
216
+ ).join("\n\n");
217
+ const insertion = evidenceBlock.lastIndexOf("END RETRIEVED CONTENT");
218
+ if (insertion >= 0) {
219
+ evidenceBlock = `${evidenceBlock.slice(0, insertion)}BEGIN STRUCTURED API ITEMS\n${items}\nEND STRUCTURED API ITEMS\n\n${evidenceBlock.slice(insertion)}`;
220
+ }
221
+ }
222
+
223
+ return {
224
+ ...governorResult,
225
+ provider: `terminal-final(${governorResult.provider}+structured:${structured.items.length}+families:${portfolioIndependence.distinctFamilies})`,
226
+ count: governorResult.sources.length + extraSources.length,
227
+ sources: [...governorResult.sources, ...extraSources],
228
+ evidenceBlock,
229
+ structuredItems: structured.items,
230
+ portfolioIndependence,
231
+ marginalGain,
232
+ };
233
+ }
234
+
235
+ export async function runTerminalFinalDiagnostics(): Promise<{
236
+ ok: boolean;
237
+ suites: Array<{ name: string; ok: boolean; checks: Array<{ id: string; passed: boolean; detail: string }> }>;
238
+ }> {
239
+ const suites: Array<{ name: string; ok: boolean; checks: Array<{ id: string; passed: boolean; detail: string }> }> = [];
240
+ const run = async (name: string, fn: () => Promise<{ ok: boolean; checks: Array<{ id: string; passed: boolean; detail: string }> }> | { ok: boolean; checks: Array<{ id: string; passed: boolean; detail: string }> }) => {
241
+ try {
242
+ const result = await fn();
243
+ suites.push({ name, ...result });
244
+ } catch (error) {
245
+ suites.push({ name, ok: false, checks: [{ id: "suite-error", passed: false, detail: error instanceof Error ? error.message : String(error) }] });
246
+ }
247
+ };
248
+
249
+ await run("canonical-portfolio-orchestrator", () => runCanonicalPortfolioDiagnostics());
250
+ await run("portfolio-consensus-adjudicator", () => runPortfolioConsensusDiagnostics());
251
+ await run("portfolio-terminal-governor", () => runPortfolioTerminalGovernorDiagnostics());
252
+ await run("spa-rescue-bridge", () => runSpaRescueBridgeDiagnostics());
253
+
254
+ const checks: Array<{ id: string; passed: boolean; detail: string }> = [];
255
+ const add = (id: string, passed: boolean, detail: string) => checks.push({ id, passed, detail });
256
+ const mock: LaneExecution[] = [
257
+ { id: "terminal-wire", priority: 100, status: "fulfilled", elapsedMs: 300, normalized: { ok: true, acceptable: true, eligibleForWinner: true, provider: "tw", evidenceBlock: "x", sources: [], sourceCount: 1, claimCount: 1, structuredItemCount: 0, attestedCount: 2, supportedCount: 0, conflictedCount: 0, proof: "verified", qualityVector: [1, 4, 2, 0, 1, 1, 100] } },
258
+ { id: "omni-nexus", priority: 60, status: "fulfilled", elapsedMs: 400, normalized: { ok: true, acceptable: true, eligibleForWinner: true, provider: "on", evidenceBlock: "y", sources: [], sourceCount: 1, claimCount: 1, structuredItemCount: 0, attestedCount: 0, supportedCount: 1, conflictedCount: 0, proof: "bound", qualityVector: [1, 3, 0, 1, 1, 1, 100] } },
259
+ { id: "sentinel-orchestrator", priority: 95, status: "rejected", elapsedMs: 50, error: "timeout" },
260
+ ];
261
+ const independence = computeIndependence(mock);
262
+ add("independence-2-families", independence.distinctFamilies === 2 && independence.fulfilledFamilies.includes("conclave-core") && independence.fulfilledFamilies.includes("omni-standalone"), `families=${independence.fulfilledFamilies.join(",")}`);
263
+ const marginal = computeMarginalGain(mock, "terminal-wire", "omni-nexus");
264
+ add("marginal-changed-winner", marginal.extraLanesChangedWinner && marginal.assessment === "high-value", marginal.assessment);
265
+ add("engine-family-import", ENGINE_FAMILY["terminal-wire"] === "conclave-core" && ENGINE_FAMILY["omni-nexus"] === "omni-standalone", `tw=${ENGINE_FAMILY["terminal-wire"]}`);
266
+ add("robots-factory-exported", typeof makeRfc9309RobotsDecision() === "function", "factory ok");
267
+ suites.push({ name: "terminal-final-synthesis", ok: checks.every((check) => check.passed), checks });
268
+ return { ok: suites.every((suite) => suite.ok), suites };
269
+ }
270
+
271
+ export {
272
+ groundWithTerminalPortfolioGovernor,
273
+ familyOf,
274
+ ENGINE_FAMILY,
275
+ type TerminalGovernorOptions,
276
+ type TerminalGovernorResult,
277
+ } from "./portfolio-terminal-governor";
@@ -0,0 +1,345 @@
1
+ /**
2
+ * terminal-saturation.ts
3
+ * ============================================================================
4
+ * Optional supplementary structured metadata layer over terminal-final.ts.
5
+ * It preserves canonical output when mode is "off" (the default), surfaces
6
+ * DataCite and Europe PMC metadata as advisory data, and only merges marked
7
+ * supplementary records when callers explicitly opt in.
8
+ */
9
+
10
+ import {
11
+ groundTerminalFinal,
12
+ type TerminalFinalOptions,
13
+ type TerminalFinalResult,
14
+ } from "./terminal-final";
15
+
16
+ export type SupplementaryMode = "off" | "advisory" | "merge";
17
+ export type SupplementarySourceKind = "datacite" | "europe-pmc";
18
+
19
+ export interface SupplementaryStructuredItem {
20
+ id: string;
21
+ kind: SupplementarySourceKind;
22
+ title: string;
23
+ abstract?: string;
24
+ authors?: string[];
25
+ publishedDate?: string;
26
+ doi?: string;
27
+ externalUrl?: string;
28
+ openAccessUrl?: string;
29
+ citationCount?: number;
30
+ pageContent: string;
31
+ sourceWeight: number;
32
+ metadata: Record<string, string | number | boolean | undefined>;
33
+ }
34
+
35
+ export interface SupplementaryManifest {
36
+ proof: "locally-bound" | "unavailable";
37
+ root: string;
38
+ itemCount: number;
39
+ hashAlgorithm: "SHA-256" | "unavailable";
40
+ }
41
+
42
+ export interface TerminalSaturationOptions extends TerminalFinalOptions {
43
+ supplementaryMode?: SupplementaryMode;
44
+ supplementarySources?: SupplementarySourceKind[];
45
+ supplementaryLimitPerSource?: number;
46
+ supplementaryTimeoutMs?: number;
47
+ cooperativeYield?: boolean;
48
+ }
49
+
50
+ export interface TerminalSaturationResult extends TerminalFinalResult {
51
+ supplementaryMode: SupplementaryMode;
52
+ supplementaryItems: SupplementaryStructuredItem[];
53
+ supplementaryQueriedSources: SupplementarySourceKind[];
54
+ supplementaryErrors: Array<{ source: SupplementarySourceKind; error: string }>;
55
+ supplementaryMergedItems: SupplementaryStructuredItem[];
56
+ supplementaryManifest: SupplementaryManifest;
57
+ runtimeYield: "scheduler" | "timer" | "disabled";
58
+ }
59
+
60
+ function clamp(value: number | undefined, fallback: number, minimum: number, maximum: number): number {
61
+ return value === undefined || !Number.isFinite(value)
62
+ ? fallback
63
+ : Math.max(minimum, Math.min(maximum, Math.floor(value)));
64
+ }
65
+
66
+ function isRecord(value: unknown): value is Record<string, unknown> {
67
+ return typeof value === "object" && value !== null && !Array.isArray(value);
68
+ }
69
+
70
+ function text(value: unknown): string {
71
+ return typeof value === "string" ? value.trim() : typeof value === "number" || typeof value === "boolean" ? String(value) : "";
72
+ }
73
+
74
+ function count(value: unknown): number | undefined {
75
+ return typeof value === "number" && Number.isFinite(value) ? value : undefined;
76
+ }
77
+
78
+ function normalizeText(value: string): string {
79
+ return (value || "")
80
+ .replace(/<(script|style|noscript|iframe|object|embed)[^>]*>[\s\S]*?<\/\1>/gi, " ")
81
+ .replace(/<[^>]+>/g, " ")
82
+ .replace(/&nbsp;/gi, " ")
83
+ .replace(/&amp;/gi, "&")
84
+ .replace(/&lt;/gi, "<")
85
+ .replace(/&gt;/gi, ">")
86
+ .replace(/[\u202A-\u202E\u2066-\u2069\u200B-\u200F\uFEFF]/g, "")
87
+ .replace(/\s+/g, " ")
88
+ .trim();
89
+ }
90
+
91
+ function cleanDoi(value: string | undefined): string {
92
+ return (value || "").trim().replace(/^https?:\/\/doi\.org\//i, "").replace(/^doi:\s*/i, "").toLowerCase();
93
+ }
94
+
95
+ function canonicalUrl(value: string | undefined): string {
96
+ if (!value) return "";
97
+ try {
98
+ const url = new URL(value);
99
+ if (url.protocol !== "http:" && url.protocol !== "https:") return "";
100
+ if (url.username || url.password) return "";
101
+ url.hash = "";
102
+ url.hostname = url.hostname.toLowerCase();
103
+ for (const key of Array.from(url.searchParams.keys())) {
104
+ if (key.toLowerCase().startsWith("utm_") || ["fbclid", "gclid", "dclid", "msclkid"].includes(key.toLowerCase())) url.searchParams.delete(key);
105
+ }
106
+ url.searchParams.sort();
107
+ return url.toString();
108
+ } catch {
109
+ return "";
110
+ }
111
+ }
112
+
113
+ function sourceText(item: Omit<SupplementaryStructuredItem, "pageContent">): string {
114
+ const lines = [
115
+ `[SUPPLEMENTARY ${item.kind.toUpperCase()} - UNATTESTED METADATA]`,
116
+ `Title: ${item.title || "Untitled"}`,
117
+ item.authors?.length ? `Authors: ${item.authors.slice(0, 12).join(", ")}` : "",
118
+ item.publishedDate ? `Published: ${item.publishedDate}` : "",
119
+ item.doi ? `DOI: ${item.doi}` : "",
120
+ item.externalUrl ? `URL: ${item.externalUrl}` : "",
121
+ item.abstract ? `Abstract: ${item.abstract}` : "",
122
+ ].filter(Boolean);
123
+ return normalizeText(lines.join("\n"));
124
+ }
125
+
126
+ function makeItem(item: Omit<SupplementaryStructuredItem, "pageContent">): SupplementaryStructuredItem {
127
+ return { ...item, title: item.title || "Untitled", pageContent: sourceText(item) };
128
+ }
129
+
130
+ async function cooperativeYield(): Promise<"scheduler" | "timer"> {
131
+ const scheduler = (globalThis as { scheduler?: { yield?: () => Promise<void> } }).scheduler;
132
+ if (typeof scheduler?.yield === "function") {
133
+ await scheduler.yield();
134
+ return "scheduler";
135
+ }
136
+ await new Promise<void>((resolve) => setTimeout(resolve, 0));
137
+ return "timer";
138
+ }
139
+
140
+ function linkedSignal(parent: AbortSignal | undefined, timeoutMs: number): { signal: AbortSignal; cleanup: () => void } {
141
+ const controller = new AbortController();
142
+ const abort = () => controller.abort();
143
+ if (parent?.aborted) abort();
144
+ else parent?.addEventListener("abort", abort, { once: true });
145
+ const timeout = setTimeout(abort, timeoutMs);
146
+ return {
147
+ signal: controller.signal,
148
+ cleanup: () => {
149
+ clearTimeout(timeout);
150
+ parent?.removeEventListener("abort", abort);
151
+ },
152
+ };
153
+ }
154
+
155
+ async function fetchJson(url: string, signal: AbortSignal | undefined, timeoutMs: number): Promise<unknown> {
156
+ const linked = linkedSignal(signal, timeoutMs);
157
+ try {
158
+ const response = await fetch(url, {
159
+ signal: linked.signal,
160
+ credentials: "omit",
161
+ referrerPolicy: "no-referrer",
162
+ headers: { Accept: "application/json,application/vnd.api+json" },
163
+ });
164
+ if (!response.ok) throw new Error(`HTTP_${response.status}`);
165
+ const body = await response.text();
166
+ return JSON.parse(body.slice(0, 2_000_000));
167
+ } finally {
168
+ linked.cleanup();
169
+ }
170
+ }
171
+
172
+ export function parseDataCiteResponse(value: unknown): SupplementaryStructuredItem[] {
173
+ if (!isRecord(value) || !Array.isArray(value.data)) return [];
174
+ const output: SupplementaryStructuredItem[] = [];
175
+ for (const record of value.data) {
176
+ if (!isRecord(record)) continue;
177
+ const attributes = isRecord(record.attributes) ? record.attributes : {};
178
+ const titles = Array.isArray(attributes.titles) ? attributes.titles : [];
179
+ const titleRecord = titles.find(isRecord);
180
+ const title = titleRecord ? text(titleRecord.title) : text(attributes.title);
181
+ const authors = (Array.isArray(attributes.creators) ? attributes.creators : []).filter(isRecord).map((creator) => text(creator.name) || [text(creator.givenName), text(creator.familyName)].filter(Boolean).join(" ")).filter(Boolean);
182
+ const descriptions = (Array.isArray(attributes.descriptions) ? attributes.descriptions : []).filter(isRecord);
183
+ const abstractRecord = descriptions.find((description) => text(description.descriptionType).toLowerCase().includes("abstract")) ?? descriptions[0];
184
+ const abstract = abstractRecord ? normalizeText(text(abstractRecord.description)) : "";
185
+ const doi = cleanDoi(text(attributes.doi) || text(record.id));
186
+ const externalUrl = canonicalUrl(text(attributes.url)) || (doi ? `https://doi.org/${doi}` : "");
187
+ if (!title && !abstract && !doi) continue;
188
+ output.push(makeItem({
189
+ id: `datacite:${doi || text(record.id) || output.length}`,
190
+ kind: "datacite",
191
+ title: title || "Untitled",
192
+ abstract: abstract || undefined,
193
+ authors: authors.length ? authors : undefined,
194
+ publishedDate: text(attributes.publicationYear) || undefined,
195
+ doi: doi || undefined,
196
+ externalUrl: externalUrl || undefined,
197
+ sourceWeight: 0.6,
198
+ metadata: { publisher: text(attributes.publisher), structuredUnattested: true },
199
+ }));
200
+ }
201
+ return output;
202
+ }
203
+
204
+ export function parseEuropePmcResponse(value: unknown): SupplementaryStructuredItem[] {
205
+ if (!isRecord(value) || !isRecord(value.resultList) || !Array.isArray(value.resultList.result)) return [];
206
+ const output: SupplementaryStructuredItem[] = [];
207
+ for (const record of value.resultList.result) {
208
+ if (!isRecord(record)) continue;
209
+ const source = text(record.source);
210
+ const id = text(record.id) || text(record.pmid) || text(record.pmcid);
211
+ const doi = cleanDoi(text(record.doi));
212
+ const title = normalizeText(text(record.title));
213
+ const abstract = normalizeText(text(record.abstractText));
214
+ const authors = text(record.authorString).split(/\s*,\s*/).filter(Boolean);
215
+ const externalUrl = source && id ? `https://europepmc.org/article/${encodeURIComponent(source)}/${encodeURIComponent(id)}` : doi ? `https://doi.org/${doi}` : "";
216
+ if (!title && !abstract && !id && !doi) continue;
217
+ output.push(makeItem({
218
+ id: `europe-pmc:${source || "unknown"}:${id || doi || output.length}`,
219
+ kind: "europe-pmc",
220
+ title: title || "Untitled",
221
+ abstract: abstract || undefined,
222
+ authors: authors.length ? authors : undefined,
223
+ publishedDate: text(record.firstPublicationDate) || text(record.dateOfPublication) || text(record.pubYear) || undefined,
224
+ doi: doi || undefined,
225
+ externalUrl: canonicalUrl(externalUrl) || externalUrl || undefined,
226
+ openAccessUrl: text(record.pmcid) ? `https://europepmc.org/articles/${text(record.pmcid)}` : undefined,
227
+ citationCount: count(record.citedByCount),
228
+ sourceWeight: 0.65,
229
+ metadata: { source, recordId: id, pmid: text(record.pmid), pmcid: text(record.pmcid), structuredUnattested: true },
230
+ }));
231
+ }
232
+ return output;
233
+ }
234
+
235
+ async function queryDataCite(query: string, signal: AbortSignal | undefined, limit: number, timeoutMs: number): Promise<{ source: SupplementarySourceKind; items: SupplementaryStructuredItem[]; error?: string }> {
236
+ try {
237
+ const value = await fetchJson(`https://api.datacite.org/dois?query=${encodeURIComponent(query)}&page[size]=${limit}`, signal, timeoutMs);
238
+ return { source: "datacite", items: parseDataCiteResponse(value) };
239
+ } catch (error) {
240
+ return { source: "datacite", items: [], error: error instanceof Error ? error.message : String(error) };
241
+ }
242
+ }
243
+
244
+ async function queryEuropePmc(query: string, signal: AbortSignal | undefined, limit: number, timeoutMs: number): Promise<{ source: SupplementarySourceKind; items: SupplementaryStructuredItem[]; error?: string }> {
245
+ try {
246
+ const value = await fetchJson(`https://www.ebi.ac.uk/europepmc/webservices/rest/search?query=${encodeURIComponent(query)}&pageSize=${limit}&resultType=core&format=json`, signal, timeoutMs);
247
+ return { source: "europe-pmc", items: parseEuropePmcResponse(value) };
248
+ } catch (error) {
249
+ return { source: "europe-pmc", items: [], error: error instanceof Error ? error.message : String(error) };
250
+ }
251
+ }
252
+
253
+ function itemKey(item: Pick<SupplementaryStructuredItem, "doi" | "externalUrl" | "title">): string {
254
+ const doi = cleanDoi(item.doi);
255
+ if (doi) return `doi:${doi}`;
256
+ const url = canonicalUrl(item.externalUrl);
257
+ return url ? `url:${url}` : `title:${normalizeText(item.title).toLowerCase()}`;
258
+ }
259
+
260
+ function deduplicate(items: SupplementaryStructuredItem[], existing: Array<{ doi?: string; externalUrl?: string; title: string }>): SupplementaryStructuredItem[] {
261
+ const seen = new Set(existing.map(itemKey));
262
+ return items.filter((item) => {
263
+ const key = itemKey(item);
264
+ if (!key || key === "title:" || seen.has(key)) return false;
265
+ seen.add(key);
266
+ return true;
267
+ });
268
+ }
269
+
270
+ async function manifestFor(items: SupplementaryStructuredItem[]): Promise<SupplementaryManifest> {
271
+ if (!items.length || typeof crypto === "undefined" || !crypto.subtle) return { proof: "unavailable", root: "", itemCount: items.length, hashAlgorithm: "unavailable" };
272
+ try {
273
+ const stable = items.map((item) => JSON.stringify({ id: item.id, kind: item.kind, title: item.title, doi: item.doi, externalUrl: item.externalUrl, pageContent: item.pageContent })).sort().join("\n");
274
+ const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(stable));
275
+ const root = Array.from(new Uint8Array(digest)).map((byte) => byte.toString(16).padStart(2, "0")).join("");
276
+ return { proof: "locally-bound", root, itemCount: items.length, hashAlgorithm: "SHA-256" };
277
+ } catch {
278
+ return { proof: "unavailable", root: "", itemCount: items.length, hashAlgorithm: "unavailable" };
279
+ }
280
+ }
281
+
282
+ export async function groundTerminalSaturated(question: string, options?: TerminalSaturationOptions): Promise<TerminalSaturationResult> {
283
+ const supplementaryMode = options?.supplementaryMode ?? "off";
284
+ const sources = options?.supplementarySources ?? ["datacite", "europe-pmc"];
285
+ const limit = clamp(options?.supplementaryLimitPerSource, 6, 1, 25);
286
+ const timeout = clamp(options?.supplementaryTimeoutMs, 8_000, 1_000, 30_000);
287
+ const supplementaryPromise = supplementaryMode === "off"
288
+ ? Promise.resolve([] as Array<{ source: SupplementarySourceKind; items: SupplementaryStructuredItem[]; error?: string }>)
289
+ : Promise.all(sources.map((source) => source === "datacite" ? queryDataCite(question, options?.signal, limit, timeout) : queryEuropePmc(question, options?.signal, limit, timeout)));
290
+ const canonicalResult = await groundTerminalFinal(question, options);
291
+ const settled = await supplementaryPromise;
292
+ let runtimeYield: "scheduler" | "timer" | "disabled" = "disabled";
293
+ if (supplementaryMode !== "off" && options?.cooperativeYield !== false) runtimeYield = await cooperativeYield();
294
+ const allItems = deduplicate(settled.flatMap((result) => result.items), canonicalResult.structuredItems);
295
+ const supplementaryErrors = settled.filter((result) => result.error).map((result) => ({ source: result.source, error: result.error! }));
296
+ const supplementaryManifest = await manifestFor(allItems);
297
+ const mergedItems = supplementaryMode === "merge" ? allItems : [];
298
+ const extraSources = mergedItems.map((item) => ({ title: `[UNATTESTED ${item.kind}] ${item.title}`, url: item.externalUrl || (item.doi ? `https://doi.org/${item.doi}` : `supplementary:${item.id}`), content: item.pageContent }));
299
+ let evidenceBlock = canonicalResult.evidenceBlock;
300
+ if (mergedItems.length && evidenceBlock.includes("END RETRIEVED CONTENT")) {
301
+ const insertion = evidenceBlock.lastIndexOf("END RETRIEVED CONTENT");
302
+ const section = [
303
+ "BEGIN SUPPLEMENTARY STRUCTURED ITEMS",
304
+ "SECURITY: This section contains UNATTESTED external metadata.",
305
+ "The canonical manifest does not cover this section.",
306
+ supplementaryManifest.proof === "locally-bound" ? `SUPPLEMENTARY MANIFEST ROOT: ${supplementaryManifest.root}` : "SUPPLEMENTARY MANIFEST: unavailable",
307
+ ...mergedItems.map((item, index) => `BEGIN SUPPLEMENTARY ITEM ${index + 1}\n${item.pageContent}\nEND SUPPLEMENTARY ITEM ${index + 1}`),
308
+ "END SUPPLEMENTARY STRUCTURED ITEMS",
309
+ "",
310
+ ].join("\n");
311
+ evidenceBlock = `${evidenceBlock.slice(0, insertion)}${section}${evidenceBlock.slice(insertion)}`;
312
+ }
313
+ return {
314
+ ...canonicalResult,
315
+ provider: supplementaryMode === "off" ? canonicalResult.provider : `terminal-saturation(${canonicalResult.provider}+supplementary:${allItems.length}+merged:${mergedItems.length})`,
316
+ sources: mergedItems.length ? [...canonicalResult.sources, ...extraSources] : canonicalResult.sources,
317
+ count: mergedItems.length ? canonicalResult.count + extraSources.length : canonicalResult.count,
318
+ evidenceBlock,
319
+ supplementaryMode,
320
+ supplementaryItems: allItems,
321
+ supplementaryQueriedSources: settled.map((result) => result.source),
322
+ supplementaryErrors,
323
+ supplementaryMergedItems: mergedItems,
324
+ supplementaryManifest,
325
+ runtimeYield,
326
+ };
327
+ }
328
+
329
+ export async function runTerminalSaturationDiagnostics(): Promise<{
330
+ ok: boolean;
331
+ checks: Array<{ id: string; passed: boolean; detail: string }>;
332
+ }> {
333
+ const checks: Array<{ id: string; passed: boolean; detail: string }> = [];
334
+ const add = (id: string, passed: boolean, detail: string) => checks.push({ id, passed, detail });
335
+ const dataCite = parseDataCiteResponse({ data: [{ id: "10.1234/example", attributes: { doi: "10.1234/example", titles: [{ title: "Dataset title" }], creators: [{ name: "Ada Example" }], descriptions: [{ descriptionType: "Abstract", description: "<p>Dataset abstract.</p>" }] } }] });
336
+ add("datacite-parser", dataCite.length === 1 && dataCite[0].doi === "10.1234/example" && dataCite[0].abstract === "Dataset abstract.", `items=${dataCite.length}`);
337
+ const europePmc = parseEuropePmcResponse({ resultList: { result: [{ source: "MED", id: "12345", doi: "10.1000/example", title: "Biomedical article", abstractText: "<p>Biomedical abstract.</p>", citedByCount: 7 }] } });
338
+ add("europe-pmc-parser", europePmc.length === 1 && europePmc[0].doi === "10.1000/example" && europePmc[0].citationCount === 7, `items=${europePmc.length}`);
339
+ add("supplementary-doi-dedupe", deduplicate([dataCite[0], { ...europePmc[0], doi: "10.1234/example" }], []).length === 1, "doi dedupe");
340
+ const manifest = await manifestFor(dataCite);
341
+ add("supplementary-manifest", typeof crypto !== "undefined" && crypto.subtle ? manifest.proof === "locally-bound" && manifest.root.length === 64 : manifest.proof === "unavailable", `proof=${manifest.proof}`);
342
+ const yielded = await cooperativeYield();
343
+ add("cooperative-yield", yielded === "scheduler" || yielded === "timer", `mode=${yielded}`);
344
+ return { ok: checks.every((check) => check.passed), checks };
345
+ }