@mindrian_os/install 1.13.0-beta.11
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/.claude-plugin/plugin.json +21 -0
- package/.mcp.json +9 -0
- package/CHANGELOG.md +3333 -0
- package/LICENSE +123 -0
- package/README.md +673 -0
- package/agents/brain-query.md +80 -0
- package/agents/framework-runner.md +237 -0
- package/agents/grading.md +188 -0
- package/agents/investor.md +128 -0
- package/agents/larry-extended.md +135 -0
- package/agents/opportunity-scanner.md +91 -0
- package/agents/persona-analyst.md +132 -0
- package/agents/research.md +89 -0
- package/agents/reverse-salient-agent.md +27 -0
- package/bin/cli.js +142 -0
- package/bin/mindrian-mcp-server.cjs +182 -0
- package/bin/mindrian-tools.cjs +765 -0
- package/commands/act.md +439 -0
- package/commands/admin.md +404 -0
- package/commands/analyze-needs.md +42 -0
- package/commands/analyze-systems.md +39 -0
- package/commands/analyze-timing.md +42 -0
- package/commands/auto-explore.md +64 -0
- package/commands/beautiful-question.md +40 -0
- package/commands/brain-derive.md +78 -0
- package/commands/build-knowledge.md +42 -0
- package/commands/build-thesis.md +46 -0
- package/commands/causal.md +234 -0
- package/commands/challenge-assumptions.md +33 -0
- package/commands/compare-ventures.md +83 -0
- package/commands/dashboard.md +110 -0
- package/commands/deep-grade.md +82 -0
- package/commands/diagnose.md +58 -0
- package/commands/diagnostics.md +151 -0
- package/commands/doctor.md +151 -0
- package/commands/dominant-designs.md +40 -0
- package/commands/explain-decision.md +87 -0
- package/commands/explore-domains.md +42 -0
- package/commands/explore-futures.md +40 -0
- package/commands/explore-trends.md +42 -0
- package/commands/export.md +103 -0
- package/commands/file-meeting.md +724 -0
- package/commands/find-analogies.md +188 -0
- package/commands/find-bottlenecks.md +62 -0
- package/commands/find-connections.md +76 -0
- package/commands/funding.md +81 -0
- package/commands/grade.md +203 -0
- package/commands/graph.md +128 -0
- package/commands/hat-briefing.md +125 -0
- package/commands/heal.md +196 -0
- package/commands/help.md +399 -0
- package/commands/hmi-status.md +172 -0
- package/commands/jtbd.md +241 -0
- package/commands/leadership.md +73 -0
- package/commands/lean-canvas.md +40 -0
- package/commands/macro-trends.md +40 -0
- package/commands/map-unknowns.md +40 -0
- package/commands/memory.md +173 -0
- package/commands/models.md +175 -0
- package/commands/mos-reason.md +285 -0
- package/commands/mullins.md +120 -0
- package/commands/new-project.md +481 -0
- package/commands/onboard.md +434 -0
- package/commands/operator.md +149 -0
- package/commands/opportunities.md +144 -0
- package/commands/organize.md +497 -0
- package/commands/persona.md +198 -0
- package/commands/pipeline.md +112 -0
- package/commands/present.md +91 -0
- package/commands/publish.md +201 -0
- package/commands/query.md +124 -0
- package/commands/radar.md +72 -0
- package/commands/reanalyze.md +91 -0
- package/commands/research.md +196 -0
- package/commands/room.md +352 -0
- package/commands/rooms.md +598 -0
- package/commands/root-cause.md +40 -0
- package/commands/rs-experts.md +85 -0
- package/commands/rs-explain.md +100 -0
- package/commands/rs-fetch.md +94 -0
- package/commands/rs-thesis.md +85 -0
- package/commands/scenario-plan.md +40 -0
- package/commands/scheduled-tasks.md +285 -0
- package/commands/score-innovation.md +43 -0
- package/commands/scout.md +239 -0
- package/commands/setup.md +618 -0
- package/commands/snapshot.md +147 -0
- package/commands/speakers.md +84 -0
- package/commands/splash.md +28 -0
- package/commands/status.md +75 -0
- package/commands/structure-argument.md +42 -0
- package/commands/suggest-next.md +80 -0
- package/commands/systems-thinking.md +40 -0
- package/commands/think-hats.md +42 -0
- package/commands/update.md +181 -0
- package/commands/user-needs.md +40 -0
- package/commands/validate.md +40 -0
- package/commands/value-proposition.md +61 -0
- package/commands/vault.md +180 -0
- package/commands/visualize.md +52 -0
- package/commands/whitespace.md +507 -0
- package/commands/wiki.md +69 -0
- package/hooks/hooks.json +381 -0
- package/hooks/run-hook.cmd +64 -0
- package/lib/__init__.py +0 -0
- package/lib/__pycache__/__init__.cpython-312.pyc +0 -0
- package/lib/agents/auto-explore-agent.cjs +1043 -0
- package/lib/agents/reverse-salient-agent.cjs +679 -0
- package/lib/agents/tension-hook-agent.cjs +544 -0
- package/lib/brain/ROOM.md +44 -0
- package/lib/brain/chain-recommender.cjs +301 -0
- package/lib/chat/chat-context.js +185 -0
- package/lib/chat/chat-panel.js +721 -0
- package/lib/chat/fabric-chat.cjs +288 -0
- package/lib/chat/generative-tools.js +219 -0
- package/lib/conversation/ROOM.md +39 -0
- package/lib/conversation/classifier-rules.json +38 -0
- package/lib/conversation/classifier.cjs +264 -0
- package/lib/conversation/operator.cjs +287 -0
- package/lib/copy/115-spec-strings.cjs +55 -0
- package/lib/core/__init__.py +0 -0
- package/lib/core/__nav-stub.cjs +14 -0
- package/lib/core/__pycache__/__init__.cpython-312.pyc +0 -0
- package/lib/core/__pycache__/rs-math.cpython-312.pyc +0 -0
- package/lib/core/__pycache__/rs_cache.cpython-312.pyc +0 -0
- package/lib/core/__pycache__/rs_corpus.cpython-312.pyc +0 -0
- package/lib/core/__pycache__/rs_hybrid.cpython-312.pyc +0 -0
- package/lib/core/__pycache__/rs_math.cpython-312.pyc +0 -0
- package/lib/core/__pycache__/rs_rooms.cpython-312.pyc +0 -0
- package/lib/core/artifact-id.cjs +148 -0
- package/lib/core/asset-ops.cjs +151 -0
- package/lib/core/auto-commit-throttle.cjs +129 -0
- package/lib/core/bearer-token.cjs +199 -0
- package/lib/core/brain-client.cjs +865 -0
- package/lib/core/brain-derivation-prompts.cjs +326 -0
- package/lib/core/brain-derivation-queue.cjs +431 -0
- package/lib/core/brain-derivation.cjs +580 -0
- package/lib/core/brain-md-schema.cjs +528 -0
- package/lib/core/brain-md-staleness.cjs +357 -0
- package/lib/core/brain-response-sanitize.cjs +188 -0
- package/lib/core/bridge-writer.cjs +477 -0
- package/lib/core/chat-context-builder.cjs +253 -0
- package/lib/core/cross-room-aggregator.cjs +762 -0
- package/lib/core/daily-briefing.cjs +438 -0
- package/lib/core/decision-capture.cjs +618 -0
- package/lib/core/deep-links.cjs +82 -0
- package/lib/core/dispatch-optimizer.cjs +354 -0
- package/lib/core/dual-path-detector.cjs +84 -0
- package/lib/core/dual-path-detector.test.cjs +334 -0
- package/lib/core/exports-log.cjs +79 -0
- package/lib/core/feynman-minto-invariants.cjs +605 -0
- package/lib/core/folder-memory-async.cjs +338 -0
- package/lib/core/folder-memory-shared.cjs +890 -0
- package/lib/core/folder-memory.cjs +416 -0
- package/lib/core/framework-chain-composer.cjs +411 -0
- package/lib/core/frontmatter-schemas.cjs +330 -0
- package/lib/core/git-ops.cjs +141 -0
- package/lib/core/graph-ops.cjs +258 -0
- package/lib/core/hat-persistence.cjs +362 -0
- package/lib/core/index.cjs +60 -0
- package/lib/core/integration-registry.cjs +232 -0
- package/lib/core/intelligence-cascade.cjs +661 -0
- package/lib/core/lazygraph-ops.cjs +1057 -0
- package/lib/core/lru-cache.cjs +139 -0
- package/lib/core/mcp-profiles.cjs +182 -0
- package/lib/core/meeting-ops.cjs +54 -0
- package/lib/core/memory-ops.cjs +600 -0
- package/lib/core/migrations/ROOM.md +33 -0
- package/lib/core/migrations/phase-109-nodes-provenance.cjs +339 -0
- package/lib/core/migrations/phase-109-session-focus.cjs +99 -0
- package/lib/core/model-profiles.cjs +246 -0
- package/lib/core/mullins-scaffold.cjs +160 -0
- package/lib/core/nav-dial.cjs +316 -0
- package/lib/core/navigation/ROOM.md +15 -0
- package/lib/core/navigation/explanation.cjs +43 -0
- package/lib/core/navigation/focus.cjs +135 -0
- package/lib/core/navigation/ingestion.cjs +82 -0
- package/lib/core/navigation/insights.cjs +350 -0
- package/lib/core/navigation/memory-events.cjs +118 -0
- package/lib/core/navigation/neighborhood.cjs +78 -0
- package/lib/core/navigation/packet.cjs +182 -0
- package/lib/core/navigation/room-home.cjs +127 -0
- package/lib/core/navigation/transitions.cjs +82 -0
- package/lib/core/navigation-engine-shared.cjs +242 -0
- package/lib/core/navigation-engine.cjs +664 -0
- package/lib/core/navigation.cjs +60 -0
- package/lib/core/nl-graph-queries.cjs +164 -0
- package/lib/core/offer-presenter.cjs +406 -0
- package/lib/core/opportunity-extractor.cjs +183 -0
- package/lib/core/opportunity-ops.cjs +1371 -0
- package/lib/core/persona-ops.cjs +537 -0
- package/lib/core/persona-taxonomy.cjs +190 -0
- package/lib/core/platform-gates.cjs +120 -0
- package/lib/core/platform.cjs +257 -0
- package/lib/core/proactive-intelligence.cjs +528 -0
- package/lib/core/problem-type-router.cjs +315 -0
- package/lib/core/reasoning-ops.cjs +639 -0
- package/lib/core/reverse-salient-persona-suffix.cjs +115 -0
- package/lib/core/room-classifier-strict-mode.cjs +229 -0
- package/lib/core/room-db.cjs +127 -0
- package/lib/core/room-ops-async.cjs +92 -0
- package/lib/core/room-ops-shared.cjs +64 -0
- package/lib/core/room-ops-sync.cjs +70 -0
- package/lib/core/room-ops.cjs +32 -0
- package/lib/core/room-type-detector.cjs +386 -0
- package/lib/core/rs-brain-substrate-prompts.cjs +129 -0
- package/lib/core/rs-brain-substrate.cjs +570 -0
- package/lib/core/rs-breakthrough-scorer.cjs +255 -0
- package/lib/core/rs-canon-violations.cjs +82 -0
- package/lib/core/rs-chain-feeder.cjs +343 -0
- package/lib/core/rs-commercial-assessor.cjs +280 -0
- package/lib/core/rs-differential-scorer.cjs +376 -0
- package/lib/core/rs-domain-analyzer.cjs +385 -0
- package/lib/core/rs-egress-prompts.cjs +113 -0
- package/lib/core/rs-egress-telemetry.cjs +225 -0
- package/lib/core/rs-egress-violations.cjs +53 -0
- package/lib/core/rs-expert-mapper.cjs +467 -0
- package/lib/core/rs-fetcher-academic.cjs +697 -0
- package/lib/core/rs-fetcher-experts.cjs +314 -0
- package/lib/core/rs-fetcher-industry.cjs +731 -0
- package/lib/core/rs-fetcher-patents.cjs +564 -0
- package/lib/core/rs-innovation-classifier.cjs +194 -0
- package/lib/core/rs-mind-map.cjs +656 -0
- package/lib/core/rs-neo4j-writer.cjs +388 -0
- package/lib/core/rs-nl-to-query.cjs +425 -0
- package/lib/core/rs-pinecone-bridge.cjs +303 -0
- package/lib/core/rs-preprocessor.cjs +350 -0
- package/lib/core/rs-query-matrix.cjs +316 -0
- package/lib/core/rs-query-to-text.cjs +438 -0
- package/lib/core/rs-sqlite-mirror.cjs +443 -0
- package/lib/core/rs-thesis-generator.cjs +188 -0
- package/lib/core/rs_cache.py +479 -0
- package/lib/core/rs_corpus.py +468 -0
- package/lib/core/rs_hybrid.py +586 -0
- package/lib/core/rs_math.py +287 -0
- package/lib/core/rs_rooms.py +193 -0
- package/lib/core/scheduled-scanner.cjs +463 -0
- package/lib/core/scratchpad-ops.cjs +201 -0
- package/lib/core/section-8-trace-schema.cjs +138 -0
- package/lib/core/section-registry.cjs +111 -0
- package/lib/core/session-state.cjs +144 -0
- package/lib/core/shallow-doc-parser.cjs +174 -0
- package/lib/core/shallow-doc-parser.test.cjs +226 -0
- package/lib/core/skill-activation-router.cjs +284 -0
- package/lib/core/state-ops.cjs +46 -0
- package/lib/core/statusline-cache.cjs +266 -0
- package/lib/core/token-estimator.cjs +348 -0
- package/lib/core/user-archetype.cjs +239 -0
- package/lib/core/user-md-ops.cjs +524 -0
- package/lib/core/visual-ops.cjs +624 -0
- package/lib/core/write-lock.cjs +149 -0
- package/lib/graph/canvas-graph.js +467 -0
- package/lib/graph/constellation-config.cjs +299 -0
- package/lib/graph/graph-detail-panel.js +165 -0
- package/lib/hmi/ROOM.md +47 -0
- package/lib/hmi/across-session-memory.cjs +604 -0
- package/lib/hmi/cross-room-memory.cjs +575 -0
- package/lib/hmi/decoy-tier.cjs +395 -0
- package/lib/hmi/jtbd-classifier.cjs +219 -0
- package/lib/hmi/jtbd-state.cjs +199 -0
- package/lib/hmi/jtbd-taxonomy.json +392 -0
- package/lib/hmi/selector-dispatcher.cjs +546 -0
- package/lib/hmi/selector-telemetry.cjs +263 -0
- package/lib/hmi/shape-f0-renderer.cjs +139 -0
- package/lib/hmi/shape-f1-fallback.cjs +80 -0
- package/lib/hmi/shape-f1-renderer.cjs +138 -0
- package/lib/hmi/shape-f2-renderer.cjs +132 -0
- package/lib/hmi/shape-f3-renderer.cjs +66 -0
- package/lib/hmi/shape-f4-renderer.cjs +72 -0
- package/lib/hmi/shape-f5-renderer.cjs +155 -0
- package/lib/hmi/shape-f6-plan-review-renderer.cjs +312 -0
- package/lib/hmi/shape-f6-renderer.cjs +144 -0
- package/lib/hmi/shape-g-renderer.cjs +219 -0
- package/lib/hmi/shape-h-renderer.cjs +222 -0
- package/lib/hmi/tier-check.cjs +63 -0
- package/lib/import/PRECONDITIONS.md +41 -0
- package/lib/import/branding.cjs +210 -0
- package/lib/import/branding.test.cjs +235 -0
- package/lib/import/classifications-sync.cjs +104 -0
- package/lib/import/classifications-sync.test.cjs +129 -0
- package/lib/import/enricher.cjs +296 -0
- package/lib/import/enricher.test.cjs +273 -0
- package/lib/import/integration.test.cjs +376 -0
- package/lib/import/manifest.cjs +129 -0
- package/lib/import/manifest.schema.json +185 -0
- package/lib/import/manifest.test.cjs +123 -0
- package/lib/import/meeting-detector.cjs +92 -0
- package/lib/import/meeting-detector.test.cjs +100 -0
- package/lib/import/person-detector.cjs +229 -0
- package/lib/import/person-detector.test.cjs +149 -0
- package/lib/import/report.cjs +186 -0
- package/lib/import/report.test.cjs +186 -0
- package/lib/import/room-md-scaffolder.cjs +49 -0
- package/lib/import/router.cjs +224 -0
- package/lib/import/router.test.cjs +356 -0
- package/lib/import/run-all-tests.cjs +36 -0
- package/lib/import/smoke-test.cjs +213 -0
- package/lib/import/smoke-test.test.cjs +148 -0
- package/lib/import/test-fixtures/collision-vault/preexisting-room/STATE.md +8 -0
- package/lib/import/test-fixtures/collision-vault/preexisting-room/problem-definition/onboarding/onboarding.md +7 -0
- package/lib/import/test-fixtures/collision-vault/source/onboarding.md +5 -0
- package/lib/import/test-fixtures/obsidian-vault/.obsidian/workspace.json +1 -0
- package/lib/import/test-fixtures/obsidian-vault/notes/with-wikilinks.md +4 -0
- package/lib/import/test-fixtures/tiny-vault/notes/2026-01-15-team-sync.md +9 -0
- package/lib/import/test-fixtures/tiny-vault/notes/empty.md +3 -0
- package/lib/import/test-fixtures/tiny-vault/notes/onboarding.md +5 -0
- package/lib/import/test-fixtures/tiny-vault/notes/pricing.md +5 -0
- package/lib/import/test-fixtures/tiny-vault/notes/random.md +4 -0
- package/lib/import/undo.test.cjs +199 -0
- package/lib/import/vault-scanner.cjs +105 -0
- package/lib/import/vault-scanner.test.cjs +67 -0
- package/lib/mcp/app-html/dashboard.html +316 -0
- package/lib/mcp/app-html/graph.html +428 -0
- package/lib/mcp/app-html/mindrian-platform.html +1841 -0
- package/lib/mcp/app-html/wiki.html +383 -0
- package/lib/mcp/app-views.cjs +322 -0
- package/lib/mcp/brain-router.cjs +418 -0
- package/lib/mcp/capability-registry.cjs +62 -0
- package/lib/mcp/larry-context.cjs +46 -0
- package/lib/mcp/larry-server-instructions.md +114 -0
- package/lib/mcp/pipeline-state.cjs +275 -0
- package/lib/mcp/prompts.cjs +302 -0
- package/lib/mcp/resources.cjs +227 -0
- package/lib/mcp/session-catchup.cjs +327 -0
- package/lib/mcp/surface-detect.cjs +75 -0
- package/lib/mcp/tool-router.cjs +1034 -0
- package/lib/memory/aaak-compress.cjs +403 -0
- package/lib/memory/aaak-compress.test.cjs +288 -0
- package/lib/memory/async-artifact-auto-commit.test.cjs +223 -0
- package/lib/memory/bearer-token.test.cjs +315 -0
- package/lib/memory/brain-cache-lru.test.cjs +259 -0
- package/lib/memory/brain-client-query-shape.test.cjs +160 -0
- package/lib/memory/brain-derivation-graceful-degradation.test.cjs +1019 -0
- package/lib/memory/brain-derivation-queue.test.cjs +539 -0
- package/lib/memory/brain-derivation.test.cjs +634 -0
- package/lib/memory/brain-derive-command.test.cjs +534 -0
- package/lib/memory/brain-md-invariants-validator.test.cjs +704 -0
- package/lib/memory/brain-md-schema.test.cjs +467 -0
- package/lib/memory/brain-md-staleness.test.cjs +525 -0
- package/lib/memory/brain-server-resolution.test.cjs +314 -0
- package/lib/memory/chain-recommender.test.cjs +233 -0
- package/lib/memory/chat-context.test.cjs +128 -0
- package/lib/memory/command-registry.test.cjs +220 -0
- package/lib/memory/cross-room-aggregator.test.cjs +909 -0
- package/lib/memory/dashboard-server.test.cjs +256 -0
- package/lib/memory/debouncer-drain-at-prompt.test.cjs +389 -0
- package/lib/memory/decision-capture.test.cjs +632 -0
- package/lib/memory/decision-capture.worker.cjs +70 -0
- package/lib/memory/explain-decision-command.test.cjs +521 -0
- package/lib/memory/explain-decision-footer.test.cjs +316 -0
- package/lib/memory/explored-materials-store.cjs +392 -0
- package/lib/memory/feynman-minto-guardian.test.cjs +736 -0
- package/lib/memory/feynman-minto-invariants.test.cjs +511 -0
- package/lib/memory/feynman-prompts-drift.test.cjs +144 -0
- package/lib/memory/feynman-prompts.cjs +151 -0
- package/lib/memory/feynman-prompts.test.cjs +96 -0
- package/lib/memory/folder-memory-quadruple.test.cjs +548 -0
- package/lib/memory/folder-memory.test.cjs +503 -0
- package/lib/memory/framework-chain-composer.test.cjs +515 -0
- package/lib/memory/frontmatter-schema-validator.test.cjs +290 -0
- package/lib/memory/heal-command.test.cjs +604 -0
- package/lib/memory/index-artifact-transaction.test.cjs +333 -0
- package/lib/memory/lazygraph-rs-discoveries-view.test.cjs +122 -0
- package/lib/memory/mcp-input-validation.test.cjs +240 -0
- package/lib/memory/mcp-server-brain-deps.test.cjs +270 -0
- package/lib/memory/mcp-stack-fallback.test.cjs +433 -0
- package/lib/memory/minto-debouncer.test.cjs +407 -0
- package/lib/memory/minto-debouncer.worker.cjs +46 -0
- package/lib/memory/minto-migration-v88.test.cjs +265 -0
- package/lib/memory/minto-schema-v88.test.cjs +390 -0
- package/lib/memory/mos-status-renderer.test.cjs +631 -0
- package/lib/memory/narrative-schema.cjs +376 -0
- package/lib/memory/narrative-schema.test.cjs +209 -0
- package/lib/memory/nav-dial.test.cjs +414 -0
- package/lib/memory/navigation-engine-core.test.cjs +722 -0
- package/lib/memory/navigation-invariants.test.cjs +483 -0
- package/lib/memory/offer-presenter.test.cjs +554 -0
- package/lib/memory/on-stop-snapshot.test.cjs +404 -0
- package/lib/memory/pending-tension-store.cjs +373 -0
- package/lib/memory/post-compact-reinjection.test.cjs +854 -0
- package/lib/memory/post-write-triple.test.cjs +317 -0
- package/lib/memory/pre-compact-snapshot.test.cjs +495 -0
- package/lib/memory/problem-type-router.test.cjs +656 -0
- package/lib/memory/query-efficiency-telemetry.test.cjs +370 -0
- package/lib/memory/recompile-room-references.test.cjs +392 -0
- package/lib/memory/recompile-room-references.worker.cjs +42 -0
- package/lib/memory/record-decision-dual-write.test.cjs +454 -0
- package/lib/memory/room-classifier-strict-mode.test.cjs +417 -0
- package/lib/memory/room-minto-hook.test.cjs +398 -0
- package/lib/memory/rs-discovery-engine.test.cjs +323 -0
- package/lib/memory/run-feynman-tests.cjs +1247 -0
- package/lib/memory/security-trifecta.test.cjs +312 -0
- package/lib/memory/session-start-brain-staleness.test.cjs +363 -0
- package/lib/memory/session-start-triple-injection.test.cjs +514 -0
- package/lib/memory/sessionstart-banner-formatter.cjs +318 -0
- package/lib/memory/sessionstart-minto-banner.test.cjs +373 -0
- package/lib/memory/skill-activation-router.test.cjs +419 -0
- package/lib/memory/stamp-artifact-write.test.cjs +304 -0
- package/lib/memory/statusline-active-room.test.cjs +315 -0
- package/lib/memory/statusline-minto-segment.test.cjs +292 -0
- package/lib/memory/sync-async-entry-points.test.cjs +204 -0
- package/lib/memory/test-bridge-writer-enhanced.cjs +452 -0
- package/lib/memory/test-rs-brain-substrate-shape.cjs +529 -0
- package/lib/memory/test-rs-brain-substrate.cjs +636 -0
- package/lib/memory/test-rs-breakthrough-scorer.cjs +375 -0
- package/lib/memory/test-rs-canon-violations.cjs +218 -0
- package/lib/memory/test-rs-chain-feeder-core.cjs +344 -0
- package/lib/memory/test-rs-chain-feeder-skill-spawn.cjs +297 -0
- package/lib/memory/test-rs-commercial-assessor.cjs +385 -0
- package/lib/memory/test-rs-differential-scorer.cjs +480 -0
- package/lib/memory/test-rs-discovery-engine.cjs +603 -0
- package/lib/memory/test-rs-domain-analyzer.cjs +492 -0
- package/lib/memory/test-rs-egress-primitives.cjs +420 -0
- package/lib/memory/test-rs-expert-mapper.cjs +547 -0
- package/lib/memory/test-rs-explain-command.cjs +443 -0
- package/lib/memory/test-rs-fetcher-academic.cjs +848 -0
- package/lib/memory/test-rs-fetcher-experts.cjs +496 -0
- package/lib/memory/test-rs-fetcher-industry.cjs +702 -0
- package/lib/memory/test-rs-fetcher-patents.cjs +674 -0
- package/lib/memory/test-rs-innovation-classifier.cjs +301 -0
- package/lib/memory/test-rs-mind-map.cjs +646 -0
- package/lib/memory/test-rs-neo4j-writer.cjs +518 -0
- package/lib/memory/test-rs-nl-to-query.cjs +449 -0
- package/lib/memory/test-rs-pinecone-bridge.cjs +277 -0
- package/lib/memory/test-rs-preprocessor.cjs +433 -0
- package/lib/memory/test-rs-query-matrix.cjs +391 -0
- package/lib/memory/test-rs-query-to-text.cjs +551 -0
- package/lib/memory/test-rs-sqlite-mirror.cjs +649 -0
- package/lib/memory/test-rs-thesis-generator.cjs +360 -0
- package/lib/memory/triple-context-formatter.cjs +473 -0
- package/lib/memory/triple-context-formatter.test.cjs +442 -0
- package/lib/memory/user-md-persona.test.cjs +565 -0
- package/lib/memory/userpromptsubmit-integration.test.cjs +690 -0
- package/lib/memory/validators/README.md +157 -0
- package/lib/memory/validators/brain-md-invariants.cjs +475 -0
- package/lib/memory/validators/brain-substrate-invariants.cjs +285 -0
- package/lib/memory/validators/external-academic-invariants.cjs +249 -0
- package/lib/memory/validators/external-industry-invariants.cjs +271 -0
- package/lib/memory/validators/external-patents-invariants.cjs +266 -0
- package/lib/memory/validators/minto-invariants.cjs +62 -0
- package/lib/memory/validators/navigation-invariants.cjs +340 -0
- package/lib/memory/validators/queue-health.cjs +95 -0
- package/lib/memory/validators/snapshot-integrity.cjs +129 -0
- package/lib/memory/validators/stale-lifecycle.cjs +116 -0
- package/lib/memory/vault-section-minto-generator-atomic.test.cjs +556 -0
- package/lib/memory/vault-section-minto-generator-atomic.worker.cjs +73 -0
- package/lib/memory/write-lock-atomic.test.cjs +137 -0
- package/lib/memory/write-lock-atomic.worker.cjs +55 -0
- package/lib/parity/check-parity.cjs +83 -0
- package/lib/presentation/presentation-server.cjs +101 -0
- package/lib/presentation/presentation-watcher.cjs +123 -0
- package/lib/quickview/hub-server.cjs +719 -0
- package/lib/quickview/server.cjs +533 -0
- package/lib/render/JTBD-PALETTES.md +145 -0
- package/lib/render/ROOM.md +59 -0
- package/lib/render/render-v2.cjs +486 -0
- package/lib/render/render-v2.test.cjs +267 -0
- package/lib/render/render.cjs +65 -0
- package/lib/state/ROOM.md +46 -0
- package/lib/state/state-md-parser.cjs +215 -0
- package/lib/statusline/ROOM.md +38 -0
- package/lib/statusline/banner-suppression.cjs +50 -0
- package/lib/statusline/surface-detect.cjs +85 -0
- package/lib/update-bootstrap.sh.template +145 -0
- package/lib/vault/frontmatter-schema.cjs +297 -0
- package/lib/vault/room-scanner.cjs +352 -0
- package/lib/vault/wikilink-builder.cjs +231 -0
- package/lib/vault/wikilink-builder.test.cjs +182 -0
- package/lib/wiki/graph-links.cjs +281 -0
- package/lib/wiki/page-renderer.cjs +229 -0
- package/lib/wiki/wiki-chat.cjs +81 -0
- package/lib/wiki/wiki-layout.cjs +1459 -0
- package/lib/wiki/wiki-search.cjs +142 -0
- package/lib/wiki/wiki-server.cjs +678 -0
- package/lib/wiki/wiki-watcher.cjs +105 -0
- package/lib/workflow/ROOM.md +47 -0
- package/lib/workflow/command-resolver.cjs +155 -0
- package/lib/workflow/command-resolver.test.cjs +235 -0
- package/package.json +44 -0
- package/pipelines/analogy/01-decompose.md +80 -0
- package/pipelines/analogy/02-abstract.md +87 -0
- package/pipelines/analogy/03-search.md +135 -0
- package/pipelines/analogy/04-transfer.md +101 -0
- package/pipelines/analogy/05-validate.md +106 -0
- package/pipelines/analogy/CHAIN.md +56 -0
- package/pipelines/discovery/01-explore-domains.md +44 -0
- package/pipelines/discovery/02-think-hats.md +50 -0
- package/pipelines/discovery/03-analyze-needs.md +54 -0
- package/pipelines/discovery/CHAIN.md +37 -0
- package/pipelines/thesis/01-structure-argument.md +45 -0
- package/pipelines/thesis/02-challenge-assumptions.md +48 -0
- package/pipelines/thesis/03-build-thesis.md +54 -0
- package/pipelines/thesis/CHAIN.md +37 -0
- package/references/brain/causal-directives.md +91 -0
- package/references/brain/causal-enrichment.cypher +165 -0
- package/references/brain/command-triggers-schema.md +226 -0
- package/references/brain/graph-architecture.md +317 -0
- package/references/brain/query-patterns.md +460 -0
- package/references/brain/room-hierarchy-schema.md +218 -0
- package/references/brain/schema.md +76 -0
- package/references/capability-radar/capabilities-index.md +241 -0
- package/references/capability-radar/changelog-cache.md +81 -0
- package/references/causal/causal-schema.md +103 -0
- package/references/design/email-template-standard.md +155 -0
- package/references/design/graph-visualization-standard.md +178 -0
- package/references/document-generation.md +179 -0
- package/references/hsi/HSI-TOOLS-REFERENCE.md +222 -0
- package/references/import-config.md +141 -0
- package/references/integrations/detection-patterns.md +101 -0
- package/references/meeting/artifact-template.md +377 -0
- package/references/meeting/cross-meeting-intelligence.md +216 -0
- package/references/meeting/cross-relationship-patterns.md +202 -0
- package/references/meeting/live-join-interface.md +244 -0
- package/references/meeting/section-mapping.md +192 -0
- package/references/meeting/segment-classification.md +258 -0
- package/references/meeting/speaker-profile-template.md +219 -0
- package/references/meeting/summary-template.md +348 -0
- package/references/meeting/transcript-patterns.md +226 -0
- package/references/methodology/analyze-needs.md +135 -0
- package/references/methodology/analyze-systems.md +121 -0
- package/references/methodology/analyze-timing.md +149 -0
- package/references/methodology/beautiful-question.md +109 -0
- package/references/methodology/build-knowledge.md +161 -0
- package/references/methodology/build-thesis.md +237 -0
- package/references/methodology/challenge-assumptions.md +127 -0
- package/references/methodology/diagnose.md +169 -0
- package/references/methodology/dominant-designs.md +212 -0
- package/references/methodology/explore-domains.md +147 -0
- package/references/methodology/explore-futures.md +163 -0
- package/references/methodology/explore-trends.md +129 -0
- package/references/methodology/find-bottlenecks.md +131 -0
- package/references/methodology/grade.md +211 -0
- package/references/methodology/index.md +97 -0
- package/references/methodology/leadership.md +200 -0
- package/references/methodology/lean-canvas.md +116 -0
- package/references/methodology/macro-trends.md +192 -0
- package/references/methodology/map-unknowns.md +137 -0
- package/references/methodology/mullins-7-domains.md +104 -0
- package/references/methodology/problem-types.md +65 -0
- package/references/methodology/root-cause.md +178 -0
- package/references/methodology/sapphire-encoding.md +355 -0
- package/references/methodology/scenario-plan.md +178 -0
- package/references/methodology/score-innovation.md +154 -0
- package/references/methodology/structure-argument.md +158 -0
- package/references/methodology/systems-thinking.md +159 -0
- package/references/methodology/think-hats.md +147 -0
- package/references/methodology/triz-matrix.json +751 -0
- package/references/methodology/triz-principles.md +501 -0
- package/references/methodology/user-needs.md +199 -0
- package/references/methodology/validate.md +163 -0
- package/references/methodology/value-proposition.md +244 -0
- package/references/opportunities/funding-lifecycle.md +103 -0
- package/references/opportunities/grant-api-patterns.md +99 -0
- package/references/opportunities/opportunity-template.md +84 -0
- package/references/personality/assessment-philosophy.md +72 -0
- package/references/personality/lexicon.md +100 -0
- package/references/personality/persona-chains.md +56 -0
- package/references/personality/pws-lexicon-full.md +499 -0
- package/references/personality/voice-dna.md +156 -0
- package/references/personas/hat-perspectives.md +76 -0
- package/references/personas/persona-template.md +63 -0
- package/references/pipeline/act-output-contract.md +88 -0
- package/references/pipeline/chains-index.md +39 -0
- package/references/pws-profile-generation.md +79 -0
- package/references/reasoning/reasoning-schema.md +143 -0
- package/references/reasoning/reasoning-template.md +68 -0
- package/references/reasoning/run-template.md +38 -0
- package/references/research/RESEARCH_14_CLAUDE_CODE_SOURCE_ARCHITECTURE.md +209 -0
- package/references/research/RESEARCH_15_V1.8_OPTIMIZATION_JTBD.md +375 -0
- package/references/research/RESEARCH_16_NATIVE_FIRST_PLUGIN_ARCHITECTURE.md +575 -0
- package/references/research/RESEARCH_17_MCP_UI_FRAMEWORKS.md +272 -0
- package/references/taxonomy/TAXONOMY.md +192 -0
- package/references/templates/MINTO.md +36 -0
- package/references/user-research/2026-04-05-leah-lawrence-session.md +202 -0
- package/references/vault-kit/README.md +35 -0
- package/references/vault-kit/app.json +12 -0
- package/references/vault-kit/appearance.json +12 -0
- package/references/vault-kit/graph.json +35 -0
- package/references/vault-kit/snippets/mindrian-destijl.css +297 -0
- package/references/vault-kit/templates/new-artifact.md +37 -0
- package/references/vault-kit/templates/new-meeting-note.md +35 -0
- package/references/vault-kit/templates/new-team-profile.md +29 -0
- package/references/vault-kit/templates/new-xref.md +35 -0
- package/references/visual/symbol-system.md +151 -0
- package/skills/MOSDeckEngine/SKILL.md +325 -0
- package/skills/brain-connector/SKILL.md +114 -0
- package/skills/context-engine/SKILL.md +147 -0
- package/skills/conversation-mode/SKILL.md +102 -0
- package/skills/larry-personality/SKILL.md +219 -0
- package/skills/larry-personality/framework-chains.md +92 -0
- package/skills/larry-personality/mode-engine.md +185 -0
- package/skills/mullins-scaffold/SKILL.md +61 -0
- package/skills/mullins-scaffold/scaffold.json +146 -0
- package/skills/pws-methodology/SKILL.md +49 -0
- package/skills/room-passive/SKILL.md +165 -0
- package/skills/room-proactive/SKILL.md +250 -0
- package/skills/ui-system/SKILL.md +277 -0
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026 Mindrian. BSL 1.1.
|
|
3
|
+
* Phase 89.1a Plan 02 -- Brain methodology substrate invariants validator.
|
|
4
|
+
*
|
|
5
|
+
* Registry-compatible drop-in for the Phase 88-13 guardian. Auto-
|
|
6
|
+
* discovered by scripts/feynman-minto-guardian.cjs's validator loader
|
|
7
|
+
* (walks lib/memory/validators/*.cjs). Zero guardian.cjs edits needed.
|
|
8
|
+
*
|
|
9
|
+
* Contract (see lib/memory/validators/README.md):
|
|
10
|
+
* module.exports = {
|
|
11
|
+
* id: 'brain-substrate-invariants',
|
|
12
|
+
* severity_map: { critical, error, warning, info },
|
|
13
|
+
* scope: 'room',
|
|
14
|
+
* validate(roomPath, ctx) -> { severity, violations[] },
|
|
15
|
+
* }
|
|
16
|
+
*
|
|
17
|
+
* Five checks:
|
|
18
|
+
* A) Cache missing -> zero violations (valid default)
|
|
19
|
+
* B) Cache unreadable / malformed / schema_version drift -> warning
|
|
20
|
+
* C) Cache substrate.length != embedding_count -> critical (partial pull, Pitfall 5)
|
|
21
|
+
* D) Cache substrate[].metadata body contains forbidden regex hit -> critical
|
|
22
|
+
* (Canon Part 8 attack surface; Pitfall 4)
|
|
23
|
+
* E) Cache substrate[] entry shape -> critical (cache_entry_shape_invalid)
|
|
24
|
+
* Phase 89.1 Plan 01 relaxation: each entry MUST carry EITHER a 1024-dim
|
|
25
|
+
* finite-Float embedding (legacy/mocked path) OR a Pinecone score in
|
|
26
|
+
* [0,1] (live brain_search wire path). Neither present is critical;
|
|
27
|
+
* both present is allowed. id must match SLUG_REGEX OR the permissive
|
|
28
|
+
* Pinecone ID regex [a-zA-Z0-9_:-]{1,512}.
|
|
29
|
+
*
|
|
30
|
+
* Fail-open: unexpected throws are caught by the guardian's validator
|
|
31
|
+
* runner. This validator does not swallow its own exceptions; the
|
|
32
|
+
* guardian owns that contract. Individual I/O paths (readFileSync) are
|
|
33
|
+
* wrapped defensively so a missing cache never produces a violation.
|
|
34
|
+
*
|
|
35
|
+
* Pure CJS, node built-ins only + re-export of prompts module for
|
|
36
|
+
* FORBIDDEN_PATTERNS + SLUG_REGEX parity. Importing the canonical
|
|
37
|
+
* vocabulary (rather than redefining) ensures any Canon Part 8
|
|
38
|
+
* amendment at lib/core/cross-room-aggregator.cjs propagates through
|
|
39
|
+
* lib/core/rs-brain-substrate-prompts.cjs to this validator with zero
|
|
40
|
+
* code change.
|
|
41
|
+
*/
|
|
42
|
+
'use strict';
|
|
43
|
+
|
|
44
|
+
const fs = require('node:fs');
|
|
45
|
+
const path = require('node:path');
|
|
46
|
+
|
|
47
|
+
const prompts = require('../../core/rs-brain-substrate-prompts.cjs');
|
|
48
|
+
const { FORBIDDEN_PATTERNS, SLUG_REGEX } = prompts;
|
|
49
|
+
|
|
50
|
+
// ---------- Constants ----------
|
|
51
|
+
|
|
52
|
+
const SEVERITY_MAP = Object.freeze({ critical: 3, error: 2, warning: 1, info: 0 });
|
|
53
|
+
const EXPECTED_EMBEDDING_DIM = 1024;
|
|
54
|
+
const CACHE_SCHEMA_VERSION = '1.0';
|
|
55
|
+
// Cap canon_boundary hits per validate() invocation so one poisoned
|
|
56
|
+
// cache cannot spam the invariant report. Five matches is the same
|
|
57
|
+
// threshold Plan 90-05 brain-md-invariants uses.
|
|
58
|
+
const MAX_CANON_HITS_REPORTED = 5;
|
|
59
|
+
|
|
60
|
+
// ---------- Severity aggregator ----------
|
|
61
|
+
|
|
62
|
+
function aggregateSeverity(violations) {
|
|
63
|
+
if (!violations || violations.length === 0) return null;
|
|
64
|
+
let max = 0;
|
|
65
|
+
const inv = { 0: 'info', 1: 'warning', 2: 'error', 3: 'critical' };
|
|
66
|
+
for (const v of violations) {
|
|
67
|
+
const s = SEVERITY_MAP[v.severity];
|
|
68
|
+
if (typeof s === 'number' && s > max) max = s;
|
|
69
|
+
}
|
|
70
|
+
return inv[max];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ---------- validate (Checks A-E) ----------
|
|
74
|
+
|
|
75
|
+
function validate(roomPath, _ctx) {
|
|
76
|
+
const violations = [];
|
|
77
|
+
|
|
78
|
+
// Defensive guard: non-string roomPath -> zero violations (guardian
|
|
79
|
+
// always passes a string, but the contract demands a structured
|
|
80
|
+
// result on every path).
|
|
81
|
+
if (typeof roomPath !== 'string' || roomPath.length === 0) {
|
|
82
|
+
return { severity: null, violations: [] };
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const cachePath = path.join(roomPath, '.mindrian', 'brain-substrate-cache.json');
|
|
86
|
+
|
|
87
|
+
// --- Check A: cache absent -> zero violations (healthy default) ---
|
|
88
|
+
if (!fs.existsSync(cachePath)) {
|
|
89
|
+
return { severity: null, violations: [] };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// --- Check B: unreadable / malformed / schema drift ---
|
|
93
|
+
let payload = null;
|
|
94
|
+
try {
|
|
95
|
+
const raw = fs.readFileSync(cachePath, 'utf8');
|
|
96
|
+
payload = JSON.parse(raw);
|
|
97
|
+
} catch (err) {
|
|
98
|
+
violations.push({
|
|
99
|
+
category: 'cache_unreadable',
|
|
100
|
+
severity: 'warning',
|
|
101
|
+
message: 'brain-substrate-cache.json unreadable: ' + String(err && err.message),
|
|
102
|
+
action_hint: 'invalidate_cache',
|
|
103
|
+
});
|
|
104
|
+
return { severity: aggregateSeverity(violations), violations };
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {
|
|
108
|
+
violations.push({
|
|
109
|
+
category: 'cache_malformed_root',
|
|
110
|
+
severity: 'warning',
|
|
111
|
+
message: 'brain-substrate-cache.json root is not a plain object',
|
|
112
|
+
action_hint: 'invalidate_cache',
|
|
113
|
+
});
|
|
114
|
+
return { severity: aggregateSeverity(violations), violations };
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (payload.schema_version !== CACHE_SCHEMA_VERSION) {
|
|
118
|
+
violations.push({
|
|
119
|
+
category: 'cache_schema_drift',
|
|
120
|
+
severity: 'warning',
|
|
121
|
+
message: 'schema_version expected ' + CACHE_SCHEMA_VERSION +
|
|
122
|
+
' got ' + String(payload.schema_version),
|
|
123
|
+
action_hint: 'invalidate_cache',
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (!Array.isArray(payload.substrate)) {
|
|
128
|
+
violations.push({
|
|
129
|
+
category: 'cache_malformed_substrate',
|
|
130
|
+
severity: 'critical',
|
|
131
|
+
message: 'substrate is not an array',
|
|
132
|
+
action_hint: 'invalidate_cache',
|
|
133
|
+
});
|
|
134
|
+
return { severity: aggregateSeverity(violations), violations };
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// --- Check C: completeness (embedding_count vs substrate.length) ---
|
|
138
|
+
// Pitfall 5 partial-pull completeness guard. Defense-in-depth against
|
|
139
|
+
// the reader-side check in lib/core/rs-brain-substrate.cjs readCache;
|
|
140
|
+
// either layer alone blocks a partial cache.
|
|
141
|
+
if (typeof payload.embedding_count === 'number' &&
|
|
142
|
+
payload.substrate.length !== payload.embedding_count) {
|
|
143
|
+
violations.push({
|
|
144
|
+
category: 'cache_partial_pull',
|
|
145
|
+
severity: 'critical',
|
|
146
|
+
message: 'embedding_count ' + payload.embedding_count +
|
|
147
|
+
' != substrate.length ' + payload.substrate.length,
|
|
148
|
+
action_hint: 'invalidate_cache',
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// --- Checks D + E: per-entry body scan + shape assertion ---
|
|
153
|
+
//
|
|
154
|
+
// Phase 89.1 Plan 01 relaxation: Check E now accepts entries with EITHER a
|
|
155
|
+
// 1024-dim Float embedding (legacy/mocked path; 89.1a-03 fixtures) OR a
|
|
156
|
+
// Pinecone score in [0,1] (live brain_search wire path; searchRecords does
|
|
157
|
+
// not return values today). Entry MUST carry at least one of the two; if
|
|
158
|
+
// neither is present that is a critical cache_entry_shape_invalid.
|
|
159
|
+
//
|
|
160
|
+
// Pinecone IDs (e.g. 'mindrian-knowledge_t2-trending-absurd_2cddc6ac2cf58ea0')
|
|
161
|
+
// exceed the 64-char SLUG_REGEX limit on the prompts module. The slug check
|
|
162
|
+
// here is a permissive fallback: accept [a-zA-Z0-9_:-]{1,512} per Pinecone
|
|
163
|
+
// ID rules (https://docs.pinecone.io/), which is wider than SLUG_REGEX but
|
|
164
|
+
// still bounded and forbids whitespace + arbitrary unicode.
|
|
165
|
+
const PINECONE_ID_REGEX = /^[a-zA-Z0-9_:-]{1,512}$/;
|
|
166
|
+
let canonHitCount = 0;
|
|
167
|
+
for (let i = 0; i < payload.substrate.length; i += 1) {
|
|
168
|
+
const entry = payload.substrate[i];
|
|
169
|
+
if (!entry || typeof entry !== 'object' || Array.isArray(entry)) {
|
|
170
|
+
violations.push({
|
|
171
|
+
category: 'cache_entry_shape_invalid',
|
|
172
|
+
severity: 'critical',
|
|
173
|
+
message: 'substrate[' + i + '] is not an object',
|
|
174
|
+
action_hint: 'invalidate_cache',
|
|
175
|
+
});
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Check E.1: id slug. Accept SLUG_REGEX OR permissive Pinecone ID regex.
|
|
180
|
+
if (typeof entry.id !== 'string' ||
|
|
181
|
+
(!SLUG_REGEX.test(entry.id) && !PINECONE_ID_REGEX.test(entry.id))) {
|
|
182
|
+
violations.push({
|
|
183
|
+
category: 'cache_entry_shape_invalid',
|
|
184
|
+
severity: 'critical',
|
|
185
|
+
message: 'substrate[' + i + '].id fails id regex: ' +
|
|
186
|
+
String(entry.id).slice(0, 80),
|
|
187
|
+
field: 'substrate[' + i + '].id',
|
|
188
|
+
action_hint: 'invalidate_cache',
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Check E.2 + E.3 + E.4: embedding-or-score required.
|
|
193
|
+
// hasEmbedding: legacy/mocked 1024-dim path
|
|
194
|
+
// hasScore: live brain_search Pinecone score path
|
|
195
|
+
// Neither -> critical (cache_entry_shape_invalid).
|
|
196
|
+
const hasEmbedding = Array.isArray(entry.embedding);
|
|
197
|
+
const hasScore = typeof entry.score === 'number';
|
|
198
|
+
if (!hasEmbedding && !hasScore) {
|
|
199
|
+
violations.push({
|
|
200
|
+
category: 'cache_entry_shape_invalid',
|
|
201
|
+
severity: 'critical',
|
|
202
|
+
message: 'substrate[' + i + '] missing both embedding[] and score',
|
|
203
|
+
field: 'substrate[' + i + ']',
|
|
204
|
+
action_hint: 'invalidate_cache',
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
if (hasEmbedding) {
|
|
208
|
+
if (entry.embedding.length !== EXPECTED_EMBEDDING_DIM) {
|
|
209
|
+
violations.push({
|
|
210
|
+
category: 'cache_entry_shape_invalid',
|
|
211
|
+
severity: 'critical',
|
|
212
|
+
message: 'substrate[' + i + '].embedding.length expected ' +
|
|
213
|
+
EXPECTED_EMBEDDING_DIM + ' got ' + entry.embedding.length,
|
|
214
|
+
field: 'substrate[' + i + '].embedding',
|
|
215
|
+
action_hint: 'invalidate_cache',
|
|
216
|
+
});
|
|
217
|
+
} else {
|
|
218
|
+
// Embedding must be all finite numbers.
|
|
219
|
+
for (let j = 0; j < entry.embedding.length; j += 1) {
|
|
220
|
+
const val = entry.embedding[j];
|
|
221
|
+
if (typeof val !== 'number' || !Number.isFinite(val)) {
|
|
222
|
+
violations.push({
|
|
223
|
+
category: 'cache_entry_shape_invalid',
|
|
224
|
+
severity: 'critical',
|
|
225
|
+
message: 'substrate[' + i + '].embedding[' + j + '] non-finite',
|
|
226
|
+
field: 'substrate[' + i + '].embedding[' + j + ']',
|
|
227
|
+
action_hint: 'invalidate_cache',
|
|
228
|
+
});
|
|
229
|
+
break; // one report per entry is enough
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
if (hasScore) {
|
|
235
|
+
if (!Number.isFinite(entry.score) || entry.score < 0 || entry.score > 1) {
|
|
236
|
+
violations.push({
|
|
237
|
+
category: 'cache_entry_shape_invalid',
|
|
238
|
+
severity: 'critical',
|
|
239
|
+
message: 'substrate[' + i + '].score out of [0,1]: ' + String(entry.score),
|
|
240
|
+
field: 'substrate[' + i + '].score',
|
|
241
|
+
action_hint: 'invalidate_cache',
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Check D: Canon Part 8 metadata body scan (Pitfall 4 attack surface).
|
|
247
|
+
// JSON.stringify the metadata so nested strings are visible to
|
|
248
|
+
// FORBIDDEN_PATTERNS. Cap at MAX_CANON_HITS_REPORTED overall to
|
|
249
|
+
// avoid report spam from a fully-poisoned cache.
|
|
250
|
+
if (canonHitCount < MAX_CANON_HITS_REPORTED &&
|
|
251
|
+
entry.metadata && typeof entry.metadata === 'object') {
|
|
252
|
+
const s = JSON.stringify(entry.metadata);
|
|
253
|
+
for (const re of FORBIDDEN_PATTERNS) {
|
|
254
|
+
if (re.test(s)) {
|
|
255
|
+
violations.push({
|
|
256
|
+
category: 'canon_boundary',
|
|
257
|
+
severity: 'critical',
|
|
258
|
+
message: 'substrate[' + i + '].metadata matched forbidden regex ' +
|
|
259
|
+
re.source,
|
|
260
|
+
field: 'substrate[' + i + '].metadata',
|
|
261
|
+
action_hint: 'invalidate_cache',
|
|
262
|
+
});
|
|
263
|
+
canonHitCount += 1;
|
|
264
|
+
break; // one match per entry is enough to fail the entry
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
return { severity: aggregateSeverity(violations), violations };
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// ---------- Exports ----------
|
|
274
|
+
|
|
275
|
+
module.exports = {
|
|
276
|
+
id: 'brain-substrate-invariants',
|
|
277
|
+
severity_map: SEVERITY_MAP,
|
|
278
|
+
scope: 'room',
|
|
279
|
+
validate,
|
|
280
|
+
// Exported for downstream introspection + Phase 89.1a Plan 03
|
|
281
|
+
// adversarial fixture suite. Not required by the registry loader.
|
|
282
|
+
EXPECTED_EMBEDDING_DIM,
|
|
283
|
+
CACHE_SCHEMA_VERSION,
|
|
284
|
+
MAX_CANON_HITS_REPORTED,
|
|
285
|
+
};
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026 Mindrian. BSL 1.1.
|
|
3
|
+
* Phase 89.2 Plan 02 -- External academic fetcher invariants validator.
|
|
4
|
+
*
|
|
5
|
+
* Registry-compatible drop-in for the Phase 88-13 guardian. Auto-discovered
|
|
6
|
+
* by scripts/feynman-minto-guardian.cjs's validator loader (walks
|
|
7
|
+
* lib/memory/validators/*.cjs). Zero guardian.cjs edits needed.
|
|
8
|
+
*
|
|
9
|
+
* Mirrors brain-substrate-invariants.cjs structure byte-for-byte. The one
|
|
10
|
+
* difference is scope: external-papers.json telemetry lives at the GLOBAL
|
|
11
|
+
* per-user path ~/.mindrian/telemetry/external-papers.json (NOT per-room),
|
|
12
|
+
* so this validator declares scope='global'. The guardian still invokes it
|
|
13
|
+
* once per pass; roomPath is ignored.
|
|
14
|
+
*
|
|
15
|
+
* Six checks (Checks A-F):
|
|
16
|
+
* A) Telemetry file absent -> {severity: null} (healthy default)
|
|
17
|
+
* B) Per-source budget exceeded in rolling 24h -> warning per source
|
|
18
|
+
* C) status enum membership -> warning per entry
|
|
19
|
+
* Allowed statuses: ok | rate_limited | api_error | network_error |
|
|
20
|
+
* timeout | api_key_missing
|
|
21
|
+
* D) Canon Part 8 audit: query_text literal -> CRITICAL canon_boundary
|
|
22
|
+
* The telemetry primitive guarantees query_text NEVER persists
|
|
23
|
+
* (only query_text_hash). If a literal query_text field ever
|
|
24
|
+
* appears, that is a Canon Part 8 breach by definition.
|
|
25
|
+
* E) query_text_hash format -> warning
|
|
26
|
+
* Must match /^[a-f0-9]{16}$/ (sha256 16-char hex prefix).
|
|
27
|
+
* F) fetched_at parseable as ISO-8601 -> warning
|
|
28
|
+
*
|
|
29
|
+
* Fail-open: unexpected throws are caught by the guardian's validator
|
|
30
|
+
* runner. This validator does not swallow its own exceptions; the
|
|
31
|
+
* guardian owns that contract. Individual I/O paths (readFileSync) are
|
|
32
|
+
* wrapped defensively so a missing telemetry file never produces a
|
|
33
|
+
* violation.
|
|
34
|
+
*
|
|
35
|
+
* Pure CJS, node built-ins only + the rs-egress-telemetry primitive
|
|
36
|
+
* shipped in Plan 89.2-01 for TELEMETRY_FILE + DEFAULT_BUDGETS + WINDOW_MS.
|
|
37
|
+
*/
|
|
38
|
+
'use strict';
|
|
39
|
+
|
|
40
|
+
const fs = require('node:fs');
|
|
41
|
+
|
|
42
|
+
const {
|
|
43
|
+
TELEMETRY_FILE,
|
|
44
|
+
DEFAULT_BUDGETS,
|
|
45
|
+
WINDOW_MS,
|
|
46
|
+
} = require('../../core/rs-egress-telemetry.cjs');
|
|
47
|
+
|
|
48
|
+
// ---------- Constants ----------
|
|
49
|
+
|
|
50
|
+
const SEVERITY_MAP = Object.freeze({ critical: 3, error: 2, warning: 1, info: 0 });
|
|
51
|
+
|
|
52
|
+
// Mirrors lib/core/rs-egress-telemetry.cjs ALLOWED_STATUSES set. Kept in
|
|
53
|
+
// sync by parity gate (any drift fails an invariant scenario downstream).
|
|
54
|
+
const ALLOWED_STATUSES = Object.freeze(new Set([
|
|
55
|
+
'ok',
|
|
56
|
+
'rate_limited',
|
|
57
|
+
'api_error',
|
|
58
|
+
'network_error',
|
|
59
|
+
'timeout',
|
|
60
|
+
'api_key_missing',
|
|
61
|
+
]));
|
|
62
|
+
|
|
63
|
+
// 16-char lowercase hex. sha256 prefix. Must match
|
|
64
|
+
// rs-egress-telemetry.cjs::hashQueryText output shape.
|
|
65
|
+
const CANON_PART_8_HASH_REGEX = /^[a-f0-9]{16}$/;
|
|
66
|
+
|
|
67
|
+
// Cap canon_boundary hits per validate() invocation so one poisoned
|
|
68
|
+
// ledger cannot spam the invariant report. Mirrors brain-substrate
|
|
69
|
+
// invariants and Plan 90-05 brain-md-invariants threshold.
|
|
70
|
+
const MAX_CANON_HITS_REPORTED = 5;
|
|
71
|
+
|
|
72
|
+
// Cap warning-class violations to bound report size on a fully-corrupt
|
|
73
|
+
// ledger. Critical hits are not capped (Check D never exceeds
|
|
74
|
+
// MAX_CANON_HITS_REPORTED on its own).
|
|
75
|
+
const MAX_WARNINGS_REPORTED = 25;
|
|
76
|
+
|
|
77
|
+
// ---------- Severity aggregator ----------
|
|
78
|
+
|
|
79
|
+
function aggregateSeverity(violations) {
|
|
80
|
+
if (!violations || violations.length === 0) return null;
|
|
81
|
+
let max = 0;
|
|
82
|
+
const inv = { 0: 'info', 1: 'warning', 2: 'error', 3: 'critical' };
|
|
83
|
+
for (const v of violations) {
|
|
84
|
+
const s = SEVERITY_MAP[v.severity];
|
|
85
|
+
if (typeof s === 'number' && s > max) max = s;
|
|
86
|
+
}
|
|
87
|
+
return inv[max];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// ---------- validate (Checks A-F) ----------
|
|
91
|
+
//
|
|
92
|
+
// scope='global'; roomPath is ignored (telemetry is per-user, not per-room).
|
|
93
|
+
// ctx is unused but accepted to match the validator contract.
|
|
94
|
+
|
|
95
|
+
function validate(_roomPath, _ctx) {
|
|
96
|
+
const violations = [];
|
|
97
|
+
|
|
98
|
+
// ---- Check A: telemetry file absent -> healthy default ----
|
|
99
|
+
if (!fs.existsSync(TELEMETRY_FILE)) {
|
|
100
|
+
return { severity: null, violations: [] };
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Read + parse defensively. A malformed ledger is a warning (not
|
|
104
|
+
// critical) because the telemetry primitive treats malformed payloads
|
|
105
|
+
// as cold-start; budgets just reset rather than crashing the fetcher.
|
|
106
|
+
let payload = null;
|
|
107
|
+
try {
|
|
108
|
+
const raw = fs.readFileSync(TELEMETRY_FILE, 'utf8');
|
|
109
|
+
payload = JSON.parse(raw);
|
|
110
|
+
} catch (err) {
|
|
111
|
+
violations.push({
|
|
112
|
+
validator: 'external-academic-invariants',
|
|
113
|
+
category: 'telemetry_unreadable',
|
|
114
|
+
severity: 'warning',
|
|
115
|
+
message: 'external-papers.json unreadable: ' + String(err && err.message),
|
|
116
|
+
action_hint: 'invalidate_telemetry',
|
|
117
|
+
});
|
|
118
|
+
return { severity: aggregateSeverity(violations), violations };
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (!payload || typeof payload !== 'object' || !Array.isArray(payload.entries)) {
|
|
122
|
+
violations.push({
|
|
123
|
+
validator: 'external-academic-invariants',
|
|
124
|
+
category: 'telemetry_malformed_root',
|
|
125
|
+
severity: 'warning',
|
|
126
|
+
message: 'external-papers.json root is not a plain object with entries[]',
|
|
127
|
+
action_hint: 'invalidate_telemetry',
|
|
128
|
+
});
|
|
129
|
+
return { severity: aggregateSeverity(violations), violations };
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// ---- Check B: per-source budget exceeded in rolling 24h ----
|
|
133
|
+
// Aggregate counts per source within the rolling window, then compare
|
|
134
|
+
// against DEFAULT_BUDGETS. One warning per over-budget source so the
|
|
135
|
+
// operator sees which surface is the contention point.
|
|
136
|
+
const now = Date.now();
|
|
137
|
+
const sourceCounts = {};
|
|
138
|
+
for (const entry of payload.entries) {
|
|
139
|
+
if (!entry || typeof entry !== 'object') continue;
|
|
140
|
+
if (typeof entry.source !== 'string') continue;
|
|
141
|
+
if (typeof entry.fetched_at !== 'string') continue;
|
|
142
|
+
const t = Date.parse(entry.fetched_at);
|
|
143
|
+
if (Number.isNaN(t)) continue;
|
|
144
|
+
if ((now - t) > WINDOW_MS) continue;
|
|
145
|
+
sourceCounts[entry.source] = (sourceCounts[entry.source] || 0) + 1;
|
|
146
|
+
}
|
|
147
|
+
for (const source of Object.keys(sourceCounts)) {
|
|
148
|
+
const cap = DEFAULT_BUDGETS[source];
|
|
149
|
+
if (typeof cap === 'number' && sourceCounts[source] > cap) {
|
|
150
|
+
violations.push({
|
|
151
|
+
validator: 'external-academic-invariants',
|
|
152
|
+
category: 'budget_exceeded',
|
|
153
|
+
severity: 'warning',
|
|
154
|
+
message: 'source ' + source + ' has ' + sourceCounts[source] +
|
|
155
|
+
' calls in last 24h; budget cap ' + cap,
|
|
156
|
+
field: 'entries[].source=' + source,
|
|
157
|
+
action_hint: 'rotate_budget',
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// ---- Checks C / D / E / F: per-entry scans ----
|
|
163
|
+
let canonHitCount = 0;
|
|
164
|
+
let warningCount = 0;
|
|
165
|
+
for (let i = 0; i < payload.entries.length; i += 1) {
|
|
166
|
+
const entry = payload.entries[i];
|
|
167
|
+
if (!entry || typeof entry !== 'object') continue;
|
|
168
|
+
|
|
169
|
+
// ---- Check D: canon_boundary literal query_text presence ----
|
|
170
|
+
// The telemetry primitive guarantees query_text NEVER persists. If
|
|
171
|
+
// any entry carries the field at all, that is a Canon Part 8 breach.
|
|
172
|
+
if (Object.prototype.hasOwnProperty.call(entry, 'query_text')
|
|
173
|
+
&& canonHitCount < MAX_CANON_HITS_REPORTED) {
|
|
174
|
+
violations.push({
|
|
175
|
+
validator: 'external-academic-invariants',
|
|
176
|
+
category: 'canon_boundary',
|
|
177
|
+
severity: 'critical',
|
|
178
|
+
message: 'entries[' + i + '] carries literal query_text (Canon Part 8 breach)',
|
|
179
|
+
field: 'entries[' + i + '].query_text',
|
|
180
|
+
action_hint: 'purge_telemetry',
|
|
181
|
+
});
|
|
182
|
+
canonHitCount += 1;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// ---- Check C: status enum membership ----
|
|
186
|
+
if (typeof entry.status === 'string' && !ALLOWED_STATUSES.has(entry.status)
|
|
187
|
+
&& warningCount < MAX_WARNINGS_REPORTED) {
|
|
188
|
+
violations.push({
|
|
189
|
+
validator: 'external-academic-invariants',
|
|
190
|
+
category: 'status_enum_violation',
|
|
191
|
+
severity: 'warning',
|
|
192
|
+
message: 'entries[' + i + '].status is not in allowed set: ' +
|
|
193
|
+
String(entry.status).slice(0, 40),
|
|
194
|
+
field: 'entries[' + i + '].status',
|
|
195
|
+
action_hint: 'invalidate_telemetry',
|
|
196
|
+
});
|
|
197
|
+
warningCount += 1;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// ---- Check E: query_text_hash format ----
|
|
201
|
+
if (typeof entry.query_text_hash === 'string'
|
|
202
|
+
&& !CANON_PART_8_HASH_REGEX.test(entry.query_text_hash)
|
|
203
|
+
&& warningCount < MAX_WARNINGS_REPORTED) {
|
|
204
|
+
violations.push({
|
|
205
|
+
validator: 'external-academic-invariants',
|
|
206
|
+
category: 'hash_format_invalid',
|
|
207
|
+
severity: 'warning',
|
|
208
|
+
message: 'entries[' + i + '].query_text_hash fails /^[a-f0-9]{16}$/: ' +
|
|
209
|
+
String(entry.query_text_hash).slice(0, 40),
|
|
210
|
+
field: 'entries[' + i + '].query_text_hash',
|
|
211
|
+
action_hint: 'invalidate_telemetry',
|
|
212
|
+
});
|
|
213
|
+
warningCount += 1;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// ---- Check F: fetched_at parseable as ISO-8601 ----
|
|
217
|
+
if (typeof entry.fetched_at === 'string'
|
|
218
|
+
&& Number.isNaN(Date.parse(entry.fetched_at))
|
|
219
|
+
&& warningCount < MAX_WARNINGS_REPORTED) {
|
|
220
|
+
violations.push({
|
|
221
|
+
validator: 'external-academic-invariants',
|
|
222
|
+
category: 'fetched_at_malformed',
|
|
223
|
+
severity: 'warning',
|
|
224
|
+
message: 'entries[' + i + '].fetched_at not parseable as ISO-8601: ' +
|
|
225
|
+
String(entry.fetched_at).slice(0, 40),
|
|
226
|
+
field: 'entries[' + i + '].fetched_at',
|
|
227
|
+
action_hint: 'invalidate_telemetry',
|
|
228
|
+
});
|
|
229
|
+
warningCount += 1;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return { severity: aggregateSeverity(violations), violations };
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// ---------- Exports ----------
|
|
237
|
+
|
|
238
|
+
module.exports = {
|
|
239
|
+
id: 'external-academic-invariants',
|
|
240
|
+
severity_map: SEVERITY_MAP,
|
|
241
|
+
scope: 'global',
|
|
242
|
+
validate: validate,
|
|
243
|
+
// Exported for downstream introspection + adversarial fixture suite.
|
|
244
|
+
// Not required by the registry loader.
|
|
245
|
+
ALLOWED_STATUSES: ALLOWED_STATUSES,
|
|
246
|
+
CANON_PART_8_HASH_REGEX: CANON_PART_8_HASH_REGEX,
|
|
247
|
+
MAX_CANON_HITS_REPORTED: MAX_CANON_HITS_REPORTED,
|
|
248
|
+
MAX_WARNINGS_REPORTED: MAX_WARNINGS_REPORTED,
|
|
249
|
+
};
|