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,235 @@
1
+ /**
2
+ * Deterministic Output Boundary — INVERTED approach.
3
+ *
4
+ * Instead of trying to enumerate every possible scratchpad pattern (infinite),
5
+ * we find the FINAL PROSE BLOCK and discard everything else.
6
+ *
7
+ * Strategy:
8
+ * 1. If <final_answer> tags exist, extract that.
9
+ * 2. Otherwise, scan backward from the end of the text to find the last
10
+ * contiguous block of clean prose (sentences, headings, tables, lists).
11
+ * Everything before the first line of that block is scratchpad.
12
+ * 3. Line-level filter strips any remaining non-prose lines.
13
+ * 4. Markdown [Source N] artifacts and meta-discourse are cleaned.
14
+ *
15
+ * This approach handles ANY new scratchpad format without code changes,
16
+ * because it identifies the answer positively rather than the scratchpad
17
+ * negatively.
18
+ */
19
+
20
+ export interface BoundaryResult {
21
+ cleaned: string;
22
+ removedSegments: number;
23
+ notes: string[];
24
+ }
25
+
26
+ // ─── Positive prose detection (what IS the answer) ──────────────────
27
+
28
+ /** A line is "definitely prose" if it's a natural sentence, heading, table, or list item. */
29
+ function isDefinitelyProse(line: string): boolean {
30
+ const t = line.trim();
31
+ if (!t) return false;
32
+ // Markdown heading
33
+ if (/^#{1,6}\s+\w/.test(t)) return true;
34
+ // Markdown table row
35
+ if (/^\|.+\|/.test(t)) return true;
36
+ // Bold heading line
37
+ if (/^\*\*[^*]+\*\*/.test(t)) return true;
38
+ // Numbered list item with substance
39
+ if (/^\d+\.\s+\S/.test(t) && t.length > 20) return true;
40
+ // Bullet list with substance (not a planning bullet)
41
+ if (/^[-*]\s+\S/.test(t) && t.length > 30 && !isPlanning(t)) return true;
42
+ // Natural sentence (40+ chars ending with period/exclamation/question)
43
+ if (t.length >= 40 && /[.!?]$/.test(t) && !isPlanning(t)) return true;
44
+ return false;
45
+ }
46
+
47
+ /** A line is "definitely planning/scratchpad" if it matches known patterns. */
48
+ function isPlanning(line: string): boolean {
49
+ const t = line.trim();
50
+ // Indented asterisk planning bullets: " * No preamble"
51
+ if (/^\s{2,}\*\s{2,}/.test(line)) return true;
52
+ // Planning labels
53
+ const labels = [
54
+ /^\*?\s*(current (date|state)|target window|style persona|output (format|structure|template)|persona|constraints?|plan|direct answer|goal|old info|new info|the unknown|drafting|check against|sentence \d|bottom[- ]line|self[- ]correction|crucial|observation|decision|refining|addressing|wait[,!]|role|style mode|output rules)/i,
55
+ /^\*?\s*\*[A-Z][^*]*:\*/,
56
+ /^(?:wait|hmm|let me|ok so|actually|self-correction|self-eval|evaluation)/i,
57
+ /\bretrieved records do not\b/i,
58
+ /\bi (cannot|can not|am unable to) (invent|actually|substantiate|confirm)/i,
59
+ /\bthis would be fabrication\b/i,
60
+ /\bthe prompt (says|asks|instructions?|rules?)\b/i,
61
+ /\b(verification|synthesis) (plan |protocol )?mode\b/i,
62
+ /^\s*hypotheses?\s*:\s*$/i,
63
+ /^\s*search quer(y|ies)\s*:\s*$/i,
64
+ /\bi am now proceeding to verify\b/i,
65
+ /\bplease wait for the (final|synthesized) (synthesis|response|answer)\b/i,
66
+ /\bproceeding to (verify|synthesise|synthesize|the final)\b/i,
67
+ /\b(operational|cognitive|reasoning) (flow|trace|ledger)\b/i,
68
+ /\bnon-negotiable rules\b/i,
69
+ /\b(humanistic|varied) phrasing\b/i,
70
+ /\bno preamble\b/i,
71
+ /\bcite inline\b/i,
72
+ /\b(use |applying )["“]?(the |cadenced |elegant )?(narrator|scholar|analyst|naturalist|essayist)["“]?/i,
73
+ /\btemporal anchor\b/i,
74
+ /\bverified entity sheet\b/i,
75
+ /\bstress position\b/i,
76
+ /\bcumulative sentences\b/i,
77
+ /\bfabrication check\b/i,
78
+ /\bsince i am an ai\b/i,
79
+ /\bsimulated (for |market |data |response |idea)/i,
80
+ /\bi (must|should|will) (generate|reconcile|use|provide|make sure|ensure|avoid|explicitly|start with|open with|address)/i,
81
+ /\b(pitfalls|alternatives|pitfalls, alternatives)\b/i,
82
+ /\b(factor 1|factor 2|factor 3)\b/i,
83
+ ];
84
+ for (const re of labels) if (re.test(t)) return true;
85
+ return false;
86
+ }
87
+
88
+ /**
89
+ * Find the final prose block by scanning backward from the end.
90
+ * Returns the index of the first line of the final contiguous prose block.
91
+ */
92
+ function findFinalProseStart(lines: string[]): number {
93
+ // Walk backward from the end, skipping blanks, to find the last prose line.
94
+ let lastProse = -1;
95
+ for (let i = lines.length - 1; i >= 0; i--) {
96
+ if (isDefinitelyProse(lines[i])) {
97
+ lastProse = i;
98
+ break;
99
+ }
100
+ }
101
+ if (lastProse < 0) return 0; // no prose found, keep everything
102
+
103
+ // Now walk backward from lastProse to find where the prose block starts.
104
+ // Allow up to 2 blank lines or short transitional lines between prose lines.
105
+ let start = lastProse;
106
+ let gapCount = 0;
107
+ for (let i = lastProse - 1; i >= 0; i--) {
108
+ const t = lines[i].trim();
109
+ if (isDefinitelyProse(lines[i])) {
110
+ start = i;
111
+ gapCount = 0;
112
+ } else if (!t) {
113
+ gapCount++;
114
+ if (gapCount <= 2) {
115
+ start = i; // blank lines between prose paragraphs are ok
116
+ } else {
117
+ break; // more than 2 consecutive blanks = end of prose block
118
+ }
119
+ } else if (isPlanning(lines[i])) {
120
+ break; // hit a planning line = end of prose block going backward
121
+ } else {
122
+ // Ambiguous line (short, not clearly prose or planning)
123
+ // If it's short (<30 chars) and between prose, include it
124
+ if (t.length < 30) {
125
+ gapCount++;
126
+ if (gapCount <= 2) start = i;
127
+ else break;
128
+ } else {
129
+ start = i; // medium-length non-planning line, probably prose
130
+ gapCount = 0;
131
+ }
132
+ }
133
+ }
134
+ return start;
135
+ }
136
+
137
+ // ─── Tag patterns and meta-discourse (same as before) ───────────────
138
+
139
+ const TAG_PATTERNS: RegExp[] = [
140
+ /\((?:L\d+(?:\/L\d+)?(?:,\s*L\d+(?:\/L\d+)?)*)\)/g,
141
+ /\(simulated for [A-Z][a-z]+ 20\d\d\)/g,
142
+ /\(simulated\)/gi,
143
+ ];
144
+
145
+ const META_DISCOURSE: RegExp[] = [
146
+ /based on the (?:provided )?(?:data|search results?|payload|json|sources?)/gi,
147
+ /according to the (?:search|retriev|payload|sources?)/gi,
148
+ /the retrieved (?:documents?|records?) (?:do not provide|shows?|indicates?|states?)/gi,
149
+ /as (?:an?|the) ai[,.]?/gi,
150
+ /\bin conclusion[,.]?/gi,
151
+ /\(self[-\s]?correction:[^)]*\)/gi,
152
+ ];
153
+
154
+ // ─── Main entry point ───────────────────────────────────────────────
155
+
156
+ export function cleanOutput(raw: string): BoundaryResult {
157
+ let s = raw.replace(/\r\n/g, "\n");
158
+ const notes: string[] = [];
159
+ let removed = 0;
160
+
161
+ // 1. If the model used <final_answer> tags, prefer those.
162
+ const tagged = s.match(/<final_answer>([\s\S]*?)(?:<\/final_answer>|$)/i);
163
+ if (tagged) {
164
+ notes.push("extracted <final_answer> tag");
165
+ s = tagged[1].trim();
166
+ } else {
167
+ // 2. Inverted approach: find the final prose block and discard the rest.
168
+ const lines = s.split("\n");
169
+ const proseStart = findFinalProseStart(lines);
170
+ if (proseStart > 0) {
171
+ removed += proseStart;
172
+ notes.push(`inverted boundary: dropped ${proseStart} pre-prose lines`);
173
+ s = lines.slice(proseStart).join("\n").trim();
174
+ }
175
+ }
176
+
177
+ // 3. Line-level filter: drop any remaining planning lines.
178
+ const linesBefore = s.split("\n");
179
+ const filtered = linesBefore.filter(line => !isPlanning(line));
180
+ if (filtered.length < linesBefore.length) {
181
+ const diff = linesBefore.length - filtered.length;
182
+ removed += diff;
183
+ notes.push(`stripped ${diff} residual planning lines`);
184
+ }
185
+ s = filtered.join("\n");
186
+
187
+ // 4. Strip raw [Source N] / [Source N, M] artifacts and tag patterns.
188
+ s = s.replace(/\[Source\s*\d+(?:\s*,\s*(?:Source\s*)?\d+)*\s*\]/gi, "");
189
+ for (const re of TAG_PATTERNS) s = s.replace(re, "");
190
+
191
+ // 5. Strip meta-discourse.
192
+ for (const re of META_DISCOURSE) s = s.replace(re, "");
193
+
194
+ // 6. Strip leaked XML/HTML structural tags (<paragraph>, <section>, <div>, etc.)
195
+ s = s.replace(/<\/?(paragraph|section|div|span|p|article|header|footer|main)\s*\/?>/gi, "");
196
+
197
+ // 7. Strip <scratchpad>...</scratchpad> and <final_response>...</final_response> wrapper tags
198
+ s = s.replace(/<\/?(scratchpad|final_response|thinking|chain_of_thought|cot)\s*>/gi, "");
199
+
200
+ // 8. Flag unpopulated placeholders inline
201
+ let placeholderCount = 0;
202
+ s = s.replace(/\[([^\]\n]{2,80})\]/g, (match, inner) => {
203
+ const v = String(inner).trim();
204
+ if (/^source\s*\d+$/i.test(v) || /^\d+$/.test(v)) return match;
205
+ if (/^(?:list of|description of|insert|tbd|placeholder|to be |fill in|add |provide |your )/i.test(v)) {
206
+ placeholderCount++;
207
+ return `⚠️ PLACEHOLDER: ${v}`;
208
+ }
209
+ return match;
210
+ });
211
+ if (placeholderCount > 0) {
212
+ notes.push(`flagged ${placeholderCount} unpopulated template placeholder(s)`);
213
+ }
214
+
215
+ // 9. PI-NAME REDACTION GATE — never emit invented Principal Investigator names.
216
+ // Replace any "PI: Dr. Jane Doe" / "Principal Investigator: John Smith" /
217
+ // "led by Dr. X" patterns with a neutral placeholder.
218
+ let piRedactions = 0;
219
+ s = s.replace(/\b(Principal Investigator|PI|Lead Investigator|Co-?PI|Project Director)\s*[:\-]\s*(Dr\.?\s+)?[A-Z][a-z]+(?:\s+[A-Z]\.?)?(?:\s+[A-Z][a-z]+)+/g, (m) => {
220
+ piRedactions++;
221
+ const role = m.split(/[:\-]/)[0].trim();
222
+ return `${role}: [To be designated]`;
223
+ });
224
+ s = s.replace(/\b(led by|headed by|directed by)\s+(Dr\.?\s+)?[A-Z][a-z]+(?:\s+[A-Z]\.?)?\s+[A-Z][a-z]+/g, (m) => {
225
+ piRedactions++;
226
+ const verb = m.split(/\s+/)[0] + " " + m.split(/\s+/)[1];
227
+ return `${verb} the designated Principal Investigator`;
228
+ });
229
+ if (piRedactions > 0) {
230
+ notes.push(`redacted ${piRedactions} invented PI name(s)`);
231
+ }
232
+
233
+ s = s.replace(/\n{3,}/g, "\n\n").trim();
234
+ return { cleaned: s, removedSegments: removed, notes };
235
+ }
@@ -0,0 +1,154 @@
1
+ /**
2
+ * vite-native-chaos-harness.ts — L5: Deterministic SSRF/NUL Fuzzing
3
+ * Uses deterministic PRNG to generate and test malicious inputs.
4
+ * Zero-dependency: pure TypeScript.
5
+ */
6
+
7
+ export interface ChaosResult {
8
+ passed: boolean;
9
+ blocked: number;
10
+ escaped: number;
11
+ total: number;
12
+ failures: string[];
13
+ ts: number;
14
+ }
15
+
16
+ // ── Deterministic PRNG: XorShift32 ───────────────────────────────────────
17
+ // Hand-trace for seed 0x0badc0de:
18
+ // let s = 0x0badc0de
19
+ // Step 1: s ^= (s << 13) = s ^ (s * 2^13) [32-bit truncated]
20
+ // 0x0badc0de << 13 in 32-bit: 0x0badc0de * 8192 mod 2^32
21
+ // 0x0badc0de = 196362462 decimal
22
+ // 196362462 * 8192 = 1608868429824 = 0x176_7A37_0000 — lower 32 bits = 0x7A370000 BUT need XOR
23
+ // Actually: (196362462 * 8192) >>> 0 = (0x0badc0de0000 >> 16 lower 32 bits)
24
+ // Let s = seed, result s ^= (s << 13) truncated to 32 bits
25
+ // This is standard XorShift32 — produces deterministic non-zero sequence
26
+ export function xorshift32(seed: number): () => number {
27
+ // Must use 32-bit arithmetic
28
+ let s = seed >>> 0;
29
+ if (s === 0) s = 1; // XorShift must not start at 0
30
+ return () => {
31
+ // Standard XorShift32 algorithm
32
+ s ^= (s << 13) >>> 0;
33
+ s ^= (s >>> 17);
34
+ s ^= (s << 5) >>> 0;
35
+ s = s >>> 0; // Enforce uint32
36
+ return s;
37
+ };
38
+ }
39
+
40
+ // ── Malicious URL Corpus ───────────────────────────────────────────────────
41
+ // These are the canonical SSRF attack vectors the system MUST block
42
+ const MALICIOUS_URLS: Array<{ url: string; expectedBlock: string }> = [
43
+ // NUL byte injection — caught by Step 1
44
+ { url: 'http://127.0.0.1%00.evil.com', expectedBlock: 'NUL byte' },
45
+ { url: 'http://evil.com%00@127.0.0.1/', expectedBlock: 'NUL byte' },
46
+ // Gopher protocol (can be used to access Redis, etc.)
47
+ { url: 'gopher://127.0.0.1:6379/_PING', expectedBlock: 'protocol' },
48
+ // AWS metadata endpoint
49
+ { url: 'http://169.254.169.254/latest/meta-data/', expectedBlock: 'blocked IP' },
50
+ // GCP metadata
51
+ { url: 'http://metadata.google.internal/computeMetadata/v1/', expectedBlock: 'blocked host' },
52
+ // IPv4-mapped IPv6 — must extract and check embedded IPv4
53
+ { url: 'http://[::ffff:127.0.0.1]/', expectedBlock: 'blocked IP' },
54
+ // Direct loopback
55
+ { url: 'http://127.0.0.1/', expectedBlock: 'blocked IP' },
56
+ { url: 'http://0.0.0.0/', expectedBlock: 'blocked IP' },
57
+ // Link-local
58
+ { url: 'http://169.254.0.1/', expectedBlock: 'blocked IP' },
59
+ // RFC 1918 private ranges
60
+ { url: 'http://10.0.0.1/', expectedBlock: 'blocked IP' },
61
+ { url: 'http://192.168.1.1/', expectedBlock: 'blocked IP' },
62
+ { url: 'http://172.16.0.1/', expectedBlock: 'blocked IP' },
63
+ // localhost variants
64
+ { url: 'http://localhost/', expectedBlock: 'blocked host' },
65
+ { url: 'http://localhost.localdomain/', expectedBlock: 'blocked host' },
66
+ // Credentialed URLs
67
+ { url: 'http://admin:password@127.0.0.1/', expectedBlock: 'credentials' },
68
+ // Carrier-grade NAT
69
+ { url: 'http://100.64.0.1/', expectedBlock: 'blocked IP' },
70
+ ];
71
+
72
+ // ── Test runner: requires prepTarget function from scraper ────────────────
73
+ // The chaos harness calls the actual prepTarget implementation to verify
74
+ // 100% of malicious inputs are blocked
75
+
76
+ export async function runChaosTests(prepTarget: (url: string) => Promise<unknown>): Promise<ChaosResult> {
77
+ const ts = Date.now();
78
+ const failures: string[] = [];
79
+ let blocked = 0;
80
+ let escaped = 0;
81
+
82
+ // Use deterministic PRNG to shuffle corpus — reproducible test order
83
+ const prng = xorshift32(0x0badc0de);
84
+ const shuffled = [...MALICIOUS_URLS].sort(() => (prng() % 2 === 0 ? 1 : -1));
85
+
86
+ for (const { url, expectedBlock } of shuffled) {
87
+ try {
88
+ await prepTarget(url);
89
+ // If we get here, the URL was NOT blocked — security failure
90
+ escaped++;
91
+ failures.push(`SSRF ESCAPE: "${url}" was not blocked (expected: ${expectedBlock})`);
92
+ } catch (e: any) {
93
+ // Expected: prepTarget should throw for all malicious URLs
94
+ blocked++;
95
+ }
96
+ }
97
+
98
+ // Additional fuzz test: generate random mutations of malicious URLs
99
+ const prng2 = xorshift32(0xdeadbeef);
100
+ const extraMalicious = [
101
+ `http://127.${prng2() % 256}.${prng2() % 256}.${prng2() % 256}/`,
102
+ `http://192.168.${prng2() % 256}.${prng2() % 256}/sensitive`,
103
+ `http://10.${prng2() % 256}.${prng2() % 256}.${prng2() % 256}:8080/`,
104
+ ];
105
+
106
+ for (const url of extraMalicious) {
107
+ try {
108
+ await prepTarget(url);
109
+ escaped++;
110
+ failures.push(`SSRF ESCAPE (fuzz): "${url}" was not blocked`);
111
+ } catch {
112
+ blocked++;
113
+ }
114
+ }
115
+
116
+ const total = shuffled.length + extraMalicious.length;
117
+
118
+ return {
119
+ passed: escaped === 0 && blocked === total,
120
+ blocked,
121
+ escaped,
122
+ total,
123
+ failures,
124
+ ts,
125
+ };
126
+ }
127
+
128
+ // ── Offline corpus test (no prepTarget needed) ────────────────────────────
129
+ // Tests only the URL parsing logic without making DNS calls
130
+ export function runOfflineChaosTests(): { passed: boolean; failures: string[] } {
131
+ const failures: string[] = [];
132
+
133
+ // Test NUL detection
134
+ const nulUrls = ['http://127.0.0.1%00.evil.com', 'http://evil.com\x00test'];
135
+ for (const url of nulUrls) {
136
+ const hasNul = url.includes('\0') || /%00/i.test(url);
137
+ if (!hasNul) failures.push(`NUL detection missed: ${url}`);
138
+ }
139
+
140
+ // Test credential detection
141
+ try {
142
+ const u = new URL('http://admin:password@127.0.0.1/');
143
+ if (!u.username || !u.password) failures.push('URL parser did not detect credentials');
144
+ } catch {}
145
+
146
+ // Test blocked host detection
147
+ const blockedHosts = ['localhost', 'metadata.google.internal', 'test.localhost'];
148
+ for (const host of blockedHosts) {
149
+ const isBlocked = host === 'localhost' || host.endsWith('.localhost') || host === 'metadata.google.internal';
150
+ if (!isBlocked) failures.push(`Host ${host} should be blocked`);
151
+ }
152
+
153
+ return { passed: failures.length === 0, failures };
154
+ }
@@ -0,0 +1,245 @@
1
+ /**
2
+ * vite-native-contract-plane.ts — L3: OpenAPI 3.1 & RFC 9457 Schemas
3
+ * Zero-dependency: pure TypeScript objects.
4
+ */
5
+
6
+ // ── RFC 9457 Problem Details ──────────────────────────────────────────────
7
+ export const PROBLEM_TYPES = {
8
+ missing_query: {
9
+ type: 'https://vite-native-gateway/problems/missing-query',
10
+ title: 'Missing Required Query Parameter',
11
+ status: 400,
12
+ detail: "The 'q' query parameter is required and was not provided.",
13
+ },
14
+ ssrf_blocked: {
15
+ type: 'https://vite-native-gateway/problems/ssrf-blocked',
16
+ title: 'SSRF Target Blocked',
17
+ status: 400,
18
+ detail: 'The requested URL was blocked by the SSRF protection policy.',
19
+ },
20
+ rate_limited: {
21
+ type: 'https://vite-native-gateway/problems/rate-limited',
22
+ title: 'Rate Limit Exceeded',
23
+ status: 429,
24
+ detail: 'Too many requests. Please slow down and retry after a moment.',
25
+ },
26
+ upstream_failed: {
27
+ type: 'https://vite-native-gateway/problems/upstream-failed',
28
+ title: 'Upstream Search Engine Failed',
29
+ status: 502,
30
+ detail: 'All search engine backends returned errors. Retry later.',
31
+ },
32
+ internal_error: {
33
+ type: 'https://vite-native-gateway/problems/internal-error',
34
+ title: 'Internal Server Error',
35
+ status: 500,
36
+ detail: 'An unexpected internal error occurred.',
37
+ },
38
+ agent_loop: {
39
+ type: 'https://vite-native-gateway/problems/agent-loop',
40
+ title: 'Agent Loop Detected',
41
+ status: 429,
42
+ detail: 'The same URL has been requested too many times in a short period.',
43
+ },
44
+ cross_origin: {
45
+ type: 'https://vite-native-gateway/problems/cross-origin',
46
+ title: 'Cross-Origin Request Rejected',
47
+ status: 403,
48
+ detail: 'Cross-origin requests to the local gateway are not permitted.',
49
+ },
50
+ } as const;
51
+
52
+ export type ProblemType = keyof typeof PROBLEM_TYPES;
53
+
54
+ export function makeProblem(type: ProblemType, extra?: Partial<{ detail: string; instance: string }>): object {
55
+ const base = PROBLEM_TYPES[type];
56
+ return {
57
+ ...base,
58
+ ...(extra?.detail && { detail: extra.detail }),
59
+ ...(extra?.instance && { instance: extra.instance }),
60
+ };
61
+ }
62
+
63
+ // ── OpenAPI 3.1 Document ──────────────────────────────────────────────────
64
+ export function getNativeOpenApiDocument(baseUrl: string): object {
65
+ const problemSchema = {
66
+ type: 'object',
67
+ properties: {
68
+ type: { type: 'string', format: 'uri' },
69
+ title: { type: 'string' },
70
+ status: { type: 'integer' },
71
+ detail: { type: 'string' },
72
+ instance: { type: 'string', format: 'uri' },
73
+ },
74
+ required: ['type', 'title', 'status'],
75
+ };
76
+
77
+ const problemResponse = {
78
+ description: 'RFC 9457 Problem Details',
79
+ content: { 'application/problem+json': { schema: { $ref: '#/components/schemas/Problem' } } },
80
+ };
81
+
82
+ return {
83
+ openapi: '3.1.0',
84
+ jsonSchemaDialect: 'https://json-schema.org/draft/2020-12/schema',
85
+ info: {
86
+ title: 'Vite Native Knowledge Gateway',
87
+ version: '1.0.0',
88
+ description: 'Zero-dependency local metasearch engine and knowledge store.',
89
+ },
90
+ servers: [{ url: baseUrl }],
91
+ paths: {
92
+ '/api/native-search': {
93
+ get: {
94
+ summary: 'Metasearch across multiple engines with RRF+MMR ranking',
95
+ parameters: [
96
+ { name: 'q', in: 'query', required: true, schema: { type: 'string', minLength: 1 } },
97
+ { name: 'count', in: 'query', required: false, schema: { type: 'integer', minimum: 1, maximum: 20, default: 5 } },
98
+ { name: 'engines', in: 'query', required: false, schema: { type: 'string' } },
99
+ ],
100
+ responses: {
101
+ '200': { description: 'Search results', content: { 'application/json': { schema: { type: 'object' } } } },
102
+ '400': { $ref: '#/components/responses/Problem' },
103
+ '429': { $ref: '#/components/responses/Problem' },
104
+ '502': { $ref: '#/components/responses/Problem' },
105
+ },
106
+ },
107
+ },
108
+ '/api/native-search/stream': {
109
+ get: {
110
+ summary: 'SSE streaming search results',
111
+ parameters: [
112
+ { name: 'q', in: 'query', required: true, schema: { type: 'string' } },
113
+ { name: 'count', in: 'query', required: false, schema: { type: 'integer', minimum: 1, maximum: 20 } },
114
+ ],
115
+ responses: {
116
+ '200': { description: 'SSE stream', content: { 'text/event-stream': { schema: { type: 'string' } } } },
117
+ '400': { $ref: '#/components/responses/Problem' },
118
+ '429': { $ref: '#/components/responses/Problem' },
119
+ },
120
+ },
121
+ },
122
+ '/api/native-read': {
123
+ get: {
124
+ summary: 'Fetch and extract text content from a URL (SSRF-protected)',
125
+ parameters: [
126
+ { name: 'url', in: 'query', required: true, schema: { type: 'string', format: 'uri' } },
127
+ ],
128
+ responses: {
129
+ '200': { description: 'Page content', content: { 'application/json': { schema: { type: 'object' } } } },
130
+ '400': { $ref: '#/components/responses/Problem' },
131
+ },
132
+ },
133
+ },
134
+ '/api/native-ingest': {
135
+ post: {
136
+ summary: 'Ingest content into the knowledge store',
137
+ requestBody: {
138
+ required: true,
139
+ content: {
140
+ 'application/json': {
141
+ schema: {
142
+ type: 'object',
143
+ properties: {
144
+ kind: { type: 'string' },
145
+ ref: { type: 'string' },
146
+ summary: { type: 'string' },
147
+ },
148
+ required: ['kind', 'ref', 'summary'],
149
+ },
150
+ },
151
+ },
152
+ },
153
+ responses: {
154
+ '200': { description: 'Ingest result', content: { 'application/json': { schema: { type: 'object' } } } },
155
+ '400': { $ref: '#/components/responses/Problem' },
156
+ },
157
+ },
158
+ },
159
+ '/api/native-knowledge': {
160
+ get: {
161
+ summary: 'Search the knowledge store',
162
+ parameters: [
163
+ { name: 'q', in: 'query', required: true, schema: { type: 'string' } },
164
+ { name: 'limit', in: 'query', schema: { type: 'integer', minimum: 1, maximum: 100 } },
165
+ ],
166
+ responses: {
167
+ '200': { description: 'Knowledge records', content: { 'application/json': { schema: { type: 'object' } } } },
168
+ },
169
+ },
170
+ },
171
+ '/api/native-knowledge/repair-index': {
172
+ post: {
173
+ summary: 'Rebuild FTS5 index',
174
+ responses: { '200': { description: 'Repair result' } },
175
+ },
176
+ },
177
+ '/api/audit/verify': {
178
+ get: {
179
+ summary: 'Verify audit log integrity',
180
+ responses: { '200': { description: 'Audit verification result' } },
181
+ },
182
+ },
183
+ '/api/native-doctor': {
184
+ get: {
185
+ summary: 'Aggregated health report',
186
+ parameters: [
187
+ { name: 'deep', in: 'query', schema: { type: 'boolean' } },
188
+ ],
189
+ responses: { '200': { description: 'Doctor report' } },
190
+ },
191
+ },
192
+ '/api/native-selftest': {
193
+ get: {
194
+ summary: 'Run static self-tests',
195
+ responses: { '200': { description: 'Self-test results' } },
196
+ },
197
+ },
198
+ '/api/native-selftest/functional': {
199
+ get: {
200
+ summary: 'Run functional golden-fixture tests',
201
+ responses: { '200': { description: 'Functional test results' } },
202
+ },
203
+ },
204
+ '/api/native-policy': {
205
+ get: { summary: 'Get all policy flags', responses: { '200': { description: 'Policy flags' } } },
206
+ post: { summary: 'Set a policy flag', responses: { '200': { description: 'Policy update result' } } },
207
+ },
208
+ '/api/native-snapshot': {
209
+ post: { summary: 'Create hot backup', responses: { '200': { description: 'Snapshot result' } } },
210
+ get: { summary: 'Get snapshot manifest', responses: { '200': { description: 'Snapshot manifest' } } },
211
+ },
212
+ '/api/native-maintenance/run': {
213
+ post: { summary: 'Run SQLite maintenance', responses: { '200': { description: 'Maintenance result' } } },
214
+ },
215
+ '/api/native-runtime': {
216
+ get: { summary: 'Get runtime stats', responses: { '200': { description: 'Runtime stats' } } },
217
+ },
218
+ },
219
+ components: {
220
+ schemas: { Problem: problemSchema },
221
+ responses: { Problem: problemResponse },
222
+ },
223
+ };
224
+ }
225
+
226
+ // ── Contract Self-Test ────────────────────────────────────────────────────
227
+ export function contractSelfTest(): { passed: boolean; failures: string[] } {
228
+ const failures: string[] = [];
229
+ const doc = getNativeOpenApiDocument('http://localhost:5173') as any;
230
+
231
+ if (doc.openapi !== '3.1.0') failures.push('openapi version must be 3.1.0');
232
+ if (!doc.jsonSchemaDialect) failures.push('jsonSchemaDialect missing');
233
+ if (!doc.paths['/api/native-search']) failures.push('/api/native-search path missing');
234
+ if (!doc.paths['/api/native-read']) failures.push('/api/native-read path missing');
235
+ if (!doc.paths['/api/native-ingest']) failures.push('/api/native-ingest path missing');
236
+ if (!doc.components?.schemas?.Problem) failures.push('Problem schema missing from components');
237
+ if (!doc.components?.responses?.Problem) failures.push('Problem response missing from components');
238
+
239
+ // Verify query param type precision
240
+ const searchParams = doc.paths['/api/native-search']?.get?.parameters;
241
+ const countParam = searchParams?.find((p: any) => p.name === 'count');
242
+ if (countParam?.schema?.type !== 'integer') failures.push('count param must be type:integer not type:number');
243
+
244
+ return { passed: failures.length === 0, failures };
245
+ }