@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,271 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026 Mindrian. BSL 1.1.
|
|
3
|
+
* Phase 89.2 Plan 04 -- External industry fetcher invariants validator.
|
|
4
|
+
*
|
|
5
|
+
* Registry-compatible drop-in for the Phase 88-13 guardian. Auto-discovered
|
|
6
|
+
* by scripts/feynman-minto-guardian.cjs's validator loader (walks
|
|
7
|
+
* lib/memory/validators/*.cjs). Zero guardian.cjs edits needed.
|
|
8
|
+
*
|
|
9
|
+
* Mirrors external-patents-invariants.cjs structure byte-for-byte. The
|
|
10
|
+
* scope is identical (telemetry lives at the GLOBAL per-user path
|
|
11
|
+
* ~/.mindrian/telemetry/external-papers.json, NOT per-room) so this
|
|
12
|
+
* validator declares scope='global'. The guardian still invokes it
|
|
13
|
+
* once per pass; roomPath is ignored.
|
|
14
|
+
*
|
|
15
|
+
* INDUSTRY_SOURCES gate: per-source / per-entry checks scope to industry
|
|
16
|
+
* sources only ('tavily' for v1.11.0). Mirrors Plan 89.2-03's
|
|
17
|
+
* PATENTS_SOURCES gate pattern -- prevents duplicate warnings across
|
|
18
|
+
* academic + patents + industry validators on the shared global ledger.
|
|
19
|
+
*
|
|
20
|
+
* Six checks (Checks A-F):
|
|
21
|
+
* A) Telemetry file absent -> {severity: null} (healthy default)
|
|
22
|
+
* B) Per-source budget exceeded in rolling 24h -> warning per source
|
|
23
|
+
* Scoped to industry sources: tavily.
|
|
24
|
+
* C) status enum membership -> warning per entry
|
|
25
|
+
* Allowed statuses: ok | rate_limited | api_error | network_error |
|
|
26
|
+
* timeout | api_key_missing
|
|
27
|
+
* D) Canon Part 8 audit: query_text literal -> CRITICAL canon_boundary
|
|
28
|
+
* The telemetry primitive guarantees query_text NEVER persists
|
|
29
|
+
* (only query_text_hash). If a literal query_text field ever
|
|
30
|
+
* appears, that is a Canon Part 8 breach by definition.
|
|
31
|
+
* E) query_text_hash format -> warning
|
|
32
|
+
* Must match /^[a-f0-9]{16}$/ (sha256 16-char hex prefix).
|
|
33
|
+
* F) fetched_at parseable as ISO-8601 -> warning
|
|
34
|
+
*
|
|
35
|
+
* Fail-open: unexpected throws are caught by the guardian's validator
|
|
36
|
+
* runner. This validator does not swallow its own exceptions; the
|
|
37
|
+
* guardian owns that contract. Individual I/O paths (readFileSync) are
|
|
38
|
+
* wrapped defensively so a missing telemetry file never produces a
|
|
39
|
+
* violation.
|
|
40
|
+
*
|
|
41
|
+
* Pure CJS, node built-ins only + the rs-egress-telemetry primitive
|
|
42
|
+
* shipped in Plan 89.2-01 for TELEMETRY_FILE + DEFAULT_BUDGETS + WINDOW_MS.
|
|
43
|
+
*/
|
|
44
|
+
'use strict';
|
|
45
|
+
|
|
46
|
+
const fs = require('node:fs');
|
|
47
|
+
|
|
48
|
+
const {
|
|
49
|
+
TELEMETRY_FILE,
|
|
50
|
+
DEFAULT_BUDGETS,
|
|
51
|
+
WINDOW_MS,
|
|
52
|
+
} = require('../../core/rs-egress-telemetry.cjs');
|
|
53
|
+
|
|
54
|
+
// ---------- Constants ----------
|
|
55
|
+
|
|
56
|
+
const SEVERITY_MAP = Object.freeze({ critical: 3, error: 2, warning: 1, info: 0 });
|
|
57
|
+
|
|
58
|
+
// Mirrors lib/core/rs-egress-telemetry.cjs ALLOWED_STATUSES set. Kept in
|
|
59
|
+
// sync by parity gate (any drift fails an invariant scenario downstream).
|
|
60
|
+
const ALLOWED_STATUSES = Object.freeze(new Set([
|
|
61
|
+
'ok',
|
|
62
|
+
'rate_limited',
|
|
63
|
+
'api_error',
|
|
64
|
+
'network_error',
|
|
65
|
+
'timeout',
|
|
66
|
+
'api_key_missing',
|
|
67
|
+
]));
|
|
68
|
+
|
|
69
|
+
// Industry-source allow-list for Check B + per-entry checks. The validator
|
|
70
|
+
// scans the global ledger but only emits violations for sources owned by
|
|
71
|
+
// the industry fetcher. Other surfaces (academic, patents) carry their
|
|
72
|
+
// own validators; running every validator on every source would duplicate
|
|
73
|
+
// warnings (Pattern 7 from Plan 89.2-03 SUMMARY).
|
|
74
|
+
const INDUSTRY_SOURCES = Object.freeze(new Set(['tavily']));
|
|
75
|
+
|
|
76
|
+
// 16-char lowercase hex. sha256 prefix. Must match
|
|
77
|
+
// rs-egress-telemetry.cjs::hashQueryText output shape.
|
|
78
|
+
const CANON_PART_8_HASH_REGEX = /^[a-f0-9]{16}$/;
|
|
79
|
+
|
|
80
|
+
// Cap canon_boundary hits per validate() invocation so one poisoned
|
|
81
|
+
// ledger cannot spam the invariant report. Mirrors brain-substrate
|
|
82
|
+
// invariants and Plan 90-05 brain-md-invariants threshold.
|
|
83
|
+
const MAX_CANON_HITS_REPORTED = 5;
|
|
84
|
+
|
|
85
|
+
// Cap warning-class violations to bound report size on a fully-corrupt
|
|
86
|
+
// ledger. Critical hits are not capped (Check D never exceeds
|
|
87
|
+
// MAX_CANON_HITS_REPORTED on its own).
|
|
88
|
+
const MAX_WARNINGS_REPORTED = 25;
|
|
89
|
+
|
|
90
|
+
// ---------- Severity aggregator ----------
|
|
91
|
+
|
|
92
|
+
function aggregateSeverity(violations) {
|
|
93
|
+
if (!violations || violations.length === 0) return null;
|
|
94
|
+
let max = 0;
|
|
95
|
+
const inv = { 0: 'info', 1: 'warning', 2: 'error', 3: 'critical' };
|
|
96
|
+
for (const v of violations) {
|
|
97
|
+
const s = SEVERITY_MAP[v.severity];
|
|
98
|
+
if (typeof s === 'number' && s > max) max = s;
|
|
99
|
+
}
|
|
100
|
+
return inv[max];
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// ---------- validate (Checks A-F) ----------
|
|
104
|
+
//
|
|
105
|
+
// scope='global'; roomPath is ignored (telemetry is per-user, not per-room).
|
|
106
|
+
// ctx is unused but accepted to match the validator contract.
|
|
107
|
+
|
|
108
|
+
function validate(_roomPath, _ctx) {
|
|
109
|
+
const violations = [];
|
|
110
|
+
|
|
111
|
+
// ---- Check A: telemetry file absent -> healthy default ----
|
|
112
|
+
if (!fs.existsSync(TELEMETRY_FILE)) {
|
|
113
|
+
return { severity: null, violations: [] };
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Read + parse defensively. A malformed ledger is a warning (not
|
|
117
|
+
// critical) because the telemetry primitive treats malformed payloads
|
|
118
|
+
// as cold-start; budgets just reset rather than crashing the fetcher.
|
|
119
|
+
let payload = null;
|
|
120
|
+
try {
|
|
121
|
+
const raw = fs.readFileSync(TELEMETRY_FILE, 'utf8');
|
|
122
|
+
payload = JSON.parse(raw);
|
|
123
|
+
} catch (err) {
|
|
124
|
+
violations.push({
|
|
125
|
+
validator: 'external-industry-invariants',
|
|
126
|
+
category: 'telemetry_unreadable',
|
|
127
|
+
severity: 'warning',
|
|
128
|
+
message: 'external-papers.json unreadable: ' + String(err && err.message),
|
|
129
|
+
action_hint: 'invalidate_telemetry',
|
|
130
|
+
});
|
|
131
|
+
return { severity: aggregateSeverity(violations), violations };
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (!payload || typeof payload !== 'object' || !Array.isArray(payload.entries)) {
|
|
135
|
+
violations.push({
|
|
136
|
+
validator: 'external-industry-invariants',
|
|
137
|
+
category: 'telemetry_malformed_root',
|
|
138
|
+
severity: 'warning',
|
|
139
|
+
message: 'external-papers.json root is not a plain object with entries[]',
|
|
140
|
+
action_hint: 'invalidate_telemetry',
|
|
141
|
+
});
|
|
142
|
+
return { severity: aggregateSeverity(violations), violations };
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// ---- Check B: per-source budget exceeded in rolling 24h ----
|
|
146
|
+
// Aggregate counts per source within the rolling window, then compare
|
|
147
|
+
// against DEFAULT_BUDGETS. Only emit warnings for INDUSTRY_SOURCES so
|
|
148
|
+
// the academic + patents fetchers' validators own their own surfaces.
|
|
149
|
+
const now = Date.now();
|
|
150
|
+
const sourceCounts = {};
|
|
151
|
+
for (const entry of payload.entries) {
|
|
152
|
+
if (!entry || typeof entry !== 'object') continue;
|
|
153
|
+
if (typeof entry.source !== 'string') continue;
|
|
154
|
+
if (typeof entry.fetched_at !== 'string') continue;
|
|
155
|
+
const t = Date.parse(entry.fetched_at);
|
|
156
|
+
if (Number.isNaN(t)) continue;
|
|
157
|
+
if ((now - t) > WINDOW_MS) continue;
|
|
158
|
+
sourceCounts[entry.source] = (sourceCounts[entry.source] || 0) + 1;
|
|
159
|
+
}
|
|
160
|
+
for (const source of Object.keys(sourceCounts)) {
|
|
161
|
+
if (!INDUSTRY_SOURCES.has(source)) continue;
|
|
162
|
+
const cap = DEFAULT_BUDGETS[source];
|
|
163
|
+
if (typeof cap === 'number' && sourceCounts[source] > cap) {
|
|
164
|
+
violations.push({
|
|
165
|
+
validator: 'external-industry-invariants',
|
|
166
|
+
category: 'budget_exceeded',
|
|
167
|
+
severity: 'warning',
|
|
168
|
+
message: 'source ' + source + ' has ' + sourceCounts[source] +
|
|
169
|
+
' calls in last 24h; budget cap ' + cap,
|
|
170
|
+
field: 'entries[].source=' + source,
|
|
171
|
+
action_hint: 'rotate_budget',
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// ---- Checks C / D / E / F: per-entry scans ----
|
|
177
|
+
let canonHitCount = 0;
|
|
178
|
+
let warningCount = 0;
|
|
179
|
+
for (let i = 0; i < payload.entries.length; i += 1) {
|
|
180
|
+
const entry = payload.entries[i];
|
|
181
|
+
if (!entry || typeof entry !== 'object') continue;
|
|
182
|
+
|
|
183
|
+
// Per-entry checks scope to INDUSTRY_SOURCES so the academic +
|
|
184
|
+
// patents validators own their own status / hash / fetched_at
|
|
185
|
+
// entries on the shared ledger.
|
|
186
|
+
if (typeof entry.source === 'string' && !INDUSTRY_SOURCES.has(entry.source)) {
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// ---- Check D: canon_boundary literal query_text presence ----
|
|
191
|
+
// The telemetry primitive guarantees query_text NEVER persists. If
|
|
192
|
+
// any entry carries the field at all, that is a Canon Part 8 breach.
|
|
193
|
+
if (Object.prototype.hasOwnProperty.call(entry, 'query_text')
|
|
194
|
+
&& canonHitCount < MAX_CANON_HITS_REPORTED) {
|
|
195
|
+
violations.push({
|
|
196
|
+
validator: 'external-industry-invariants',
|
|
197
|
+
category: 'canon_boundary',
|
|
198
|
+
severity: 'critical',
|
|
199
|
+
message: 'entries[' + i + '] carries literal query_text (Canon Part 8 breach)',
|
|
200
|
+
field: 'entries[' + i + '].query_text',
|
|
201
|
+
action_hint: 'purge_telemetry',
|
|
202
|
+
});
|
|
203
|
+
canonHitCount += 1;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// ---- Check C: status enum membership ----
|
|
207
|
+
if (typeof entry.status === 'string' && !ALLOWED_STATUSES.has(entry.status)
|
|
208
|
+
&& warningCount < MAX_WARNINGS_REPORTED) {
|
|
209
|
+
violations.push({
|
|
210
|
+
validator: 'external-industry-invariants',
|
|
211
|
+
category: 'status_enum_violation',
|
|
212
|
+
severity: 'warning',
|
|
213
|
+
message: 'entries[' + i + '].status is not in allowed set: ' +
|
|
214
|
+
String(entry.status).slice(0, 40),
|
|
215
|
+
field: 'entries[' + i + '].status',
|
|
216
|
+
action_hint: 'invalidate_telemetry',
|
|
217
|
+
});
|
|
218
|
+
warningCount += 1;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// ---- Check E: query_text_hash format ----
|
|
222
|
+
if (typeof entry.query_text_hash === 'string'
|
|
223
|
+
&& !CANON_PART_8_HASH_REGEX.test(entry.query_text_hash)
|
|
224
|
+
&& warningCount < MAX_WARNINGS_REPORTED) {
|
|
225
|
+
violations.push({
|
|
226
|
+
validator: 'external-industry-invariants',
|
|
227
|
+
category: 'hash_format_invalid',
|
|
228
|
+
severity: 'warning',
|
|
229
|
+
message: 'entries[' + i + '].query_text_hash fails /^[a-f0-9]{16}$/: ' +
|
|
230
|
+
String(entry.query_text_hash).slice(0, 40),
|
|
231
|
+
field: 'entries[' + i + '].query_text_hash',
|
|
232
|
+
action_hint: 'invalidate_telemetry',
|
|
233
|
+
});
|
|
234
|
+
warningCount += 1;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// ---- Check F: fetched_at parseable as ISO-8601 ----
|
|
238
|
+
if (typeof entry.fetched_at === 'string'
|
|
239
|
+
&& Number.isNaN(Date.parse(entry.fetched_at))
|
|
240
|
+
&& warningCount < MAX_WARNINGS_REPORTED) {
|
|
241
|
+
violations.push({
|
|
242
|
+
validator: 'external-industry-invariants',
|
|
243
|
+
category: 'fetched_at_malformed',
|
|
244
|
+
severity: 'warning',
|
|
245
|
+
message: 'entries[' + i + '].fetched_at not parseable as ISO-8601: ' +
|
|
246
|
+
String(entry.fetched_at).slice(0, 40),
|
|
247
|
+
field: 'entries[' + i + '].fetched_at',
|
|
248
|
+
action_hint: 'invalidate_telemetry',
|
|
249
|
+
});
|
|
250
|
+
warningCount += 1;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return { severity: aggregateSeverity(violations), violations };
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// ---------- Exports ----------
|
|
258
|
+
|
|
259
|
+
module.exports = {
|
|
260
|
+
id: 'external-industry-invariants',
|
|
261
|
+
severity_map: SEVERITY_MAP,
|
|
262
|
+
scope: 'global',
|
|
263
|
+
validate: validate,
|
|
264
|
+
// Exported for downstream introspection + adversarial fixture suite.
|
|
265
|
+
// Not required by the registry loader.
|
|
266
|
+
ALLOWED_STATUSES: ALLOWED_STATUSES,
|
|
267
|
+
INDUSTRY_SOURCES: INDUSTRY_SOURCES,
|
|
268
|
+
CANON_PART_8_HASH_REGEX: CANON_PART_8_HASH_REGEX,
|
|
269
|
+
MAX_CANON_HITS_REPORTED: MAX_CANON_HITS_REPORTED,
|
|
270
|
+
MAX_WARNINGS_REPORTED: MAX_WARNINGS_REPORTED,
|
|
271
|
+
};
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026 Mindrian. BSL 1.1.
|
|
3
|
+
* Phase 89.2 Plan 03 -- External patents fetcher invariants validator.
|
|
4
|
+
*
|
|
5
|
+
* Registry-compatible drop-in for the Phase 88-13 guardian. Auto-discovered
|
|
6
|
+
* by scripts/feynman-minto-guardian.cjs's validator loader (walks
|
|
7
|
+
* lib/memory/validators/*.cjs). Zero guardian.cjs edits needed.
|
|
8
|
+
*
|
|
9
|
+
* Mirrors external-academic-invariants.cjs structure byte-for-byte. The
|
|
10
|
+
* scope is identical (telemetry lives at the GLOBAL per-user path
|
|
11
|
+
* ~/.mindrian/telemetry/external-papers.json, NOT per-room) so this
|
|
12
|
+
* validator declares scope='global'. The guardian still invokes it
|
|
13
|
+
* once per pass; roomPath is ignored.
|
|
14
|
+
*
|
|
15
|
+
* Six checks (Checks A-F):
|
|
16
|
+
* A) Telemetry file absent -> {severity: null} (healthy default)
|
|
17
|
+
* B) Per-source budget exceeded in rolling 24h -> warning per source
|
|
18
|
+
* Scoped to patents sources: google_patents + uspto.
|
|
19
|
+
* C) status enum membership -> warning per entry
|
|
20
|
+
* Allowed statuses: ok | rate_limited | api_error | network_error |
|
|
21
|
+
* timeout | api_key_missing
|
|
22
|
+
* D) Canon Part 8 audit: query_text literal -> CRITICAL canon_boundary
|
|
23
|
+
* The telemetry primitive guarantees query_text NEVER persists
|
|
24
|
+
* (only query_text_hash). If a literal query_text field ever
|
|
25
|
+
* appears, that is a Canon Part 8 breach by definition.
|
|
26
|
+
* E) query_text_hash format -> warning
|
|
27
|
+
* Must match /^[a-f0-9]{16}$/ (sha256 16-char hex prefix).
|
|
28
|
+
* F) fetched_at parseable as ISO-8601 -> warning
|
|
29
|
+
*
|
|
30
|
+
* Fail-open: unexpected throws are caught by the guardian's validator
|
|
31
|
+
* runner. This validator does not swallow its own exceptions; the
|
|
32
|
+
* guardian owns that contract. Individual I/O paths (readFileSync) are
|
|
33
|
+
* wrapped defensively so a missing telemetry file never produces a
|
|
34
|
+
* violation.
|
|
35
|
+
*
|
|
36
|
+
* Pure CJS, node built-ins only + the rs-egress-telemetry primitive
|
|
37
|
+
* shipped in Plan 89.2-01 for TELEMETRY_FILE + DEFAULT_BUDGETS + WINDOW_MS.
|
|
38
|
+
*/
|
|
39
|
+
'use strict';
|
|
40
|
+
|
|
41
|
+
const fs = require('node:fs');
|
|
42
|
+
|
|
43
|
+
const {
|
|
44
|
+
TELEMETRY_FILE,
|
|
45
|
+
DEFAULT_BUDGETS,
|
|
46
|
+
WINDOW_MS,
|
|
47
|
+
} = require('../../core/rs-egress-telemetry.cjs');
|
|
48
|
+
|
|
49
|
+
// ---------- Constants ----------
|
|
50
|
+
|
|
51
|
+
const SEVERITY_MAP = Object.freeze({ critical: 3, error: 2, warning: 1, info: 0 });
|
|
52
|
+
|
|
53
|
+
// Mirrors lib/core/rs-egress-telemetry.cjs ALLOWED_STATUSES set. Kept in
|
|
54
|
+
// sync by parity gate (any drift fails an invariant scenario downstream).
|
|
55
|
+
const ALLOWED_STATUSES = Object.freeze(new Set([
|
|
56
|
+
'ok',
|
|
57
|
+
'rate_limited',
|
|
58
|
+
'api_error',
|
|
59
|
+
'network_error',
|
|
60
|
+
'timeout',
|
|
61
|
+
'api_key_missing',
|
|
62
|
+
]));
|
|
63
|
+
|
|
64
|
+
// Patents-source allow-list for Check B. The validator scans the global
|
|
65
|
+
// ledger but only emits budget_exceeded warnings for sources owned by
|
|
66
|
+
// the patents fetcher. Other surfaces (academic, industry) carry their
|
|
67
|
+
// own validators; running every validator on every source would
|
|
68
|
+
// duplicate warnings.
|
|
69
|
+
const PATENTS_SOURCES = Object.freeze(new Set(['google_patents', 'uspto']));
|
|
70
|
+
|
|
71
|
+
// 16-char lowercase hex. sha256 prefix. Must match
|
|
72
|
+
// rs-egress-telemetry.cjs::hashQueryText output shape.
|
|
73
|
+
const CANON_PART_8_HASH_REGEX = /^[a-f0-9]{16}$/;
|
|
74
|
+
|
|
75
|
+
// Cap canon_boundary hits per validate() invocation so one poisoned
|
|
76
|
+
// ledger cannot spam the invariant report. Mirrors brain-substrate
|
|
77
|
+
// invariants and Plan 90-05 brain-md-invariants threshold.
|
|
78
|
+
const MAX_CANON_HITS_REPORTED = 5;
|
|
79
|
+
|
|
80
|
+
// Cap warning-class violations to bound report size on a fully-corrupt
|
|
81
|
+
// ledger. Critical hits are not capped (Check D never exceeds
|
|
82
|
+
// MAX_CANON_HITS_REPORTED on its own).
|
|
83
|
+
const MAX_WARNINGS_REPORTED = 25;
|
|
84
|
+
|
|
85
|
+
// ---------- Severity aggregator ----------
|
|
86
|
+
|
|
87
|
+
function aggregateSeverity(violations) {
|
|
88
|
+
if (!violations || violations.length === 0) return null;
|
|
89
|
+
let max = 0;
|
|
90
|
+
const inv = { 0: 'info', 1: 'warning', 2: 'error', 3: 'critical' };
|
|
91
|
+
for (const v of violations) {
|
|
92
|
+
const s = SEVERITY_MAP[v.severity];
|
|
93
|
+
if (typeof s === 'number' && s > max) max = s;
|
|
94
|
+
}
|
|
95
|
+
return inv[max];
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// ---------- validate (Checks A-F) ----------
|
|
99
|
+
//
|
|
100
|
+
// scope='global'; roomPath is ignored (telemetry is per-user, not per-room).
|
|
101
|
+
// ctx is unused but accepted to match the validator contract.
|
|
102
|
+
|
|
103
|
+
function validate(_roomPath, _ctx) {
|
|
104
|
+
const violations = [];
|
|
105
|
+
|
|
106
|
+
// ---- Check A: telemetry file absent -> healthy default ----
|
|
107
|
+
if (!fs.existsSync(TELEMETRY_FILE)) {
|
|
108
|
+
return { severity: null, violations: [] };
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Read + parse defensively. A malformed ledger is a warning (not
|
|
112
|
+
// critical) because the telemetry primitive treats malformed payloads
|
|
113
|
+
// as cold-start; budgets just reset rather than crashing the fetcher.
|
|
114
|
+
let payload = null;
|
|
115
|
+
try {
|
|
116
|
+
const raw = fs.readFileSync(TELEMETRY_FILE, 'utf8');
|
|
117
|
+
payload = JSON.parse(raw);
|
|
118
|
+
} catch (err) {
|
|
119
|
+
violations.push({
|
|
120
|
+
validator: 'external-patents-invariants',
|
|
121
|
+
category: 'telemetry_unreadable',
|
|
122
|
+
severity: 'warning',
|
|
123
|
+
message: 'external-papers.json unreadable: ' + String(err && err.message),
|
|
124
|
+
action_hint: 'invalidate_telemetry',
|
|
125
|
+
});
|
|
126
|
+
return { severity: aggregateSeverity(violations), violations };
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (!payload || typeof payload !== 'object' || !Array.isArray(payload.entries)) {
|
|
130
|
+
violations.push({
|
|
131
|
+
validator: 'external-patents-invariants',
|
|
132
|
+
category: 'telemetry_malformed_root',
|
|
133
|
+
severity: 'warning',
|
|
134
|
+
message: 'external-papers.json root is not a plain object with entries[]',
|
|
135
|
+
action_hint: 'invalidate_telemetry',
|
|
136
|
+
});
|
|
137
|
+
return { severity: aggregateSeverity(violations), violations };
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// ---- Check B: per-source budget exceeded in rolling 24h ----
|
|
141
|
+
// Aggregate counts per source within the rolling window, then compare
|
|
142
|
+
// against DEFAULT_BUDGETS. Only emit warnings for PATENTS_SOURCES so
|
|
143
|
+
// the academic + industry fetchers' validators own their own surfaces.
|
|
144
|
+
const now = Date.now();
|
|
145
|
+
const sourceCounts = {};
|
|
146
|
+
for (const entry of payload.entries) {
|
|
147
|
+
if (!entry || typeof entry !== 'object') continue;
|
|
148
|
+
if (typeof entry.source !== 'string') continue;
|
|
149
|
+
if (typeof entry.fetched_at !== 'string') continue;
|
|
150
|
+
const t = Date.parse(entry.fetched_at);
|
|
151
|
+
if (Number.isNaN(t)) continue;
|
|
152
|
+
if ((now - t) > WINDOW_MS) continue;
|
|
153
|
+
sourceCounts[entry.source] = (sourceCounts[entry.source] || 0) + 1;
|
|
154
|
+
}
|
|
155
|
+
for (const source of Object.keys(sourceCounts)) {
|
|
156
|
+
if (!PATENTS_SOURCES.has(source)) continue;
|
|
157
|
+
const cap = DEFAULT_BUDGETS[source];
|
|
158
|
+
if (typeof cap === 'number' && sourceCounts[source] > cap) {
|
|
159
|
+
violations.push({
|
|
160
|
+
validator: 'external-patents-invariants',
|
|
161
|
+
category: 'budget_exceeded',
|
|
162
|
+
severity: 'warning',
|
|
163
|
+
message: 'source ' + source + ' has ' + sourceCounts[source] +
|
|
164
|
+
' calls in last 24h; budget cap ' + cap,
|
|
165
|
+
field: 'entries[].source=' + source,
|
|
166
|
+
action_hint: 'rotate_budget',
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// ---- Checks C / D / E / F: per-entry scans ----
|
|
172
|
+
let canonHitCount = 0;
|
|
173
|
+
let warningCount = 0;
|
|
174
|
+
for (let i = 0; i < payload.entries.length; i += 1) {
|
|
175
|
+
const entry = payload.entries[i];
|
|
176
|
+
if (!entry || typeof entry !== 'object') continue;
|
|
177
|
+
|
|
178
|
+
// Per-entry checks scope to PATENTS_SOURCES so the academic +
|
|
179
|
+
// industry validators own their own status / hash / fetched_at
|
|
180
|
+
// entries on the shared ledger.
|
|
181
|
+
if (typeof entry.source === 'string' && !PATENTS_SOURCES.has(entry.source)) {
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// ---- Check D: canon_boundary literal query_text presence ----
|
|
186
|
+
// The telemetry primitive guarantees query_text NEVER persists. If
|
|
187
|
+
// any entry carries the field at all, that is a Canon Part 8 breach.
|
|
188
|
+
if (Object.prototype.hasOwnProperty.call(entry, 'query_text')
|
|
189
|
+
&& canonHitCount < MAX_CANON_HITS_REPORTED) {
|
|
190
|
+
violations.push({
|
|
191
|
+
validator: 'external-patents-invariants',
|
|
192
|
+
category: 'canon_boundary',
|
|
193
|
+
severity: 'critical',
|
|
194
|
+
message: 'entries[' + i + '] carries literal query_text (Canon Part 8 breach)',
|
|
195
|
+
field: 'entries[' + i + '].query_text',
|
|
196
|
+
action_hint: 'purge_telemetry',
|
|
197
|
+
});
|
|
198
|
+
canonHitCount += 1;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// ---- Check C: status enum membership ----
|
|
202
|
+
if (typeof entry.status === 'string' && !ALLOWED_STATUSES.has(entry.status)
|
|
203
|
+
&& warningCount < MAX_WARNINGS_REPORTED) {
|
|
204
|
+
violations.push({
|
|
205
|
+
validator: 'external-patents-invariants',
|
|
206
|
+
category: 'status_enum_violation',
|
|
207
|
+
severity: 'warning',
|
|
208
|
+
message: 'entries[' + i + '].status is not in allowed set: ' +
|
|
209
|
+
String(entry.status).slice(0, 40),
|
|
210
|
+
field: 'entries[' + i + '].status',
|
|
211
|
+
action_hint: 'invalidate_telemetry',
|
|
212
|
+
});
|
|
213
|
+
warningCount += 1;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// ---- Check E: query_text_hash format ----
|
|
217
|
+
if (typeof entry.query_text_hash === 'string'
|
|
218
|
+
&& !CANON_PART_8_HASH_REGEX.test(entry.query_text_hash)
|
|
219
|
+
&& warningCount < MAX_WARNINGS_REPORTED) {
|
|
220
|
+
violations.push({
|
|
221
|
+
validator: 'external-patents-invariants',
|
|
222
|
+
category: 'hash_format_invalid',
|
|
223
|
+
severity: 'warning',
|
|
224
|
+
message: 'entries[' + i + '].query_text_hash fails /^[a-f0-9]{16}$/: ' +
|
|
225
|
+
String(entry.query_text_hash).slice(0, 40),
|
|
226
|
+
field: 'entries[' + i + '].query_text_hash',
|
|
227
|
+
action_hint: 'invalidate_telemetry',
|
|
228
|
+
});
|
|
229
|
+
warningCount += 1;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// ---- Check F: fetched_at parseable as ISO-8601 ----
|
|
233
|
+
if (typeof entry.fetched_at === 'string'
|
|
234
|
+
&& Number.isNaN(Date.parse(entry.fetched_at))
|
|
235
|
+
&& warningCount < MAX_WARNINGS_REPORTED) {
|
|
236
|
+
violations.push({
|
|
237
|
+
validator: 'external-patents-invariants',
|
|
238
|
+
category: 'fetched_at_malformed',
|
|
239
|
+
severity: 'warning',
|
|
240
|
+
message: 'entries[' + i + '].fetched_at not parseable as ISO-8601: ' +
|
|
241
|
+
String(entry.fetched_at).slice(0, 40),
|
|
242
|
+
field: 'entries[' + i + '].fetched_at',
|
|
243
|
+
action_hint: 'invalidate_telemetry',
|
|
244
|
+
});
|
|
245
|
+
warningCount += 1;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return { severity: aggregateSeverity(violations), violations };
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// ---------- Exports ----------
|
|
253
|
+
|
|
254
|
+
module.exports = {
|
|
255
|
+
id: 'external-patents-invariants',
|
|
256
|
+
severity_map: SEVERITY_MAP,
|
|
257
|
+
scope: 'global',
|
|
258
|
+
validate: validate,
|
|
259
|
+
// Exported for downstream introspection + adversarial fixture suite.
|
|
260
|
+
// Not required by the registry loader.
|
|
261
|
+
ALLOWED_STATUSES: ALLOWED_STATUSES,
|
|
262
|
+
PATENTS_SOURCES: PATENTS_SOURCES,
|
|
263
|
+
CANON_PART_8_HASH_REGEX: CANON_PART_8_HASH_REGEX,
|
|
264
|
+
MAX_CANON_HITS_REPORTED: MAX_CANON_HITS_REPORTED,
|
|
265
|
+
MAX_WARNINGS_REPORTED: MAX_WARNINGS_REPORTED,
|
|
266
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026 Mindrian. BSL 1.1.
|
|
3
|
+
* Phase 88-13 first-in validator for the guardian registry.
|
|
4
|
+
*
|
|
5
|
+
* Thin adapter over lib/core/feynman-minto-invariants.cjs so the guardian
|
|
6
|
+
* never requires that module directly. Downstream phases register their
|
|
7
|
+
* own validators by dropping a .cjs file in this directory.
|
|
8
|
+
*
|
|
9
|
+
* Contract (shared with all validators):
|
|
10
|
+
* module.exports = {
|
|
11
|
+
* id: string, unique registry identifier
|
|
12
|
+
* severity_map: object, reference numeric levels per severity name
|
|
13
|
+
* validate: function, (sectionDir) -> { severity, violations[] }
|
|
14
|
+
* }
|
|
15
|
+
*
|
|
16
|
+
* Each returned violation carries at minimum:
|
|
17
|
+
* { validator: 'minto-invariants', category, severity, message, field? }
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
'use strict';
|
|
21
|
+
|
|
22
|
+
const fs = require('node:fs');
|
|
23
|
+
const path = require('node:path');
|
|
24
|
+
|
|
25
|
+
const { validate: invariantsValidate } = require('../../core/feynman-minto-invariants.cjs');
|
|
26
|
+
|
|
27
|
+
module.exports = {
|
|
28
|
+
id: 'minto-invariants',
|
|
29
|
+
severity_map: { critical: 3, error: 2, warning: 1, info: 0 },
|
|
30
|
+
validate: function (sectionDir) {
|
|
31
|
+
const mintoPath = path.join(sectionDir, 'MINTO.md');
|
|
32
|
+
if (!fs.existsSync(mintoPath)) {
|
|
33
|
+
// MINTO absence is handled by the guardian existence-check layer; this
|
|
34
|
+
// validator is specifically about the content contract of an existing
|
|
35
|
+
// MINTO.md. Returning null + empty here keeps aggregation deterministic.
|
|
36
|
+
return { severity: null, violations: [] };
|
|
37
|
+
}
|
|
38
|
+
let result;
|
|
39
|
+
try {
|
|
40
|
+
result = invariantsValidate(mintoPath);
|
|
41
|
+
} catch (e) {
|
|
42
|
+
// Defensive: the invariants module itself must not crash the guardian.
|
|
43
|
+
return {
|
|
44
|
+
severity: 'error',
|
|
45
|
+
violations: [{
|
|
46
|
+
validator: 'minto-invariants',
|
|
47
|
+
category: 'invariants_module_fault',
|
|
48
|
+
severity: 'error',
|
|
49
|
+
message: 'invariants validate() threw: ' + (e && e.message || String(e)),
|
|
50
|
+
}],
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
const violations = (result && result.violations) || [];
|
|
54
|
+
const tagged = violations.map(function (v) {
|
|
55
|
+
return Object.assign({}, v, { validator: 'minto-invariants' });
|
|
56
|
+
});
|
|
57
|
+
return {
|
|
58
|
+
severity: result ? result.severity : null,
|
|
59
|
+
violations: tagged,
|
|
60
|
+
};
|
|
61
|
+
},
|
|
62
|
+
};
|