@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,570 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026 Mindrian. BSL 1.1.
|
|
3
|
+
* Phase 89.1a Plan 01 + Plan 02 -- Brain methodology substrate loader core.
|
|
4
|
+
*
|
|
5
|
+
* Single chokepoint for pulling the Brain Pinecone methodology
|
|
6
|
+
* substrate into a local cache. Wraps lib/core/brain-client.cjs
|
|
7
|
+
* (Canon Part 7 Reuse Before Build; do NOT fork). Enforces Canon
|
|
8
|
+
* Part 8 at three layers:
|
|
9
|
+
* (1) validateCtx allow-list from rs-brain-substrate-prompts.cjs
|
|
10
|
+
* (2) buildBrainSubstrateQuery extracts ONLY slug-safe scalars
|
|
11
|
+
* (3) preSendAudit JSON.stringify scan against FORBIDDEN_PATTERNS
|
|
12
|
+
* before any network call
|
|
13
|
+
*
|
|
14
|
+
* loadSubstrate NEVER throws. Every external boundary returns a
|
|
15
|
+
* structured {success, substrate, mode, reason?, warning?} result.
|
|
16
|
+
*
|
|
17
|
+
* Plan 02 adds the cache persistence layer:
|
|
18
|
+
* readCache + atomicWriteSubstrateCache + isCacheFresh +
|
|
19
|
+
* getCacheAgeDays + sha256OfString + full 6-mode loadSubstrate
|
|
20
|
+
* matrix (A1/A2/A3/B1/B2/B3) against real .mindrian/brain-substrate-
|
|
21
|
+
* cache.json files on disk. Atomic write mirrors Phase 88-04-B
|
|
22
|
+
* openSync 'wx' + fsync + rename 7-step protocol.
|
|
23
|
+
*
|
|
24
|
+
* Pure CJS, zero npm deps, node built-ins only (fs, path, crypto).
|
|
25
|
+
*/
|
|
26
|
+
'use strict';
|
|
27
|
+
|
|
28
|
+
const fs = require('node:fs');
|
|
29
|
+
const path = require('node:path');
|
|
30
|
+
const crypto = require('node:crypto');
|
|
31
|
+
const brainClient = require('./brain-client.cjs');
|
|
32
|
+
const prompts = require('./rs-brain-substrate-prompts.cjs');
|
|
33
|
+
const {
|
|
34
|
+
ALLOWED_CTX_KEYS,
|
|
35
|
+
FORBIDDEN_PATTERNS,
|
|
36
|
+
SLUG_REGEX,
|
|
37
|
+
validateCtx,
|
|
38
|
+
PROMPT_VERSION,
|
|
39
|
+
} = prompts;
|
|
40
|
+
|
|
41
|
+
// ---------- BrainBoundaryViolation custom error ----------
|
|
42
|
+
|
|
43
|
+
class BrainBoundaryViolation extends Error {
|
|
44
|
+
constructor(message, meta) {
|
|
45
|
+
super(message);
|
|
46
|
+
this.name = 'BrainBoundaryViolation';
|
|
47
|
+
this.meta = meta || {};
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// ---------- RESULT_MODES frozen enum ----------
|
|
52
|
+
//
|
|
53
|
+
// A1 = Brain reachable + cache fresh (serve cache, no network).
|
|
54
|
+
// A2 = Brain reachable + cache stale (re-pull, write cache, serve fresh).
|
|
55
|
+
// A3 = Brain reachable + cache missing (pull, write cache, serve fresh).
|
|
56
|
+
// B1 = Brain offline + cache fresh (serve cache with offline warning).
|
|
57
|
+
// B2 = Brain offline + cache stale (serve stale with warning + cache age).
|
|
58
|
+
// B3 = Brain offline + cache missing (tier-0 empty substrate, RS on user corpus only).
|
|
59
|
+
|
|
60
|
+
const RESULT_MODES = Object.freeze({
|
|
61
|
+
A1: 'A1', A2: 'A2', A3: 'A3',
|
|
62
|
+
B1: 'B1', B2: 'B2', B3: 'B3',
|
|
63
|
+
});
|
|
64
|
+
const RESULT_MODE_SET = Object.freeze(new Set(Object.values(RESULT_MODES)));
|
|
65
|
+
|
|
66
|
+
// ---------- Cache schema + TTL constants (Plan 02) ----------
|
|
67
|
+
//
|
|
68
|
+
// schema_version is locked at 1.0 per CONTEXT.md §Cache Design. Any
|
|
69
|
+
// future schema break must bump this string; the reader refuses to
|
|
70
|
+
// consume a cache whose schema_version is not '1.0'. The atomic-write
|
|
71
|
+
// tmpfile suffix 'substrate' distinguishes this producer's tmpfiles
|
|
72
|
+
// from any other .mindrian/*.tmp.* sibling (Phase 90-01 uses '.brain').
|
|
73
|
+
|
|
74
|
+
const CACHE_SCHEMA_VERSION = '1.0';
|
|
75
|
+
const DEFAULT_TTL_DAYS = 30;
|
|
76
|
+
const EXPECTED_EMBEDDING_DIM = 1024;
|
|
77
|
+
const TMP_SUFFIX = 'substrate';
|
|
78
|
+
// Tmpfile naming: brain-substrate-cache.json.tmp.<rand>.substrate.
|
|
79
|
+
// The 88-13 guardian can sweep orphans by walking .mindrian/ and matching
|
|
80
|
+
// this regex. The rand component is base36 slice + Date.now().toString(36)
|
|
81
|
+
// concatenation to guarantee uniqueness under concurrency.
|
|
82
|
+
const TMP_FILENAME_REGEX = /^brain-substrate-cache\.json\.tmp\.[a-z0-9]+\.substrate$/;
|
|
83
|
+
|
|
84
|
+
function getTtlDays() {
|
|
85
|
+
const env = process.env.MINDRIAN_BRAIN_SUBSTRATE_TTL_DAYS;
|
|
86
|
+
const n = env ? parseInt(env, 10) : DEFAULT_TTL_DAYS;
|
|
87
|
+
// Bound-check: [1, 3650] days is a sensible range. Anything outside
|
|
88
|
+
// falls back to the 30d default rather than crashing. Out-of-range
|
|
89
|
+
// values are silently clamped because the env var is user-tunable
|
|
90
|
+
// and a bad value should degrade gracefully, not break session-start.
|
|
91
|
+
if (!Number.isFinite(n) || n < 1 || n > 3650) return DEFAULT_TTL_DAYS;
|
|
92
|
+
return n;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function cachePath(roomDir) {
|
|
96
|
+
return path.join(roomDir, '.mindrian', 'brain-substrate-cache.json');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function cacheExists(roomDir) {
|
|
100
|
+
try { return fs.existsSync(cachePath(roomDir)); } catch (_e) { return false; }
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function sha256OfString(s) {
|
|
104
|
+
return 'sha256:' + crypto.createHash('sha256').update(String(s)).digest('hex');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// ---------- Audit log writer (append-only JSONL, Canon Part 8 tripwire #3) ----------
|
|
108
|
+
//
|
|
109
|
+
// Local-only. Generic handles only. JSON-Lines format so grep -c outcome:reject
|
|
110
|
+
// answers "how many adversarial queries blocked" at a glance (per CONTEXT.md).
|
|
111
|
+
|
|
112
|
+
function getAuditPath(roomDir) {
|
|
113
|
+
return path.join(roomDir, '.mindrian', 'brain-substrate-audit.jsonl');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function appendAudit(roomDir, entry) {
|
|
117
|
+
try {
|
|
118
|
+
const auditDir = path.join(roomDir, '.mindrian');
|
|
119
|
+
fs.mkdirSync(auditDir, { recursive: true });
|
|
120
|
+
const line = JSON.stringify({
|
|
121
|
+
timestamp: new Date().toISOString(),
|
|
122
|
+
...entry,
|
|
123
|
+
}) + '\n';
|
|
124
|
+
fs.appendFileSync(getAuditPath(roomDir), line);
|
|
125
|
+
} catch (_e) {
|
|
126
|
+
// Audit log failure must not crash loadSubstrate; log to stderr only.
|
|
127
|
+
process.stderr.write(
|
|
128
|
+
'rs-brain-substrate: audit append failed: ' +
|
|
129
|
+
String(_e && _e.message) + '\n'
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// ---------- preSendAudit (THE third tripwire; runs before every brainClient call) ----------
|
|
135
|
+
//
|
|
136
|
+
// JSON.stringify(payload) + FORBIDDEN_PATTERNS scan. Any match -> throw
|
|
137
|
+
// BrainBoundaryViolation BEFORE the payload leaves the process. This is the
|
|
138
|
+
// last line of defense if validateCtx and buildBrainSubstrateQuery both fail
|
|
139
|
+
// to catch a user-specific byte.
|
|
140
|
+
|
|
141
|
+
function preSendAudit(roomDir, payload, caller) {
|
|
142
|
+
const s = JSON.stringify(payload);
|
|
143
|
+
for (const re of FORBIDDEN_PATTERNS) {
|
|
144
|
+
if (re.test(s)) {
|
|
145
|
+
appendAudit(roomDir, {
|
|
146
|
+
caller: caller || 'unknown',
|
|
147
|
+
outcome: 'reject',
|
|
148
|
+
reason: 'forbidden_regex',
|
|
149
|
+
pattern: re.source,
|
|
150
|
+
});
|
|
151
|
+
throw new BrainBoundaryViolation(
|
|
152
|
+
'forbidden regex match in outbound payload: ' + re.source,
|
|
153
|
+
{ caller, pattern: re.source }
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
appendAudit(roomDir, {
|
|
158
|
+
caller: caller || 'unknown',
|
|
159
|
+
outcome: 'pass',
|
|
160
|
+
handles: Object.keys(payload || {}),
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// ---------- buildBrainSubstrateQuery (THE Canon Part 8 chokepoint) ----------
|
|
165
|
+
//
|
|
166
|
+
// Every outbound Brain methodology query MUST pass through this function.
|
|
167
|
+
// validateCtx is called as the FIRST statement so no non-allow-list key
|
|
168
|
+
// can produce a searchParams descriptor.
|
|
169
|
+
|
|
170
|
+
function buildBrainSubstrateQuery(ctx) {
|
|
171
|
+
validateCtx(ctx || {});
|
|
172
|
+
const handles = Object.keys(ctx || {}).sort();
|
|
173
|
+
// Return a descriptor that pullFromBrain consumes. We do NOT build a
|
|
174
|
+
// Cypher string here; brain-client.search takes (queryText, {namespace, topK}).
|
|
175
|
+
// We return the SEARCH param shape derived from allow-list scalars only.
|
|
176
|
+
const searchParams = {
|
|
177
|
+
namespace: ctx.namespace || 'tools',
|
|
178
|
+
topK: ctx.limit || 100,
|
|
179
|
+
};
|
|
180
|
+
const audit_meta = {
|
|
181
|
+
handles,
|
|
182
|
+
prompt_version: PROMPT_VERSION,
|
|
183
|
+
built_at: new Date().toISOString(),
|
|
184
|
+
};
|
|
185
|
+
return { searchParams, audit_meta };
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// ---------- categorizeError (mirror Phase 90-01 shape) ----------
|
|
189
|
+
|
|
190
|
+
function categorizeError(err) {
|
|
191
|
+
if (!err) return 'unknown';
|
|
192
|
+
const msg = String(err.message || err);
|
|
193
|
+
if (/timeout|ETIMEDOUT/i.test(msg)) return 'timeout';
|
|
194
|
+
if (/rate.?limit|quota/i.test(msg)) return 'rate_limited';
|
|
195
|
+
if (/401|auth|unauthorized/i.test(msg)) return 'auth_failed';
|
|
196
|
+
if (/ECONNREFUSED|ENETUNREACH|network/i.test(msg)) return 'network_error';
|
|
197
|
+
return 'unknown';
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// ---------- adaptBrainSearchResponse (Phase 89.1 Plan 01; live MCP shape adapter) ----------
|
|
201
|
+
//
|
|
202
|
+
// brain-client.search returns one of TWO shapes depending on Pinecone path:
|
|
203
|
+
// LIVE (post-89.1a smoke): { result: { hits: [{_id, _score, fields}] }, usage }
|
|
204
|
+
// LEGACY (mocked 89.1a-03): { matches: [{id, values, metadata}] }
|
|
205
|
+
//
|
|
206
|
+
// This adapter normalizes both into the {matches:[{id, score?, embedding?, metadata}]}
|
|
207
|
+
// shape pullFromBrain returns to loadSubstrate. The adapter NEVER throws; on any
|
|
208
|
+
// unexpected shape it returns null which pullFromBrain converts to malformed_response.
|
|
209
|
+
//
|
|
210
|
+
// Field renames (live -> normalized):
|
|
211
|
+
// _id -> id
|
|
212
|
+
// _score -> score
|
|
213
|
+
// fields -> metadata
|
|
214
|
+
// fields.framework -> metadata.framework_name (per 89.1a smoke direct-probe finding)
|
|
215
|
+
//
|
|
216
|
+
// Score is preserved because the live brain_search MCP path (Pinecone searchRecords
|
|
217
|
+
// integrated inference) does NOT return embedding vectors. Downstream uses score
|
|
218
|
+
// directly until a separate raw-Pinecone fetch path is added (deferred to 89.2/89.5).
|
|
219
|
+
// Validator Check E is relaxed to "embedding-or-score required" in lockstep.
|
|
220
|
+
|
|
221
|
+
function adaptBrainSearchResponse(result) {
|
|
222
|
+
if (!result || typeof result !== 'object') return null;
|
|
223
|
+
// Legacy / mocked shape: already normalized.
|
|
224
|
+
if (Array.isArray(result.matches)) {
|
|
225
|
+
return { matches: result.matches };
|
|
226
|
+
}
|
|
227
|
+
// Live shape: { result: { hits: [...] } }
|
|
228
|
+
if (result.result && typeof result.result === 'object' &&
|
|
229
|
+
Array.isArray(result.result.hits)) {
|
|
230
|
+
const matches = result.result.hits.map(function (hit) {
|
|
231
|
+
const fields = (hit && hit.fields && typeof hit.fields === 'object') ? hit.fields : {};
|
|
232
|
+
const metadata = {};
|
|
233
|
+
// Rename framework -> framework_name; copy every other field as-is.
|
|
234
|
+
for (const k of Object.keys(fields)) {
|
|
235
|
+
if (k === 'framework') metadata.framework_name = fields[k];
|
|
236
|
+
else metadata[k] = fields[k];
|
|
237
|
+
}
|
|
238
|
+
const out = {
|
|
239
|
+
id: (hit && typeof hit._id === 'string') ? hit._id : '',
|
|
240
|
+
metadata: metadata,
|
|
241
|
+
};
|
|
242
|
+
if (typeof hit._score === 'number' && Number.isFinite(hit._score)) {
|
|
243
|
+
out.score = hit._score;
|
|
244
|
+
}
|
|
245
|
+
return out;
|
|
246
|
+
});
|
|
247
|
+
return { matches: matches };
|
|
248
|
+
}
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// ---------- pullFromBrain (thin wrapper; preSendAudit before every network call) ----------
|
|
253
|
+
//
|
|
254
|
+
// Pitfall 1: detect pinecone_quota_exhausted AND _source === 'neo4j_fallback';
|
|
255
|
+
// do NOT treat Neo4j keyword-match fallback as substrate-quality embeddings.
|
|
256
|
+
//
|
|
257
|
+
// Phase 89.1 Plan 01: adaptBrainSearchResponse called immediately after
|
|
258
|
+
// await brainClient.search to translate the live MCP {result:{hits:[]}}
|
|
259
|
+
// shape into the legacy {matches:[]} shape. Adapter is fully localized
|
|
260
|
+
// here; brain-client.cjs surface unchanged (Canon Part 7 Reuse Before Build).
|
|
261
|
+
|
|
262
|
+
async function pullFromBrain(roomDir, ctx) {
|
|
263
|
+
const built = buildBrainSubstrateQuery(ctx);
|
|
264
|
+
const outboundPayload = { query: '*', ...built.searchParams };
|
|
265
|
+
preSendAudit(roomDir, outboundPayload, 'pullFromBrain');
|
|
266
|
+
try {
|
|
267
|
+
const raw = await brainClient.search('*', built.searchParams);
|
|
268
|
+
// Pitfall 1: Pinecone quota fallback must NOT be cached as substrate.
|
|
269
|
+
if (raw && (raw.error === 'pinecone_quota_exhausted' || raw._source === 'neo4j_fallback')) {
|
|
270
|
+
return { ok: false, reason: 'brain_quota_exhausted', err_category: 'rate_limited' };
|
|
271
|
+
}
|
|
272
|
+
let adapted;
|
|
273
|
+
try {
|
|
274
|
+
adapted = adaptBrainSearchResponse(raw);
|
|
275
|
+
} catch (_adapterErr) {
|
|
276
|
+
return { ok: false, reason: 'adapter_error', err_category: 'unknown' };
|
|
277
|
+
}
|
|
278
|
+
if (!adapted || !Array.isArray(adapted.matches)) {
|
|
279
|
+
return { ok: false, reason: 'malformed_response', err_category: 'unknown' };
|
|
280
|
+
}
|
|
281
|
+
return { ok: true, matches: adapted.matches };
|
|
282
|
+
} catch (err) {
|
|
283
|
+
return { ok: false, reason: 'brain_error', err_category: categorizeError(err) };
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// ---------- Cache reader (Plan 02; never throws, always structured result) ----------
|
|
288
|
+
//
|
|
289
|
+
// readCache returns {ok, payload} on success, or {ok:false, reason, ...} on
|
|
290
|
+
// any failure. Reasons: 'missing', 'read_error', 'malformed_root',
|
|
291
|
+
// 'schema_version_mismatch', 'malformed_substrate_array', 'partial_cache'.
|
|
292
|
+
//
|
|
293
|
+
// Pitfall 5 completeness guard (partial_cache): if the payload declares
|
|
294
|
+
// embedding_count and the substrate array length disagrees, the cache is
|
|
295
|
+
// treated as invalid at the reader. The validator at lib/memory/validators/
|
|
296
|
+
// brain-substrate-invariants.cjs ALSO catches this case at session-start
|
|
297
|
+
// and pre-commit. Defense-in-depth: either layer alone blocks a partial
|
|
298
|
+
// cache from polluting downstream RS runs.
|
|
299
|
+
|
|
300
|
+
function readCache(roomDir) {
|
|
301
|
+
const p = cachePath(roomDir);
|
|
302
|
+
try {
|
|
303
|
+
if (!fs.existsSync(p)) return { ok: false, reason: 'missing' };
|
|
304
|
+
const raw = fs.readFileSync(p, 'utf8');
|
|
305
|
+
const payload = JSON.parse(raw);
|
|
306
|
+
if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {
|
|
307
|
+
return { ok: false, reason: 'malformed_root' };
|
|
308
|
+
}
|
|
309
|
+
if (payload.schema_version !== CACHE_SCHEMA_VERSION) {
|
|
310
|
+
return {
|
|
311
|
+
ok: false,
|
|
312
|
+
reason: 'schema_version_mismatch',
|
|
313
|
+
got: payload.schema_version,
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
if (!Array.isArray(payload.substrate)) {
|
|
317
|
+
return { ok: false, reason: 'malformed_substrate_array' };
|
|
318
|
+
}
|
|
319
|
+
// Pitfall 5 completeness guard.
|
|
320
|
+
if (typeof payload.embedding_count === 'number' &&
|
|
321
|
+
payload.substrate.length !== payload.embedding_count) {
|
|
322
|
+
return {
|
|
323
|
+
ok: false,
|
|
324
|
+
reason: 'partial_cache',
|
|
325
|
+
declared: payload.embedding_count,
|
|
326
|
+
actual: payload.substrate.length,
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
return { ok: true, payload };
|
|
330
|
+
} catch (err) {
|
|
331
|
+
return {
|
|
332
|
+
ok: false,
|
|
333
|
+
reason: 'read_error',
|
|
334
|
+
err_message: String(err && err.message),
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// ---------- TTL math (Plan 02; Invariant I6) ----------
|
|
340
|
+
//
|
|
341
|
+
// getCacheAgeDays: (now - pulled_at) in days. Returns Infinity if
|
|
342
|
+
// pulled_at is missing or unparseable so a degenerate cache always
|
|
343
|
+
// sorts as stale. isCacheFresh: strictly less-than comparison against
|
|
344
|
+
// the payload-local ttl_days (falls back to env-driven default).
|
|
345
|
+
|
|
346
|
+
function getCacheAgeDays(payload) {
|
|
347
|
+
if (!payload || !payload.pulled_at) return Infinity;
|
|
348
|
+
const pulledMs = Date.parse(payload.pulled_at);
|
|
349
|
+
if (!Number.isFinite(pulledMs)) return Infinity;
|
|
350
|
+
return (Date.now() - pulledMs) / 86400000;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
function isCacheFresh(payload) {
|
|
354
|
+
const ttl = (payload && typeof payload.ttl_days === 'number')
|
|
355
|
+
? payload.ttl_days
|
|
356
|
+
: getTtlDays();
|
|
357
|
+
return getCacheAgeDays(payload) < ttl;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// ---------- Atomic write (Plan 02; Phase 88-04-B 7-step protocol) ----------
|
|
361
|
+
//
|
|
362
|
+
// Pattern mirrors lib/core/brain-derivation.cjs atomicWriteBrainMd
|
|
363
|
+
// byte-for-byte. Seven steps:
|
|
364
|
+
// 1. mkdirSync parent (recursive)
|
|
365
|
+
// 2. openSync(tmpPath, 'wx') -- exclusive create, EEXIST on collision
|
|
366
|
+
// 3. writeFileSync(fd, body)
|
|
367
|
+
// 4. fsyncSync(fd) -- durability: flush OS + disk buffers
|
|
368
|
+
// 5. closeSync(fd)
|
|
369
|
+
// 6. renameSync(tmpPath, finalPath) -- atomic publish
|
|
370
|
+
// 7. return {success, path}
|
|
371
|
+
// On ANY failure: closeSync (if fd open) + unlinkSync (best-effort) +
|
|
372
|
+
// return structured {success:false, fs_error}. loadSubstrate wraps this
|
|
373
|
+
// so a cache write failure never throws to the caller; it emits a
|
|
374
|
+
// warning on the result object instead.
|
|
375
|
+
|
|
376
|
+
function atomicWriteSubstrateCache(roomDir, payload) {
|
|
377
|
+
const finalPath = cachePath(roomDir);
|
|
378
|
+
const rand = Math.random().toString(36).slice(2) + Date.now().toString(36);
|
|
379
|
+
const tmpPath = finalPath + '.tmp.' + rand + '.' + TMP_SUFFIX;
|
|
380
|
+
let fd = null;
|
|
381
|
+
try {
|
|
382
|
+
fs.mkdirSync(path.dirname(finalPath), { recursive: true });
|
|
383
|
+
fd = fs.openSync(tmpPath, 'wx'); // exclusive create
|
|
384
|
+
fs.writeFileSync(fd, JSON.stringify(payload, null, 2));
|
|
385
|
+
fs.fsyncSync(fd); // durability fence
|
|
386
|
+
fs.closeSync(fd);
|
|
387
|
+
fd = null;
|
|
388
|
+
fs.renameSync(tmpPath, finalPath); // atomic publish
|
|
389
|
+
return { success: true, path: finalPath };
|
|
390
|
+
} catch (err) {
|
|
391
|
+
try { if (fd !== null) fs.closeSync(fd); } catch (_e) { /* ignore */ }
|
|
392
|
+
try { fs.unlinkSync(tmpPath); } catch (_e) { /* ignore */ }
|
|
393
|
+
return { success: false, fs_error: String(err && err.message) };
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// ---------- loadSubstrate (top-level entry; NEVER throws; full 6-mode matrix) ----------
|
|
398
|
+
//
|
|
399
|
+
// Plan 02 behavior: implements all six graceful-degradation modes
|
|
400
|
+
// against real cache files on disk per CONTEXT.md §Graceful Degradation
|
|
401
|
+
// Contract. The mode matrix below names each RESULT_MODES value so a
|
|
402
|
+
// future reader can grep for RESULT_MODES.<mode> and find both its
|
|
403
|
+
// return site AND its documented contract in one place.
|
|
404
|
+
//
|
|
405
|
+
// RESULT_MODES.A1 : Brain reachable + cache fresh -> cached substrate, no network
|
|
406
|
+
// RESULT_MODES.A2 : Brain reachable + cache stale -> re-pull, write cache, return fresh
|
|
407
|
+
// RESULT_MODES.A3 : Brain reachable + cache missing -> pull, write cache, return fresh
|
|
408
|
+
// RESULT_MODES.B1 : Brain offline + cache fresh -> cached + offline warning
|
|
409
|
+
// RESULT_MODES.B2 : Brain offline + cache stale -> cached + stale warning (stale_days)
|
|
410
|
+
// RESULT_MODES.B3 : Brain offline + cache missing -> tier-0 empty substrate + warning
|
|
411
|
+
//
|
|
412
|
+
// Additional options:
|
|
413
|
+
// opts.forceRefresh = true -> skip Mode A1, always attempt pull when Brain up
|
|
414
|
+
// opts.roomDir -> override MINDRIAN_ROOM / process.cwd()
|
|
415
|
+
// opts.limit -> topK for pullFromBrain (default 100)
|
|
416
|
+
|
|
417
|
+
async function loadSubstrate(options) {
|
|
418
|
+
const opts = options || {};
|
|
419
|
+
const roomDir = opts.roomDir || process.env.MINDRIAN_ROOM || process.cwd();
|
|
420
|
+
try {
|
|
421
|
+
const cacheRead = readCache(roomDir);
|
|
422
|
+
const cacheOk = cacheRead.ok;
|
|
423
|
+
const fresh = cacheOk && isCacheFresh(cacheRead.payload);
|
|
424
|
+
const ageDays = cacheOk ? getCacheAgeDays(cacheRead.payload) : null;
|
|
425
|
+
const brainUp = brainClient.isAvailable();
|
|
426
|
+
|
|
427
|
+
const forceRefresh = opts.forceRefresh === true;
|
|
428
|
+
|
|
429
|
+
// Mode A1: Brain reachable + fresh cache + not forced -> serve cache,
|
|
430
|
+
// no network. Also covers Mode B1 when Brain is offline but cache is
|
|
431
|
+
// fresh (offline warning attached).
|
|
432
|
+
if (!forceRefresh && cacheOk && fresh) {
|
|
433
|
+
const mode = brainUp ? RESULT_MODES.A1 : RESULT_MODES.B1;
|
|
434
|
+
return {
|
|
435
|
+
success: true,
|
|
436
|
+
substrate: cacheRead.payload.substrate,
|
|
437
|
+
mode,
|
|
438
|
+
cache_age_days: ageDays,
|
|
439
|
+
warning: brainUp ? undefined : 'Brain offline; using cached methodology',
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// Paths that need a pull (A2, A3, or forced refresh). If Brain up,
|
|
444
|
+
// attempt pull; on success, overwrite cache atomically and return.
|
|
445
|
+
if (brainUp) {
|
|
446
|
+
const pull = await pullFromBrain(roomDir, {
|
|
447
|
+
namespace: 'tools',
|
|
448
|
+
limit: opts.limit || 100,
|
|
449
|
+
});
|
|
450
|
+
if (pull.ok) {
|
|
451
|
+
const substrate = pull.matches.slice();
|
|
452
|
+
// Phase 89.1 Plan 01: cache _completeness reflects whether entries
|
|
453
|
+
// carry 1024-dim embedding vectors (legacy/mocked path) or only
|
|
454
|
+
// a Pinecone score (live brain_search path; no values returned by
|
|
455
|
+
// searchRecords today). Backward-compatible: pre-89.1 caches without
|
|
456
|
+
// this field are treated as 'full-vectors' by downstream readers.
|
|
457
|
+
let completeness = 'partial';
|
|
458
|
+
if (substrate.length === 0) {
|
|
459
|
+
completeness = 'partial';
|
|
460
|
+
} else {
|
|
461
|
+
const hasAnyEmbedding = substrate.some(function (e) {
|
|
462
|
+
return e && Array.isArray(e.embedding);
|
|
463
|
+
});
|
|
464
|
+
const hasAnyScore = substrate.some(function (e) {
|
|
465
|
+
return e && typeof e.score === 'number';
|
|
466
|
+
});
|
|
467
|
+
const allEmbedding = substrate.every(function (e) {
|
|
468
|
+
return e && Array.isArray(e.embedding);
|
|
469
|
+
});
|
|
470
|
+
const allScore = substrate.every(function (e) {
|
|
471
|
+
return e && typeof e.score === 'number';
|
|
472
|
+
});
|
|
473
|
+
if (allEmbedding) completeness = 'full-vectors';
|
|
474
|
+
else if (allScore && !hasAnyEmbedding) completeness = 'score-only';
|
|
475
|
+
else if (hasAnyEmbedding || hasAnyScore) completeness = 'partial';
|
|
476
|
+
}
|
|
477
|
+
const newPayload = {
|
|
478
|
+
schema_version: CACHE_SCHEMA_VERSION,
|
|
479
|
+
pulled_at: new Date().toISOString(),
|
|
480
|
+
ttl_days: getTtlDays(),
|
|
481
|
+
source_index: 'pws-brain',
|
|
482
|
+
source_namespaces: ['tools'],
|
|
483
|
+
embedding_count: substrate.length,
|
|
484
|
+
content_hash: sha256OfString(JSON.stringify(substrate)),
|
|
485
|
+
_completeness: completeness,
|
|
486
|
+
substrate,
|
|
487
|
+
};
|
|
488
|
+
const write = atomicWriteSubstrateCache(roomDir, newPayload);
|
|
489
|
+
const mode = cacheOk ? RESULT_MODES.A2 : RESULT_MODES.A3;
|
|
490
|
+
return {
|
|
491
|
+
success: true,
|
|
492
|
+
substrate,
|
|
493
|
+
mode,
|
|
494
|
+
cache_age_days: 0,
|
|
495
|
+
warning: write.success
|
|
496
|
+
? undefined
|
|
497
|
+
: 'Cache write failed: ' + write.fs_error,
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
// Brain up but pull failed (including Pitfall 1 quota fallback)
|
|
501
|
+
// -> fall through to cache-present (B1/B2) or B3.
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
// Mode B1/B2: Brain unreachable (or pull failed) with cache present.
|
|
505
|
+
// Serve existing cache with appropriate warning. Fresh -> B1, stale -> B2.
|
|
506
|
+
if (cacheOk) {
|
|
507
|
+
const mode = fresh ? RESULT_MODES.B1 : RESULT_MODES.B2;
|
|
508
|
+
const warning = fresh
|
|
509
|
+
? 'Brain offline; using cached methodology'
|
|
510
|
+
: 'Brain offline; using stale methodology (cache age ' +
|
|
511
|
+
Math.floor(ageDays) + ' days)';
|
|
512
|
+
return {
|
|
513
|
+
success: true,
|
|
514
|
+
substrate: cacheRead.payload.substrate,
|
|
515
|
+
mode,
|
|
516
|
+
cache_age_days: ageDays,
|
|
517
|
+
stale_days: fresh ? 0 : Math.floor(ageDays),
|
|
518
|
+
warning,
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
// Mode B3: tier-0 empty substrate, graceful degradation.
|
|
523
|
+
return {
|
|
524
|
+
success: true,
|
|
525
|
+
substrate: [],
|
|
526
|
+
mode: RESULT_MODES.B3,
|
|
527
|
+
warning: 'Brain offline and no cache; RS will run on user corpus only',
|
|
528
|
+
};
|
|
529
|
+
} catch (err) {
|
|
530
|
+
// Catch-all: loadSubstrate NEVER throws.
|
|
531
|
+
return {
|
|
532
|
+
success: true,
|
|
533
|
+
substrate: [],
|
|
534
|
+
mode: RESULT_MODES.B3,
|
|
535
|
+
warning: 'loadSubstrate caught: ' + String(err && err.message),
|
|
536
|
+
reason: categorizeError(err),
|
|
537
|
+
};
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// ---------- Exports ----------
|
|
542
|
+
|
|
543
|
+
module.exports = {
|
|
544
|
+
loadSubstrate,
|
|
545
|
+
buildBrainSubstrateQuery,
|
|
546
|
+
preSendAudit,
|
|
547
|
+
categorizeError,
|
|
548
|
+
BrainBoundaryViolation,
|
|
549
|
+
RESULT_MODES,
|
|
550
|
+
_test: {
|
|
551
|
+
pullFromBrain,
|
|
552
|
+
adaptBrainSearchResponse,
|
|
553
|
+
appendAudit,
|
|
554
|
+
getAuditPath,
|
|
555
|
+
RESULT_MODE_SET,
|
|
556
|
+
// Plan 02 cache I/O surface (test-only; production callers use loadSubstrate).
|
|
557
|
+
readCache,
|
|
558
|
+
atomicWriteSubstrateCache,
|
|
559
|
+
isCacheFresh,
|
|
560
|
+
getCacheAgeDays,
|
|
561
|
+
cachePath,
|
|
562
|
+
cacheExists,
|
|
563
|
+
sha256OfString,
|
|
564
|
+
getTtlDays,
|
|
565
|
+
CACHE_SCHEMA_VERSION,
|
|
566
|
+
DEFAULT_TTL_DAYS,
|
|
567
|
+
EXPECTED_EMBEDDING_DIM,
|
|
568
|
+
TMP_FILENAME_REGEX,
|
|
569
|
+
},
|
|
570
|
+
};
|