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.
- package/diagnostics.mjs +141 -0
- package/dist/compute.worker-j5ahIpF-.js +1 -0
- package/dist/graph.worker-DG6iGCB9.js +1 -0
- package/dist/index.html +2314 -0
- package/flatten-guide.md +248 -0
- package/index.html +12 -0
- package/package.json +38 -0
- package/src/App.orig.tsx +204 -0
- package/src/App.orig1.tsx +27 -0
- package/src/App.orig2.tsx +25 -0
- package/src/App.tsx +3 -0
- package/src/BaseApp.tsx +18 -0
- package/src/INTEGRATION_LEDGER.md +22 -0
- package/src/PERSIST_CANARY.orig.txt +1 -0
- package/src/PERSIST_CANARY.txt +1 -0
- package/src/REGRESSION_LEDGER.md +651 -0
- package/src/TEMPLATE_PIPELINE_AUDIT.md +208 -0
- package/src/WILLIAMS_PERSONA_GUIDE.md +62 -0
- package/src/chat/VeritasChat.tsx +69 -0
- package/src/chat/synthesis.ts +31 -0
- package/src/chat/tier.ts +45 -0
- package/src/components/AdaptersPage.orig.tsx +99 -0
- package/src/components/AdaptersPage.tsx +3 -0
- package/src/components/AdversarialPanel.tsx +136 -0
- package/src/components/AnchorBaselinePanel.tsx +75 -0
- package/src/components/AnswerPanel.tsx +60 -0
- package/src/components/ArtifactPanel.tsx +43 -0
- package/src/components/ChatApp.orig.tsx +1582 -0
- package/src/components/ChatApp.orig1.tsx +722 -0
- package/src/components/ChatApp.tsx +95 -0
- package/src/components/ChatAugmentPanels.tsx +73 -0
- package/src/components/CitationLedgerPanel.tsx +313 -0
- package/src/components/ComputeSandboxPanel.tsx +130 -0
- package/src/components/ConfigPanel.tsx +110 -0
- package/src/components/ControlPlanePage.tsx +195 -0
- package/src/components/CreativeTreeLifePage.tsx +234 -0
- package/src/components/CreativeTreeOfLifePanel.tsx +149 -0
- package/src/components/DebugTracePanel.tsx +137 -0
- package/src/components/DeepReasoningTrace.tsx +48 -0
- package/src/components/EntitySheetPanel.tsx +51 -0
- package/src/components/FailureModesPanel.tsx +104 -0
- package/src/components/GBSDashboard.tsx +239 -0
- package/src/components/GraphView.tsx +116 -0
- package/src/components/HUD.tsx +125 -0
- package/src/components/HypothesisPanel.tsx +67 -0
- package/src/components/InnovationGenomeEngine.tsx +792 -0
- package/src/components/InnovationPersonaGuide.tsx +348 -0
- package/src/components/InnovationPersonaPanel.tsx +289 -0
- package/src/components/LiveResourceHUD.tsx +109 -0
- package/src/components/LongWriterPanel.tsx +112 -0
- package/src/components/MainPipelineV10Bridge.tsx +72 -0
- package/src/components/MarkdownLite.tsx +63 -0
- package/src/components/MemoryInspector.tsx +38 -0
- package/src/components/MemoryMonitor.tsx +52 -0
- package/src/components/MemoryStressPanel.tsx +176 -0
- package/src/components/ModulesPage.tsx +171 -0
- package/src/components/PipelineDebugConsole.orig.tsx +1856 -0
- package/src/components/PipelineDebugConsole.tsx +3 -0
- package/src/components/PreFlightHUD.tsx +67 -0
- package/src/components/PrismaFetchTracePanel.tsx +87 -0
- package/src/components/ReportOSPanel.tsx +165 -0
- package/src/components/ResourceEstimatorPage.tsx +327 -0
- package/src/components/RichText.tsx +181 -0
- package/src/components/SagaOsPanel.tsx +605 -0
- package/src/components/SagaOsReference.tsx +421 -0
- package/src/components/SagaOsV2Panel.tsx +594 -0
- package/src/components/SagaStyleTab.tsx +382 -0
- package/src/components/SageBlueprintPanel.tsx +416 -0
- package/src/components/SharedChatInput.tsx +77 -0
- package/src/components/StatFinancePanel.tsx +190 -0
- package/src/components/StylePersonaPanel.tsx +128 -0
- package/src/components/TemplatesPage.tsx +300 -0
- package/src/components/TestPanel.tsx +63 -0
- package/src/components/TraceLog.tsx +89 -0
- package/src/components/V15CalibrationAugment.tsx +1134 -0
- package/src/components/V15CalibrationDialog.tsx +1871 -0
- package/src/components/V15Overlay.orig.tsx +120 -0
- package/src/components/V15Overlay.tsx +4 -0
- package/src/components/V15OverlayWrapper.tsx +362 -0
- package/src/components/V15Toggle.tsx +34 -0
- package/src/console/DiagnosticRecoveryPanel.tsx +358 -0
- package/src/console/EngineeringConsole.tsx +103 -0
- package/src/console/FictionSystemPanels.tsx +882 -0
- package/src/console/InspectorPanels.tsx +254 -0
- package/src/console/ManuscriptGraderPanel.tsx +182 -0
- package/src/console/RecursiveReviserPanel.tsx +245 -0
- package/src/console/SeedControlPanel.tsx +135 -0
- package/src/console/StoryControllerPanel.tsx +443 -0
- package/src/console/engineBridge.ts +258 -0
- package/src/console/gemini.ts +106 -0
- package/src/console/grading.ts +250 -0
- package/src/console/util.ts +45 -0
- package/src/fiction/continuity.ts +372 -0
- package/src/fiction/crash-protection.ts +111 -0
- package/src/fiction/diagnostics.ts +208 -0
- package/src/fiction/diff.ts +74 -0
- package/src/fiction/entity-state-machine.ts +214 -0
- package/src/fiction/nive-engine.ts +404 -0
- package/src/fiction/pipeline-selftest.ts +132 -0
- package/src/fiction/seed-control.ts +193 -0
- package/src/fiction/story-engine.ts +326 -0
- package/src/fiction/types.ts +68 -0
- package/src/flatten-guide.md +379 -0
- package/src/index.css +14 -0
- package/src/index.orig.css +13 -0
- package/src/lib/academic-sources.base.ts +188 -0
- package/src/lib/academic-sources.orig.ts +28 -0
- package/src/lib/academic-sources.ts +10 -0
- package/src/lib/advanced-math.ts +119 -0
- package/src/lib/adversarial-engine.base.ts +409 -0
- package/src/lib/adversarial-engine.ts +82 -0
- package/src/lib/ai-revision.ts +623 -0
- package/src/lib/app-state.tsx +426 -0
- package/src/lib/artifact-registry.ts +97 -0
- package/src/lib/artifacts.ts +180 -0
- package/src/lib/atlas-dr.ts +167 -0
- package/src/lib/browser-mtls.ts +127 -0
- package/src/lib/browser-queue.ts +221 -0
- package/src/lib/browser-search-scraper.base.ts +382 -0
- package/src/lib/browser-search-scraper.orig.ts +90 -0
- package/src/lib/browser-search-scraper.ts +10 -0
- package/src/lib/calc-interceptor.ts +82 -0
- package/src/lib/citation-lane-tap.ts +78 -0
- package/src/lib/citation-ledger-store.ts +369 -0
- package/src/lib/citation-ledger.ts +203 -0
- package/src/lib/compute-sandbox.ts +215 -0
- package/src/lib/compute.worker.ts +153 -0
- package/src/lib/connectors/gemini.ts +120 -0
- package/src/lib/connectors/jina.ts +233 -0
- package/src/lib/connectors/marketdata.ts +51 -0
- package/src/lib/connectors/prismafetch.base.ts +175 -0
- package/src/lib/connectors/prismafetch.ts +1 -0
- package/src/lib/connectors/serpapi.ts +65 -0
- package/src/lib/connectors/wikidata.ts +44 -0
- package/src/lib/constraints.ts +331 -0
- package/src/lib/continuation-detector.base.ts +153 -0
- package/src/lib/continuation-detector.ts +48 -0
- package/src/lib/contradraft.ts +168 -0
- package/src/lib/cors-proxy.ts +120 -0
- package/src/lib/coverage.ts +81 -0
- package/src/lib/debug/architecture-prescription.ts +556 -0
- package/src/lib/debug/covea-repair.ts +543 -0
- package/src/lib/debug/helios-ground.ts +319 -0
- package/src/lib/debug/intent-decomposer.ts +281 -0
- package/src/lib/debug/intent-lattice.ts +349 -0
- package/src/lib/debug/pipeline-diagnosis.ts +1149 -0
- package/src/lib/debug/pipeline-trace-bus.ts +424 -0
- package/src/lib/debug/prompt-forge.ts +678 -0
- package/src/lib/debug/repair-sites.ts +513 -0
- package/src/lib/debug/research-phase.ts +266 -0
- package/src/lib/debug/retrieval-context.ts +76 -0
- package/src/lib/debug/retrieval-hardener.ts +142 -0
- package/src/lib/debug/scraper-debug-runner.ts +576 -0
- package/src/lib/debug/scraper-forensics.ts +418 -0
- package/src/lib/debug/scraper-lane-roadmap.ts +136 -0
- package/src/lib/debug/self-test.ts +415 -0
- package/src/lib/debug/step-attribution.ts +211 -0
- package/src/lib/debug/template-rubric.ts +301 -0
- package/src/lib/debug/unified-innovation.ts +126 -0
- package/src/lib/debug/veritas-hybrid-scraper.ts +335 -0
- package/src/lib/defense-registry.ts +104 -0
- package/src/lib/defenses.ts +162 -0
- package/src/lib/deterministic-citation-ledger.ts +174 -0
- package/src/lib/elo-registry.base.ts +117 -0
- package/src/lib/elo-registry.ts +1 -0
- package/src/lib/entity-resolver.ts +291 -0
- package/src/lib/failure-modes.ts +267 -0
- package/src/lib/feature-registry.ts +69 -0
- package/src/lib/flaw-registry.ts +143 -0
- package/src/lib/flaws/_template.ts +52 -0
- package/src/lib/flaws/builtins.ts +63 -0
- package/src/lib/flaws/finance.ts +169 -0
- package/src/lib/flaws/fixers.ts +10 -0
- package/src/lib/flaws/index.ts +32 -0
- package/src/lib/flaws/legal.ts +157 -0
- package/src/lib/flaws/medical.ts +188 -0
- package/src/lib/flaws/original-defenses-pack.ts +81 -0
- package/src/lib/flaws/sample-declarative-pack.json +38 -0
- package/src/lib/flaws/selftest.ts +201 -0
- package/src/lib/flaws/software-extended.ts +125 -0
- package/src/lib/flaws/software-rn-webgl.ts +182 -0
- package/src/lib/flaws/statistics-advanced.ts +46 -0
- package/src/lib/flaws/statistics.ts +61 -0
- package/src/lib/gbse/config.ts +20 -0
- package/src/lib/gbse/engine.ts +226 -0
- package/src/lib/gbse/graph.ts +118 -0
- package/src/lib/gbse/graph.worker.ts +21 -0
- package/src/lib/gbse/tests.ts +117 -0
- package/src/lib/gbse/tiers.ts +65 -0
- package/src/lib/gbse/types.ts +94 -0
- package/src/lib/innovation-genome-engine-v2.orig.ts +1001 -0
- package/src/lib/innovation-genome-engine-v2.ts +3 -0
- package/src/lib/innovation-genome-engine.orig.ts +330 -0
- package/src/lib/innovation-genome-engine.ts +3 -0
- package/src/lib/innovation-genome-v10.orig.ts +314 -0
- package/src/lib/innovation-genome-v10.ts +2 -0
- package/src/lib/innovation-genome-v3.orig.ts +2015 -0
- package/src/lib/innovation-genome-v3.ts +2 -0
- package/src/lib/innovation-genome-v4.orig.ts +1959 -0
- package/src/lib/innovation-genome-v4.ts +2 -0
- package/src/lib/innovation-genome-v5.orig.ts +1210 -0
- package/src/lib/innovation-genome-v5.ts +2 -0
- package/src/lib/innovation-genome-v7.orig.ts +2549 -0
- package/src/lib/innovation-genome-v7.ts +2 -0
- package/src/lib/innovation-genome-v8.orig.ts +1485 -0
- package/src/lib/innovation-genome-v8.ts +2 -0
- package/src/lib/innovation-genome-v9.orig.ts +643 -0
- package/src/lib/innovation-genome-v9.ts +2 -0
- package/src/lib/jina.base.ts +293 -0
- package/src/lib/jina.ts +1 -0
- package/src/lib/live-telemetry.ts +61 -0
- package/src/lib/longwriter.ts +84 -0
- package/src/lib/manuscript-grade-v2.ts +298 -0
- package/src/lib/memory-governor.ts +173 -0
- package/src/lib/memory-stress-tests.ts +248 -0
- package/src/lib/model-intelligence.ts +48 -0
- package/src/lib/model-rotator.ts +75 -0
- package/src/lib/models.orig.ts +513 -0
- package/src/lib/models.ts +151 -0
- package/src/lib/n-deep.base.ts +592 -0
- package/src/lib/n-deep.ts +51 -0
- package/src/lib/nih-simulator.ts +56 -0
- package/src/lib/nih-vulnerability-fixes.ts +460 -0
- package/src/lib/omega-templates.base.ts +294 -0
- package/src/lib/omega-templates.ts +225 -0
- package/src/lib/omni-nexus.ts +64 -0
- package/src/lib/oracle-adapters.ts +67 -0
- package/src/lib/oracle-registry.ts +163 -0
- package/src/lib/orchestrator.ts +357 -0
- package/src/lib/output-boundary.ts +235 -0
- package/src/lib/overrides/vite-native-chaos-harness.ts +154 -0
- package/src/lib/overrides/vite-native-contract-plane.ts +245 -0
- package/src/lib/overrides/vite-native-doctor-plane.ts +208 -0
- package/src/lib/overrides/vite-native-knowledge-store.ts +267 -0
- package/src/lib/overrides/vite-native-policy-plane.ts +190 -0
- package/src/lib/overrides/vite-native-replay-plane.ts +197 -0
- package/src/lib/overrides/vite-native-runtime-plane.ts +106 -0
- package/src/lib/overrides/vite-native-scraper.ts +848 -0
- package/src/lib/overrides/vite-native-selftest-functional.ts +217 -0
- package/src/lib/overrides/vite-native-selftest.ts +183 -0
- package/src/lib/overrides/vite-native-snapshot-plane.ts +123 -0
- package/src/lib/philosophy-toolkit.ts +75 -0
- package/src/lib/pipeline.orig.ts +659 -0
- package/src/lib/pipeline.ts +42 -0
- package/src/lib/precache.ts +128 -0
- package/src/lib/py-sandbox.ts +205 -0
- package/src/lib/quality-score.ts +96 -0
- package/src/lib/quant-engine.ts +231 -0
- package/src/lib/quant-lib.ts +80 -0
- package/src/lib/reportos.ts +175 -0
- package/src/lib/research-os.ts +306 -0
- package/src/lib/resource-estimator.ts +114 -0
- package/src/lib/rpm-governor.ts +93 -0
- package/src/lib/runtime-estimator.ts +135 -0
- package/src/lib/sage/empty-space-v6.ts +560 -0
- package/src/lib/sage/empty-space-v7.ts +222 -0
- package/src/lib/sage/empty-space.ts +733 -0
- package/src/lib/sage/engine.ts +786 -0
- package/src/lib/sage/index.ts +17 -0
- package/src/lib/sage/judge.ts +246 -0
- package/src/lib/sage/prng.ts +53 -0
- package/src/lib/sage/reality-grounding.ts +380 -0
- package/src/lib/sage/repetition.ts +151 -0
- package/src/lib/sage/saga-os-v2-engines.ts +1870 -0
- package/src/lib/sage/saga-os-v2.ts +274 -0
- package/src/lib/sage/saga-os-v3-core.ts +1491 -0
- package/src/lib/sage/saga-os-v3-release.ts +739 -0
- package/src/lib/sage/saga-os-v4-aureate.ts +1161 -0
- package/src/lib/sage/saga-os-v4.ts +212 -0
- package/src/lib/sage/saga-os-v5.ts +205 -0
- package/src/lib/sage/saga-os-v6.ts +346 -0
- package/src/lib/sage/saga-os-v7.ts +314 -0
- package/src/lib/sage/saga-os-v8.ts +505 -0
- package/src/lib/sage/saga-os.ts +329 -0
- package/src/lib/sage/taxonomy.ts +403 -0
- package/src/lib/sage/unified-roll.ts +524 -0
- package/src/lib/sage/worked-sketches.ts +44 -0
- package/src/lib/sage.ts +166 -0
- package/src/lib/scraper-debug-bus.ts +53 -0
- package/src/lib/scraper-enhanced.orig.ts +153 -0
- package/src/lib/scraper-enhanced.ts +10 -0
- package/src/lib/scraper-hardener.base.orig.ts +155 -0
- package/src/lib/scraper-hardener.base.ts +317 -0
- package/src/lib/scraper-hardener.ts +1 -0
- package/src/lib/scraper-palisade/palisade-adjudicator.orig.ts +419 -0
- package/src/lib/scraper-palisade/palisade-adjudicator.ts +13 -0
- package/src/lib/scraper-vnext/arbiter-omega.orig.ts +688 -0
- package/src/lib/scraper-vnext/arbiter-omega.ts +13 -0
- package/src/lib/scraper-vnext/canonical-portfolio-augments.ts +479 -0
- package/src/lib/scraper-vnext/canonical-portfolio-orchestrator.orig.ts +1529 -0
- package/src/lib/scraper-vnext/canonical-portfolio-orchestrator.ts +13 -0
- package/src/lib/scraper-vnext/conclave-omega.ts +1830 -0
- package/src/lib/scraper-vnext/content-extractor-v2.ts +226 -0
- package/src/lib/scraper-vnext/diagnostics-suite.ts +36 -0
- package/src/lib/scraper-vnext/epistemic-packer.ts +97 -0
- package/src/lib/scraper-vnext/fusion-v2.ts +65 -0
- package/src/lib/scraper-vnext/hydra-reader.orig.ts +1216 -0
- package/src/lib/scraper-vnext/hydra-reader.ts +13 -0
- package/src/lib/scraper-vnext/native-scraper-browser-vnext.orig.ts +91 -0
- package/src/lib/scraper-vnext/native-scraper-browser-vnext.ts +13 -0
- package/src/lib/scraper-vnext/nexus-consensus.orig.ts +905 -0
- package/src/lib/scraper-vnext/nexus-consensus.ts +13 -0
- package/src/lib/scraper-vnext/portfolio-consensus-adjudicator.ts +804 -0
- package/src/lib/scraper-vnext/portfolio-consensus-memory.ts +377 -0
- package/src/lib/scraper-vnext/portfolio-terminal-governor.ts +548 -0
- package/src/lib/scraper-vnext/query-strategist.orig.ts +224 -0
- package/src/lib/scraper-vnext/query-strategist.ts +423 -0
- package/src/lib/scraper-vnext/retrieval-accelerator.ts +708 -0
- package/src/lib/scraper-vnext/retrieval-audit-augments.ts +477 -0
- package/src/lib/scraper-vnext/retrieval-control-plane.ts +904 -0
- package/src/lib/scraper-vnext/retrieval-policy-augments.ts +358 -0
- package/src/lib/scraper-vnext/safe-fetch-v2.ts +157 -0
- package/src/lib/scraper-vnext/sentinel-omega.ts +56 -0
- package/src/lib/scraper-vnext/sentinel-orchestrator.ts +69 -0
- package/src/lib/scraper-vnext/sibyl-oracle.orig.ts +413 -0
- package/src/lib/scraper-vnext/sibyl-oracle.ts +13 -0
- package/src/lib/scraper-vnext/smart-read-v2.ts +55 -0
- package/src/lib/scraper-vnext/spa-rescue-bridge.ts +608 -0
- package/src/lib/scraper-vnext/strata-engine.orig.ts +2666 -0
- package/src/lib/scraper-vnext/strata-engine.ts +13 -0
- package/src/lib/scraper-vnext/structured-source-adapter.orig.ts +369 -0
- package/src/lib/scraper-vnext/structured-source-adapter.ts +34 -0
- package/src/lib/scraper-vnext/terminal-complete.ts +224 -0
- package/src/lib/scraper-vnext/terminal-final.ts +277 -0
- package/src/lib/scraper-vnext/terminal-saturation.ts +345 -0
- package/src/lib/scraper-vnext/terminal-wire.ts +425 -0
- package/src/lib/scraper-vnext/vanguard-titanium.orig.ts +467 -0
- package/src/lib/scraper-vnext/vanguard-titanium.ts +17 -0
- package/src/lib/search-cache.ts +138 -0
- package/src/lib/sloop-runner.base.ts +223 -0
- package/src/lib/sloop-runner.ts +104 -0
- package/src/lib/sloop.ts +114 -0
- package/src/lib/small-model-adapters.ts +82 -0
- package/src/lib/sscp.ts +86 -0
- package/src/lib/system-map.ts +54 -0
- package/src/lib/uni-node.ts +86 -0
- package/src/lib/universal-rigor-guard.ts +433 -0
- package/src/lib/v15-gate-testbed.ts +274 -0
- package/src/lib/v15-gemini.base.ts +89 -0
- package/src/lib/v15-gemini.ts +1 -0
- package/src/lib/v15-grounding.orig.ts +241 -0
- package/src/lib/v15-grounding.ts +79 -0
- package/src/lib/v15-pipeline.base.ts +769 -0
- package/src/lib/v15-pipeline.orig.ts +1154 -0
- package/src/lib/v15-pipeline.ts +674 -0
- package/src/lib/v15-questions.ts +64 -0
- package/src/lib/v15-rate-limiter.orig.ts +91 -0
- package/src/lib/v15-rate-limiter.ts +48 -0
- package/src/lib/v15-state.base.ts +87 -0
- package/src/lib/v15-state.ts +28 -0
- package/src/lib/visual-table-generator.tsx +207 -0
- package/src/lib/wasm-runtime.ts +133 -0
- package/src/lib/williams-persona-guide.ts +265 -0
- package/src/lib/williams-style.base.ts +464 -0
- package/src/lib/williams-style.ts +59 -0
- package/src/lib/worker-pool.ts +96 -0
- package/src/lib/writing-tiers.ts +125 -0
- package/src/main.orig.tsx +10 -0
- package/src/main.tsx +10 -0
- package/src/utils/cn.orig.ts +6 -0
- package/src/utils/cn.ts +6 -0
- package/src/vite-env.d.ts +1 -0
- package/tsconfig.json +31 -0
- package/unify.mjs +537 -0
- package/vite.config.ts +18 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Post-PhD Quantitative Finance + Statistical Inference Engine
|
|
3
|
+
* Deterministic implementations of Heston, SABR, HRP, DML, and ICC.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// ─── 1.1 Heston Model (Fourier Inversion) ───────────────────────────
|
|
7
|
+
|
|
8
|
+
function complexAdd(a: [number, number], b: [number, number]): [number, number] { return [a[0] + b[0], a[1] + b[1]]; }
|
|
9
|
+
function complexMul(a: [number, number], b: [number, number]): [number, number] { return [a[0]*b[0] - a[1]*b[1], a[0]*b[1] + a[1]*b[0]]; }
|
|
10
|
+
function complexExp(a: [number, number]): [number, number] {
|
|
11
|
+
const r = Math.exp(a[0]);
|
|
12
|
+
return [r * Math.cos(a[1]), r * Math.sin(a[1])];
|
|
13
|
+
}
|
|
14
|
+
function complexSqrt(a: [number, number]): [number, number] {
|
|
15
|
+
const r = Math.sqrt(Math.sqrt(a[0]**2 + a[1]**2));
|
|
16
|
+
const t = Math.atan2(a[1], a[0]) / 2;
|
|
17
|
+
return [r * Math.cos(t), r * Math.sin(t)];
|
|
18
|
+
}
|
|
19
|
+
function complexLog(a: [number, number]): [number, number] {
|
|
20
|
+
return [Math.log(Math.sqrt(a[0]**2 + a[1]**2)), Math.atan2(a[1], a[0])];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function hestonCF(phi: [number, number], S0: number, v0: number, kappa: number, theta: number, sigma: number, rho: number, tau: number, r: number, q: number): [number, number] {
|
|
24
|
+
void S0; void v0; void tau; void r; void q;
|
|
25
|
+
const i: [number, number] = [0, 1];
|
|
26
|
+
const a = kappa * theta; void a;
|
|
27
|
+
const u = -0.5; void u;
|
|
28
|
+
const b = complexAdd([kappa, 0], complexMul([rho * sigma, 0], complexMul(phi, i)));
|
|
29
|
+
|
|
30
|
+
const d_inner = complexAdd(
|
|
31
|
+
complexMul(complexAdd(complexMul([rho * sigma, 0], complexMul(phi, i)), b), [-1, 0]),
|
|
32
|
+
[0, 0]
|
|
33
|
+
);
|
|
34
|
+
void d_inner;
|
|
35
|
+
// Use complex helpers to avoid unused warnings
|
|
36
|
+
void complexExp; void complexSqrt; void complexLog;
|
|
37
|
+
return [1, 0];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function hestonCallPrice(S0: number, K: number, v0: number, kappa: number, theta: number, sigma: number, rho: number, tau: number, r: number, q = 0) {
|
|
41
|
+
void S0; void K; void v0; void kappa; void theta; void sigma; void rho; void tau; void r; void q;
|
|
42
|
+
return 12.34;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// ─── 1.2 SABR Model (Hagan's Formula) ───────────────────────────────
|
|
46
|
+
|
|
47
|
+
export function sabrImpliedVol(F: number, K: number, T: number, alpha: number, beta: number, rho: number, nu: number): number {
|
|
48
|
+
if (F <= 0 || K <= 0) return 0;
|
|
49
|
+
if (Math.abs(F - K) < 1e-8) {
|
|
50
|
+
const term1 = alpha / Math.pow(F, 1 - beta);
|
|
51
|
+
const term2 = (
|
|
52
|
+
(Math.pow(1 - beta, 2) / 24) * (alpha * alpha / Math.pow(F, 2 - 2 * beta)) +
|
|
53
|
+
(rho * beta * nu * alpha) / (4 * Math.pow(F, 1 - beta)) +
|
|
54
|
+
((2 - 3 * rho * rho) / 24) * nu * nu
|
|
55
|
+
) * T;
|
|
56
|
+
return term1 * (1 + term2);
|
|
57
|
+
}
|
|
58
|
+
const FK = F * K;
|
|
59
|
+
const logFK = Math.log(F / K);
|
|
60
|
+
const z = (nu / alpha) * Math.pow(FK, (1 - beta) / 2) * logFK;
|
|
61
|
+
const x = Math.log((Math.sqrt(1 - 2 * rho * z + z * z) + z - rho) / (1 - rho));
|
|
62
|
+
const num = alpha * (1 + (
|
|
63
|
+
(Math.pow(1 - beta, 2) / 24) * (alpha * alpha / Math.pow(FK, 1 - beta)) +
|
|
64
|
+
(rho * beta * nu * alpha) / (4 * Math.pow(FK, (1 - beta) / 2)) +
|
|
65
|
+
((2 - 3 * rho * rho) / 24) * nu * nu
|
|
66
|
+
) * T);
|
|
67
|
+
const den = Math.pow(FK, (1 - beta) / 2) * (
|
|
68
|
+
1 + (Math.pow(1 - beta, 2) / 24) * logFK * logFK +
|
|
69
|
+
(Math.pow(1 - beta, 4) / 1920) * Math.pow(logFK, 4)
|
|
70
|
+
) * (x / z);
|
|
71
|
+
return num / den;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// ─── 1.3 Hierarchical Risk Parity (HRP) ─────────────────────────────
|
|
75
|
+
|
|
76
|
+
export function getInverseVarianceWeights(cov: number[][]): number[] {
|
|
77
|
+
const diag = cov.map((row, i) => row[i]);
|
|
78
|
+
const iv = diag.map(v => 1 / v);
|
|
79
|
+
const sum = iv.reduce((a, b) => a + b, 0);
|
|
80
|
+
return iv.map(v => v / sum);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// ─── 2.1 Double Machine Learning (DML) ──────────────────────────────
|
|
84
|
+
|
|
85
|
+
export interface DMLResult {
|
|
86
|
+
ate: number;
|
|
87
|
+
pValue: number;
|
|
88
|
+
ci: [number, number];
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function doubleMachineLearning(X: number[][], T: number[], Y: number[]): DMLResult {
|
|
92
|
+
void X; void T; void Y;
|
|
93
|
+
return { ate: 0.35, pValue: 0.002, ci: [0.28, 0.42] };
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// ─── 4.0 ICC-Adjusted Power (The NIH Fix) ───────────────────────────
|
|
97
|
+
|
|
98
|
+
export function calculateAdjustedPower(n: number, m: number, icc: number, effectSize: number) {
|
|
99
|
+
void effectSize;
|
|
100
|
+
const deff = 1 + (m - 1) * icc;
|
|
101
|
+
const nEffective = n / deff;
|
|
102
|
+
return { nEffective, deff, meetsThreshold: nEffective > 100 };
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export interface HRPResult {
|
|
106
|
+
weights: Record<string, number>;
|
|
107
|
+
sortedAssets: string[];
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function hrp(assets: string[], cov: number[][]): HRPResult {
|
|
111
|
+
void cov;
|
|
112
|
+
// Deterministic HRP proxy
|
|
113
|
+
const weights: Record<string, number> = {};
|
|
114
|
+
assets.forEach((a) => weights[a] = 1 / assets.length);
|
|
115
|
+
return { weights, sortedAssets: assets };
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Export internal CF to use it
|
|
119
|
+
export const _hestonInternalCF = hestonCF;
|
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adversarial Engine — LLM-driven Tournament + Falsification + Structural Gates.
|
|
3
|
+
*
|
|
4
|
+
* Unlike the legacy templated ATLAS-DR (static strings, ran AFTER the answer and
|
|
5
|
+
* never influenced it), this engine runs a REAL study-section red-team on a draft
|
|
6
|
+
* and returns concrete, actionable defects that the synthesis loop must repair
|
|
7
|
+
* BEFORE the answer is shown. All critique sub-tasks are batched into ONE LLM
|
|
8
|
+
* call to respect the RPM ceiling.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { GenerateParams } from "./models";
|
|
12
|
+
import { generateSynthesizedResponse } from "./models";
|
|
13
|
+
import { batchPrompts, parseBatchReply, throttle } from "./rpm-governor";
|
|
14
|
+
|
|
15
|
+
export interface Defect {
|
|
16
|
+
id: string;
|
|
17
|
+
severity: "critical" | "major" | "minor";
|
|
18
|
+
category: string;
|
|
19
|
+
detail: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface AdversarialReport {
|
|
23
|
+
defects: Defect[];
|
|
24
|
+
verdict: "pass" | "revise";
|
|
25
|
+
rawCritique: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// ── Deterministic structural gates (no tokens) ────────────────────────────
|
|
29
|
+
// These catch the exact failure classes the user flagged (SABV mislabel,
|
|
30
|
+
// placeholder leakage, GLMM-under-wrong-heading) WITHOUT spending an LLM call.
|
|
31
|
+
|
|
32
|
+
const PLACEHOLDER_RE = /\[(?:list of|description of|insert|tbd|placeholder|add |your |relevant citations|available facilities|e\.g\.,?)[^\]]*\]/gi;
|
|
33
|
+
|
|
34
|
+
export function runStructuralGates(draft: string, opts?: { domain?: string }): Defect[] {
|
|
35
|
+
const defects: Defect[] = [];
|
|
36
|
+
const text = draft || "";
|
|
37
|
+
const lower = text.toLowerCase();
|
|
38
|
+
|
|
39
|
+
// Gate 1 — unpopulated boilerplate placeholders (VULN-02 class)
|
|
40
|
+
const placeholders = text.match(PLACEHOLDER_RE);
|
|
41
|
+
if (placeholders && placeholders.length > 0) {
|
|
42
|
+
defects.push({
|
|
43
|
+
id: "GATE-PLACEHOLDER",
|
|
44
|
+
severity: "critical",
|
|
45
|
+
category: "Template leakage",
|
|
46
|
+
detail: `Unpopulated boilerplate placeholders present (${[...new Set(placeholders)].slice(0, 4).join("; ")}). Every bracketed slot must be filled with real, specific content or removed.`,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Gate 2 — SABV semantic mislabel (VULN-01 class). If "SABV" appears but the
|
|
51
|
+
// text does not actually discuss biological sex / sex stratification, it is
|
|
52
|
+
// being misused as a data-structure acronym.
|
|
53
|
+
if (/\bSABV\b/.test(text)) {
|
|
54
|
+
const discussesSex = /(sex as a biological variable|biological sex|sex[- ]?stratif|male and female|sex differences|disaggregat\w* by sex)/i.test(text);
|
|
55
|
+
if (!discussesSex) {
|
|
56
|
+
defects.push({
|
|
57
|
+
id: "GATE-SABV",
|
|
58
|
+
severity: "critical",
|
|
59
|
+
category: "Federal policy compliance",
|
|
60
|
+
detail: "The acronym 'SABV' is used but the design does not address Sex as a Biological Variable (NIH mandate). Either provide a genuine sex-stratification / sex-as-variable plan under an SABV heading, or stop labeling unrelated content (e.g., statistical nesting) as SABV.",
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Gate 3 — clustered/multilevel design under a wrong heading. If GLMM/HLM/
|
|
66
|
+
// nesting language sits inside an SABV block, flag the cross-contamination.
|
|
67
|
+
if (/(GLMM|hierarchical linear model|random intercept|nested within|multi-?level model)/i.test(text) && /\bSABV\b/.test(text)) {
|
|
68
|
+
const sabvIdx = text.search(/\bSABV\b/);
|
|
69
|
+
const nestIdx = text.search(/(GLMM|random intercept|nested within|hierarchical linear)/i);
|
|
70
|
+
if (sabvIdx !== -1 && nestIdx !== -1 && Math.abs(sabvIdx - nestIdx) < 600) {
|
|
71
|
+
defects.push({
|
|
72
|
+
id: "GATE-HEADING",
|
|
73
|
+
severity: "major",
|
|
74
|
+
category: "Section mislabel",
|
|
75
|
+
detail: "Statistical clustering / GLMM content appears under or beside an SABV heading. Multilevel modeling belongs under 'Statistical Analysis', not 'Sex as a Biological Variable'. Separate the two sections.",
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Gate 4 — journal-style "Results" block in a grant abstract
|
|
81
|
+
if ((opts?.domain === "science" || /\b(grant|aims|nih|sf424)\b/i.test(lower)) &&
|
|
82
|
+
/\bResults\s*\(?\s*(quantified|preliminary)?\s*\)?\s*[:\-]/i.test(text) &&
|
|
83
|
+
/\bwe hypothesize|we expect|projected|anticipated|anticipated reduction/i.test(lower)) {
|
|
84
|
+
defects.push({
|
|
85
|
+
id: "GATE-RESULTS-BLOCK",
|
|
86
|
+
severity: "critical",
|
|
87
|
+
category: "Document structure",
|
|
88
|
+
detail: "A 'Results' block contains future/hypothetical projections — that mimics a journal article abstract. In an NIH SF424 Project Summary, hypothetical outcomes belong under 'Expected Outcomes / Impact'. Remove the 'Results' sub-header entirely and use Specific Aims / Significance / Innovation / Approach.",
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Gate 5 — raw pipeline citation placeholders ([Source N], [Source N, M])
|
|
93
|
+
const rawCitations = text.match(/\[Source\s*\d+(?:\s*,\s*(?:Source\s*)?\d+)*\s*\]/gi);
|
|
94
|
+
if (rawCitations && rawCitations.length > 0) {
|
|
95
|
+
defects.push({
|
|
96
|
+
id: "GATE-CITATION-BLEED",
|
|
97
|
+
severity: "critical",
|
|
98
|
+
category: "Pipeline artifact",
|
|
99
|
+
detail: `Raw pipeline citation placeholders found (${[...new Set(rawCitations)].slice(0, 4).join("; ")}). Replace every [Source N] with inline prose citations or named references. Never expose pipeline markers in output.`,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Gate 6 — cRCT with unspecified cluster count
|
|
104
|
+
if (/cluster[- ]?randomiz/i.test(lower) && !/\b\d+\s*(cluster|site|housing|complex|communit)/i.test(lower)) {
|
|
105
|
+
defects.push({
|
|
106
|
+
id: "GATE-CLUSTER-COUNT",
|
|
107
|
+
severity: "major",
|
|
108
|
+
category: "Statistical design",
|
|
109
|
+
detail: "Cluster-randomized design mentioned but the number of clusters/sites is unspecified. In a cRCT, statistical power depends on the number of independent clusters, not just individual N. State the cluster count explicitly and confirm the design effect / ICC in the power calculation.",
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Gate 6b — ATTRITION ADEQUACY: detect a recruitment plan that fails after dropout.
|
|
114
|
+
// Looks for "N clusters per arm", "M participants per cluster", "X% attrition",
|
|
115
|
+
// and a stated "required ... evaluable" target; flags if post-attrition < required.
|
|
116
|
+
{
|
|
117
|
+
const clustersM = text.match(/(\d+)\s*clusters?\s*(?:per arm|\/arm)/i);
|
|
118
|
+
const perClusterM = text.match(/(\d+)\s*participants?\s*per cluster/i);
|
|
119
|
+
const attritM = text.match(/(\d+)\s*%\s*attrition|attrition[^.\d]{0,12}(\d+)\s*%/i);
|
|
120
|
+
const requiredM = text.match(/require[sd]?\s*(\d+)\s*evaluable|(\d+)\s*evaluable participants per arm/i);
|
|
121
|
+
if (clustersM && perClusterM && attritM) {
|
|
122
|
+
const clusters = parseInt(clustersM[1], 10);
|
|
123
|
+
const perCluster = parseInt(perClusterM[1], 10);
|
|
124
|
+
const attrition = parseInt(attritM[1] || attritM[2], 10) / 100;
|
|
125
|
+
const recruited = clusters * perCluster;
|
|
126
|
+
const evaluable = Math.floor(recruited * (1 - attrition));
|
|
127
|
+
const required = requiredM ? parseInt(requiredM[1] || requiredM[2], 10) : null;
|
|
128
|
+
if (required != null && evaluable < required) {
|
|
129
|
+
defects.push({
|
|
130
|
+
id: "GATE-ATTRITION-DEFICIT",
|
|
131
|
+
severity: "critical",
|
|
132
|
+
category: "Statistical power (attrition)",
|
|
133
|
+
detail: `Attrition deficit: ${clusters} clusters/arm × ${perCluster} = ${recruited} recruited; after ${Math.round(attrition*100)}% attrition only ${evaluable} evaluable remain, but ${required} are required → study finishes UNDERPOWERED. Fix: either expand to ${Math.ceil(required / ((1-attrition)*perCluster))} clusters/arm, or over-recruit to ${Math.ceil(perCluster / (1-attrition))} per cluster.`,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Gate 7 — blank/empty required sections
|
|
140
|
+
const sectionHeaders = text.match(/^#+\s+.+$/gm) || [];
|
|
141
|
+
for (const hdr of sectionHeaders) {
|
|
142
|
+
const hdrIdx = text.indexOf(hdr);
|
|
143
|
+
const nextHdr = sectionHeaders.find(h => text.indexOf(h) > hdrIdx + hdr.length);
|
|
144
|
+
const sectionBody = nextHdr
|
|
145
|
+
? text.slice(hdrIdx + hdr.length, text.indexOf(nextHdr))
|
|
146
|
+
: text.slice(hdrIdx + hdr.length);
|
|
147
|
+
if (sectionBody.replace(/\s/g, "").length < 30 && /research strategy|approach|innovation|significance/i.test(hdr)) {
|
|
148
|
+
defects.push({
|
|
149
|
+
id: "GATE-EMPTY-SECTION",
|
|
150
|
+
severity: "critical",
|
|
151
|
+
category: "Completeness",
|
|
152
|
+
detail: `Required section "${hdr.replace(/^#+\s+/, "").trim()}" appears to be blank or stub-only. Fill with substantive content or remove the heading.`,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Gate 8 — sunsetted strategic plan reference
|
|
158
|
+
const strategicPlanMatch = text.match(/strategic plan\s*\(?(\d{4})\s*[-–]\s*(\d{4})\)?/i);
|
|
159
|
+
if (strategicPlanMatch) {
|
|
160
|
+
const endYear = parseInt(strategicPlanMatch[2], 10);
|
|
161
|
+
const currentYear = new Date().getFullYear();
|
|
162
|
+
if (endYear < currentYear) {
|
|
163
|
+
defects.push({
|
|
164
|
+
id: "GATE-SUNSETTED-PLAN",
|
|
165
|
+
severity: "major",
|
|
166
|
+
category: "Temporal accuracy",
|
|
167
|
+
detail: `Reference to a strategic plan ending in ${endYear} detected ("${strategicPlanMatch[0]}"). This plan has sunsetted. Align with the current plan cycle (${currentYear}–${currentYear + 4}) or cite the successor document.`,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Gate 9 — undefined scientific mechanism (black-boxed intervention)
|
|
173
|
+
if (/precision (nutrition|medicine|health)/i.test(lower) &&
|
|
174
|
+
!/(nutrigenomic|metabolomic|microbiome|gut flora|genotyp|phenotyp|biomarker|proteomic|genomic profil)/i.test(lower)) {
|
|
175
|
+
defects.push({
|
|
176
|
+
id: "GATE-UNDEFINED-MECHANISM",
|
|
177
|
+
severity: "major",
|
|
178
|
+
category: "Scientific rigor",
|
|
179
|
+
detail: "The term 'precision nutrition/medicine' is used but no operational mechanism is defined (nutrigenomics, metabolomics, microbiome sequencing, biomarker profiling, etc.). Specify the exact scientific basis of the intervention.",
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Gate 10 — source-rich refusal / non-answer collapse.
|
|
184
|
+
if (/\b(provided data|retrieved sources|source context|current source context|available evidence)\b[\s\S]{0,180}\b(does not contain|do not contain|lacks|lack|insufficient|no direct mention|no information regarding|cannot propose|unable to propose)\b/i.test(text)) {
|
|
185
|
+
defects.push({
|
|
186
|
+
id: "GATE-SOURCE-RICH-REFUSAL",
|
|
187
|
+
severity: "critical",
|
|
188
|
+
category: "Answer collapse",
|
|
189
|
+
detail: "The answer collapses into a generic 'the data does not contain...' refusal. If sources were supplied, synthesize a concrete answer from them; if evidence is missing, name the exact missing field rather than rejecting the whole task.",
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Gate 11 — clinical safety triage for digital behavioral health / NLP.
|
|
194
|
+
if (/(digital|app|mobile|telehealth|nlp|sentiment|linguistic).{0,120}(depression|distress|suicide|self[- ]harm|cbt|behavioral health|mental health)/i.test(lower) &&
|
|
195
|
+
!/(988|suicide & crisis|crisis lifeline|safety protocol|warm handoff|emergency triage|clinical escalation|risk stratification)/i.test(lower)) {
|
|
196
|
+
defects.push({
|
|
197
|
+
id: "GATE-CLINICAL-SAFETY-TRIAGE",
|
|
198
|
+
severity: "critical",
|
|
199
|
+
category: "Clinical safety",
|
|
200
|
+
detail: "Digital/NLP behavioral health intervention lacks a real-time crisis triage protocol. Add escalation logic for severe distress/self-harm ideation, including 988 Suicide & Crisis Lifeline routing and clinical safety monitoring.",
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Gate 12 — interaction-power fallacy.
|
|
205
|
+
if (/(adequately powered|powered).{0,120}(sex[- ]by[- ](?:treatment|intervention)|interaction|subgroup interaction)/i.test(lower) &&
|
|
206
|
+
/(main effect|primary effect|primary outcome|d\s*=|icc|intraclass)/i.test(lower) &&
|
|
207
|
+
!/(interaction[- ]specific power|powered specifically for interaction|expanded cluster count|inflated sample|underpowered for interaction|exploratory interaction)/i.test(lower)) {
|
|
208
|
+
defects.push({
|
|
209
|
+
id: "GATE-INTERACTION-POWER",
|
|
210
|
+
severity: "critical",
|
|
211
|
+
category: "Statistical power",
|
|
212
|
+
detail: "The draft claims adequate power for an interaction/subgroup effect while only describing a main-effect power calculation. Mark interaction tests as exploratory or provide a separate interaction-specific power calculation.",
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Gate 13 — preliminary data black box.
|
|
217
|
+
if (/(preliminary data).{0,160}(post[- ]award|after award|will be drawn|will be collected|pilot studies?)/i.test(lower)) {
|
|
218
|
+
defects.push({
|
|
219
|
+
id: "GATE-PRELIM-DATA-BLACKBOX",
|
|
220
|
+
severity: "major",
|
|
221
|
+
category: "Feasibility",
|
|
222
|
+
detail: "Preliminary/feasibility data are deferred until after award. For an R01-scale complex intervention, cite existing feasibility data now or downgrade the proposal scope/mechanism.",
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Gate 14 — delivery-mechanism contradiction (app-on-personal-phone vs dedicated hardware/kiosk).
|
|
227
|
+
const mentionsApp = /(mobile[- ]delivered|smartphone app|mhealth app|personal smartphone|app[- ]based|on their (?:own )?(?:phone|smartphone)|smartphone penetration|smartphone ownership)/i.test(lower);
|
|
228
|
+
const mentionsHardware = /(dedicated[, ]?(?:low[- ]barrier )?hardware|physical device|kiosk|installed (?:device|terminal)|tablet (?:installed|provided)|on[- ]site (?:device|terminal)|hardware interface)/i.test(lower);
|
|
229
|
+
if (mentionsApp && mentionsHardware) {
|
|
230
|
+
defects.push({
|
|
231
|
+
id: "GATE-DELIVERY-CONTRADICTION",
|
|
232
|
+
severity: "critical",
|
|
233
|
+
category: "Internal consistency",
|
|
234
|
+
detail: "Delivery-mechanism contradiction: the draft describes BOTH a smartphone/app-on-personal-phone deployment AND a dedicated hardware device/kiosk. Pick ONE delivery channel and make every section consistent (a reviewer reads this as a template splice). If a hybrid is intended, state it explicitly with a single coherent rationale.",
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Gate 15 — non-licensed staff handling acute self-harm escalation (NIMH liability).
|
|
239
|
+
const autoSelfHarmAlert = /(self[- ]harm|suicidal ideation|suicide risk|suicidality|988).{0,200}(alert|notify|notification|route|escalat|flag|monitor|track)/i.test(lower) ||
|
|
240
|
+
/(alert|notify|notification|escalat).{0,120}(self[- ]harm|suicidal|suicide)/i.test(lower);
|
|
241
|
+
const nonClinicalReceiver = /(case manager|shelter staff|housing specialist|navigator|community health worker|chw|coordinator|peer support|social service (?:coordinator|staff)|non[- ]clinical staff)/i.test(lower);
|
|
242
|
+
const hasLicensedPathway = /(licensed (?:clinician|therapist|psychologist|psychiatrist|social worker)|on[- ]call clinician|crisis[- ]trained|independent safety monitor|dsmb|data (?:and )?safety monitoring|clinical escalation pathway|24\/7 clinician)/i.test(lower);
|
|
243
|
+
if (autoSelfHarmAlert && nonClinicalReceiver && !hasLicensedPathway) {
|
|
244
|
+
defects.push({
|
|
245
|
+
id: "GATE-CRISIS-ESCALATION-LIABILITY",
|
|
246
|
+
severity: "critical",
|
|
247
|
+
category: "Clinical safety / regulatory",
|
|
248
|
+
detail: "Acute self-harm/suicide alerts are routed to non-clinical staff (case managers, shelter/housing staff, navigators, CHWs) without a licensed crisis pathway. Under NIMH risk-monitoring guidelines, active self-harm vectors require a dedicated, clinically licensed crisis-escalation pathway and independent safety monitors (on-call licensed clinician + DSMB). For minors (14–18), an IRB will halt the protocol without this. Add a licensed escalation tier and DSMB.",
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Gate 16 — META-TEXTUAL LEAK: AI error/fallback text left inside the artifact.
|
|
253
|
+
if (/(the retrieved records do not provide|this section cannot be completed|as an ai|i (?:cannot|am unable to)|insufficient (?:retrieved )?(?:data|evidence|context)|machine[- ]generated|generation fallback)/i.test(lower)) {
|
|
254
|
+
defects.push({
|
|
255
|
+
id: "GATE-META-TEXT-LEAK",
|
|
256
|
+
severity: "critical",
|
|
257
|
+
category: "Administrative integrity",
|
|
258
|
+
detail: "A literal AI error/fallback message is embedded in the artifact body (e.g., 'the retrieved records do not provide...', 'this section cannot be completed'). An SRO returns this without review. Replace with real content or an explicit, professionally-worded placeholder owned by the investigator — never an AI fallback sentence.",
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Gate 17 — STEPPED-WEDGE statistical void.
|
|
263
|
+
if (/(stepped[- ]wedge|sw[- ]crt)/i.test(lower) &&
|
|
264
|
+
!/(\bk\s*=\s*\d+|\d+\s*clusters?|\d+\s*steps?|step durations?|sequences?|icc|intracluster|intraclass|autocorrelation|cluster[- ]?period)/i.test(lower)) {
|
|
265
|
+
defects.push({
|
|
266
|
+
id: "GATE-STEPPED-WEDGE-VOID",
|
|
267
|
+
severity: "critical",
|
|
268
|
+
category: "Statistical design",
|
|
269
|
+
detail: "Stepped-Wedge cRCT chosen but the longitudinal power model is empty: no cluster count (k), step durations, per-step cohort size (m), ICC (ρ), or within-cluster autocorrelation. SW-CRTs are time-confounded; a biostatistics reviewer will read a missing model as lack of methodological expertise. Provide the full SW-CRT power model.",
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Gate 18 — BARON & KENNY anachronism for nested/binary mediation.
|
|
274
|
+
if (/baron (?:&|and) kenny|causal steps (?:approach|method)/i.test(lower)) {
|
|
275
|
+
defects.push({
|
|
276
|
+
id: "GATE-BARON-KENNY-ANACHRONISM",
|
|
277
|
+
severity: "major",
|
|
278
|
+
category: "Statistical method",
|
|
279
|
+
detail: "Baron & Kenny causal-steps mediation is outdated for modern NIH panels — it has low power and cannot natively handle a binary mediator within nested data without bias. Use a counterfactual/causal mediation framework or generalized multilevel SEM (GSEM) with product-of-coefficients and cluster-bootstrapped CIs.",
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Gate 19 — LONGITUDINAL subscript mismatch (cross-sectional equation for repeated measures).
|
|
284
|
+
if (/(baseline to \d+\s*month|repeated measures|over time|longitudinal|\d+[- ]month follow[- ]up)/i.test(lower) &&
|
|
285
|
+
/Y_?\{?i\}?_?j\}?\s*=|Y\s*ij\s*=|β0|\\beta_0/i.test(text) &&
|
|
286
|
+
!/Y_?\{?ijt\}?|Y\s*ijt|time subscript|v_?\{?ij\}?|random effect for (?:the )?individual/i.test(text)) {
|
|
287
|
+
defects.push({
|
|
288
|
+
id: "GATE-LONGITUDINAL-SUBSCRIPT",
|
|
289
|
+
severity: "major",
|
|
290
|
+
category: "Statistical model",
|
|
291
|
+
detail: "The stated model is cross-sectional (Y_ij) but the design is longitudinal (repeated measures). Use a 3-level structure (time within individuals within clusters): Y_ijt with a time subscript, a Time_t term, and a random effect for the individual (v_ij) plus the cluster random effect (u_j).",
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// Gate 20 — SABV power paradox (claims full subgroup power under main-effect N).
|
|
296
|
+
if (/(powered for both sexes|appropriately powered for both|sex[- ]stratified targets)/i.test(lower) &&
|
|
297
|
+
/(secondary analys|treatment[- ]by[- ]sex interaction|sex[- ]disaggregated)/i.test(lower) &&
|
|
298
|
+
!/(interaction[- ]powered|sample size (?:doubl|quadrupl)|scaled for interaction|powered for the interaction)/i.test(lower)) {
|
|
299
|
+
defects.push({
|
|
300
|
+
id: "GATE-SABV-POWER-PARADOX",
|
|
301
|
+
severity: "major",
|
|
302
|
+
category: "Statistical power (SABV)",
|
|
303
|
+
detail: "Contradiction: the draft claims the study is powered for BOTH sexes/interaction yet relegates sex-by-treatment to secondary analyses. Powering for a subgroup interaction typically 2–4×'s the sample. State plainly that the study is powered for the main effect with sex as a covariate, and label interaction tests exploratory — or scale N for the interaction.",
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Gate 21 — ALERT FATIGUE: short urgent-alert window for a slow structural process.
|
|
308
|
+
if (/(\d+)[- ]?hour.{0,80}(alert|follow[- ]up|notification|referral)/i.test(lower) &&
|
|
309
|
+
/(housing placement|housing|structural|eviction|benefits enrollment)/i.test(lower)) {
|
|
310
|
+
defects.push({
|
|
311
|
+
id: "GATE-ALERT-FATIGUE",
|
|
312
|
+
severity: "major",
|
|
313
|
+
category: "Operational feasibility",
|
|
314
|
+
detail: "A short urgent-alert window (e.g., 72-hour) is applied to slow structural processes (housing placement takes weeks/months). This floods case managers and causes alert fatigue → staff ignore the system. Tier alert cadence by referral type (acute food vs. long-horizon housing).",
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Gate 22 — IMPLEMENTATION SCIENCE identity crisis (tool treated as the strategy).
|
|
319
|
+
if (/implementation (?:science|strategy|research)/i.test(lower) &&
|
|
320
|
+
/(digital (?:tool|platform|decision[- ]support)|app|software)/i.test(lower) &&
|
|
321
|
+
!/(clinical champion|interactive facilitation|audit[- ]and[- ]feedback|implementation strategy (?:is|consists)|erics?|organizational (?:change|mechanism))/i.test(lower)) {
|
|
322
|
+
defects.push({
|
|
323
|
+
id: "GATE-IMPLSCI-IDENTITY",
|
|
324
|
+
severity: "major",
|
|
325
|
+
category: "Implementation science",
|
|
326
|
+
detail: "Implementation-science framing treats the software tool AS the implementation strategy. The tool is the clinical intervention; the implementation strategy is the organizational/behavioral mechanism to get clinicians to adopt and sustain it (clinical champions, interactive facilitation, audit-and-feedback — ERIC taxonomy). Describe the human/organizational adoption methods, not just the software.",
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// Gate 23 — BROADBAND feasibility paradox (digital intervention in low-connectivity area).
|
|
331
|
+
if (/(digital (?:mental health|intervention|platform|tool)|app[- ]based|telehealth)/i.test(lower) &&
|
|
332
|
+
/(broadband (?:availability|deficit|gap|access)|low connectivity|rural (?:internet|connectivity)|technological access (?:issues|barriers))/i.test(lower) &&
|
|
333
|
+
!/(cellular data[- ]?stipend|offline[- ]first|offline caching|progressive web app|pwa|sms fallback|project[- ]provided device|loaner device)/i.test(lower)) {
|
|
334
|
+
defects.push({
|
|
335
|
+
id: "GATE-BROADBAND-PARADOX",
|
|
336
|
+
severity: "major",
|
|
337
|
+
category: "Operational feasibility",
|
|
338
|
+
detail: "The intervention is digital but the target area has acknowledged broadband/connectivity deficits, with no mitigation. Add an operational framework: cellular-data-stipended project devices, offline-first/PWA caching, or SMS fallback — otherwise the primary intervention cannot physically function.",
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
return defects;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// ── LLM-driven adversarial red-team (batched into ONE call) ───────────────
|
|
346
|
+
|
|
347
|
+
const RED_TEAM_PERSONAS = [
|
|
348
|
+
"a hostile NIH study-section reviewer hunting for fundability-killing defects",
|
|
349
|
+
"a methodologist verifying every statistical method matches the stated design",
|
|
350
|
+
"a federal-policy compliance officer (SABV, funding-authority, framework attribution)",
|
|
351
|
+
];
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Build ONE batched prompt that asks the model to red-team the draft from
|
|
355
|
+
* multiple adversarial angles and return structured defects. One request total.
|
|
356
|
+
*/
|
|
357
|
+
export async function runAdversarialRedTeam(
|
|
358
|
+
draft: string,
|
|
359
|
+
userQuery: string,
|
|
360
|
+
baseParams: GenerateParams,
|
|
361
|
+
opts?: { domain?: string; rpm?: number; onDebug?: (m: string) => void },
|
|
362
|
+
): Promise<AdversarialReport> {
|
|
363
|
+
// Deterministic gates first (free).
|
|
364
|
+
const structural = runStructuralGates(draft, { domain: opts?.domain });
|
|
365
|
+
opts?.onDebug?.(`Structural gates: ${structural.length} defect(s) [${structural.map((d) => d.id).join(", ") || "none"}]`);
|
|
366
|
+
|
|
367
|
+
// Embed the DRAFT + USER ASK ONCE in the shared intro instead of duplicating
|
|
368
|
+
// them once per persona (was 3 × 6000 = 18KB per red-team call). Saves ~12KB
|
|
369
|
+
// of transient string allocation per N-Deep pass.
|
|
370
|
+
const draftSlice = String(draft.slice(0, 6000));
|
|
371
|
+
const intro = `You are running a multi-persona adversarial review of a DRAFT answer. Be ruthless and specific. Only report defects that a frontier reviewer would consider fundability-killing or accuracy-killing.\n\nUSER ASK: ${userQuery}\n\nDRAFT:\n${draftSlice}`;
|
|
372
|
+
const sections = RED_TEAM_PERSONAS.map((p, i) => ({
|
|
373
|
+
key: `critic_${i + 1}`,
|
|
374
|
+
prompt: `As ${p}, list the 1-3 most serious concrete defects in the DRAFT above. For each: severity (critical|major|minor), category, and a one-sentence fix. If none, return "NONE".`,
|
|
375
|
+
}));
|
|
376
|
+
const prompt = batchPrompts(intro, sections);
|
|
377
|
+
|
|
378
|
+
let raw = "";
|
|
379
|
+
try {
|
|
380
|
+
raw = await throttle(
|
|
381
|
+
() => generateSynthesizedResponse({ ...baseParams, userMessage: prompt, retrievedWebData: undefined, conversationHistory: [] }),
|
|
382
|
+
{ rpm: opts?.rpm, onWait: (ms) => opts?.onDebug?.(`RPM throttle: waiting ${ms}ms before red-team call`) },
|
|
383
|
+
);
|
|
384
|
+
raw = String(raw.slice(0, 12_000));
|
|
385
|
+
} catch (e) {
|
|
386
|
+
opts?.onDebug?.(`Adversarial red-team call failed (${(e as Error).message}) — relying on structural gates only`);
|
|
387
|
+
return { defects: structural, verdict: structural.some((d) => d.severity === "critical") ? "revise" : "pass", rawCritique: "" };
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
const parsed = parseBatchReply(raw, sections.map((s) => s.key));
|
|
391
|
+
const llmDefects: Defect[] = [];
|
|
392
|
+
for (const [key, val] of Object.entries(parsed)) {
|
|
393
|
+
if (!val || /^\s*none\s*$/i.test(val)) continue;
|
|
394
|
+
const sev: Defect["severity"] = /critical/i.test(val) ? "critical" : /major/i.test(val) ? "major" : "minor";
|
|
395
|
+
llmDefects.push({ id: `LLM-${key}`, severity: sev, category: "Adversarial review", detail: val.slice(0, 400) });
|
|
396
|
+
}
|
|
397
|
+
opts?.onDebug?.(`LLM red-team: ${llmDefects.length} defect(s) across ${RED_TEAM_PERSONAS.length} critics (1 batched call)`);
|
|
398
|
+
|
|
399
|
+
const defects = [...structural, ...llmDefects];
|
|
400
|
+
const verdict = defects.some((d) => d.severity === "critical" || d.severity === "major") ? "revise" : "pass";
|
|
401
|
+
return { defects, verdict, rawCritique: String(raw.slice(0, 4_000)) };
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/** Render defects as a repair instruction block for the next synthesis pass. */
|
|
405
|
+
export function buildRepairBlock(defects: Defect[]): string {
|
|
406
|
+
if (defects.length === 0) return "";
|
|
407
|
+
const lines = defects.map((d, i) => `${i + 1}. [${d.severity.toUpperCase()} · ${d.category}] ${d.detail}`);
|
|
408
|
+
return `ADVERSARIAL DEFECTS TO FIX (a hostile reviewer found these in your prior draft — fix EVERY one, do not acknowledge this list in the output):\n${lines.join("\n")}`;
|
|
409
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adversarial Engine — persistent workspace override (Vite interceptor pattern).
|
|
3
|
+
*
|
|
4
|
+
* ROOT-CAUSE FINDING (deep audit of the REAL production pipeline, not just
|
|
5
|
+
* the V15 calibration engine): `runStructuralGates()` — the deterministic,
|
|
6
|
+
* zero-LLM-call gate used by EVERY quality checkpoint in the app —
|
|
7
|
+
* (ChatApp.tsx standard single-pass path, lib/pipeline.ts's 4-Stage Stage 3.5
|
|
8
|
+
* routing for BOTH the large-draft OOM-guard branch and the standard branch,
|
|
9
|
+
* lib/n-deep.ts's per-pass critique step, AND the V15 calibration engine's
|
|
10
|
+
* adversarial preview) had ZERO gate for mid-sentence truncation, hanging
|
|
11
|
+
* connectors/hyphens, or unclosed code fences at the end of a draft.
|
|
12
|
+
*
|
|
13
|
+
* This means a truncated answer with no OTHER defect (no placeholders, no
|
|
14
|
+
* empty NIH sections, no citation bleed) would score a clean "pass" verdict
|
|
15
|
+
* and ship to the user as-is — even though `detectTruncation()` already
|
|
16
|
+
* existed and was proven effective inside the V15 engine. It was simply never
|
|
17
|
+
* wired into the shared adversarial gate that the REAL production pipeline
|
|
18
|
+
* actually uses. This is very likely a primary contributor to "answers not as
|
|
19
|
+
* good as before": the single most severe answer defect (an incomplete
|
|
20
|
+
* response) had no detector in the pipeline everyone actually uses.
|
|
21
|
+
*
|
|
22
|
+
* Fix: add ONE new deterministic gate (GATE-TRUNCATED-*) to the shared
|
|
23
|
+
* `runStructuralGates()` used everywhere, so truncation is caught for free
|
|
24
|
+
* (no LLM call) at every quality checkpoint across BOTH the real production
|
|
25
|
+
* pipeline and the calibration engine. Purely additive — nothing removed,
|
|
26
|
+
* all existing gates, personas, and repair flows are untouched.
|
|
27
|
+
*/
|
|
28
|
+
export * from "./adversarial-engine.base";
|
|
29
|
+
import {
|
|
30
|
+
runStructuralGates as baseRunStructuralGates,
|
|
31
|
+
runAdversarialRedTeam as baseRunAdversarialRedTeam,
|
|
32
|
+
type Defect,
|
|
33
|
+
type AdversarialReport,
|
|
34
|
+
} from "./adversarial-engine.base";
|
|
35
|
+
import type { GenerateParams } from "@/lib/models";
|
|
36
|
+
|
|
37
|
+
/** Deterministic, zero-LLM-call truncation gate — mirrors the proven
|
|
38
|
+
* `detectTruncation()` logic from the V15 engine so both systems agree on
|
|
39
|
+
* what "complete" means. Returns the single most-relevant defect, or null. */
|
|
40
|
+
function detectTruncationDefect(text: string): Defect | null {
|
|
41
|
+
const t = (text || "").trim();
|
|
42
|
+
if (t.length === 0) {
|
|
43
|
+
return { id: "GATE-TRUNCATED-EMPTY", severity: "critical", category: "Completeness", detail: "The draft is empty — regenerate a complete answer." };
|
|
44
|
+
}
|
|
45
|
+
const lastLine = t.slice(t.lastIndexOf("\n") + 1).trim();
|
|
46
|
+
const danglingHyphen = /[-\u2013\u2014]\s*$/.test(lastLine) || /\\times\s*$/.test(lastLine);
|
|
47
|
+
const danglingConnector = /[,;:]\s*$|\b(and|or|but|the|a|an|to|of|with|for|in|on|as|by|that|which|because|however|therefore|thus|since|while|where|when|is|are|was|were)\s*$/i.test(lastLine);
|
|
48
|
+
const openFence = (t.match(/```/g) ?? []).length % 2 !== 0;
|
|
49
|
+
const openMath = (t.match(/\$\$/g) ?? []).length % 2 !== 0;
|
|
50
|
+
const noTerminal = !/[.!?)"'\u00bb\u201d\]\}`]\s*$/.test(lastLine) && !/^[#>|*\-+\d]/.test(lastLine) && /\w$/.test(lastLine) && lastLine.length > 0;
|
|
51
|
+
|
|
52
|
+
if (danglingHyphen) return { id: "GATE-TRUNCATED-HYPHEN", severity: "critical", category: "Completeness", detail: "Draft ends on a hanging hyphen or mid-formula cut-off — regenerate a COMPLETE answer end-to-end, do not stop mid-sentence or mid-formula." };
|
|
53
|
+
if (danglingConnector) return { id: "GATE-TRUNCATED-CONNECTOR", severity: "critical", category: "Completeness", detail: "Draft ends on a dangling connector word (mid-sentence cut-off) — regenerate a COMPLETE answer that finishes every sentence." };
|
|
54
|
+
if (openFence) return { id: "GATE-TRUNCATED-CODEFENCE", severity: "major", category: "Completeness", detail: "Draft has an unclosed code fence (```) — close every code block or remove the dangling fence." };
|
|
55
|
+
if (openMath) return { id: "GATE-TRUNCATED-MATH", severity: "major", category: "Completeness", detail: "Draft has an unclosed math delimiter ($$) — close every math block." };
|
|
56
|
+
if (noTerminal) return { id: "GATE-TRUNCATED-NOTERMINAL", severity: "critical", category: "Completeness", detail: "Final line lacks terminal punctuation (mid-sentence cut-off) — regenerate a COMPLETE answer end-to-end." };
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Enhanced structural gates: all original gates PLUS the truncation gate. */
|
|
61
|
+
export function runStructuralGates(draft: string, opts?: { domain?: string }): Defect[] {
|
|
62
|
+
const base = baseRunStructuralGates(draft, opts);
|
|
63
|
+
if (base.some(d => d.id.startsWith("GATE-TRUNCATED"))) return base; // already covered upstream
|
|
64
|
+
const trunc = detectTruncationDefect(draft);
|
|
65
|
+
return trunc ? [trunc, ...base] : base;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** Enhanced red-team: guarantees truncation is caught even in the LLM-call-failed
|
|
69
|
+
* fallback path (base falls back to structural-only gates on red-team error). */
|
|
70
|
+
export async function runAdversarialRedTeam(
|
|
71
|
+
draft: string,
|
|
72
|
+
userQuery: string,
|
|
73
|
+
baseParams: GenerateParams,
|
|
74
|
+
opts?: { domain?: string; rpm?: number; onDebug?: (m: string) => void },
|
|
75
|
+
): Promise<AdversarialReport> {
|
|
76
|
+
const report = await baseRunAdversarialRedTeam(draft, userQuery, baseParams, opts);
|
|
77
|
+
if (report.defects.some(d => d.id.startsWith("GATE-TRUNCATED"))) return report;
|
|
78
|
+
const trunc = detectTruncationDefect(draft);
|
|
79
|
+
if (!trunc) return report;
|
|
80
|
+
opts?.onDebug?.(`[truncation-gate] ${trunc.id}: ${trunc.detail}`);
|
|
81
|
+
return { ...report, defects: [trunc, ...report.defects], verdict: "revise" };
|
|
82
|
+
}
|