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,231 @@
|
|
|
1
|
+
// MODULE A — VC / Medallion-grade Quantitative Engine.
|
|
2
|
+
// Deterministic, pure-TypeScript, composable, side-effect free.
|
|
3
|
+
|
|
4
|
+
// ─── Unit economics ─────────────────────────────────────────────────
|
|
5
|
+
export const mrr = (customers: number, arpu: number) => customers * arpu;
|
|
6
|
+
export const arr = (m: number) => m * 12;
|
|
7
|
+
export const cac = (sm: number, n: number) => n > 0 ? sm / n : NaN;
|
|
8
|
+
export const ltv = (arpuM: number, gm: number, churnM: number) => churnM > 0 ? (arpuM * gm) / churnM : NaN;
|
|
9
|
+
export const ltvCacRatio = (l: number, c: number) => c > 0 ? l / c : NaN;
|
|
10
|
+
export const cacPaybackMonths = (c: number, arpuM: number, gm: number) => c / (arpuM * gm);
|
|
11
|
+
export const nrr = (start: number, exp: number, contr: number, churn: number) => start > 0 ? (start + exp - contr - churn) / start : NaN;
|
|
12
|
+
export const grr = (start: number, contr: number, churn: number) => start > 0 ? (start - contr - churn) / start : NaN;
|
|
13
|
+
export const magicNumber = (netNewARR: number, priorQSM: number) => priorQSM > 0 ? netNewARR / priorQSM : NaN;
|
|
14
|
+
export const burnMultiple = (netBurn: number, netNewARR: number) => netNewARR > 0 ? netBurn / netNewARR : NaN;
|
|
15
|
+
export const ruleOf40 = (growthPct: number, marginPct: number) => growthPct + marginPct;
|
|
16
|
+
export const monthsRunway = (cash: number, monthlyBurn: number) => monthlyBurn > 0 ? cash / monthlyBurn : Infinity;
|
|
17
|
+
|
|
18
|
+
// ─── DCF / IRR / WACC / CAPM ────────────────────────────────────────
|
|
19
|
+
export interface DcfResult {
|
|
20
|
+
pvCashFlows: number; pvTerminal: number; enterpriseValue: number;
|
|
21
|
+
terminalPctOfEV: number; impliedExitMultiple: number;
|
|
22
|
+
}
|
|
23
|
+
export function dcfNpv(cashFlows: number[], discountRate: number, terminalGrowth = 0.02): DcfResult {
|
|
24
|
+
const n = cashFlows.length;
|
|
25
|
+
const tv = cashFlows[n - 1] * (1 + terminalGrowth) / (discountRate - terminalGrowth);
|
|
26
|
+
const pvCfs = cashFlows.reduce((acc, cf, t) => acc + cf / Math.pow(1 + discountRate, t + 1), 0);
|
|
27
|
+
const pvTerm = tv / Math.pow(1 + discountRate, n);
|
|
28
|
+
const ev = pvCfs + pvTerm;
|
|
29
|
+
return { pvCashFlows: pvCfs, pvTerminal: pvTerm, enterpriseValue: ev,
|
|
30
|
+
terminalPctOfEV: pvTerm / ev, impliedExitMultiple: tv / cashFlows[n - 1] };
|
|
31
|
+
}
|
|
32
|
+
export function irr(cashFlows: number[], guess = 0.1): number {
|
|
33
|
+
let rate = guess;
|
|
34
|
+
for (let i = 0; i < 1000; i++) {
|
|
35
|
+
const npv = cashFlows.reduce((a, cf, t) => a + cf / Math.pow(1 + rate, t), 0);
|
|
36
|
+
const dnpv = cashFlows.reduce((a, cf, t) => a + (-t * cf) / Math.pow(1 + rate, t + 1), 0);
|
|
37
|
+
if (Math.abs(dnpv) < 1e-12) break;
|
|
38
|
+
rate -= npv / dnpv;
|
|
39
|
+
}
|
|
40
|
+
return rate;
|
|
41
|
+
}
|
|
42
|
+
export const moic = (exit: number, invested: number) => invested > 0 ? exit / invested : NaN;
|
|
43
|
+
export const wacc = (eq: number, costEq: number, dbt: number, costDbt: number, tax: number) =>
|
|
44
|
+
eq * costEq + dbt * costDbt * (1 - tax);
|
|
45
|
+
export const capm = (rf: number, beta: number, mp: number, size = 0, country = 0) =>
|
|
46
|
+
rf + beta * mp + size + country;
|
|
47
|
+
|
|
48
|
+
// ─── VC method ──────────────────────────────────────────────────────
|
|
49
|
+
export function vcMethodPreMoney(exitValue: number, targetIRR: number, years: number, dilution = 0.2): number {
|
|
50
|
+
const pv = exitValue / Math.pow(1 + targetIRR, years);
|
|
51
|
+
return pv * (1 - dilution);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// ─── Portfolio / fund / signal stats ───────────────────────────────
|
|
55
|
+
export interface WaterfallResult {
|
|
56
|
+
grossMOIC: number; netMOIC: number; grossIRRApprox: number;
|
|
57
|
+
totalMgmtFees: number; gpCarry: number; lpDistributions: number; dpi: number;
|
|
58
|
+
}
|
|
59
|
+
export function fundWaterfall(committed: number, invested: number, totalDistributed: number,
|
|
60
|
+
mgmtFeePct = 0.02, carryPct = 0.2, preferredReturn = 0.08, fundLife = 10): WaterfallResult {
|
|
61
|
+
const totalMgmtFees = committed * mgmtFeePct * fundLife;
|
|
62
|
+
const netInvested = invested - totalMgmtFees;
|
|
63
|
+
const hurdle = netInvested * (Math.pow(1 + preferredReturn, fundLife) - 1);
|
|
64
|
+
const profit = Math.max(0, totalDistributed - netInvested);
|
|
65
|
+
const gpCarry = Math.max(0, (profit - hurdle) * carryPct);
|
|
66
|
+
const lpNet = totalDistributed - gpCarry;
|
|
67
|
+
return {
|
|
68
|
+
grossMOIC: totalDistributed / invested,
|
|
69
|
+
netMOIC: lpNet / committed,
|
|
70
|
+
grossIRRApprox: Math.pow(totalDistributed / invested, 1 / fundLife) - 1,
|
|
71
|
+
totalMgmtFees, gpCarry, lpDistributions: lpNet, dpi: lpNet / committed,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
export function powerLawPortfolio(n: number, winnerPct = 0.1, winnerMultiple = 20, loserReturn = -1) {
|
|
75
|
+
const nW = Math.max(1, Math.round(n * winnerPct));
|
|
76
|
+
const nL = n - nW;
|
|
77
|
+
const total = nW * winnerMultiple + nL * loserReturn;
|
|
78
|
+
return { nCompanies: n, nWinners: nW, nLosers: nL,
|
|
79
|
+
totalPortfolioMOIC: total / n,
|
|
80
|
+
winnerContributionPct: total !== 0 ? (nW * winnerMultiple) / total : 0,
|
|
81
|
+
lossRatio: nL / n };
|
|
82
|
+
}
|
|
83
|
+
export function hhi(shares: number[]) {
|
|
84
|
+
const v = shares.reduce((a, s) => a + s * s, 0) * 10000;
|
|
85
|
+
return { hhi: v, classification: v > 2500 ? "Highly Concentrated" : v > 1500 ? "Moderately Concentrated" : "Competitive" };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// ─── Statistical / signal processing ───────────────────────────────
|
|
89
|
+
const mean = (xs: number[]) => xs.reduce((a, b) => a + b, 0) / xs.length;
|
|
90
|
+
const std = (xs: number[], ddof = 1) => {
|
|
91
|
+
const m = mean(xs);
|
|
92
|
+
const v = xs.reduce((a, x) => a + (x - m) ** 2, 0) / (xs.length - ddof);
|
|
93
|
+
return Math.sqrt(v);
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export const zScore = (value: number, m: number, s: number) => (value - m) / s;
|
|
97
|
+
export const sharpeRatio = (returns: number[], rf = 0) => {
|
|
98
|
+
const ex = returns.map(r => r - rf);
|
|
99
|
+
return mean(ex) / std(ex);
|
|
100
|
+
};
|
|
101
|
+
export function sortinoRatio(returns: number[], rf = 0, target = 0) {
|
|
102
|
+
const ex = returns.map(r => r - rf);
|
|
103
|
+
const dn = returns.map(r => Math.min(0, r - target) ** 2);
|
|
104
|
+
const dd = Math.sqrt(mean(dn));
|
|
105
|
+
return dd > 0 ? mean(ex) / dd : Infinity;
|
|
106
|
+
}
|
|
107
|
+
export function maxDrawdown(equity: number[]): number {
|
|
108
|
+
let peak = equity[0], maxDD = 0;
|
|
109
|
+
for (const v of equity) { peak = Math.max(peak, v); maxDD = Math.max(maxDD, (peak - v) / peak); }
|
|
110
|
+
return maxDD;
|
|
111
|
+
}
|
|
112
|
+
export function kellyCriterion(winProb: number, winLossRatio: number): number {
|
|
113
|
+
const q = 1 - winProb;
|
|
114
|
+
return (winProb * winLossRatio - q) / winLossRatio;
|
|
115
|
+
}
|
|
116
|
+
export const informationRatio = (active: number[]) => mean(active) / std(active);
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* ICC-adjusted Sample Size (Design Effect)
|
|
120
|
+
* neffective = n / (1 + (m - 1) * rho)
|
|
121
|
+
* m: cluster size, rho: intraclass correlation
|
|
122
|
+
*/
|
|
123
|
+
export const calcEffectiveN = (n: number, m: number, rho: number) => {
|
|
124
|
+
const deff = 1 + (m - 1) * rho;
|
|
125
|
+
return n / deff;
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Required nominal N to reach target power given cluster design.
|
|
130
|
+
* nNominal = nTarget * (1 + (m - 1) * rho)
|
|
131
|
+
*/
|
|
132
|
+
export const calcRequiredNominalN = (nTarget: number, m: number, rho: number) => {
|
|
133
|
+
return nTarget * (1 + (m - 1) * rho);
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
// ─── Inverse normal CDF (Acklam's algorithm) — needed for power calcs ───
|
|
137
|
+
function invNorm(p: number): number {
|
|
138
|
+
if (p <= 0) return -Infinity;
|
|
139
|
+
if (p >= 1) return Infinity;
|
|
140
|
+
const a = [-3.969683028665376e+01, 2.209460984245205e+02, -2.759285104469687e+02, 1.383577518672690e+02, -3.066479806614716e+01, 2.506628277459239e+00];
|
|
141
|
+
const b = [-5.447609879822406e+01, 1.615858368580409e+02, -1.556989798598866e+02, 6.680131188771972e+01, -1.328068155288572e+01];
|
|
142
|
+
const c = [-7.784894002430293e-03, -3.223964580411365e-01, -2.400758277161838e+00, -2.549732539343734e+00, 4.374664141464968e+00, 2.938163982698783e+00];
|
|
143
|
+
const d = [7.784695709041462e-03, 3.224671290700398e-01, 2.445134137142996e+00, 3.754408661907416e+00];
|
|
144
|
+
const plow = 0.02425, phigh = 1 - plow;
|
|
145
|
+
let q, r;
|
|
146
|
+
if (p < plow) { q = Math.sqrt(-2 * Math.log(p)); return (((((c[0]*q+c[1])*q+c[2])*q+c[3])*q+c[4])*q+c[5]) / ((((d[0]*q+d[1])*q+d[2])*q+d[3])*q+1); }
|
|
147
|
+
if (p <= phigh) { q = p - 0.5; r = q*q; return (((((a[0]*r+a[1])*r+a[2])*r+a[3])*r+a[4])*r+a[5])*q / (((((b[0]*r+b[1])*r+b[2])*r+b[3])*r+b[4])*r+1); }
|
|
148
|
+
q = Math.sqrt(-2 * Math.log(1 - p)); return -(((((c[0]*q+c[1])*q+c[2])*q+c[3])*q+c[4])*q+c[5]) / ((((d[0]*q+d[1])*q+d[2])*q+d[3])*q+1);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* cRCT power calculation: required clusters PER ARM to detect a mean
|
|
153
|
+
* difference with given power, accounting for ICC design effect AND attrition.
|
|
154
|
+
*
|
|
155
|
+
* Two-arm parallel cluster-randomized trial, continuous outcome.
|
|
156
|
+
* delta: target mean difference
|
|
157
|
+
* sd: pooled standard deviation
|
|
158
|
+
* alpha: two-sided significance (default 0.05)
|
|
159
|
+
* power: target power (default 0.80)
|
|
160
|
+
* icc: intraclass correlation
|
|
161
|
+
* clusterSize: AVERAGE evaluable participants per cluster at endpoint
|
|
162
|
+
* attrition: fraction lost to follow-up (default 0)
|
|
163
|
+
*/
|
|
164
|
+
export function calcClusterRCTPower(opts: {
|
|
165
|
+
delta: number; sd: number; alpha?: number; power?: number;
|
|
166
|
+
icc: number; clusterSize: number; attrition?: number;
|
|
167
|
+
}): {
|
|
168
|
+
individualsPerArm: number;
|
|
169
|
+
designEffect: number;
|
|
170
|
+
evaluablePerArm: number;
|
|
171
|
+
clustersPerArmIdeal: number;
|
|
172
|
+
recruitPerCluster: number;
|
|
173
|
+
clustersPerArmWithAttrition: number;
|
|
174
|
+
totalClustersWithAttrition: number;
|
|
175
|
+
totalRecruit: number;
|
|
176
|
+
} {
|
|
177
|
+
const alpha = opts.alpha ?? 0.05;
|
|
178
|
+
const power = opts.power ?? 0.80;
|
|
179
|
+
const attrition = Math.max(0, Math.min(0.95, opts.attrition ?? 0));
|
|
180
|
+
const m = Math.max(1, opts.clusterSize);
|
|
181
|
+
const zAlpha = invNorm(1 - alpha / 2);
|
|
182
|
+
const zBeta = invNorm(power);
|
|
183
|
+
const effectSize = Math.abs(opts.delta) / opts.sd;
|
|
184
|
+
// Individual-level N per arm for a two-sample test
|
|
185
|
+
const nIndiv = Math.ceil((2 * Math.pow(zAlpha + zBeta, 2)) / Math.pow(effectSize, 2));
|
|
186
|
+
// Design effect inflation
|
|
187
|
+
const deff = 1 + (m - 1) * opts.icc;
|
|
188
|
+
const evaluablePerArm = Math.ceil(nIndiv * deff);
|
|
189
|
+
// Ideal clusters per arm (no attrition)
|
|
190
|
+
const clustersIdeal = Math.ceil(evaluablePerArm / m);
|
|
191
|
+
// Attrition adjustment: recruit more per cluster so evaluable = target
|
|
192
|
+
const recruitPerCluster = attrition > 0 ? Math.ceil(m / (1 - attrition)) : m;
|
|
193
|
+
const clustersWithAttrition = Math.ceil(evaluablePerArm / m);
|
|
194
|
+
const totalRecruit = clustersWithAttrition * recruitPerCluster * 2;
|
|
195
|
+
return {
|
|
196
|
+
individualsPerArm: nIndiv,
|
|
197
|
+
designEffect: Math.round(deff * 1000) / 1000,
|
|
198
|
+
evaluablePerArm,
|
|
199
|
+
clustersPerArmIdeal: clustersIdeal,
|
|
200
|
+
recruitPerCluster,
|
|
201
|
+
clustersPerArmWithAttrition: clustersWithAttrition,
|
|
202
|
+
totalClustersWithAttrition: clustersWithAttrition * 2,
|
|
203
|
+
totalRecruit,
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Attrition adequacy check: given a recruitment plan, does it survive attrition?
|
|
209
|
+
* Returns the post-attrition evaluable count and whether it clears the threshold.
|
|
210
|
+
*/
|
|
211
|
+
export function calcAttritionAdequacy(opts: {
|
|
212
|
+
clustersPerArm: number; recruitPerCluster: number; attrition: number; requiredEvaluablePerArm: number;
|
|
213
|
+
}): { recruitedPerArm: number; evaluablePerArm: number; adequate: boolean; deficit: number } {
|
|
214
|
+
const recruited = opts.clustersPerArm * opts.recruitPerCluster;
|
|
215
|
+
const evaluable = Math.floor(recruited * (1 - opts.attrition));
|
|
216
|
+
const deficit = opts.requiredEvaluablePerArm - evaluable;
|
|
217
|
+
return { recruitedPerArm: recruited, evaluablePerArm: evaluable, adequate: deficit <= 0, deficit: Math.max(0, deficit) };
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// ─── Display helper ─────────────────────────────────────────────────
|
|
221
|
+
export interface QuantResult { label: string; value: number; unit?: string; formula: string; }
|
|
222
|
+
|
|
223
|
+
export function fmtPct(x: number): string { return `${(x * 100).toFixed(1)}%`; }
|
|
224
|
+
export function fmtMoney(x: number): string {
|
|
225
|
+
if (!isFinite(x)) return "—";
|
|
226
|
+
const abs = Math.abs(x);
|
|
227
|
+
if (abs >= 1e9) return `$${(x / 1e9).toFixed(2)}B`;
|
|
228
|
+
if (abs >= 1e6) return `$${(x / 1e6).toFixed(2)}M`;
|
|
229
|
+
if (abs >= 1e3) return `$${(x / 1e3).toFixed(1)}K`;
|
|
230
|
+
return `$${x.toFixed(0)}`;
|
|
231
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// MODULE A.2 — VC / Medallion-grade Quantitative Engine
|
|
2
|
+
// All formulas below are deterministic functions, taking inputs and returning outputs.
|
|
3
|
+
// These are wired into the ReportOS v3 system for high-rigor financial reporting.
|
|
4
|
+
|
|
5
|
+
import { QuantResult } from "./reportos";
|
|
6
|
+
|
|
7
|
+
// ── 8.1.1 Unit Economics ──────────────────────────────────────────────
|
|
8
|
+
|
|
9
|
+
export function calcCAC(smSpend: number, newCustomers: number): QuantResult {
|
|
10
|
+
const val = newCustomers > 0 ? smSpend / newCustomers : 0;
|
|
11
|
+
return { label: "CAC", value: val, unit: "$", formula: "S&M spend / new customers", inputs: { smSpend, newCustomers } };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function calcLTV(arpuMonthly: number, grossMarginPct: number, churnMonthly: number): QuantResult {
|
|
15
|
+
const val = churnMonthly > 0 ? (arpuMonthly * grossMarginPct) / churnMonthly : 0;
|
|
16
|
+
return { label: "LTV", value: val, unit: "$", formula: "(ARPU × GM%) / churn", inputs: { arpuMonthly, grossMarginPct, churnMonthly } };
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function calcNRR(beginningRev: number, expansionRev: number, contractionRev: number, churnRev: number): QuantResult {
|
|
20
|
+
const val = beginningRev > 0 ? (beginningRev + expansionRev - contractionRev - churnRev) / beginningRev : 0;
|
|
21
|
+
return { label: "NRR", value: val, unit: "%", formula: "(start + exp - contr - churn) / start", inputs: { beginningRev, expansionRev, contractionRev, churnRev } };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function calcBurnMultiple(netBurn: number, netNewArr: number): QuantResult {
|
|
25
|
+
const val = netNewArr > 0 ? netBurn / netNewArr : 0;
|
|
26
|
+
return { label: "Burn Multiple", value: val, unit: "x", formula: "net burn / net new ARR", inputs: { netBurn, netNewArr } };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function calcMagicNumber(netNewArr: number, priorSMSpend: number): QuantResult {
|
|
30
|
+
const val = priorSMSpend > 0 ? netNewArr / priorSMSpend : 0;
|
|
31
|
+
return { label: "Magic Number", value: val, unit: "x", formula: "net new ARR / prior S&M", inputs: { netNewArr, priorSMSpend } };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function calcRuleOf40(growthPct: number, marginPct: number): QuantResult {
|
|
35
|
+
const val = growthPct + marginPct;
|
|
36
|
+
return { label: "Rule of 40", value: val, unit: "%", formula: "growth% + profit margin%", inputs: { growthPct, marginPct } };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function calcRunway(cash: number, monthlyBurn: number): QuantResult {
|
|
40
|
+
const val = monthlyBurn > 0 ? cash / monthlyBurn : 0;
|
|
41
|
+
return { label: "Runway", value: val, unit: "mo", formula: "cash / monthly burn", inputs: { cash, monthlyBurn } };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// ── 8.2.1 Advanced Valuation ─────────────────────────────────────────
|
|
45
|
+
|
|
46
|
+
export function calcWACC(equityPct: number, costEquity: number, debtPct: number, costDebt: number, taxRate: number): QuantResult {
|
|
47
|
+
const val = (equityPct * costEquity) + (debtPct * costDebt * (1 - taxRate));
|
|
48
|
+
return { label: "WACC", value: val, unit: "%", formula: "(E/V * Re) + (D/V * Rd * (1-T))", inputs: { equityPct, costEquity, debtPct, costDebt, taxRate } };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function calcCAPM(riskFree: number, beta: number, marketPremium: number): QuantResult {
|
|
52
|
+
const val = riskFree + (beta * marketPremium);
|
|
53
|
+
return { label: "Cost of Equity", value: val, unit: "%", formula: "Rf + β(Rm - Rf)", inputs: { riskFree, beta, marketPremium } };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function calcVCMethedPreMoney(exitValue: number, targetIrr: number, yearsToExit: number, dilutionPct: number): QuantResult {
|
|
57
|
+
const pvExit = exitValue / Math.pow(1 + targetIrr, yearsToExit);
|
|
58
|
+
const val = pvExit * (1 - dilutionPct);
|
|
59
|
+
return { label: "VC Pre-money", value: val, unit: "$", formula: "(Exit / (1+IRR)^n) * (1-dilution)", inputs: { exitValue, targetIrr, yearsToExit, dilutionPct } };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// ── 8.12.1 Energy & Signals ──────────────────────────────────────────
|
|
63
|
+
|
|
64
|
+
export function calcLCOE(lifecycleCost: number, totalEnergy: number): QuantResult {
|
|
65
|
+
const val = totalEnergy > 0 ? lifecycleCost / totalEnergy : 0;
|
|
66
|
+
return { label: "LCOE", value: val, unit: "$/MWh", formula: "lifecycle cost / energy generated", inputs: { lifecycleCost, totalEnergy } };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function calcSharpe(returns: number[], riskFree: number): QuantResult {
|
|
70
|
+
const avg = returns.reduce((a, b) => a + b, 0) / returns.length;
|
|
71
|
+
const variance = returns.reduce((a, b) => a + Math.pow(b - avg, 2), 0) / returns.length;
|
|
72
|
+
const std = Math.sqrt(variance);
|
|
73
|
+
const val = std > 0 ? (avg - riskFree) / std : 0;
|
|
74
|
+
return { label: "Sharpe Ratio", value: val, formula: "(Rp - Rf) / σp", inputs: { returns: returns.length, riskFree } };
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function calcKelly(winProb: number, winLossRatio: number): QuantResult {
|
|
78
|
+
const val = winProb - ((1 - winProb) / winLossRatio);
|
|
79
|
+
return { label: "Kelly Criterion", value: val, unit: "%", formula: "p - (q/b)", inputs: { winProb, winLossRatio } };
|
|
80
|
+
}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ReportOS v3 — calculation engines + quality gates.
|
|
3
|
+
* Real, runnable math (not prose). Every engine returns numeric outputs
|
|
4
|
+
* plus the formula used, so reports are reproducible and auditable.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export interface CalcResult {
|
|
8
|
+
label: string;
|
|
9
|
+
value: number;
|
|
10
|
+
unit?: string;
|
|
11
|
+
formula: string;
|
|
12
|
+
inputs: Record<string, number>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// ── 8.1 Market sizing ───────────────────────────────────────────────
|
|
16
|
+
export function calcMarketSizing(i: { customers: number; spendPerCustomer: number; servedShare: number; captureRate: number; }): CalcResult[] {
|
|
17
|
+
const tam = i.customers * i.spendPerCustomer;
|
|
18
|
+
const sam = tam * i.servedShare;
|
|
19
|
+
const som = sam * i.captureRate;
|
|
20
|
+
return [
|
|
21
|
+
{ label: "TAM", value: tam, unit: "$", formula: "customers × spend/customer", inputs: i },
|
|
22
|
+
{ label: "SAM", value: sam, unit: "$", formula: "TAM × served share", inputs: i },
|
|
23
|
+
{ label: "SOM", value: som, unit: "$", formula: "SAM × capture rate", inputs: i },
|
|
24
|
+
];
|
|
25
|
+
}
|
|
26
|
+
export function calcCAGR(begin: number, end: number, years: number): CalcResult {
|
|
27
|
+
const v = years > 0 && begin > 0 ? Math.pow(end / begin, 1 / years) - 1 : 0;
|
|
28
|
+
return { label: "CAGR", value: v, unit: "%", formula: "(end/begin)^(1/years) - 1", inputs: { begin, end, years } };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// ── 8.2 Valuation ───────────────────────────────────────────────────
|
|
32
|
+
export function calcNPV(cashflows: number[], rate: number, initial = 0): CalcResult {
|
|
33
|
+
const npv = cashflows.reduce((acc, cf, t) => acc + cf / Math.pow(1 + rate, t + 1), 0) - initial;
|
|
34
|
+
return { label: "NPV", value: npv, unit: "$", formula: "Σ FCF_t/(1+r)^t − initial", inputs: { rate, initial, periods: cashflows.length } };
|
|
35
|
+
}
|
|
36
|
+
export function calcIRR(cashflows: number[], initial: number): CalcResult {
|
|
37
|
+
// bisection on rate in [-0.9, 1.0]
|
|
38
|
+
const npvAt = (r: number) => cashflows.reduce((a, cf, t) => a + cf / Math.pow(1 + r, t + 1), 0) - initial;
|
|
39
|
+
let lo = -0.9, hi = 1.0, mid = 0;
|
|
40
|
+
for (let k = 0; k < 100; k++) {
|
|
41
|
+
mid = (lo + hi) / 2;
|
|
42
|
+
const v = npvAt(mid);
|
|
43
|
+
if (Math.abs(v) < 1e-6) break;
|
|
44
|
+
if (v > 0) lo = mid; else hi = mid;
|
|
45
|
+
}
|
|
46
|
+
return { label: "IRR", value: mid, unit: "%", formula: "rate where NPV = 0 (bisection)", inputs: { initial, periods: cashflows.length } };
|
|
47
|
+
}
|
|
48
|
+
export function calcMOIC(exitEquity: number, investedEquity: number): CalcResult {
|
|
49
|
+
return { label: "MOIC", value: investedEquity > 0 ? exitEquity / investedEquity : 0, unit: "x", formula: "exit equity / invested equity", inputs: { exitEquity, investedEquity } };
|
|
50
|
+
}
|
|
51
|
+
export function calcAdjEBITDA(i: { reportedEBITDA: number; nonRecurringExp: number; nonRecurringInc: number; runRateAdj: number; }): CalcResult {
|
|
52
|
+
const v = i.reportedEBITDA + i.nonRecurringExp - i.nonRecurringInc + i.runRateAdj;
|
|
53
|
+
return { label: "Adjusted EBITDA", value: v, unit: "$", formula: "reported + non-recurring exp − non-recurring inc + run-rate", inputs: i };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// ── 8.3 Scenario / sensitivity ──────────────────────────────────────
|
|
57
|
+
export function calcExpectedValue(scenarios: { p: number; value: number }[]): CalcResult {
|
|
58
|
+
const ev = scenarios.reduce((a, s) => a + s.p * s.value, 0);
|
|
59
|
+
return { label: "Expected Value", value: ev, unit: "$", formula: "Σ p × value", inputs: { scenarios: scenarios.length } };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// ── 8.4 Risk scoring ────────────────────────────────────────────────
|
|
63
|
+
export function calcRisk(probability: number, impact: number): CalcResult {
|
|
64
|
+
return { label: "Risk Score", value: probability * impact, formula: "P × I", inputs: { probability, impact } };
|
|
65
|
+
}
|
|
66
|
+
export function calcResidualRisk(inherent: number, controlEffectiveness: number): CalcResult {
|
|
67
|
+
return { label: "Residual Risk", value: inherent * (1 - controlEffectiveness), formula: "inherent × (1 − control effectiveness)", inputs: { inherent, controlEffectiveness } };
|
|
68
|
+
}
|
|
69
|
+
export function calcRPN(severity: number, occurrence: number, detectability: number): CalcResult {
|
|
70
|
+
return { label: "RPN", value: severity * occurrence * detectability, formula: "severity × occurrence × detectability", inputs: { severity, occurrence, detectability } };
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ── 8.5 Evidence confidence ─────────────────────────────────────────
|
|
74
|
+
export function calcConfidence(evidenceStrength: number, methodValidity: number, assumptionStability: number): CalcResult {
|
|
75
|
+
// claim confidence cannot exceed weakest link
|
|
76
|
+
const v = Math.min(evidenceStrength, methodValidity, assumptionStability);
|
|
77
|
+
return { label: "Claim Confidence", value: v, unit: "/100", formula: "min(evidence, method, assumption)", inputs: { evidenceStrength, methodValidity, assumptionStability } };
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// ── 8.6 Research statistics ─────────────────────────────────────────
|
|
81
|
+
export function calcEffectSize(meanDiff: number, pooledSD: number): CalcResult {
|
|
82
|
+
return { label: "Effect Size (d)", value: pooledSD > 0 ? meanDiff / pooledSD : 0, formula: "mean diff / pooled SD", inputs: { meanDiff, pooledSD } };
|
|
83
|
+
}
|
|
84
|
+
export function calcRelativeRisk(treatmentRisk: number, controlRisk: number): CalcResult {
|
|
85
|
+
return { label: "Relative Risk", value: controlRisk > 0 ? treatmentRisk / controlRisk : 0, formula: "treatment risk / control risk", inputs: { treatmentRisk, controlRisk } };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// ── 8.7 Policy cost-benefit ─────────────────────────────────────────
|
|
89
|
+
export function calcCostBenefit(pvBenefits: number, pvCosts: number): CalcResult[] {
|
|
90
|
+
return [
|
|
91
|
+
{ label: "Benefit-Cost Ratio", value: pvCosts > 0 ? pvBenefits / pvCosts : 0, formula: "PV(benefits) / PV(costs)", inputs: { pvBenefits, pvCosts } },
|
|
92
|
+
{ label: "Net Social Benefit", value: pvBenefits - pvCosts, unit: "$", formula: "PV(benefits) − PV(costs)", inputs: { pvBenefits, pvCosts } },
|
|
93
|
+
];
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// ── 8.8 ESG / climate ───────────────────────────────────────────────
|
|
97
|
+
export function calcGHG(scope1: number, scope2: number, scope3: number): CalcResult {
|
|
98
|
+
return { label: "Total GHG", value: scope1 + scope2 + scope3, unit: "tCO₂e", formula: "Scope 1 + 2 + 3", inputs: { scope1, scope2, scope3 } };
|
|
99
|
+
}
|
|
100
|
+
export function calcCarbonIntensity(tco2e: number, revenue: number): CalcResult {
|
|
101
|
+
return { label: "Carbon Intensity", value: revenue > 0 ? tco2e / revenue : 0, unit: "tCO₂e/$", formula: "tCO₂e / revenue", inputs: { tco2e, revenue } };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// ── 8.9 Digital / AI readiness ──────────────────────────────────────
|
|
105
|
+
export function calcAIReadiness(i: { dataQuality: number; infra: number; talent: number; governance: number; process: number; change: number; }): CalcResult {
|
|
106
|
+
const v = 0.25 * i.dataQuality + 0.20 * i.infra + 0.20 * i.talent + 0.15 * i.governance + 0.10 * i.process + 0.10 * i.change;
|
|
107
|
+
return { label: "AI Readiness", value: v, unit: "/100", formula: "0.25·data + 0.20·infra + 0.20·talent + 0.15·gov + 0.10·process + 0.10·change", inputs: i };
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// ── 8.11 Pricing ────────────────────────────────────────────────────
|
|
111
|
+
export function calcPocketPrice(list: number, discounts: number, rebates: number, promos: number, leakage: number): CalcResult {
|
|
112
|
+
return { label: "Pocket Price", value: list - discounts - rebates - promos - leakage, unit: "$", formula: "list − discounts − rebates − promos − leakage", inputs: { list, discounts, rebates, promos, leakage } };
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// ── 8.12 Energy LCOE ────────────────────────────────────────────────
|
|
116
|
+
export function calcLCOE(pvLifecycleCosts: number, pvEnergyMWh: number): CalcResult {
|
|
117
|
+
return { label: "LCOE", value: pvEnergyMWh > 0 ? pvLifecycleCosts / pvEnergyMWh : 0, unit: "$/MWh", formula: "PV(lifecycle costs) / PV(energy)", inputs: { pvLifecycleCosts, pvEnergyMWh } };
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// ── Quality gates (Section 9) ───────────────────────────────────────
|
|
121
|
+
export interface QuantResult { label: string; value: number; unit?: string; formula: string; inputs: Record<string, number>; }
|
|
122
|
+
export interface QualityGate { id: string; name: string; check: string; }
|
|
123
|
+
export const QUALITY_GATES: QualityGate[] = [
|
|
124
|
+
{ id: "G1", name: "Objective fit", check: "Every section supports the stated decision/question/objective" },
|
|
125
|
+
{ id: "G2", name: "Evidence binding", check: "Every factual claim links to source, data, calculation, or explicit assumption" },
|
|
126
|
+
{ id: "G3", name: "Status labeling", check: "Facts ≠ assumptions ≠ forecasts ≠ recommendations" },
|
|
127
|
+
{ id: "G4", name: "MECE structure", check: "Categories non-overlapping, no gaps, same logical level" },
|
|
128
|
+
{ id: "G5", name: "Calculation reproducibility", check: "Numbers show formula, inputs, assumptions, sensitivity" },
|
|
129
|
+
{ id: "G6", name: "Falsification / red-team", check: "What would make the recommendation wrong; what data reverses it" },
|
|
130
|
+
{ id: "G7", name: "Compliance", check: "Satisfies applicable standard (NIH/NSF/GAO/PRISMA/SEC/CSRD/NIST AI RMF)" },
|
|
131
|
+
{ id: "G8", name: "Audience density", check: "Exec decides from summary; analyst reproduces from appendix" },
|
|
132
|
+
];
|
|
133
|
+
|
|
134
|
+
// ── Archetype routing (Section 4 + Step 2) ──────────────────────────
|
|
135
|
+
export type ArchetypeId =
|
|
136
|
+
| "decision-strategy" | "investment-financial" | "implementation-tech"
|
|
137
|
+
| "audit-assurance" | "scientific-academic" | "policy-public" | "market-commercial";
|
|
138
|
+
|
|
139
|
+
export interface Archetype { id: ArchetypeId; name: string; covers: string; sections: string[]; }
|
|
140
|
+
|
|
141
|
+
export const ARCHETYPES: Archetype[] = [
|
|
142
|
+
{ id: "decision-strategy", name: "Decision / Strategy", covers: "McKinsey, BCG, Bain, Strategy&, EY-Parthenon strategy, Roland Berger, Innosight, market entry, growth strategy",
|
|
143
|
+
sections: ["Decision Summary", "Situation / Context", "Core Question", "Evidence & Diagnosis", "Strategic Options", "Recommendation", "Business Case", "Implementation Roadmap", "Risk & Falsification", "Appendix"] },
|
|
144
|
+
{ id: "investment-financial", name: "Investment / Transaction / Financial", covers: "Bain PE diligence, EY-Parthenon CDD, Deloitte/PwC transaction services, QofE, AlixPartners restructuring, equity research, IC memos",
|
|
145
|
+
sections: ["Investment / Transaction Thesis", "Target / Asset Overview", "Market & Competitive Assessment", "Commercial Diligence", "Financial Diligence", "Value Creation Plan", "Valuation", "Risks & Deal Protections", "Decision Package", "Appendix"] },
|
|
146
|
+
{ id: "implementation-tech", name: "Implementation / Technology / Transformation", covers: "Accenture, Deloitte Digital, IBM, Capgemini, digital/AI transformation, cloud migration, ERP, cyber modernization",
|
|
147
|
+
sections: ["Transformation Summary", "Current-State Assessment", "Target-State Blueprint", "Use Case / Initiative Portfolio", "Operating Model", "Roadmap", "Business Case", "Risk, Security & Responsible AI", "Adoption & Change", "Appendix"] },
|
|
148
|
+
{ id: "audit-assurance", name: "Audit / Assurance / Risk / Compliance", covers: "KPMG risk advisory, Big 4 audit, internal audit, GAO/IG audit, cyber incident, FTI forensic, ERM",
|
|
149
|
+
sections: ["Executive Assurance Summary", "Scope & Criteria", "Methodology", "Finding Register", "Risk Assessment", "Control / Compliance Matrix", "Recommendations & Remediation", "Governance & Tracking", "Appendix"] },
|
|
150
|
+
{ id: "scientific-academic", name: "Scientific / Academic / Evidence-Synthesis", covers: "IMRAD article, NIH R01/RPPR, NSF proposal, dissertation, PRISMA review, RAND research, policy research",
|
|
151
|
+
sections: ["Research Summary", "Background & Gap", "Objectives / Aims", "Methods", "Results / Preliminary Data", "Interpretation / Discussion", "Impact / Broader Significance", "Compliance & Reporting", "References", "Supplementary"] },
|
|
152
|
+
{ id: "policy-public", name: "Policy / Public Sector / Multilateral", covers: "GAO program evaluation, CRS, OMB memo, World Bank, IMF, OECD, UNDP, EC impact assessment, think tanks",
|
|
153
|
+
sections: ["Policy Summary", "Mandate / Context", "Diagnostic", "Evidence & Comparative Analysis", "Policy Options", "Impact Analysis", "Preferred Option / Recommendations", "Implementation & Governance", "Annexes"] },
|
|
154
|
+
{ id: "market-commercial", name: "Market / Sector / Commercial Intelligence", covers: "Market entry, industry outlook, ESG strategy, healthcare ops, real estate, pricing strategy, HR benchmarking, energy/climate",
|
|
155
|
+
sections: ["Market / Sector Summary", "Market Definition", "Market Sizing & Growth", "Demand & Customer Analysis", "Competitive Landscape", "Economics", "Trends & Disruption", "Strategic Implications", "Appendix"] },
|
|
156
|
+
];
|
|
157
|
+
|
|
158
|
+
const ARCH_ROUTES: { re: RegExp; id: ArchetypeId }[] = [
|
|
159
|
+
{ re: /\b(invest|acquir|due diligence|valuation|ebitda|m&a|buyout|equity research|restructur|10-?k)\b/i, id: "investment-financial" },
|
|
160
|
+
{ re: /\b(audit|assurance|compliance|controls|finding|forensic|incident|erm|gagas|yellow book)\b/i, id: "audit-assurance" },
|
|
161
|
+
{ re: /\b(transform|modernize|architecture|migration|cloud|erp|implementation|devops|mlops)\b/i, id: "implementation-tech" },
|
|
162
|
+
{ re: /\b(grant|hypothesis|study|trial|systematic review|prisma|nih|nsf|imrad|dissertation|meta-analysis)\b/i, id: "scientific-academic" },
|
|
163
|
+
{ re: /\b(policy|public sector|world bank|imf|oecd|undp|legislation|regulation impact|cost-benefit|program evaluation)\b/i, id: "policy-public" },
|
|
164
|
+
{ re: /\b(market size|tam|sam|som|industry outlook|pricing|esg|sustainability|lcoe|sector|benchmark)\b/i, id: "market-commercial" },
|
|
165
|
+
{ re: /\b(strateg|recommend|should we|grow|options|board|decision)\b/i, id: "decision-strategy" },
|
|
166
|
+
];
|
|
167
|
+
|
|
168
|
+
export function routeArchetype(query: string): ArchetypeId {
|
|
169
|
+
for (const r of ARCH_ROUTES) if (r.re.test(query)) return r.id;
|
|
170
|
+
return "decision-strategy";
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export function findArchetype(id: ArchetypeId): Archetype {
|
|
174
|
+
return ARCHETYPES.find(a => a.id === id) ?? ARCHETYPES[0];
|
|
175
|
+
}
|