@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,357 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* Copyright (c) 2026 Mindrian. BSL 1.1.
|
|
5
|
+
*
|
|
6
|
+
* Phase 90-03 Task 1 -- BRAIN.md staleness computation
|
|
7
|
+
* =====================================================
|
|
8
|
+
* LOCAL computation of whether a BRAIN.md file is fresh, stale, or absent.
|
|
9
|
+
* Consumed by scripts/session-start (Phase 90-03 injection block) to decide
|
|
10
|
+
* which sections to enqueue for background regeneration via the Phase 90-02
|
|
11
|
+
* brain-derivation-queue. Never queries Brain content. Never walks the graph.
|
|
12
|
+
* Compares local hashes against the local triple and against the local
|
|
13
|
+
* brain_graph_version that was recorded in BRAIN.md frontmatter at the time
|
|
14
|
+
* the derivation was written.
|
|
15
|
+
*
|
|
16
|
+
* Canon Part 8 invariant (load-bearing):
|
|
17
|
+
* The scan NEVER queries the Brain for user content. It may call:
|
|
18
|
+
* - brain-client.isAvailable() -> boolean (no network on cache hit)
|
|
19
|
+
* - brain-client.schema() -> { brain_graph_version: number, ... }
|
|
20
|
+
* It MUST NOT call:
|
|
21
|
+
* - brain-client.query / search / smartSearch / enrich*
|
|
22
|
+
* Test 13 in brain-md-staleness.test.cjs instruments a mock brain-client
|
|
23
|
+
* and asserts ZERO content queries across 10 sections.
|
|
24
|
+
*
|
|
25
|
+
* Staleness precedence (ordered, first match wins):
|
|
26
|
+
* 1. File missing / non-regular / zero-byte -> absent
|
|
27
|
+
* (recommended_action=enqueue_when_brain_online)
|
|
28
|
+
* 2. Parse-fail (malformed frontmatter) -> stale, stale_reason=parse_failed
|
|
29
|
+
* (recommended_action=enqueue_regen, demoted if Brain offline)
|
|
30
|
+
* 3. governing_thought_hash mismatch vs triple -> stale, stale_reason=governing_thought_changed
|
|
31
|
+
* 4. age_days > STALE_AGE_DAYS -> stale, stale_reason=age_exceeded
|
|
32
|
+
* 5. brain_graph_version < current schema().graph_version -> stale,
|
|
33
|
+
* stale_reason=brain_graph_version_mismatch
|
|
34
|
+
* 6. else -> fresh
|
|
35
|
+
*
|
|
36
|
+
* Brain-offline behavior:
|
|
37
|
+
* - absent + offline: unchanged (recommended_action=enqueue_when_brain_online)
|
|
38
|
+
* - stale + offline: stale persists, recommended_action DEMOTED to
|
|
39
|
+
* enqueue_when_brain_online (we cannot drain without Brain; hold the
|
|
40
|
+
* intent for when it comes back; next drain or next session-start's
|
|
41
|
+
* scan will pick it up)
|
|
42
|
+
* - fresh + offline: unchanged (no action)
|
|
43
|
+
* - brain_graph_version check SKIPPED when offline (schema() unavailable)
|
|
44
|
+
*
|
|
45
|
+
* Env override:
|
|
46
|
+
* BRAIN_STALE_AGE_DAYS=3 claude -- tighter staleness (3-day threshold)
|
|
47
|
+
* BRAIN_STALE_AGE_DAYS=30 claude -- looser (30-day threshold)
|
|
48
|
+
* BRAIN_STALE_AGE_DAYS='abc' -- fallback to 7 (no warning)
|
|
49
|
+
* BRAIN_STALE_AGE_DAYS=0 -- fallback to 7 (positive integer only)
|
|
50
|
+
*
|
|
51
|
+
* Return shape:
|
|
52
|
+
* {
|
|
53
|
+
* exists: boolean,
|
|
54
|
+
* staleness: 'fresh' | 'stale' | 'absent',
|
|
55
|
+
* stale_reason: null | 'governing_thought_changed' | 'age_exceeded'
|
|
56
|
+
* | 'brain_graph_version_mismatch' | 'brain_offline'
|
|
57
|
+
* | 'parse_failed',
|
|
58
|
+
* brain_generated_at: string | null,
|
|
59
|
+
* brain_graph_version: number | null,
|
|
60
|
+
* age_days: number | null,
|
|
61
|
+
* recommended_action: 'none' | 'enqueue_regen' | 'enqueue_when_brain_online' | 'skip'
|
|
62
|
+
* }
|
|
63
|
+
*
|
|
64
|
+
* Three-surface pure: CLI + Desktop MCP + Cowork all share this module.
|
|
65
|
+
* Pure CJS, node built-ins only, zero npm deps.
|
|
66
|
+
*/
|
|
67
|
+
|
|
68
|
+
const fs = require('node:fs');
|
|
69
|
+
const path = require('node:path');
|
|
70
|
+
const crypto = require('node:crypto');
|
|
71
|
+
|
|
72
|
+
// ---------- Constants ----------
|
|
73
|
+
|
|
74
|
+
const DEFAULT_STALE_AGE_DAYS = 7;
|
|
75
|
+
|
|
76
|
+
// ---------- Env override ----------
|
|
77
|
+
|
|
78
|
+
function getStaleAgeDays() {
|
|
79
|
+
const raw = process.env.BRAIN_STALE_AGE_DAYS;
|
|
80
|
+
if (raw === undefined || raw === null || raw === '') {
|
|
81
|
+
return DEFAULT_STALE_AGE_DAYS;
|
|
82
|
+
}
|
|
83
|
+
const n = parseInt(raw, 10);
|
|
84
|
+
// Positive integer only; garbage (NaN, 0, negative, non-integer) falls back.
|
|
85
|
+
if (Number.isFinite(n) && n > 0 && String(n) === String(raw).trim()) {
|
|
86
|
+
return n;
|
|
87
|
+
}
|
|
88
|
+
return DEFAULT_STALE_AGE_DAYS;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// STALE_AGE_DAYS constant for grep discoverability; env override via getter.
|
|
92
|
+
const STALE_AGE_DAYS = DEFAULT_STALE_AGE_DAYS;
|
|
93
|
+
|
|
94
|
+
// ---------- Narrow-dialect frontmatter parser ----------
|
|
95
|
+
//
|
|
96
|
+
// Scoped to BRAIN.md fields (flat scalars only). Mirrors the same narrow
|
|
97
|
+
// dialect shipped in Phase 90-00 brain-md-schema.cjs. Kept local to this
|
|
98
|
+
// module so we do not cross-import (keeps lib/core dependency graph flat
|
|
99
|
+
// per Phase 88-01 key decision). Parse failure returns { ok: false } and
|
|
100
|
+
// the caller maps to stale_reason='parse_failed'.
|
|
101
|
+
|
|
102
|
+
function unquote(raw) {
|
|
103
|
+
const s = raw.trim();
|
|
104
|
+
if (s.length === 0) return '';
|
|
105
|
+
if (s[0] === '"') {
|
|
106
|
+
if (s.length < 2 || s[s.length - 1] !== '"') return null;
|
|
107
|
+
return s.slice(1, -1);
|
|
108
|
+
}
|
|
109
|
+
if (s[0] === "'") {
|
|
110
|
+
if (s.length < 2 || s[s.length - 1] !== "'") return null;
|
|
111
|
+
return s.slice(1, -1);
|
|
112
|
+
}
|
|
113
|
+
return s;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function castScalar(s) {
|
|
117
|
+
if (s === 'null' || s === '~') return null;
|
|
118
|
+
if (s === 'true') return true;
|
|
119
|
+
if (s === 'false') return false;
|
|
120
|
+
if (/^-?\d+$/.test(s)) {
|
|
121
|
+
const n = parseInt(s, 10);
|
|
122
|
+
if (Number.isSafeInteger(n)) return n;
|
|
123
|
+
}
|
|
124
|
+
if (/^-?\d+\.\d+$/.test(s)) {
|
|
125
|
+
const f = parseFloat(s);
|
|
126
|
+
if (Number.isFinite(f)) return f;
|
|
127
|
+
}
|
|
128
|
+
return s;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function parseFrontmatter(raw) {
|
|
132
|
+
if (typeof raw !== 'string' || raw.length === 0) {
|
|
133
|
+
return { ok: false, error: 'empty' };
|
|
134
|
+
}
|
|
135
|
+
const fmRe = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
|
|
136
|
+
const m = raw.match(fmRe);
|
|
137
|
+
if (!m) {
|
|
138
|
+
return { ok: false, error: 'missing_delimiters' };
|
|
139
|
+
}
|
|
140
|
+
const src = m[1];
|
|
141
|
+
const lines = src.split(/\r?\n/);
|
|
142
|
+
const root = {};
|
|
143
|
+
for (let i = 0; i < lines.length; i++) {
|
|
144
|
+
const line = lines[i];
|
|
145
|
+
if (line.length === 0 || /^\s*$/.test(line) || /^\s*#/.test(line)) continue;
|
|
146
|
+
const m2 = line.match(/^([A-Za-z_][A-Za-z0-9_-]*):(.*)$/);
|
|
147
|
+
if (!m2) {
|
|
148
|
+
return { ok: false, error: 'unrecognized_line_' + (i + 1) };
|
|
149
|
+
}
|
|
150
|
+
const key = m2[1];
|
|
151
|
+
const rest = m2[2];
|
|
152
|
+
if (rest.trim().length === 0) {
|
|
153
|
+
root[key] = '';
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
const vStr = unquote(rest);
|
|
157
|
+
if (vStr === null) {
|
|
158
|
+
return { ok: false, error: 'unterminated_quote_' + key };
|
|
159
|
+
}
|
|
160
|
+
root[key] = castScalar(vStr);
|
|
161
|
+
}
|
|
162
|
+
return { ok: true, data: root };
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// ---------- Hash helper ----------
|
|
166
|
+
|
|
167
|
+
function sha256OfGoverningThought(gt) {
|
|
168
|
+
const s = gt == null ? '' : String(gt);
|
|
169
|
+
return 'sha256:' + crypto.createHash('sha256')
|
|
170
|
+
.update(s.normalize('NFC'))
|
|
171
|
+
.digest('hex');
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// ---------- Age helper ----------
|
|
175
|
+
|
|
176
|
+
function computeAgeDays(isoTs) {
|
|
177
|
+
if (typeof isoTs !== 'string' || isoTs.length === 0) return null;
|
|
178
|
+
const t = Date.parse(isoTs);
|
|
179
|
+
if (!Number.isFinite(t)) return null;
|
|
180
|
+
const ageMs = Date.now() - t;
|
|
181
|
+
if (ageMs < 0) return 0; // clock-skew guard: future timestamps treated as fresh-now
|
|
182
|
+
return ageMs / (24 * 60 * 60 * 1000);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// ---------- Result helpers ----------
|
|
186
|
+
|
|
187
|
+
function emptyResult() {
|
|
188
|
+
return {
|
|
189
|
+
exists: false,
|
|
190
|
+
staleness: 'fresh',
|
|
191
|
+
stale_reason: null,
|
|
192
|
+
brain_generated_at: null,
|
|
193
|
+
brain_graph_version: null,
|
|
194
|
+
age_days: null,
|
|
195
|
+
recommended_action: 'none',
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Demote recommended_action when Brain offline. Stale cases become "hold
|
|
200
|
+
// for when Brain comes back"; absent unchanged; fresh unchanged.
|
|
201
|
+
function demoteWhenOffline(result, offline) {
|
|
202
|
+
if (!offline) return result;
|
|
203
|
+
if (result.staleness === 'stale' && result.recommended_action === 'enqueue_regen') {
|
|
204
|
+
result.recommended_action = 'enqueue_when_brain_online';
|
|
205
|
+
}
|
|
206
|
+
return result;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// ---------- Main entry ----------
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* computeBrainStaleness(sectionPath, triple) -> Promise<result>
|
|
213
|
+
*
|
|
214
|
+
* Never throws. Every failure mode returns a structured result object.
|
|
215
|
+
* The caller (scripts/session-start Phase 90-03 block) uses the result
|
|
216
|
+
* to decide whether to enqueue a regeneration and how to annotate the
|
|
217
|
+
* TRIPLE_CONTEXT block.
|
|
218
|
+
*/
|
|
219
|
+
async function computeBrainStaleness(sectionPath, triple) {
|
|
220
|
+
const result = emptyResult();
|
|
221
|
+
|
|
222
|
+
// --- Check Brain availability (non-throwing) ---
|
|
223
|
+
let brainClient;
|
|
224
|
+
let offline = false;
|
|
225
|
+
try {
|
|
226
|
+
brainClient = require('./brain-client.cjs');
|
|
227
|
+
} catch (_e) {
|
|
228
|
+
brainClient = null;
|
|
229
|
+
}
|
|
230
|
+
try {
|
|
231
|
+
if (brainClient && typeof brainClient.isAvailable === 'function') {
|
|
232
|
+
offline = brainClient.isAvailable() !== true;
|
|
233
|
+
} else {
|
|
234
|
+
offline = true;
|
|
235
|
+
}
|
|
236
|
+
} catch (_e) {
|
|
237
|
+
offline = true;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// --- Check BRAIN.md existence ---
|
|
241
|
+
const brainMdPath = path.join(sectionPath, 'BRAIN.md');
|
|
242
|
+
let stat;
|
|
243
|
+
try {
|
|
244
|
+
stat = fs.statSync(brainMdPath);
|
|
245
|
+
} catch (_e) {
|
|
246
|
+
// Absent.
|
|
247
|
+
result.exists = false;
|
|
248
|
+
result.staleness = 'absent';
|
|
249
|
+
result.stale_reason = offline ? 'brain_offline' : null;
|
|
250
|
+
result.recommended_action = 'enqueue_when_brain_online';
|
|
251
|
+
return result;
|
|
252
|
+
}
|
|
253
|
+
if (!stat.isFile() || stat.size === 0) {
|
|
254
|
+
result.exists = false;
|
|
255
|
+
result.staleness = 'absent';
|
|
256
|
+
result.stale_reason = offline ? 'brain_offline' : null;
|
|
257
|
+
result.recommended_action = 'enqueue_when_brain_online';
|
|
258
|
+
return result;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
result.exists = true;
|
|
262
|
+
|
|
263
|
+
// --- Read + parse frontmatter ---
|
|
264
|
+
let raw;
|
|
265
|
+
try {
|
|
266
|
+
raw = fs.readFileSync(brainMdPath, 'utf8');
|
|
267
|
+
} catch (_e) {
|
|
268
|
+
result.staleness = 'stale';
|
|
269
|
+
result.stale_reason = 'parse_failed';
|
|
270
|
+
result.recommended_action = 'enqueue_regen';
|
|
271
|
+
return demoteWhenOffline(result, offline);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const parsed = parseFrontmatter(raw);
|
|
275
|
+
if (!parsed.ok) {
|
|
276
|
+
result.staleness = 'stale';
|
|
277
|
+
result.stale_reason = 'parse_failed';
|
|
278
|
+
result.recommended_action = 'enqueue_regen';
|
|
279
|
+
return demoteWhenOffline(result, offline);
|
|
280
|
+
}
|
|
281
|
+
const fm = parsed.data;
|
|
282
|
+
|
|
283
|
+
// Populate metadata.
|
|
284
|
+
result.brain_generated_at = typeof fm.brain_generated_at === 'string'
|
|
285
|
+
? fm.brain_generated_at
|
|
286
|
+
: null;
|
|
287
|
+
result.brain_graph_version = typeof fm.brain_graph_version === 'number'
|
|
288
|
+
? fm.brain_graph_version
|
|
289
|
+
: null;
|
|
290
|
+
result.age_days = computeAgeDays(result.brain_generated_at);
|
|
291
|
+
|
|
292
|
+
// --- Precedence 3: governing_thought_hash mismatch vs triple ---
|
|
293
|
+
const tripleReasoning = (triple && triple.reasoning) || {};
|
|
294
|
+
const tripleGt = tripleReasoning.governing_thought;
|
|
295
|
+
const currentHash = sha256OfGoverningThought(tripleGt);
|
|
296
|
+
const recordedHash = typeof fm.governing_thought_hash === 'string'
|
|
297
|
+
? fm.governing_thought_hash
|
|
298
|
+
: null;
|
|
299
|
+
|
|
300
|
+
if (recordedHash && recordedHash !== currentHash) {
|
|
301
|
+
result.staleness = 'stale';
|
|
302
|
+
result.stale_reason = 'governing_thought_changed';
|
|
303
|
+
result.recommended_action = 'enqueue_regen';
|
|
304
|
+
return demoteWhenOffline(result, offline);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// --- Precedence 4: age > STALE_AGE_DAYS ---
|
|
308
|
+
const threshold = getStaleAgeDays();
|
|
309
|
+
if (result.age_days != null && result.age_days > threshold) {
|
|
310
|
+
result.staleness = 'stale';
|
|
311
|
+
result.stale_reason = 'age_exceeded';
|
|
312
|
+
result.recommended_action = 'enqueue_regen';
|
|
313
|
+
return demoteWhenOffline(result, offline);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// --- Precedence 5: brain_graph_version mismatch ---
|
|
317
|
+
// Skip when offline; we cannot call schema() without Brain. An offline
|
|
318
|
+
// run keeps the file as 'fresh' for the version axis; the next online
|
|
319
|
+
// session-start will re-evaluate.
|
|
320
|
+
if (!offline && result.brain_graph_version != null && brainClient && typeof brainClient.schema === 'function') {
|
|
321
|
+
let currentSchema = null;
|
|
322
|
+
try {
|
|
323
|
+
currentSchema = await brainClient.schema();
|
|
324
|
+
} catch (_e) {
|
|
325
|
+
currentSchema = null;
|
|
326
|
+
}
|
|
327
|
+
if (currentSchema && typeof currentSchema.brain_graph_version === 'number') {
|
|
328
|
+
if (result.brain_graph_version < currentSchema.brain_graph_version) {
|
|
329
|
+
result.staleness = 'stale';
|
|
330
|
+
result.stale_reason = 'brain_graph_version_mismatch';
|
|
331
|
+
result.recommended_action = 'enqueue_regen';
|
|
332
|
+
return result;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// --- Precedence 6: fresh ---
|
|
338
|
+
result.staleness = 'fresh';
|
|
339
|
+
result.stale_reason = null;
|
|
340
|
+
result.recommended_action = 'none';
|
|
341
|
+
return result;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// ---------- Exports ----------
|
|
345
|
+
|
|
346
|
+
module.exports = {
|
|
347
|
+
computeBrainStaleness: computeBrainStaleness,
|
|
348
|
+
STALE_AGE_DAYS: STALE_AGE_DAYS,
|
|
349
|
+
DEFAULT_STALE_AGE_DAYS: DEFAULT_STALE_AGE_DAYS,
|
|
350
|
+
// Test surface (not public API)
|
|
351
|
+
_test: Object.freeze({
|
|
352
|
+
sha256OfGoverningThought: sha256OfGoverningThought,
|
|
353
|
+
parseFrontmatter: parseFrontmatter,
|
|
354
|
+
computeAgeDays: computeAgeDays,
|
|
355
|
+
getStaleAgeDays: getStaleAgeDays,
|
|
356
|
+
}),
|
|
357
|
+
};
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026 Mindrian. BSL 1.1.
|
|
3
|
+
*
|
|
4
|
+
* Phase 117-04 -- Brain response sanitizer (SEED-003 A3 implementation).
|
|
5
|
+
*
|
|
6
|
+
* Per SEED-003 A3 spec: PostToolUse hook on Brain MCP tool calls uses
|
|
7
|
+
* hookSpecificOutput.updatedToolOutput to scan + redact accidental
|
|
8
|
+
* user-data echo before the response reaches the model. This is the
|
|
9
|
+
* structural enforcement of Canon Part 8 the canon has been describing
|
|
10
|
+
* as "PR review" (check-brain-boundary.cjs PR gate, listed as "pending"
|
|
11
|
+
* in CANON-PHASE-MAP.md Part 8 row).
|
|
12
|
+
*
|
|
13
|
+
* Phase 90 shipped 5 Canon Part 8 tripwires (schema-leak heuristic scan,
|
|
14
|
+
* deriveSection chokepoint, brain-md-invariants body-text scan,
|
|
15
|
+
* sanitizeDetailScalar in cross-room aggregator, cross-scenario sweep).
|
|
16
|
+
* This module adds the 6th tripwire: response-side scan.
|
|
17
|
+
*
|
|
18
|
+
* v1 ships PII pattern redaction ONLY. Conservative non-allowlist
|
|
19
|
+
* redaction (8+ consecutive non-allowlist tokens) stays DISABLED until
|
|
20
|
+
* Phase 121 telemetry calibrates false-positive rate. Risk T4 mitigated
|
|
21
|
+
* by starting permissive; tighten after empirical observation.
|
|
22
|
+
*
|
|
23
|
+
* Pure CJS, node built-ins only.
|
|
24
|
+
*/
|
|
25
|
+
'use strict';
|
|
26
|
+
|
|
27
|
+
const crypto = require('node:crypto');
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* PII_PATTERNS -- regex catalogue per RESEARCH Section 4.6.
|
|
31
|
+
* Each pattern carries a name for telemetry attribution (Phase 121).
|
|
32
|
+
*
|
|
33
|
+
* Patterns (6 total):
|
|
34
|
+
* ssn -- US SSN format XXX-XX-XXXX
|
|
35
|
+
* email -- RFC 5322 simplified
|
|
36
|
+
* phone -- US phone XXX-XXX-XXXX or XXX.XXX.XXXX
|
|
37
|
+
* money -- $X, $X.XX, $XM/K/B suffix
|
|
38
|
+
* iso_date -- YYYY-MM-DD
|
|
39
|
+
* abs_path -- POSIX absolute paths under /home/X or /Users/X
|
|
40
|
+
*/
|
|
41
|
+
const PII_PATTERNS = Object.freeze([
|
|
42
|
+
{ name: 'ssn', regex: /\b\d{3}-\d{2}-\d{4}\b/g },
|
|
43
|
+
{ name: 'email', regex: /\b[\w.+-]+@[\w-]+\.[\w.-]+\b/g },
|
|
44
|
+
{ name: 'phone', regex: /\b\d{3}[-.]\d{3}[-.]\d{4}\b/g },
|
|
45
|
+
{ name: 'money', regex: /\$\d+(?:\.\d+)?[MmKkBb]?\b/g },
|
|
46
|
+
{ name: 'iso_date', regex: /\b\d{4}-\d{2}-\d{2}\b/g },
|
|
47
|
+
{ name: 'abs_path', regex: /\/(?:home|Users)\/[\w-]+\/[\w/.-]+/g },
|
|
48
|
+
]);
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* ALLOWLIST -- framework names + section names + methodology verbs + enum scalars.
|
|
52
|
+
* v1 list seeds from RESEARCH Section 4.6 + references/methodology/index.md.
|
|
53
|
+
* Tightened over time as Phase 121 telemetry calibrates.
|
|
54
|
+
*
|
|
55
|
+
* v1 redaction is pattern-only (PII_PATTERNS). The ALLOWLIST is exported
|
|
56
|
+
* for downstream consumers (e.g. Phase 121 telemetry attribution) and is
|
|
57
|
+
* NOT consulted by sanitize() in v1. When Phase 121 calibrates a non-
|
|
58
|
+
* allowlist redaction mode, ALLOWLIST membership becomes the carve-out.
|
|
59
|
+
*/
|
|
60
|
+
const ALLOWLIST = Object.freeze(new Set([
|
|
61
|
+
// Framework names (from references/methodology/index.md):
|
|
62
|
+
'JTBD', 'MECE', 'Six Thinking Hats', 'Beautiful Questions', 'BONO', 'PAEI',
|
|
63
|
+
'SWOT', 'Porter Five Forces', 'Reverse Salients', 'Hooked Model',
|
|
64
|
+
'Cynefin', 'OODA', 'BMC', 'STP',
|
|
65
|
+
// Section names:
|
|
66
|
+
'problem-definition', 'market-analysis', 'solution-design', 'business-model',
|
|
67
|
+
'competitive-analysis', 'team-execution', 'legal-ip', 'financial-model',
|
|
68
|
+
'team', 'meetings',
|
|
69
|
+
// Methodology verbs:
|
|
70
|
+
'decomposition', 'hypothesis', 'cascade', 'whitespace', 'analogy',
|
|
71
|
+
'contradiction', 'convergence', 'reverse salient', 'cross-domain',
|
|
72
|
+
// Enum scalars:
|
|
73
|
+
'Tier 0', 'Tier 1', 'Tier 2', 'Mode A', 'Mode B', 'Mode C',
|
|
74
|
+
]));
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* isBrainTool(toolName) -- matcher for PostToolUse hook scope.
|
|
78
|
+
* Per SEED-003 A3: scope is mcp__brain_* tool calls.
|
|
79
|
+
*
|
|
80
|
+
* @param {string} toolName tool name string from PostToolUse stdin
|
|
81
|
+
* @returns {boolean} true iff the tool is a Brain MCP tool
|
|
82
|
+
*/
|
|
83
|
+
function isBrainTool(toolName) {
|
|
84
|
+
return typeof toolName === 'string' && toolName.indexOf('mcp__brain_') === 0;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* sanitize(text) -- apply PII pattern redaction with deterministic sha256
|
|
89
|
+
* placeholder. ALLOWLIST entries pass through unchanged in v1 because the
|
|
90
|
+
* v1 redaction engine is pattern-only (regex matches). The ALLOWLIST is
|
|
91
|
+
* for the Phase 121 calibration path.
|
|
92
|
+
*
|
|
93
|
+
* v1 ships PII patterns only. Generic-token redaction (8+ consecutive
|
|
94
|
+
* non-allowlist tokens) is DISABLED until Phase 121 telemetry calibrates.
|
|
95
|
+
*
|
|
96
|
+
* Determinism: same input always produces the same redacted output.
|
|
97
|
+
* The placeholder format is `[REDACTED:<8-hex>]` where the hex is the
|
|
98
|
+
* first 8 chars of sha256(matched-substring).
|
|
99
|
+
*
|
|
100
|
+
* @param {string} text input text (any type; coerced to string)
|
|
101
|
+
* @returns {string} sanitized text
|
|
102
|
+
*/
|
|
103
|
+
function sanitize(text) {
|
|
104
|
+
const input = String(text == null ? '' : text);
|
|
105
|
+
if (input.length === 0) return input;
|
|
106
|
+
let result = input;
|
|
107
|
+
for (const pat of PII_PATTERNS) {
|
|
108
|
+
result = result.replace(pat.regex, function(match) {
|
|
109
|
+
const hash = crypto.createHash('sha256').update(match).digest('hex').slice(0, 8);
|
|
110
|
+
return '[REDACTED:' + hash + ']';
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
return result;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* sanitizeDetailed(text) -- Phase 117-05 extension. Returns BOTH sanitized
|
|
118
|
+
* text AND a per-pattern redaction count map so the PostToolUse hook can
|
|
119
|
+
* emit one auto_explore_sanitizer_hit telemetry event per matched pattern.
|
|
120
|
+
*
|
|
121
|
+
* Backward-compatible: sanitize() still returns the sanitized string only.
|
|
122
|
+
* This variant is for telemetry callers (brain-response-sanitize-hook.cjs).
|
|
123
|
+
*
|
|
124
|
+
* @param {string} text input text
|
|
125
|
+
* @returns {{text: string, redactions: object}} redactions keyed by pattern name
|
|
126
|
+
*/
|
|
127
|
+
function sanitizeDetailed(text) {
|
|
128
|
+
const input = String(text == null ? '' : text);
|
|
129
|
+
const redactions = { ssn: 0, email: 0, phone: 0, money: 0, iso_date: 0, abs_path: 0 };
|
|
130
|
+
if (input.length === 0) return { text: input, redactions: redactions };
|
|
131
|
+
let result = input;
|
|
132
|
+
for (const pat of PII_PATTERNS) {
|
|
133
|
+
result = result.replace(pat.regex, function(match) {
|
|
134
|
+
redactions[pat.name] = (redactions[pat.name] || 0) + 1;
|
|
135
|
+
const hash = crypto.createHash('sha256').update(match).digest('hex').slice(0, 8);
|
|
136
|
+
return '[REDACTED:' + hash + ']';
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
return { text: result, redactions: redactions };
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* buildEnvelope(toolName, originalToolResponse) -- produce PostToolUse hook
|
|
144
|
+
* envelope per SEED-003 A3 spec. Returns the JSON object to write to stdout.
|
|
145
|
+
*
|
|
146
|
+
* If isBrainTool returns false, returns a passthrough envelope (no
|
|
147
|
+
* updatedToolOutput). Other tools' responses are not modified.
|
|
148
|
+
*
|
|
149
|
+
* Per SEED-003 A3 envelope shape:
|
|
150
|
+
* {
|
|
151
|
+
* continue: true,
|
|
152
|
+
* hookSpecificOutput: {
|
|
153
|
+
* hookEventName: 'PostToolUse',
|
|
154
|
+
* updatedToolOutput: { text: '<sanitized response>' }
|
|
155
|
+
* }
|
|
156
|
+
* }
|
|
157
|
+
*
|
|
158
|
+
* @param {string} toolName tool name from PostToolUse stdin
|
|
159
|
+
* @param {object} originalToolResponse tool_response object (expects .text)
|
|
160
|
+
* @returns {object} envelope ready for JSON.stringify -> stdout
|
|
161
|
+
*/
|
|
162
|
+
function buildEnvelope(toolName, originalToolResponse) {
|
|
163
|
+
if (!isBrainTool(toolName)) {
|
|
164
|
+
return { continue: true };
|
|
165
|
+
}
|
|
166
|
+
const text = (originalToolResponse && typeof originalToolResponse.text === 'string')
|
|
167
|
+
? originalToolResponse.text
|
|
168
|
+
: '';
|
|
169
|
+
const sanitized = sanitize(text);
|
|
170
|
+
return {
|
|
171
|
+
continue: true,
|
|
172
|
+
hookSpecificOutput: {
|
|
173
|
+
hookEventName: 'PostToolUse',
|
|
174
|
+
updatedToolOutput: {
|
|
175
|
+
text: sanitized,
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
module.exports = {
|
|
182
|
+
sanitize,
|
|
183
|
+
sanitizeDetailed,
|
|
184
|
+
buildEnvelope,
|
|
185
|
+
isBrainTool,
|
|
186
|
+
PII_PATTERNS,
|
|
187
|
+
ALLOWLIST,
|
|
188
|
+
};
|