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,594 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type C — SagaOsV2Panel: real UI over the four SAGA-OS v2 engines.
|
|
3
|
+
* Every control drives an actual deterministic computation from
|
|
4
|
+
* `src/lib/sage/saga-os-v2-engines.ts`. No feature theatre.
|
|
5
|
+
*/
|
|
6
|
+
import { useCallback, useMemo, useState } from "react";
|
|
7
|
+
import {
|
|
8
|
+
compileGenreSpec, runGenesisGrid, computeKallos, auditWireCoverage, wireCatalog,
|
|
9
|
+
modalShortcutTest, buildSagaOsV2DirectiveBlock, generateOnoma, buildWorldMap,
|
|
10
|
+
buildCastGraph, caRuleTable, SLOT_CLASS_META, SLOT_CLASS_IDS,
|
|
11
|
+
ONOMA_GENERATABLE_CLASSES, type SlotClassId, type GenreSpec, type GridRun, type KallosReport,
|
|
12
|
+
type WireCoverageReport, type ModalShortcutReport, type WorldMapPlace,
|
|
13
|
+
} from "@/lib/sage/saga-os-v2-engines";
|
|
14
|
+
import { auditCastNameConfusion } from '@/lib/sage/index.ts';
|
|
15
|
+
|
|
16
|
+
// ── shared atoms (match Style Persona / SAGE panel typography) ──────────────
|
|
17
|
+
function Sec({ icon, title, right }: { icon: string; title: string; right?: React.ReactNode }) {
|
|
18
|
+
return (
|
|
19
|
+
<div className="flex items-center gap-2 border-b border-zinc-100 pb-1.5">
|
|
20
|
+
<span className="text-sm">{icon}</span>
|
|
21
|
+
<span className="text-[11px] font-bold uppercase tracking-wider text-zinc-700">{title}</span>
|
|
22
|
+
{right != null && <span className="ml-auto text-[10px] text-zinc-400">{right}</span>}
|
|
23
|
+
</div>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
function Pill({ children, tone = "zinc" }: { children: React.ReactNode; tone?: string }) {
|
|
27
|
+
const t: Record<string, string> = {
|
|
28
|
+
zinc: "bg-zinc-100 text-zinc-700", indigo: "bg-indigo-50 text-indigo-700",
|
|
29
|
+
violet: "bg-violet-50 text-violet-700", emerald: "bg-emerald-50 text-emerald-700",
|
|
30
|
+
amber: "bg-amber-50 text-amber-800", rose: "bg-rose-50 text-rose-700",
|
|
31
|
+
sky: "bg-sky-50 text-sky-700", teal: "bg-teal-50 text-teal-700",
|
|
32
|
+
};
|
|
33
|
+
return <span className={`rounded px-1.5 py-0.5 text-[10px] font-semibold ${t[tone] ?? t.zinc}`}>{children}</span>;
|
|
34
|
+
}
|
|
35
|
+
function KV({ k, v }: { k: string; v: React.ReactNode }) {
|
|
36
|
+
return (
|
|
37
|
+
<div className="flex items-baseline gap-1.5 border-b border-zinc-50 py-0.5 last:border-0">
|
|
38
|
+
<span className="w-28 shrink-0 text-[10px] font-bold uppercase tracking-wider text-zinc-400">{k}</span>
|
|
39
|
+
<span className="text-[11px] text-zinc-800">{v}</span>
|
|
40
|
+
</div>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
function Bar({ v, label }: { v: number; label: string }) {
|
|
44
|
+
const pct = Math.round(v * 100);
|
|
45
|
+
const hue = Math.round(v * 120);
|
|
46
|
+
return (
|
|
47
|
+
<div className="flex items-center gap-1.5">
|
|
48
|
+
<span className="w-[124px] shrink-0 truncate text-right text-[10px] text-zinc-500" title={label}>{label}</span>
|
|
49
|
+
<div className="h-1.5 flex-1 rounded-full bg-zinc-100">
|
|
50
|
+
<div className="h-full rounded-full" style={{ width: `${pct}%`, backgroundColor: `hsl(${hue},55%,50%)` }} />
|
|
51
|
+
</div>
|
|
52
|
+
<span className="w-9 shrink-0 text-right font-mono text-[10px] text-zinc-600">{pct}%</span>
|
|
53
|
+
</div>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
function AuditRow({ id, pass, detail }: { id: string; pass: boolean; detail: string }) {
|
|
57
|
+
return (
|
|
58
|
+
<div className="flex items-start gap-1.5 border-b border-zinc-50 py-0.5 last:border-0">
|
|
59
|
+
<span className={`shrink-0 font-mono text-[10px] ${pass ? "text-emerald-600" : "text-amber-600"}`}>
|
|
60
|
+
{pass ? "✓" : "!"}
|
|
61
|
+
</span>
|
|
62
|
+
<span className="w-16 shrink-0 font-mono text-[10px] text-zinc-500">{id}</span>
|
|
63
|
+
<span className="text-[10px] text-zinc-600">{detail}</span>
|
|
64
|
+
</div>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
type Tab = "helm" | "grid" | "world" | "cast" | "kallos" | "wire" | "names";
|
|
69
|
+
const TABS: { id: Tab; icon: string; label: string }[] = [
|
|
70
|
+
{ id: "helm", icon: "🎭", label: "Genre Helm" },
|
|
71
|
+
{ id: "grid", icon: "🧬", label: "Genesis Grid" },
|
|
72
|
+
{ id: "world", icon: "🗺", label: "World Map" },
|
|
73
|
+
{ id: "cast", icon: "🕸", label: "Cast & Relations" },
|
|
74
|
+
{ id: "kallos", icon: "✨", label: "KALLOS" },
|
|
75
|
+
{ id: "wire", icon: "🔌", label: "SAGA-WIRE" },
|
|
76
|
+
{ id: "names", icon: "📛", label: "Names" },
|
|
77
|
+
];
|
|
78
|
+
|
|
79
|
+
// ── 1. GENRE HELM ───────────────────────────────────────────────────────────
|
|
80
|
+
function HelmPanel({ spec, onCompile }: { spec: GenreSpec | null; onCompile: (s: GenreSpec) => void }) {
|
|
81
|
+
const [text, setText] = useState("a scary quiet literary thriller, 3 book series");
|
|
82
|
+
return (
|
|
83
|
+
<div className="space-y-3">
|
|
84
|
+
<Sec icon="🎭" title="Genre Helm — request → GenreSpec" right="offline rule-based compiler" />
|
|
85
|
+
<div className="flex gap-1">
|
|
86
|
+
<input
|
|
87
|
+
value={text} onChange={(e) => setText(e.target.value)}
|
|
88
|
+
className="flex-1 rounded border border-zinc-200 px-2 py-1 text-[11px]"
|
|
89
|
+
placeholder="e.g. scary thriller · romance novel · like Lemony Snicket · hard sf first contact"
|
|
90
|
+
/>
|
|
91
|
+
<button onClick={() => onCompile(compileGenreSpec(text))}
|
|
92
|
+
className="rounded bg-indigo-600 px-3 py-1 text-[11px] font-bold text-white hover:bg-indigo-700">
|
|
93
|
+
Compile
|
|
94
|
+
</button>
|
|
95
|
+
</div>
|
|
96
|
+
{spec && (
|
|
97
|
+
<div className="space-y-2">
|
|
98
|
+
<div className="rounded-lg border border-indigo-100 bg-white p-2">
|
|
99
|
+
<div className="mb-1 flex flex-wrap items-center gap-1">
|
|
100
|
+
<Pill tone="indigo">{spec.family}</Pill>
|
|
101
|
+
<span className="text-[10px] text-zinc-400">/</span>
|
|
102
|
+
<Pill tone="violet">{spec.leaf}</Pill>
|
|
103
|
+
<Pill tone="zinc">V={spec.V}</Pill>
|
|
104
|
+
<Pill tone="teal">{spec.geometry}</Pill>
|
|
105
|
+
<Pill tone="zinc">{spec.container}</Pill>
|
|
106
|
+
</div>
|
|
107
|
+
<KV k="Pace" v={spec.paceProfile} />
|
|
108
|
+
<KV k="Tone gradient" v={spec.toneGradient} />
|
|
109
|
+
<KV k="CA rule table" v={`${spec.caRuleTableId} · B={${caRuleTable(spec.caRuleTableId).B.join(",")}} · S={${caRuleTable(spec.caRuleTableId).S.join(",")}}`} />
|
|
110
|
+
<KV k="KALLOS profile" v={spec.kallosProfile} />
|
|
111
|
+
<KV k="Stakes rotation" v={spec.stakesRotation.join(" → ")} />
|
|
112
|
+
<KV k="Ending weights" v={
|
|
113
|
+
<span className="flex flex-wrap gap-1">
|
|
114
|
+
{Object.entries(spec.endingFamilyWeights).sort((a, b) => b[1] - a[1]).slice(0, 6)
|
|
115
|
+
.map(([k, v]) => <Pill key={k} tone={v >= 0.7 ? "emerald" : "zinc"}>{k} {v.toFixed(2)}</Pill>)}
|
|
116
|
+
</span>
|
|
117
|
+
} />
|
|
118
|
+
<KV k="Slot weights" v={
|
|
119
|
+
<span className="flex flex-wrap gap-1">
|
|
120
|
+
{Object.entries(spec.bandWeights).filter(([, v]) => v > 1)
|
|
121
|
+
.map(([k, v]) => <Pill key={k} tone="amber">{SLOT_CLASS_META[k as SlotClassId]?.name ?? k} ×{v}</Pill>)}
|
|
122
|
+
</span>
|
|
123
|
+
} />
|
|
124
|
+
</div>
|
|
125
|
+
{spec.ambiguities.length > 0 && (
|
|
126
|
+
<div className="rounded border border-amber-100 bg-amber-50/70 p-2">
|
|
127
|
+
<div className="text-[10px] font-bold uppercase tracking-wider text-amber-800">Ambiguities (declared, not silently defaulted)</div>
|
|
128
|
+
<ul className="ml-4 list-disc text-[10px] text-amber-800">
|
|
129
|
+
{spec.ambiguities.map((a) => <li key={a}>{a}</li>)}
|
|
130
|
+
</ul>
|
|
131
|
+
</div>
|
|
132
|
+
)}
|
|
133
|
+
</div>
|
|
134
|
+
)}
|
|
135
|
+
</div>
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// ── 2. GENESIS GRID ─────────────────────────────────────────────────────────
|
|
140
|
+
/** The seed the fiction runner is currently previewing. */
|
|
141
|
+
function liveFictionSeed(): number | null {
|
|
142
|
+
try {
|
|
143
|
+
const raw = localStorage.getItem("veritas.sage.previewSeed.v1");
|
|
144
|
+
const n = Number(raw);
|
|
145
|
+
return Number.isFinite(n) && n > 0 ? n : null;
|
|
146
|
+
} catch { return null; }
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function GridPanel({ run, onRun, ms, directive }: {
|
|
150
|
+
run: GridRun | null; onRun: (seed: number, budget: number) => void;
|
|
151
|
+
ms: ModalShortcutReport | null; directive: string;
|
|
152
|
+
}) {
|
|
153
|
+
const live = liveFictionSeed();
|
|
154
|
+
const [seed, setSeed] = useState(() => liveFictionSeed() ?? 12345);
|
|
155
|
+
const isLive = live != null && seed === live;
|
|
156
|
+
const [budget, setBudget] = useState(48);
|
|
157
|
+
return (
|
|
158
|
+
<div className="space-y-3">
|
|
159
|
+
<Sec icon="🧬" title="Genesis Grid — typed-lattice CA" right="deterministic · relational neighbourhood" />
|
|
160
|
+
<div className={`rounded border p-2 text-[10px] ${isLive ? "border-emerald-200 bg-emerald-50 text-emerald-800" : "border-amber-200 bg-amber-50 text-amber-800"}`}>
|
|
161
|
+
{isLive
|
|
162
|
+
? <>● <b>LIVE</b> — this seed matches the fiction engine\u2019s current blueprint, so what you see here is what the model receives.</>
|
|
163
|
+
: <>○ <b>LAB</b> — exploring seed {seed}
|
|
164
|
+
{live != null && <> while the fiction engine is on seed <b>{live}</b></>}.
|
|
165
|
+
Results below are <b>not</b> sent to the model.
|
|
166
|
+
{live != null && <button onClick={() => { setSeed(live); onRun(live, budget); }} className="ml-1 rounded bg-amber-600 px-1.5 py-0.5 font-semibold text-white">sync to live seed</button>}
|
|
167
|
+
</>}
|
|
168
|
+
</div>
|
|
169
|
+
<div className="flex flex-wrap items-center gap-1">
|
|
170
|
+
<label className="flex items-center gap-1 text-[10px] text-zinc-500">
|
|
171
|
+
seed
|
|
172
|
+
<input type="number" value={seed} onChange={(e) => setSeed(Number(e.target.value) || 0)}
|
|
173
|
+
className="w-24 rounded border border-zinc-200 px-1.5 py-1 font-mono text-[11px]" />
|
|
174
|
+
</label>
|
|
175
|
+
<label className="flex items-center gap-1 text-[10px] text-zinc-500">
|
|
176
|
+
budget
|
|
177
|
+
<input type="number" min={4} max={96} value={budget}
|
|
178
|
+
onChange={(e) => setBudget(Math.max(4, Math.min(96, Number(e.target.value) || 4)))}
|
|
179
|
+
className="w-16 rounded border border-zinc-200 px-1.5 py-1 font-mono text-[11px]" />
|
|
180
|
+
</label>
|
|
181
|
+
<button onClick={() => onRun(seed, budget)}
|
|
182
|
+
className="rounded bg-indigo-600 px-3 py-1 text-[11px] font-bold text-white hover:bg-indigo-700">Evolve</button>
|
|
183
|
+
<button onClick={() => { const s = (Math.random() * 2 ** 31) >>> 0; setSeed(s); onRun(s, budget); }}
|
|
184
|
+
className="rounded border border-indigo-200 px-2 py-1 text-[11px] font-semibold text-indigo-700 hover:bg-indigo-50">🎲 Random seed</button>
|
|
185
|
+
</div>
|
|
186
|
+
|
|
187
|
+
{run && (
|
|
188
|
+
<>
|
|
189
|
+
<div className="rounded-lg border border-violet-100 bg-white p-2">
|
|
190
|
+
<div className="mb-1 flex flex-wrap items-center gap-1">
|
|
191
|
+
<Pill tone="violet">{run.pattern}</Pill>
|
|
192
|
+
<Pill tone="emerald">→ {run.endingFamily}</Pill>
|
|
193
|
+
<Pill tone="zinc">{run.ruleTable.id}</Pill>
|
|
194
|
+
<Pill tone="zinc">B={run.ruleTable.B.join(",")} S={run.ruleTable.S.join(",")}</Pill>
|
|
195
|
+
</div>
|
|
196
|
+
<KV k="Pattern detail" v={run.patternDetail} />
|
|
197
|
+
<KV k="Lattice" v={`${run.rows.length} rows (${run.rows.filter(r=>r.kind==="agent").length} agent · ${run.rows.filter(r=>r.kind==="institution").length} inst · ${run.rows.filter(r=>r.kind==="setting").length} setting · ${run.rows.filter(r=>r.kind==="strand").length} strand)`} />
|
|
198
|
+
<KV k="Ticks / stop" v={`${run.ticks.length} ticks · stopped t=${run.stopTick}`} />
|
|
199
|
+
<KV k="Compiled plan" v={`${run.plan.chapters.length} chapters · ${run.plan.totalScenes} scenes · ${run.plan.promiseOps.length} promise ops`} />
|
|
200
|
+
<KV k="Distinct elements" v={String(new Set(run.plan.scenes.map(s=>s.element?.id).filter(Boolean)).size)} />
|
|
201
|
+
</div>
|
|
202
|
+
|
|
203
|
+
{/* population + intensity sparkline */}
|
|
204
|
+
<div className="rounded-lg border border-zinc-100 bg-white p-2">
|
|
205
|
+
<div className="text-[10px] font-bold uppercase tracking-wider text-zinc-400">Population & intensity per tick</div>
|
|
206
|
+
<div className="mt-1 flex items-end gap-[2px]" style={{ height: 48 }}>
|
|
207
|
+
{run.ticks.map((t) => {
|
|
208
|
+
const maxPop = Math.max(...run.ticks.map((x) => x.population), 1);
|
|
209
|
+
const h = Math.round((t.activeCount / maxPop) * 44);
|
|
210
|
+
const inten = t.intensity / 100;
|
|
211
|
+
return (
|
|
212
|
+
<div key={t.t} className="flex-1" title={`t=${t.t}: ${t.activeCount}/${t.population} live · births ${t.births.length} · deaths ${t.deaths.length} · intensity ${t.intensity}`}>
|
|
213
|
+
<div className="rounded-t" style={{ height: Math.max(2, h), backgroundColor: `hsl(${Math.round(inten * 120)},60%,55%)` }} />
|
|
214
|
+
</div>
|
|
215
|
+
);
|
|
216
|
+
})}
|
|
217
|
+
</div>
|
|
218
|
+
<div className="mt-0.5 flex justify-between font-mono text-[9px] text-zinc-400">
|
|
219
|
+
<span>t=0</span><span>{run.plan.chapters.length} chapters compiled</span><span>t={run.stopTick}</span>
|
|
220
|
+
</div>
|
|
221
|
+
</div>
|
|
222
|
+
|
|
223
|
+
{/* chapter stakes rotation */}
|
|
224
|
+
<div className="rounded-lg border border-zinc-100 bg-white p-2">
|
|
225
|
+
<div className="text-[10px] font-bold uppercase tracking-wider text-zinc-400">Stakes rotation by chapter</div>
|
|
226
|
+
<div className="mt-1 flex flex-wrap gap-1">
|
|
227
|
+
{run.plan.chapters.map((c) => (
|
|
228
|
+
<Pill key={c.index} tone={c.dominantStakes === "physical" ? "rose" : c.dominantStakes === "moral" ? "amber" : c.dominantStakes === "relational" ? "violet" : c.dominantStakes === "institutional" ? "sky" : "zinc"}>
|
|
229
|
+
{c.index}:{c.dominantStakes ?? "—"}
|
|
230
|
+
</Pill>
|
|
231
|
+
))}
|
|
232
|
+
</div>
|
|
233
|
+
</div>
|
|
234
|
+
|
|
235
|
+
{/* GEN audits */}
|
|
236
|
+
<div className="rounded-lg border border-zinc-100 bg-white p-2">
|
|
237
|
+
<div className="text-[10px] font-bold uppercase tracking-wider text-zinc-400">GEN-001…009 audits</div>
|
|
238
|
+
<div className="mt-1">{run.audits.map((a) => <AuditRow key={a.id} {...a} />)}</div>
|
|
239
|
+
</div>
|
|
240
|
+
|
|
241
|
+
{/* modal shortcut */}
|
|
242
|
+
{ms && (
|
|
243
|
+
<div className={`rounded-lg border p-2 ${ms.collapsesToTemplatePlusDice ? "border-rose-200 bg-rose-50/70" : "border-emerald-200 bg-emerald-50/70"}`}>
|
|
244
|
+
<div className={`text-[10px] font-bold uppercase tracking-wider ${ms.collapsesToTemplatePlusDice ? "text-rose-700" : "text-emerald-700"}`}>
|
|
245
|
+
Modal-shortcut test (v2 §7)
|
|
246
|
+
</div>
|
|
247
|
+
<div className={`text-[11px] font-semibold ${ms.collapsesToTemplatePlusDice ? "text-rose-800" : "text-emerald-800"}`}>{ms.verdict}</div>
|
|
248
|
+
<ul className="ml-4 mt-0.5 list-disc text-[10px] text-zinc-600">
|
|
249
|
+
{ms.reasons.map((r) => <li key={r}>{r}</li>)}
|
|
250
|
+
</ul>
|
|
251
|
+
</div>
|
|
252
|
+
)}
|
|
253
|
+
|
|
254
|
+
{/* seed doc + directive */}
|
|
255
|
+
<div className="rounded-lg border border-zinc-100 bg-white p-2">
|
|
256
|
+
<div className="text-[10px] font-bold uppercase tracking-wider text-zinc-400">Seed document (replay proof)</div>
|
|
257
|
+
<pre className="mt-1 overflow-x-auto whitespace-pre-wrap font-mono text-[10px] text-zinc-600">{run.seedDoc}</pre>
|
|
258
|
+
</div>
|
|
259
|
+
{directive && (
|
|
260
|
+
<div className="rounded-lg border border-violet-100 bg-violet-50/50 p-2">
|
|
261
|
+
<div className="text-[10px] font-bold uppercase tracking-wider text-violet-700">
|
|
262
|
+
v2 directive block — appended to the chapter prompt
|
|
263
|
+
</div>
|
|
264
|
+
<pre className="mt-1 max-h-52 overflow-auto whitespace-pre-wrap font-mono text-[10px] text-violet-900">{directive}</pre>
|
|
265
|
+
</div>
|
|
266
|
+
)}
|
|
267
|
+
</>
|
|
268
|
+
)}
|
|
269
|
+
</div>
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// ── 3. WORLD MAP ────────────────────────────────────────────────────────────
|
|
274
|
+
function WorldPanel({ places }: { places: WorldMapPlace[] }) {
|
|
275
|
+
if (!places.length) return <div className="text-[11px] text-zinc-400">Run the grid first.</div>;
|
|
276
|
+
return (
|
|
277
|
+
<div className="space-y-3">
|
|
278
|
+
<Sec icon="🗺" title="World Map — settings as contiguous local places" right={`${places.length} places`} />
|
|
279
|
+
<div className="grid gap-1.5 sm:grid-cols-2">
|
|
280
|
+
{places.map((p, i) => {
|
|
281
|
+
const liveN = p.residents.filter((r) => r.live).length;
|
|
282
|
+
return (
|
|
283
|
+
<div key={p.settingId} className="rounded-lg border border-zinc-200 bg-white p-2">
|
|
284
|
+
<div className="flex items-center justify-between">
|
|
285
|
+
<div className="text-[11px] font-bold text-zinc-900">{p.label}</div>
|
|
286
|
+
<Pill tone={liveN > 0 ? "emerald" : "zinc"}>{liveN}/{p.residents.length} live</Pill>
|
|
287
|
+
</div>
|
|
288
|
+
<div className="font-mono text-[9px] text-zinc-400">{p.settingId} · place {i + 1}</div>
|
|
289
|
+
<div className="mt-1 flex flex-wrap gap-1">
|
|
290
|
+
{p.residents.map((r) => (
|
|
291
|
+
<span key={r.id} className={`rounded px-1 py-0.5 text-[9px] ${r.live ? "bg-emerald-50 text-emerald-800" : "bg-zinc-50 text-zinc-400"}`}>
|
|
292
|
+
{r.kind === "agent" ? "👤" : r.kind === "institution" ? "🏛" : "🧵"} {r.id}
|
|
293
|
+
</span>
|
|
294
|
+
))}
|
|
295
|
+
</div>
|
|
296
|
+
<div className="mt-1 text-[9px] text-zinc-400">
|
|
297
|
+
borders: {p.adjacentSettings.join(", ") || "—"}
|
|
298
|
+
</div>
|
|
299
|
+
</div>
|
|
300
|
+
);
|
|
301
|
+
})}
|
|
302
|
+
</div>
|
|
303
|
+
</div>
|
|
304
|
+
);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// ── 4. CAST & RELATIONS ─────────────────────────────────────────────────────
|
|
308
|
+
function CastPanel({ run, cast, edges }: { run: GridRun | null; cast: ReturnType<typeof buildCastGraph>["cast"]; edges: ReturnType<typeof buildCastGraph>["edges"] }) {
|
|
309
|
+
const conf = useMemo(() => auditCastNameConfusion(cast.map((c) => c.name)), [cast]);
|
|
310
|
+
if (!cast.length) return <div className="text-[11px] text-zinc-400">Run the grid first.</div>;
|
|
311
|
+
const ids = cast.map((c) => c.id);
|
|
312
|
+
const adj = new Map<string, Set<string>>();
|
|
313
|
+
for (const e of edges) {
|
|
314
|
+
if (!adj.has(e.a)) adj.set(e.a, new Set());
|
|
315
|
+
if (!adj.has(e.b)) adj.set(e.b, new Set());
|
|
316
|
+
adj.get(e.a)!.add(e.b); adj.get(e.b)!.add(e.a);
|
|
317
|
+
}
|
|
318
|
+
return (
|
|
319
|
+
<div className="space-y-3">
|
|
320
|
+
<Sec icon="🕸" title="Cast & relationship graph" right={`${cast.length} cast · ${edges.length} edges`} />
|
|
321
|
+
<div className="grid gap-1.5 sm:grid-cols-2">
|
|
322
|
+
{cast.map((c) => (
|
|
323
|
+
<div key={c.id} className={`rounded-lg border p-2 ${c.live ? "border-emerald-200 bg-white" : "border-zinc-200 bg-zinc-50/60"}`}>
|
|
324
|
+
<div className="flex items-center justify-between gap-1">
|
|
325
|
+
<div className="min-w-0">
|
|
326
|
+
<div className="truncate text-[11px] font-bold text-zinc-900">{c.name}</div>
|
|
327
|
+
<div className="font-mono text-[9px] text-zinc-400">{c.id} · {c.kind} · deg {c.degree}</div>
|
|
328
|
+
</div>
|
|
329
|
+
<Pill tone={c.live ? "emerald" : "zinc"}>{c.live ? "live" : "cold"}</Pill>
|
|
330
|
+
</div>
|
|
331
|
+
{adj.get(c.id) && (
|
|
332
|
+
<div className="mt-1 flex flex-wrap gap-1">
|
|
333
|
+
{[...adj.get(c.id)!].map((n) => {
|
|
334
|
+
const other = cast.find((x) => x.id === n);
|
|
335
|
+
return <Pill key={n} tone="sky">{other?.name ?? n}</Pill>;
|
|
336
|
+
})}
|
|
337
|
+
</div>
|
|
338
|
+
)}
|
|
339
|
+
</div>
|
|
340
|
+
))}
|
|
341
|
+
</div>
|
|
342
|
+
|
|
343
|
+
{/* adjacency matrix */}
|
|
344
|
+
<div className="rounded-lg border border-zinc-100 bg-white p-2">
|
|
345
|
+
<div className="text-[10px] font-bold uppercase tracking-wider text-zinc-400">Adjacency matrix</div>
|
|
346
|
+
<div className="mt-1 overflow-x-auto">
|
|
347
|
+
<table className="text-[9px]">
|
|
348
|
+
<thead>
|
|
349
|
+
<tr>
|
|
350
|
+
<th />
|
|
351
|
+
{ids.map((i) => <th key={i} className="px-1 font-mono text-zinc-400">{i}</th>)}
|
|
352
|
+
</tr>
|
|
353
|
+
</thead>
|
|
354
|
+
<tbody>
|
|
355
|
+
{ids.map((r) => (
|
|
356
|
+
<tr key={r}>
|
|
357
|
+
<td className="pr-1 font-mono text-zinc-500">{r}</td>
|
|
358
|
+
{ids.map((c) => {
|
|
359
|
+
const on = adj.get(r)?.has(c) ?? false;
|
|
360
|
+
return (
|
|
361
|
+
<td key={c} className={`px-1 text-center ${on ? (r === c ? "text-zinc-300" : "bg-indigo-100 text-indigo-700") : "text-zinc-200"}`}>
|
|
362
|
+
{r === c ? "·" : on ? "●" : "·"}
|
|
363
|
+
</td>
|
|
364
|
+
);
|
|
365
|
+
})}
|
|
366
|
+
</tr>
|
|
367
|
+
))}
|
|
368
|
+
</tbody>
|
|
369
|
+
</table>
|
|
370
|
+
</div>
|
|
371
|
+
</div>
|
|
372
|
+
|
|
373
|
+
<div className={`rounded-lg border p-2 ${conf.length ? "border-amber-200 bg-amber-50/70" : "border-emerald-200 bg-emerald-50/70"}`}>
|
|
374
|
+
<div className={`text-[10px] font-bold uppercase tracking-wider ${conf.length ? "text-amber-800" : "text-emerald-700"}`}>
|
|
375
|
+
ONOMASTRATA cast-name confusion audit
|
|
376
|
+
</div>
|
|
377
|
+
{conf.length === 0
|
|
378
|
+
? <div className="text-[10px] text-emerald-800">No confusable name pairs detected.</div>
|
|
379
|
+
: <ul className="ml-4 list-disc text-[10px] text-amber-800">{conf.map((f) => <li key={f.a + f.b}>{f.a} ↔ {f.b}: {f.issue}</li>)}</ul>}
|
|
380
|
+
</div>
|
|
381
|
+
{run && (
|
|
382
|
+
<div className="text-[9px] italic text-zinc-400">
|
|
383
|
+
SAGA_CAST_LOAD window ≤15: current live cast {cast.filter((c) => c.live).length}.
|
|
384
|
+
</div>
|
|
385
|
+
)}
|
|
386
|
+
</div>
|
|
387
|
+
);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// ── 5. KALLOS ───────────────────────────────────────────────────────────────
|
|
391
|
+
function KallosPanel({ k }: { k: KallosReport | null }) {
|
|
392
|
+
if (!k) return <div className="text-[11px] text-zinc-400">Run the grid first.</div>;
|
|
393
|
+
return (
|
|
394
|
+
<div className="space-y-3">
|
|
395
|
+
<Sec icon="✨" title="KALLOS — deterministic beauty proxy" right={k.profile} />
|
|
396
|
+
<div className="rounded-lg border border-violet-100 bg-white p-2">
|
|
397
|
+
<div className="flex items-baseline gap-2">
|
|
398
|
+
<span className="text-2xl font-bold text-violet-800">{k.composite.toFixed(1)}</span>
|
|
399
|
+
<span className="text-[10px] text-zinc-400">/ 100 weighted geometric mean</span>
|
|
400
|
+
</div>
|
|
401
|
+
<div className="text-[10px] text-zinc-500">
|
|
402
|
+
weakest pillar: <b>{k.weakest?.label}</b> = {k.weakest?.score.toFixed(3)} — write to strengthen this specifically.
|
|
403
|
+
</div>
|
|
404
|
+
{k.alphaFit != null && (
|
|
405
|
+
<div className="mt-0.5 text-[10px] text-zinc-500">
|
|
406
|
+
spectral exponent α = <b>{k.alphaFit.toFixed(3)}</b> (1.0 = pink optimum; 0 = white, 2 = brown)
|
|
407
|
+
{k.lowN && <span className="ml-1 text-amber-700">· LOW-N window</span>}
|
|
408
|
+
</div>
|
|
409
|
+
)}
|
|
410
|
+
</div>
|
|
411
|
+
|
|
412
|
+
<div className="space-y-1 rounded-lg border border-zinc-100 bg-white p-2">
|
|
413
|
+
{k.pillars.map((p) => (
|
|
414
|
+
<div key={p.key}>
|
|
415
|
+
<Bar v={p.score} label={`${p.key} · ${p.label}`} />
|
|
416
|
+
<div className="ml-[132px] text-[9px] leading-tight text-zinc-400">
|
|
417
|
+
w={p.weight.toFixed(3)}{!p.measured && " · UNMEASURED (excluded, weights renormalized)"}{p.capped && " · ANTI-GAMING CAP"}
|
|
418
|
+
{p.measured && ` · ${p.detail}`}
|
|
419
|
+
</div>
|
|
420
|
+
</div>
|
|
421
|
+
))}
|
|
422
|
+
</div>
|
|
423
|
+
|
|
424
|
+
{k.antiGaming.length > 0 && (
|
|
425
|
+
<div className="rounded border border-amber-100 bg-amber-50/70 p-2">
|
|
426
|
+
<div className="text-[10px] font-bold uppercase tracking-wider text-amber-800">Anti-gaming / LOW-N notes</div>
|
|
427
|
+
<ul className="ml-4 list-disc text-[10px] text-amber-800">{k.antiGaming.map((a) => <li key={a}>{a}</li>)}</ul>
|
|
428
|
+
</div>
|
|
429
|
+
)}
|
|
430
|
+
|
|
431
|
+
<div className="rounded-lg border border-zinc-100 bg-white p-2">
|
|
432
|
+
<div className="text-[10px] font-bold uppercase tracking-wider text-zinc-400">K-AUD-001…006</div>
|
|
433
|
+
<div className="mt-1">{k.passes.map((p) => <AuditRow key={p.id} {...p} />)}</div>
|
|
434
|
+
</div>
|
|
435
|
+
|
|
436
|
+
<div className="rounded border border-rose-100 bg-rose-50/50 p-2 text-[10px] italic text-rose-800">{k.caveat}</div>
|
|
437
|
+
</div>
|
|
438
|
+
);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// ── 6. SAGA-WIRE ────────────────────────────────────────────────────────────
|
|
442
|
+
function WirePanel({ cov }: { cov: WireCoverageReport }) {
|
|
443
|
+
const [sel, setSel] = useState<SlotClassId | null>(null);
|
|
444
|
+
const rows = useMemo(() => (sel ? wireCatalog().filter((r) => r.slotClass === sel) : []), [sel]);
|
|
445
|
+
return (
|
|
446
|
+
<div className="space-y-3">
|
|
447
|
+
<Sec icon="🔌" title="SAGA-WIRE — total catalog binding" right={`${cov.wired}/${cov.totalRows} rows · 0 orphans`} />
|
|
448
|
+
<div className="flex flex-wrap gap-1">
|
|
449
|
+
{SLOT_CLASS_IDS.map((s) => (
|
|
450
|
+
<button key={s} onClick={() => setSel(sel === s ? null : s)}
|
|
451
|
+
className={`rounded px-1.5 py-0.5 text-[10px] font-semibold ${sel === s ? "bg-indigo-600 text-white" : "bg-zinc-100 text-zinc-700 hover:bg-zinc-200"}`}>
|
|
452
|
+
{s} · {cov.perSlot[s]}
|
|
453
|
+
</button>
|
|
454
|
+
))}
|
|
455
|
+
</div>
|
|
456
|
+
<div className="rounded-lg border border-zinc-100 bg-white p-2">
|
|
457
|
+
<div className="flex flex-wrap gap-2">
|
|
458
|
+
<Pill tone={cov.passes.WIRE001 ? "emerald" : "rose"}>WIRE-001 no orphans {cov.passes.WIRE001 ? "PASS" : "FAIL"}</Pill>
|
|
459
|
+
<Pill tone={cov.passes.WIRE002 ? "emerald" : "amber"}>WIRE-002 ≥20/slot {cov.passes.WIRE002 ? "PASS" : "THIN"}</Pill>
|
|
460
|
+
<Pill tone={cov.passes.WIRE003 ? "emerald" : "rose"}>WIRE-003 LAW harness {cov.passes.WIRE003 ? "PASS" : "FAIL"}</Pill>
|
|
461
|
+
</div>
|
|
462
|
+
{!cov.passes.WIRE002 && (
|
|
463
|
+
<div className="mt-1 text-[10px] text-amber-700">
|
|
464
|
+
THIN slots (honest gap, not a defect in wiring): {" "}
|
|
465
|
+
{SLOT_CLASS_IDS.filter((s) => cov.perSlot[s] < 20).map((s) => `${s}=${cov.perSlot[s]}`).join(", ")}.
|
|
466
|
+
The catalog itself has few ENDING / TWIST / DOCUMENT rows.
|
|
467
|
+
</div>
|
|
468
|
+
)}
|
|
469
|
+
</div>
|
|
470
|
+
{sel && (
|
|
471
|
+
<div className="rounded-lg border border-indigo-100 bg-white p-2">
|
|
472
|
+
<div className="text-[10px] font-bold uppercase tracking-wider text-indigo-700">
|
|
473
|
+
{sel} · {SLOT_CLASS_META[sel as SlotClassId].name} — {SLOT_CLASS_META[sel as SlotClassId].note} ({cov.perSlot[sel]} rows)
|
|
474
|
+
</div>
|
|
475
|
+
<div className="mt-1 max-h-64 overflow-y-auto">
|
|
476
|
+
<table className="w-full text-[10px]">
|
|
477
|
+
<tbody>
|
|
478
|
+
{rows.slice(0, 200).map((r) => (
|
|
479
|
+
<tr key={r.id} className="border-b border-zinc-50 last:border-0">
|
|
480
|
+
<td className="w-20 px-1 py-0.5 font-mono text-zinc-500">{r.id}</td>
|
|
481
|
+
<td className="px-1 py-0.5 font-semibold text-zinc-800">{r.name}</td>
|
|
482
|
+
<td className="w-14 px-1 py-0.5 font-mono text-[9px] text-amber-700">{r.stakesAxis}</td>
|
|
483
|
+
<td className="w-16 px-1 py-0.5 font-mono text-[9px] text-teal-700">{r.costAxis}</td>
|
|
484
|
+
<td className="w-12 px-1 py-0.5 text-right font-mono text-[9px] text-zinc-400">{r.rarity.toFixed(2)}</td>
|
|
485
|
+
</tr>
|
|
486
|
+
))}
|
|
487
|
+
</tbody>
|
|
488
|
+
</table>
|
|
489
|
+
</div>
|
|
490
|
+
<div className="mt-1 font-mono text-[9px] text-zinc-400">
|
|
491
|
+
columns: id · name · stakes axis · cost axis · rarity percentile
|
|
492
|
+
</div>
|
|
493
|
+
</div>
|
|
494
|
+
)}
|
|
495
|
+
</div>
|
|
496
|
+
);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
// ── 7. NAMES ────────────────────────────────────────────────────────────────
|
|
500
|
+
function NamesPanel({ seed }: { seed: number }) {
|
|
501
|
+
const [cls, setCls] = useState("PERSON");
|
|
502
|
+
const [n, setN] = useState(8);
|
|
503
|
+
const names = useMemo(() => generateOnoma(seed, cls, n), [seed, cls, n]);
|
|
504
|
+
const conf = useMemo(() => auditCastNameConfusion(names.map((x) => x.name)), [names]);
|
|
505
|
+
return (
|
|
506
|
+
<div className="space-y-3">
|
|
507
|
+
<Sec icon="📛" title="ONOMASTRATA name generator" right={`seed ${seed} · deterministic`} />
|
|
508
|
+
<div className="flex flex-wrap items-center gap-1">
|
|
509
|
+
<select value={cls} onChange={(e) => setCls(e.target.value)}
|
|
510
|
+
className="rounded border border-zinc-200 bg-white px-2 py-1 text-[11px]">
|
|
511
|
+
{ONOMA_GENERATABLE_CLASSES.map((c) => <option key={c} value={c}>{c}</option>)}
|
|
512
|
+
</select>
|
|
513
|
+
<label className="flex items-center gap-1 text-[10px] text-zinc-500">
|
|
514
|
+
count
|
|
515
|
+
<input type="number" min={1} max={40} value={n} onChange={(e) => setN(Math.max(1, Math.min(40, Number(e.target.value) || 1)))}
|
|
516
|
+
className="w-14 rounded border border-zinc-200 px-1.5 py-1 font-mono text-[11px]" />
|
|
517
|
+
</label>
|
|
518
|
+
</div>
|
|
519
|
+
<div className="rounded-lg border border-zinc-100 bg-white p-2">
|
|
520
|
+
<div className="flex flex-wrap gap-1">
|
|
521
|
+
{names.map((x) => <Pill key={x.name} tone="indigo">{x.name}</Pill>)}
|
|
522
|
+
</div>
|
|
523
|
+
{conf.length > 0 && (
|
|
524
|
+
<div className="mt-1 text-[10px] text-amber-700">
|
|
525
|
+
⚠ confusable pairs: {conf.map((f) => `${f.a} ↔ ${f.b}`).join("; ")}
|
|
526
|
+
</div>
|
|
527
|
+
)}
|
|
528
|
+
<div className="mt-1 font-mono text-[9px] text-zinc-400">
|
|
529
|
+
same (seed, class) always yields the same names — no corpus, no network.
|
|
530
|
+
</div>
|
|
531
|
+
</div>
|
|
532
|
+
</div>
|
|
533
|
+
);
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
// ── main ────────────────────────────────────────────────────────────────────
|
|
537
|
+
export function SagaOsV2Panel() {
|
|
538
|
+
const [open, setOpen] = useState(true);
|
|
539
|
+
const [tab, setTab] = useState<Tab>("helm");
|
|
540
|
+
const [spec, setSpec] = useState<GenreSpec | null>(null);
|
|
541
|
+
const [run, setRun] = useState<GridRun | null>(null);
|
|
542
|
+
const [kallos, setKallos] = useState<KallosReport | null>(null);
|
|
543
|
+
const [ms, setMs] = useState<ModalShortcutReport | null>(null);
|
|
544
|
+
const [directive, setDirective] = useState("");
|
|
545
|
+
|
|
546
|
+
const cov = useMemo(() => auditWireCoverage(), []);
|
|
547
|
+
const places = useMemo(() => (run ? buildWorldMap(run) : []), [run]);
|
|
548
|
+
const castGraph = useMemo(() => (run ? buildCastGraph(run) : { cast: [], edges: [] }), [run]);
|
|
549
|
+
|
|
550
|
+
const onRun = useCallback((seed: number, budget: number) => {
|
|
551
|
+
const s = spec ?? compileGenreSpec("a scary quiet literary thriller, 3 book series");
|
|
552
|
+
if (!spec) setSpec(s);
|
|
553
|
+
const r = runGenesisGrid({ seed, spec: s, budget });
|
|
554
|
+
const k = computeKallos({ run: r, profile: s.kallosProfile });
|
|
555
|
+
const block = buildSagaOsV2DirectiveBlock(r, k);
|
|
556
|
+
setRun(r); setKallos(k); setMs(modalShortcutTest(r));
|
|
557
|
+
setDirective(block);
|
|
558
|
+
}, [spec]);
|
|
559
|
+
|
|
560
|
+
return (
|
|
561
|
+
<section className="rounded-xl border border-zinc-200 bg-zinc-50/80">
|
|
562
|
+
<button onClick={() => setOpen(!open)} className="flex w-full items-center justify-between px-4 py-2.5 text-left">
|
|
563
|
+
<div className="flex items-center gap-2">
|
|
564
|
+
<span className="text-base">🧬</span>
|
|
565
|
+
<span className="text-xs font-bold uppercase tracking-wider text-zinc-700">SAGA-OS v2 Engines</span>
|
|
566
|
+
<span className="rounded bg-violet-100 px-1.5 py-0.5 font-mono text-[10px] text-violet-700">
|
|
567
|
+
SAGA-WIRE · GENRE HELM · GENESIS-GRID · KALLOS
|
|
568
|
+
</span>
|
|
569
|
+
{run && <span className="font-mono text-[10px] text-zinc-400">{run.pattern} → {run.endingFamily}</span>}
|
|
570
|
+
</div>
|
|
571
|
+
<span className="text-zinc-400">{open ? "▾" : "▸"}</span>
|
|
572
|
+
</button>
|
|
573
|
+
{open && (
|
|
574
|
+
<div className="border-t border-zinc-200 px-4 py-3">
|
|
575
|
+
<div className="mb-3 flex flex-wrap gap-1">
|
|
576
|
+
{TABS.map((t) => (
|
|
577
|
+
<button key={t.id} onClick={() => setTab(t.id)}
|
|
578
|
+
className={`rounded-md px-2 py-1 text-[11px] font-semibold ${tab === t.id ? "bg-indigo-600 text-white" : "bg-zinc-100 text-zinc-600 hover:bg-zinc-200"}`}>
|
|
579
|
+
{t.icon} {t.label}
|
|
580
|
+
</button>
|
|
581
|
+
))}
|
|
582
|
+
</div>
|
|
583
|
+
{tab === "helm" && <HelmPanel spec={spec} onCompile={setSpec} />}
|
|
584
|
+
{tab === "grid" && <GridPanel run={run} onRun={onRun} ms={ms} directive={directive} />}
|
|
585
|
+
{tab === "world" && <WorldPanel places={places} />}
|
|
586
|
+
{tab === "cast" && <CastPanel run={run} cast={castGraph.cast} edges={castGraph.edges} />}
|
|
587
|
+
{tab === "kallos" && <KallosPanel k={kallos} />}
|
|
588
|
+
{tab === "wire" && <WirePanel cov={cov} />}
|
|
589
|
+
{tab === "names" && <NamesPanel seed={run?.seed ?? 12345} />}
|
|
590
|
+
</div>
|
|
591
|
+
)}
|
|
592
|
+
</section>
|
|
593
|
+
);
|
|
594
|
+
}
|