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,166 @@
1
+ /**
2
+ * Type B shim — SAGE barrel with a PROMPT OVERRIDE.
3
+ * ---------------------------------------------------------------------------
4
+ * WHY THIS FILE IS A WRAPPER AND NOT A PURE RE-EXPORT
5
+ *
6
+ * The packaged fiction runner (`src/components/ChatApp.tsx`) builds
7
+ * every chapter prompt with:
8
+ *
9
+ * import { compileCompactChapterPrompt } from "@/lib/sage";
10
+ * ...
11
+ * compileCompactChapterPrompt(bp, i, priorSummary, bp.cadence)
12
+ *
13
+ * `@/lib/sage` resolves to THIS file. So overriding the export here is the one
14
+ * durable, non-DOM seam that puts SAGA-OS v2 + reality grounding into the text
15
+ * that is actually sent to the model — and therefore into the main output box.
16
+ *
17
+ * A previous turn attempted this with a capture-phase `submit` listener that
18
+ * mutated the textarea and gated on `getV15Enabled()`. That was wrong twice
19
+ * over: V15 is a different toggle from Fiction mode, and the fiction runner
20
+ * never re-reads the textarea (it uses the frozen `blueprint` memo). That
21
+ * bridge is REMOVED and replaced by this override.
22
+ *
23
+ * INVARIANTS
24
+ * - Everything the package exports is still exported (`export *`).
25
+ * - The override is ADDITIVE: it calls the original compiler first and appends.
26
+ * - The unified block is derived from `bp.seed`, so SAGE, the Genesis-Grid,
27
+ * KALLOS and the reality level all ride the SAME seed as the blueprint the
28
+ * user previewed. No second roll, no divergence.
29
+ * - If anything throws, the ORIGINAL prompt is returned unchanged. The fiction
30
+ * engine can never be broken by this layer.
31
+ */
32
+
33
+ export * from '@/lib/sage/index.ts';
34
+
35
+ // Net-new workspace subsystems, re-exported through the same barrel so any
36
+ // consumer importing "@/lib/sage" sees one coherent surface.
37
+ export * from "./sage/reality-grounding";
38
+ export * from "./sage/saga-os-v2-engines";
39
+ export * from "./sage/unified-roll";
40
+ export * from "./sage/saga-os-v3-core";
41
+ export * from "./sage/saga-os-v3-release";
42
+ export * from "./sage/saga-os-v4-aureate";
43
+
44
+ import {
45
+ compileCompactChapterPrompt as _origCompileCompactChapterPrompt,
46
+ scrubLeakedDirective as _origScrubLeakedDirective,
47
+ type SageBlueprint, type SageProseCadence,
48
+ } from '@/lib/sage/engine.ts';
49
+ import { unifiedRoll } from "./sage/unified-roll";
50
+ import {
51
+ loadRealityLevel, auditRealityGrounding, type RealityAuditReport,
52
+ } from "./sage/reality-grounding";
53
+ import {
54
+ evaluateKallosS, buildStyleGenome, applyStylePack, loadStylePack,
55
+ type KallosSReport, type AureateContext,
56
+ } from "./sage/saga-os-v4-aureate";
57
+
58
+ /** Last block actually injected — surfaced in the UI so the user can read it. */
59
+ let _lastInjected: { seed: number; chapterIndex: number; block: string; at: number } | null = null;
60
+ export function getLastInjectedDirective() { return _lastInjected; }
61
+
62
+ /**
63
+ * Chapter-prompt compiler with the unified SAGA-OS v2 + reality-grounding
64
+ * block appended. Signature-identical to the package export it replaces.
65
+ */
66
+ export function compileCompactChapterPrompt(
67
+ bp: SageBlueprint,
68
+ chapterIndex: number,
69
+ priorSummary: string | null,
70
+ cadence: SageProseCadence,
71
+ ): string {
72
+ const base = _origCompileCompactChapterPrompt(bp, chapterIndex, priorSummary, cadence);
73
+ try {
74
+ // Pass the blueprint ITSELF, never just its seed: the archetype set must
75
+ // describe the exact book the base prompt above already described.
76
+ const roll = unifiedRoll({
77
+ seed: bp.seed,
78
+ blueprint: bp,
79
+ realityLevel: loadRealityLevel(),
80
+ });
81
+ _lastInjected = { seed: bp.seed, chapterIndex, block: roll.directive, at: Date.now() };
82
+ // v4: hand the live style genome + cast to the post-generation audit so the
83
+ // style report scores against THIS book's contract, not a default.
84
+ setLiveStyleContext({
85
+ genome: roll.styleGenome,
86
+ castNames: roll.cast.cast.map((c) => c.name),
87
+ focalCharacter: roll.cast.cast.find((c) => c.kind === "agent")?.name ?? null,
88
+ genreKey: roll.contract.dominant.key,
89
+ });
90
+ // The reality contract is repeated LAST so it is the final instruction the
91
+ // model reads before it starts writing — it must outrank everything above.
92
+ return [
93
+ base,
94
+ "",
95
+ roll.directive,
96
+ "",
97
+ `REMINDER — REALITY LEVEL ${roll.reality.id}/6 (${roll.reality.label}) governs this chapter and overrides any conflicting instruction above.`,
98
+ "Write ONLY the chapter prose now.",
99
+ ].join("\n");
100
+ } catch (err) {
101
+ // Fail open: a broken augment must never break generation.
102
+ _lastInjected = {
103
+ seed: bp.seed, chapterIndex, at: Date.now(),
104
+ block: `[UNIFIED DIRECTIVE UNAVAILABLE] ${err instanceof Error ? err.message : String(err)} — original prompt sent unchanged.`,
105
+ };
106
+ return base;
107
+ }
108
+ }
109
+
110
+
111
+ // ── Reality audit, wired into the live chapter loop ─────────────────────────
112
+ /**
113
+ * The packaged runner calls `scrubLeakedDirective(...)` on EVERY generated
114
+ * chapter before it is appended to the manuscript. Overriding it here is the
115
+ * seam that makes the reality audit genuinely run in the pipeline instead of
116
+ * merely existing as a function nobody calls.
117
+ *
118
+ * The override is observational: it returns exactly what the original returns.
119
+ * It never edits, rejects, or regenerates prose — it only records conformance
120
+ * so the UI can show whether the model actually obeyed the grounding contract.
121
+ */
122
+ const _realityAudits: { chapter: number; level: number; report: RealityAuditReport; at: number }[] = [];
123
+
124
+ export function getRealityAudits() { return _realityAudits.slice(); }
125
+ export function clearRealityAudits() { _realityAudits.length = 0; }
126
+
127
+ // ── SAGA-OS v4 AUREATE style audit, on the SAME live seam ───────────────────
128
+ /**
129
+ * The v4 revision stack (PASS-001..015) and KALLOS-S are only honest if they
130
+ * run on the prose the model actually produced. They ride the same
131
+ * `scrubLeakedDirective` override as the reality audit: observational only,
132
+ * never editing or rejecting, so a failure here can never break generation.
133
+ * The Studio "Style" tab reads these records.
134
+ */
135
+ const _styleAudits: { chapter: number; report: KallosSReport; at: number }[] = [];
136
+ export function getStyleAudits() { return _styleAudits.slice(); }
137
+ export function clearStyleAudits() { _styleAudits.length = 0; }
138
+
139
+ /** Style context for the live audit — rebuilt per chapter from the last roll. */
140
+ let _lastStyleCtx: AureateContext | null = null;
141
+ export function setLiveStyleContext(ctx: AureateContext): void { _lastStyleCtx = ctx; }
142
+
143
+ export function scrubLeakedDirective(text: string): string {
144
+ const cleaned = _origScrubLeakedDirective(text);
145
+ try {
146
+ const level = loadRealityLevel();
147
+ const words = (cleaned.trim().match(/\S+/g) || []).length;
148
+ if (words >= 40) {
149
+ _realityAudits.push({
150
+ chapter: _realityAudits.length + 1,
151
+ level,
152
+ report: auditRealityGrounding(cleaned, level),
153
+ at: Date.now(),
154
+ });
155
+ if (_realityAudits.length > 200) _realityAudits.shift();
156
+
157
+ // v4: style audit over the same finished chapter.
158
+ const ctx = _lastStyleCtx ?? {
159
+ genome: applyStylePack(buildStyleGenome("literary"), loadStylePack()),
160
+ };
161
+ _styleAudits.push({ chapter: _styleAudits.length + 1, report: evaluateKallosS(cleaned, ctx), at: Date.now() });
162
+ if (_styleAudits.length > 200) _styleAudits.shift();
163
+ }
164
+ } catch { /* observation must never break generation */ }
165
+ return cleaned;
166
+ }
@@ -0,0 +1,53 @@
1
+ /**
2
+ * scraper-debug-bus.ts
3
+ * ============================================================================
4
+ * Lightweight, additive, dependency-free pub/sub bus so every scraper lane
5
+ * (accelerator, hydra, nexus, sibyl, strata, palisade, arbiter, academic
6
+ * sources, enhanced scraper, OG scraper, package original groundQuestion,
7
+ * VNext terminal/portfolio stack) can emit a visible, timestamped log line
8
+ * that the V15 Rigor Guard UI renders live AND that always echoes to the
9
+ * browser console via console.log — closing the "I still don't see them
10
+ * log" gap. Purely additive; nothing existing is modified.
11
+ * ============================================================================ */
12
+
13
+ export interface ScraperLogLine {
14
+ ts: number;
15
+ lane: string;
16
+ message: string;
17
+ }
18
+
19
+ const listeners = new Set<(line: ScraperLogLine) => void>();
20
+ const HISTORY_MAX = 300;
21
+ let history: ScraperLogLine[] = [];
22
+
23
+ export function emitScraperDebug(lane: string, message: string): void {
24
+ const line: ScraperLogLine = { ts: Date.now(), lane, message };
25
+ history.push(line);
26
+ if (history.length > HISTORY_MAX) history = history.slice(-HISTORY_MAX);
27
+ try {
28
+ // eslint-disable-next-line no-console
29
+ console.log(`[scraper:${lane}] ${message}`);
30
+ } catch {
31
+ /* console unavailable */
32
+ }
33
+ for (const cb of listeners) {
34
+ try {
35
+ cb(line);
36
+ } catch {
37
+ /* fail-open per subscriber */
38
+ }
39
+ }
40
+ }
41
+
42
+ export function subscribeScraperDebug(cb: (line: ScraperLogLine) => void): () => void {
43
+ listeners.add(cb);
44
+ return () => listeners.delete(cb);
45
+ }
46
+
47
+ export function getScraperDebugHistory(): ScraperLogLine[] {
48
+ return history.slice();
49
+ }
50
+
51
+ export function clearScraperDebugHistory(): void {
52
+ history = [];
53
+ }
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Enhanced Scraper — patched with preserveSourceDuplicates to allow RRF accumulation.
3
+ * This is a verbatim copy of the package's implementation with the single additive option.
4
+ */
5
+ export interface SearchResult {
6
+ title: string;
7
+ url: string;
8
+ snippet: string;
9
+ source: string;
10
+ relevanceScore?: number;
11
+ publishedAt?: string;
12
+ domain?: string;
13
+ }
14
+ export interface ScraperResult {
15
+ url: string;
16
+ title: string;
17
+ content: string;
18
+ extractedData: { dates?: string[]; numbers?: string[]; entities?: string[]; citations?: string[]; emails?: string[]; urls?: string[] };
19
+ qualityScore: number;
20
+ contentLength: number;
21
+ }
22
+
23
+ const SEARCH_ENGINES = {
24
+ google: (q: string) => `https://www.google.com/search?q=${encodeURIComponent(q)}`,
25
+ bing: (q: string) => `https://www.bing.com/search?q=${encodeURIComponent(q)}`,
26
+ duckduckgo: (q: string) => `https://duckduckgo.com/html/?q=${encodeURIComponent(q)}`,
27
+ wikipedia: (q: string) => `https://en.wikipedia.org/w/index.php?search=${encodeURIComponent(q)}`,
28
+ scholar: (q: string) => `https://scholar.google.com/scholar?q=${encodeURIComponent(q)}`,
29
+ arxiv: (q: string) => `https://arxiv.org/search/?query=${encodeURIComponent(q)}&searchtype=all`,
30
+ };
31
+
32
+ const NICHE_APIS = {
33
+ hackernews: (q: string) => `https://hn.algolia.com/api/v1/search?query=${encodeURIComponent(q)}&hitsPerPage=10`,
34
+ stackexchange: (q: string, site = "stackoverflow") => `https://api.stackexchange.com/2.3/search/advanced?order=desc&sort=relevance&q=${encodeURIComponent(q)}&site=${site}&pagesize=10`,
35
+ reddit: (q: string) => `https://www.reddit.com/search.json?q=${encodeURIComponent(q)}&limit=10&sort=relevance`,
36
+ semanticscholar: (q: string) => `https://api.semanticscholar.org/graph/v1/paper/search?query=${encodeURIComponent(q)}&limit=10&fields=title,abstract,authors,year,url,venue,citationCount`,
37
+ crossref: (q: string) => `https://api.crossref.org/works?query=${encodeURIComponent(q)}&rows=10`,
38
+ openalex: (q: string) => `https://api.openalex.org/works?search=${encodeURIComponent(q)}&per-page=10`,
39
+ pubmed: (q: string) => `https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?db=pubmed&term=${encodeURIComponent(q)}&retmax=10&retmode=json`,
40
+ sec_edgar: (q: string) => `https://efts.sec.gov/LATEST/search-index?q=${encodeURIComponent(q)}&dateRange=custom&forms=10-K,10-Q,8-K`,
41
+ patents: (q: string) => `https://api.patentsview.org/patents/query?q={"_text_any":{"patent_title":"${encodeURIComponent(q)}"}}&f=["patent_number","patent_title","patent_date","patent_abstract"]&o={"per_page":10}`,
42
+ wayback: (url: string) => `https://archive.org/wayback/available?url=${encodeURIComponent(url)}`,
43
+ github: (q: string) => `https://api.github.com/search/repositories?q=${encodeURIComponent(q)}&per_page=10`,
44
+ };
45
+
46
+ const STACK_EXCHANGE_SITES = ["stackoverflow","stats","math","physics","chemistry","biology","engineering","medicalsciences","law","money","quant","datascience","ai","electronics","workplace","academia"];
47
+
48
+ const PROXY_FLEET = [
49
+ { name: "corsproxy.io", build: (u: string) => `https://corsproxy.io/?url=${encodeURIComponent(u)}` },
50
+ { name: "allorigins-raw", build: (u: string) => `https://api.allorigins.win/raw?url=${encodeURIComponent(u)}` },
51
+ { name: "codetabs", build: (u: string) => `https://api.codetabs.com/v1/proxy/?quest=${encodeURIComponent(u)}` },
52
+ { name: "cors.sh", build: (u: string) => `https://proxy.cors.sh/${u}` },
53
+ { name: "yacdn", build: (u: string) => `https://yacdn.org/proxy/${u}` },
54
+ { name: "thingproxy", build: (u: string) => `https://thingproxy.freeboard.io/fetch/${u}` },
55
+ { name: "cors-anywhere", build: (u: string) => `https://cors-anywhere.herokuapp.com/${u}` },
56
+ { name: "corsproxy.org", build: (u: string) => `https://corsproxy.org/?${encodeURIComponent(u)}` },
57
+ ];
58
+
59
+ const TRUSTED_DOMAINS: Record<string, number> = {
60
+ "nature.com":0.3,"science.org":0.3,"cell.com":0.3,"nejm.org":0.3,"thelancet.com":0.3,"bmj.com":0.25,
61
+ "ieee.org":0.25,"acm.org":0.25,"springer.com":0.2,"sciencedirect.com":0.2,"wiley.com":0.2,"jstor.org":0.2,
62
+ "sec.gov":0.3,"federalreserve.gov":0.3,"bls.gov":0.3,"census.gov":0.3,"who.int":0.3,"cdc.gov":0.3,"nih.gov":0.3,"fda.gov":0.3,
63
+ "arxiv.org":0.2,"biorxiv.org":0.15,"ssrn.com":0.15,"reuters.com":0.15,"ft.com":0.2,"bloomberg.com":0.2,"wsj.com":0.2,
64
+ "economist.com":0.15,"hbr.org":0.15,"mckinsey.com":0.15,"bain.com":0.15,"bcg.com":0.15,"deloitte.com":0.1,"pwc.com":0.1,"kpmg.com":0.1,
65
+ "gartner.com":0.15,"forrester.com":0.15,"idc.com":0.15,"github.com":0.1,"stackoverflow.com":0.1,
66
+ };
67
+
68
+ function domainOf(url: string): string { try{ return new URL(url).hostname.replace(/^www\./,""); }catch{ return ""; } }
69
+ function trustBoost(url: string): number { const d=domainOf(url); for (const [k,v] of Object.entries(TRUSTED_DOMAINS)) if (d.endsWith(k)) return v; return 0; }
70
+
71
+ export async function enhancedSearch(
72
+ query: string,
73
+ options?: {
74
+ engines?: Array<keyof typeof SEARCH_ENGINES>;
75
+ maxResults?: number;
76
+ includeAcademic?: boolean;
77
+ includeIndustry?: boolean;
78
+ includeForums?: boolean;
79
+ stackExchangeSites?: string[];
80
+ preserveSourceDuplicates?: boolean;
81
+ }
82
+ ): Promise<SearchResult[]> {
83
+ const engines = options?.engines || ["google","bing","duckduckgo"];
84
+ const maxResults = options?.maxResults || 20;
85
+ const includeAcademic = options?.includeAcademic !== false;
86
+ const includeIndustry = options?.includeIndustry !== false;
87
+ const includeForums = options?.includeForums !== false;
88
+ const seSites = options?.stackExchangeSites || ["stackoverflow","stats","engineering"];
89
+ const promises: Promise<SearchResult[]>[] = [];
90
+ for (const engine of engines) {
91
+ promises.push((async ()=>{ try{ const r=await fetch(SEARCH_ENGINES[engine](query)); if (!r.ok) return []; const html=await r.text(); return parseSearchResults(html,engine); }catch{ return []; } })());
92
+ }
93
+ if (includeAcademic){ promises.push(fetchSemanticScholar(query)); promises.push(fetchCrossref(query)); promises.push(fetchOpenAlex(query)); promises.push(fetchPubMed(query)); }
94
+ if (includeForums){ promises.push(fetchHackerNews(query)); for (const site of seSites) promises.push(fetchStackExchange(query,site)); promises.push(fetchReddit(query)); }
95
+ if (includeIndustry){ promises.push(fetchGitHub(query)); }
96
+ const all=(await Promise.allSettled(promises)).flatMap((p)=> p.status==="fulfilled" ? p.value : []);
97
+ const seen=new Set<string>();
98
+ const deduped=all.filter((result)=>{
99
+ if (!result.url) return false;
100
+ const dedupeKey = options?.preserveSourceDuplicates ? `${result.source||"web"}\u0000${result.url}` : result.url;
101
+ if (seen.has(dedupeKey)) return false;
102
+ seen.add(dedupeKey);
103
+ result.domain=domainOf(result.url);
104
+ result.relevanceScore=(result.relevanceScore ?? 0.5)+trustBoost(result.url);
105
+ return true;
106
+ });
107
+ deduped.sort((a,b)=>(b.relevanceScore ?? 0)-(a.relevanceScore ?? 0));
108
+ return deduped.slice(0,maxResults);
109
+ }
110
+
111
+ async function fetchHackerNews(q: string): Promise<SearchResult[]> {
112
+ try{ const r=await fetch(NICHE_APIS.hackernews(q)); if (!r.ok) return []; const j=await r.json(); return (j.hits||[]).slice(0,10).map((h:any)=>({ title:h.title||h.story_title||"HN discussion", url:h.url||`https://news.ycombinator.com/item?id=${h.objectID}`, snippet:(h.story_text||h.comment_text||"").replace(/<[^>]*>/g,"").slice(0,300), source:"hackernews", relevanceScore: Math.min(1,0.5+(h.points||0)/200+(h.num_comments||0)/200), publishedAt:h.created_at })); }catch{ return []; }
113
+ }
114
+ async function fetchStackExchange(q: string, site: string): Promise<SearchResult[]> {
115
+ try{ const r=await fetch(NICHE_APIS.stackexchange(q,site)); if (!r.ok) return []; const j=await r.json(); return (j.items||[]).slice(0,5).map((it:any)=>({ title:it.title||"SE question", url:it.link, snippet:`${it.answer_count} answer(s) · score ${it.score} · [${site}]`, source:`se-${site}`, relevanceScore: Math.min(1,0.4+(it.score||0)/50+(it.is_answered?0.2:0)) })); }catch{ return []; }
116
+ }
117
+ async function fetchReddit(q: string): Promise<SearchResult[]> {
118
+ try{ const r=await fetch(NICHE_APIS.reddit(q),{headers:{"User-Agent":"veritas-scraper/1.0"}}); if (!r.ok) return []; const j=await r.json(); return (j.data?.children||[]).slice(0,10).map((c:any)=>({ title:c.data.title, url:`https://reddit.com${c.data.permalink}`, snippet:(c.data.selftext||"").slice(0,300), source:`reddit-r/${c.data.subreddit}`, relevanceScore: Math.min(1,0.4+(c.data.score||0)/500) })); }catch{ return []; }
119
+ }
120
+ async function fetchSemanticScholar(q: string): Promise<SearchResult[]> {
121
+ try{ const r=await fetch(NICHE_APIS.semanticscholar(q)); if (!r.ok) return []; const j=await r.json(); return (j.data||[]).slice(0,10).map((p:any)=>({ title:p.title, url:p.url, snippet:(p.abstract||"").slice(0,400), source:"semantic-scholar", relevanceScore: Math.min(1,0.6+(p.citationCount||0)/500), publishedAt:p.year?String(p.year):undefined })); }catch{ return []; }
122
+ }
123
+ async function fetchCrossref(q: string): Promise<SearchResult[]> {
124
+ try{ const r=await fetch(NICHE_APIS.crossref(q)); if (!r.ok) return []; const j=await r.json(); return (j.message?.items||[]).slice(0,10).map((it:any)=>({ title:(it.title||[""])[0], url:it.URL||(it.DOI?`https://doi.org/${it.DOI}`:""), snippet:(it.abstract||"").replace(/<[^>]*>/g,"").slice(0,400), source:"crossref", relevanceScore: Math.min(1,0.55+(it["is-referenced-by-count"]||0)/300), publishedAt:it.created?.["date-time"] })); }catch{ return []; }
125
+ }
126
+ async function fetchOpenAlex(q: string): Promise<SearchResult[]> {
127
+ try{ const r=await fetch(NICHE_APIS.openalex(q)); if (!r.ok) return []; const j=await r.json(); return (j.results||[]).slice(0,10).map((w:any)=>({ title:w.title, url:w.doi?`https://doi.org/${w.doi.replace("https://doi.org/","")}`:w.id, snippet:(w.abstract_inverted_index ? Object.keys(w.abstract_inverted_index).slice(0,60).join(" ") : "").slice(0,400), source:"openalex", relevanceScore: Math.min(1,0.55+(w.cited_by_count||0)/500), publishedAt:w.publication_year?String(w.publication_year):undefined })); }catch{ return []; }
128
+ }
129
+ async function fetchPubMed(q: string): Promise<SearchResult[]> {
130
+ try{ const r=await fetch(NICHE_APIS.pubmed(q)); if (!r.ok) return []; const j=await r.json(); const ids:string[]=j?.esearchresult?.idlist||[]; return ids.slice(0,10).map((id)=>({ title:`PubMed PMID ${id}`, url:`https://pubmed.ncbi.nlm.nih.gov/${id}/`, snippet:"PubMed record — resolve via PMID for abstract", source:"pubmed", relevanceScore:0.7 })); }catch{ return []; }
131
+ }
132
+ async function fetchGitHub(q: string): Promise<SearchResult[]> {
133
+ try{ const r=await fetch(NICHE_APIS.github(q)); if (!r.ok) return []; const j=await r.json(); return (j.items||[]).slice(0,10).map((it:any)=>({ title:`${it.full_name} — ${it.description||"GitHub repo"}`, url:it.html_url, snippet:(it.description||"").slice(0,300), source:"github", relevanceScore: Math.min(1,0.4+(it.stargazers_count||0)/5000) })); }catch{ return []; }
134
+ }
135
+ export async function deepScrape(url: string): Promise<ScraperResult> {
136
+ try{ const r=await fetch(url,{headers:{"User-Agent":"Mozilla/5.0 (X11; Linux x86_64) veritas-scraper/2.0",Accept:"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.5"}}); if (r.ok){ const html=await r.text(); return parseAndExtract(html,url); } }catch{}
137
+ for (const proxy of PROXY_FLEET){ try{ const r=await fetch(proxy.build(url),{headers:{"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",Accept:"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8","Accept-Language":"en-US,en;q=0.9"}}); if (!r.ok) continue; const html=await r.text(); return parseAndExtract(html,url); }catch{ continue; } }
138
+ throw new Error(`Failed to scrape ${url} — all proxies exhausted`);
139
+ }
140
+ function parseSearchResults(html: string, engine: string): SearchResult[] {
141
+ const results: SearchResult[]=[]; const titleRegex=/<h3[^>]*>([\s\S]*?)<\/h3>/gi; let m; while((m=titleRegex.exec(html))!==null){ results.push({ title:m[1].replace(/<[^>]*>/g,"").trim(), url:"", snippet:"", source:engine, relevanceScore:0.5 }); } return results;
142
+ }
143
+ function parseAndExtract(html: string, url: string): ScraperResult {
144
+ const titleMatch=html.match(/<title[^>]*>([\s\S]*?)<\/title>/i); const title=titleMatch?titleMatch[1].trim():"Untitled";
145
+ const bodyMatch=html.match(/<body[^>]*>([\s\S]*?)<\/body>/i); const body=bodyMatch?bodyMatch[1]:html;
146
+ const content=body.replace(/<script[\s\S]*?<\/script>/gi,"").replace(/<style[\s\S]*?<\/style>/gi,"").replace(/<[^>]+>/g," ").replace(/\s+/g," ").trim().slice(0,80000);
147
+ const extractedData={ dates: content.match(/\b(19|20)\d{2}\b/g)?.slice(0,100)||[], numbers: content.match(/\b\d+(?:\.\d+)?(?:%|K|M|B|T)?\b/g)?.slice(0,200)||[], entities: content.match(/\b[A-Z][A-Za-z]+(?:\s+[A-Z][A-Za-z]+)+\b/g)?.slice(0,100)||[], citations: content.match(/\[\d+\]/g)?.slice(0,100)||[], emails: content.match(/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g)?.slice(0,50)||[], urls: content.match(/https?:\/\/[^\s<>"']+/g)?.slice(0,100)||[] };
148
+ let qualityScore=0.4; if (content.length>3000) qualityScore+=0.15; if (content.length>15000) qualityScore+=0.1; if (extractedData.dates.length>5) qualityScore+=0.1; if (extractedData.numbers.length>15) qualityScore+=0.1; if (extractedData.entities.length>8) qualityScore+=0.1; if (extractedData.citations.length>3) qualityScore+=0.05; qualityScore+=trustBoost(url);
149
+ return { url, title, content, extractedData, qualityScore: Math.min(1.0,qualityScore), contentLength: content.length };
150
+ }
151
+ export const STACK_EXCHANGE_ALL_SITES=STACK_EXCHANGE_SITES;
152
+ export { PROXY_FLEET, TRUSTED_DOMAINS };
153
+ export * from "./scraper-hardener";
@@ -0,0 +1,10 @@
1
+ // SIDECAR SEAM — see flatten-guide.md.
2
+ // Alias-reachable retrieval lane: the packaged `v15-grounding.ts` imports this
3
+ // module via `@/lib/scraper-enhanced`, so this seam IS on the live path.
4
+ // Adds a provenance tap only; retrieval behaviour is byte-for-byte unchanged.
5
+ export * from "./scraper-enhanced.orig";
6
+
7
+ import { enhancedSearch as packageEnhancedSearch } from "./scraper-enhanced.orig";
8
+ import { withLaneTap } from "@/lib/citation-lane-tap";
9
+
10
+ export const enhancedSearch = withLaneTap("enhanced-scraper", packageEnhancedSearch);
@@ -0,0 +1,155 @@
1
+ /**
2
+ * Deterministic CORS Proxy & Scraper Hardening (May 2026 fleet).
3
+ *
4
+ * Public CORS relays churn constantly, so we keep a broad, prioritized list and
5
+ * rotate through several response shapes (raw passthrough vs. JSON-wrapped).
6
+ * The first relay to return usable bytes wins.
7
+ */
8
+
9
+ export interface ProxyDef {
10
+ name: string;
11
+ build: (url: string) => string;
12
+ /** Some relays wrap the body in JSON ({contents:"..."}); extract if so. */
13
+ unwrap?: (body: string) => string;
14
+ }
15
+
16
+ // Ordered fastest/most-reliable first as of May 2026. Raw passthrough relays are
17
+ // preferred because they don't double-encode HTML entities. Expanded fleet for
18
+ // resilience — the OG browser scraper is the workhorse so it must rarely fail.
19
+ export const PROXY_FLEET: ProxyDef[] = [
20
+ { name: "corsproxy.io", build: (u) => `https://corsproxy.io/?url=${encodeURIComponent(u)}` },
21
+ { name: "allorigins-raw", build: (u) => `https://api.allorigins.win/raw?url=${encodeURIComponent(u)}` },
22
+ { name: "codetabs", build: (u) => `https://api.codetabs.com/v1/proxy/?quest=${encodeURIComponent(u)}` },
23
+ { name: "corsproxy.org", build: (u) => `https://corsproxy.org/?${encodeURIComponent(u)}` },
24
+ { name: "thingproxy", build: (u) => `https://thingproxy.freeboard.io/fetch/${u}` },
25
+ { name: "cors.eu.org", build: (u) => `https://cors.eu.org/${u}` },
26
+ { name: "cors-anywhere-hf", build: (u) => `https://cors-anywhere.herokuapp.com/${u}` },
27
+ { name: "proxy.cors.sh", build: (u) => `https://proxy.cors.sh/${u}` },
28
+ { name: "yacdn", build: (u) => `https://yacdn.org/proxy/${u}` },
29
+ { name: "whateverorigin", build: (u) => `https://whateverorigin.org/get?url=${encodeURIComponent(u)}`, unwrap: jsonContents },
30
+ { name: "allorigins-get", build: (u) => `https://api.allorigins.win/get?url=${encodeURIComponent(u)}`, unwrap: jsonContents },
31
+ { name: "jsonp.afeld", build: (u) => `https://jsonp.afeld.me/?url=${encodeURIComponent(u)}` },
32
+ ];
33
+
34
+ function jsonContents(body: string): string {
35
+ try {
36
+ const data = JSON.parse(body);
37
+ return typeof data?.contents === "string" ? data.contents : body;
38
+ } catch {
39
+ return body;
40
+ }
41
+ }
42
+
43
+ const BROWSER_HEADERS: Record<string, string> = {
44
+ "User-Agent":
45
+ "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
46
+ Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,text/plain;q=0.8,*/*;q=0.5",
47
+ "Accept-Language": "en-US,en;q=0.9",
48
+ };
49
+
50
+ async function timedFetch(url: string, signal: AbortSignal | undefined, headers: Record<string, string>): Promise<Response> {
51
+ // Compose caller signal with an internal timeout so one dead relay can't hang the chain.
52
+ const ctrl = new AbortController();
53
+ const timer = setTimeout(() => ctrl.abort(), 8_000);
54
+ const onAbort = () => ctrl.abort();
55
+ signal?.addEventListener("abort", onAbort, { once: true });
56
+ try {
57
+ return await fetch(url, { signal: ctrl.signal, headers, redirect: "follow" });
58
+ } finally {
59
+ clearTimeout(timer);
60
+ signal?.removeEventListener("abort", onAbort);
61
+ }
62
+ }
63
+
64
+ function looksUsable(text: string): boolean {
65
+ if (!text) return false;
66
+ if (text.length < 80) return false;
67
+ // Reject obvious relay error envelopes.
68
+ if (/^\s*(error|forbidden|too many requests|rate limit)/i.test(text) && text.length < 400) return false;
69
+ return true;
70
+ }
71
+
72
+ export interface RobustFetchResult {
73
+ text: string;
74
+ source: "direct" | "proxy";
75
+ proxy?: string;
76
+ }
77
+
78
+ /** Try a single proxy, resolving to a usable body or rejecting. */
79
+ async function tryProxy(proxy: ProxyDef, url: string, signal?: AbortSignal): Promise<RobustFetchResult> {
80
+ const res = await timedFetch(proxy.build(url), signal, BROWSER_HEADERS);
81
+ if (!res.ok) throw new Error(`${proxy.name}:${res.status}`);
82
+ const raw = await res.text();
83
+ const body = proxy.unwrap ? proxy.unwrap(raw) : raw;
84
+ if (!looksUsable(body)) throw new Error(`${proxy.name}:thin`);
85
+ return { text: body, source: "proxy", proxy: proxy.name };
86
+ }
87
+
88
+ /** Resolve the first fulfilled promise; reject only if ALL reject. */
89
+ function firstSuccess<T>(promises: Promise<T>[]): Promise<T> {
90
+ return new Promise((resolve, reject) => {
91
+ let remaining = promises.length;
92
+ const errors: any[] = [];
93
+ if (remaining === 0) reject(new Error("no candidates"));
94
+ promises.forEach(p => p.then(resolve, (e) => {
95
+ errors.push(e);
96
+ if (--remaining === 0) reject(new Error(errors.map(x => x?.message ?? x).join(", ")));
97
+ }));
98
+ });
99
+ }
100
+
101
+ /**
102
+ * Resilient fetch: optional pinned proxy → direct → RACE the proxy fleet.
103
+ * Racing collapses the old sequential per-proxy delay into ~1 wave latency.
104
+ * Returns the first usable body. Throws CORS_BLOCKED only when everything fails.
105
+ */
106
+ export async function fetchRobust(url: string, signal?: AbortSignal, preferProxy?: string): Promise<RobustFetchResult> {
107
+ // 0. Pinned proxy first (e.g. codetabs for Bing — confirmed working combos).
108
+ if (preferProxy) {
109
+ const pinned = PROXY_FLEET.find(p => p.name === preferProxy);
110
+ if (pinned) {
111
+ try { return await tryProxy(pinned, url, signal); } catch { /* fall through */ }
112
+ }
113
+ }
114
+
115
+ // 1. Direct (works for CORS-enabled origins) — short timeout.
116
+ try {
117
+ const res = await timedFetch(url, signal, BROWSER_HEADERS);
118
+ if (res.ok) {
119
+ const text = await res.text();
120
+ if (looksUsable(text)) return { text, source: "direct" };
121
+ }
122
+ } catch { /* fall through */ }
123
+
124
+ // 2. Race the proxy fleet in small waves — first usable wins. Keep this at
125
+ // 2 because cluster search can launch several scraper reads in parallel.
126
+ const WAVE = 2;
127
+ const errs: string[] = [];
128
+ for (let i = 0; i < PROXY_FLEET.length; i += WAVE) {
129
+ if (signal?.aborted) break;
130
+ const wave = PROXY_FLEET.slice(i, i + WAVE);
131
+ try {
132
+ return await firstSuccess(wave.map(p => tryProxy(p, url, signal)));
133
+ } catch (e: any) {
134
+ errs.push(e?.message ?? "wave-failed");
135
+ }
136
+ }
137
+
138
+ throw new Error(`CORS_BLOCKED: all paths failed for ${url} [${errs.join("; ").slice(0, 200)}]`);
139
+ }
140
+
141
+ /**
142
+ * Extract substantive text from raw HTML (lightweight, no DOM).
143
+ */
144
+ export function extractTextFromHtml(html: string): string {
145
+ let text = html.replace(/<(script|style|nav|footer|header|noscript|svg)[^>]*>[\s\S]*?<\/\1>/gi, "");
146
+ text = text.replace(/<[^>]+>/g, " ");
147
+ text = text
148
+ .replace(/&nbsp;/g, " ")
149
+ .replace(/&amp;/g, "&")
150
+ .replace(/&lt;/g, "<")
151
+ .replace(/&gt;/g, ">")
152
+ .replace(/&quot;/g, '"')
153
+ .replace(/&#x27;|&#39;/g, "'");
154
+ return text.replace(/\s+/g, " ").trim().slice(0, 12_000);
155
+ }