@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,340 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026 Mindrian. BSL 1.1.
|
|
3
|
+
* Phase 91-09 -- navigation-invariants validator.
|
|
4
|
+
*
|
|
5
|
+
* Registry-compatible drop-in for the Phase 88-13 guardian. Auto-loaded
|
|
6
|
+
* by scripts/feynman-minto-guardian.cjs's loadValidators() walker; no
|
|
7
|
+
* guardian.cjs edits required (extensibility promise of Phase 88-13
|
|
8
|
+
* registry contract).
|
|
9
|
+
*
|
|
10
|
+
* Converts five silent Phase 91 navigation failure modes into first-class
|
|
11
|
+
* health signals visible at session-start, on-stop, and pre-commit:
|
|
12
|
+
*
|
|
13
|
+
* INV-1 trace_missing_field every persisted decision_trace
|
|
14
|
+
* entry must carry all 8 Section 8
|
|
15
|
+
* brain_md_* fields per
|
|
16
|
+
* navigation-engine-brain-interface
|
|
17
|
+
* v1. Missing field -> error.
|
|
18
|
+
* INV-2 recommended_in_wrong_mode RECOMMENDED marker may render only
|
|
19
|
+
* in mode_a (Canon Part 3 Section 6).
|
|
20
|
+
* Rendered in mode_b or tier_0 ->
|
|
21
|
+
* error.
|
|
22
|
+
* INV-3 weight_clamp_breach brain_md_weight_applied must lie
|
|
23
|
+
* in [0.0, 1.0] inclusive. Out-of-
|
|
24
|
+
* range -> error.
|
|
25
|
+
* INV-4 trace_file_malformed decision-traces/*.json that fails
|
|
26
|
+
* JSON.parse -> error. Sibling files
|
|
27
|
+
* continue to be scanned.
|
|
28
|
+
* INV-5 unknown_verb_passed trace.fire_skill (when present)
|
|
29
|
+
* must be in CANONICAL_VERBS (Canon
|
|
30
|
+
* Part 3 frozen 10-verb vocabulary).
|
|
31
|
+
* Unknown -> warning. Graceful when
|
|
32
|
+
* shared module unavailable.
|
|
33
|
+
*
|
|
34
|
+
* Canon Part 8 (Graph Boundary): pure LOCAL reader. Reads only files
|
|
35
|
+
* under <roomDir>/.mindrian/decision-traces/. Zero network surface; zero
|
|
36
|
+
* Brain MCP queries; zero shell-out. Test 13 source-scans this file for
|
|
37
|
+
* forbidden references.
|
|
38
|
+
*
|
|
39
|
+
* Canon Part 7 (Reuse Before Build): Phase 88-13 built the validator
|
|
40
|
+
* registry for exactly this scenario. This file plugs in; guardian.cjs
|
|
41
|
+
* stays untouched. Fail-open is inherited from the registry loader (a
|
|
42
|
+
* malformed sibling validator never prevents this validator from running).
|
|
43
|
+
*
|
|
44
|
+
* Three-surface compatibility: pure CJS + node built-ins (fs, path).
|
|
45
|
+
* Works identically on Claude Code CLI, Claude Desktop MCP, and Cowork
|
|
46
|
+
* shared-room scenarios.
|
|
47
|
+
*
|
|
48
|
+
* Mode dispatch (set by guardian invocation):
|
|
49
|
+
* session-start advisory; emitted to TRIPLE_CONTEXT footer.
|
|
50
|
+
* on-stop advisory; aggregated into invariant-report.json.
|
|
51
|
+
* pre-commit blocking at error/critical (guardian exits 2). This
|
|
52
|
+
* validator just emits; guardian owns exit codes.
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
'use strict';
|
|
56
|
+
|
|
57
|
+
const fs = require('node:fs');
|
|
58
|
+
const path = require('node:path');
|
|
59
|
+
|
|
60
|
+
// ---------- Constants ----------
|
|
61
|
+
|
|
62
|
+
const SEVERITY_MAP = Object.freeze({
|
|
63
|
+
// 6 categories the validator emits, mapped to severities the guardian
|
|
64
|
+
// aggregates. Phase 88-13 expects the shape (object); the guardian's
|
|
65
|
+
// SEVERITY_ORDER alone owns numeric ordering.
|
|
66
|
+
trace_missing_field: 'error',
|
|
67
|
+
recommended_in_wrong_mode: 'error',
|
|
68
|
+
weight_clamp_breach: 'error',
|
|
69
|
+
unknown_verb_passed: 'warning',
|
|
70
|
+
trace_file_malformed: 'error',
|
|
71
|
+
session_file_absent: 'info',
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// 8 Section 8 fields per .planning/research/navigation-engine-brain-
|
|
75
|
+
// interface.md v1. Order is documentation-stable; the validator does not
|
|
76
|
+
// rely on order, but the test suite reads this list defensively.
|
|
77
|
+
const REQUIRED_TRACE_FIELDS = Object.freeze([
|
|
78
|
+
'brain_md_version',
|
|
79
|
+
'brain_md_staleness',
|
|
80
|
+
'brain_md_stale_reason',
|
|
81
|
+
'brain_md_weight_applied',
|
|
82
|
+
'brain_md_recommended_confidence',
|
|
83
|
+
'brain_md_recommended_marker_rendered',
|
|
84
|
+
'brain_md_tier_mode',
|
|
85
|
+
'brain_md_sections_consumed',
|
|
86
|
+
]);
|
|
87
|
+
|
|
88
|
+
const VALID_TIER_MODES = Object.freeze(['mode_a', 'mode_b', 'tier_0']);
|
|
89
|
+
const ROOM_SCOPE = '__room__';
|
|
90
|
+
|
|
91
|
+
// ---------- Lazy CANONICAL_VERBS load (graceful degradation) ----------
|
|
92
|
+
|
|
93
|
+
let _canonicalVerbs = undefined; // undefined: not yet loaded; null: unavailable.
|
|
94
|
+
function getCanonicalVerbs() {
|
|
95
|
+
if (_canonicalVerbs !== undefined) return _canonicalVerbs;
|
|
96
|
+
try {
|
|
97
|
+
const sharedPath = path.join(__dirname, '..', '..', 'core',
|
|
98
|
+
'navigation-engine-shared.cjs');
|
|
99
|
+
// Best-effort require. If the shared module fails to load (missing,
|
|
100
|
+
// syntax error), fall back to null so INV-5 silently skips. Per the
|
|
101
|
+
// plan: graceful degradation, not noisy failure.
|
|
102
|
+
const mod = require(sharedPath);
|
|
103
|
+
if (mod && Array.isArray(mod.CANONICAL_VERBS) && mod.CANONICAL_VERBS.length > 0) {
|
|
104
|
+
_canonicalVerbs = mod.CANONICAL_VERBS;
|
|
105
|
+
} else {
|
|
106
|
+
_canonicalVerbs = null;
|
|
107
|
+
}
|
|
108
|
+
} catch (_) {
|
|
109
|
+
_canonicalVerbs = null;
|
|
110
|
+
}
|
|
111
|
+
return _canonicalVerbs;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// ---------- Helpers ----------
|
|
115
|
+
|
|
116
|
+
function isFiniteNumber(n) {
|
|
117
|
+
return typeof n === 'number' && isFinite(n);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function safeReadDir(dir) {
|
|
121
|
+
try {
|
|
122
|
+
return fs.readdirSync(dir, { withFileTypes: true })
|
|
123
|
+
.filter(function (d) { return d.isFile() && /\.json$/i.test(d.name); })
|
|
124
|
+
.map(function (d) { return d.name; })
|
|
125
|
+
.sort();
|
|
126
|
+
} catch (_) {
|
|
127
|
+
return null; // sentinel: directory absent or unreadable
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function makeViolation(category, message, extras) {
|
|
132
|
+
const sev = SEVERITY_MAP[category] || 'warning';
|
|
133
|
+
const base = {
|
|
134
|
+
validator: 'navigation-invariants',
|
|
135
|
+
category: category,
|
|
136
|
+
severity: sev,
|
|
137
|
+
message: message,
|
|
138
|
+
scope: ROOM_SCOPE,
|
|
139
|
+
};
|
|
140
|
+
if (extras && typeof extras === 'object') {
|
|
141
|
+
return Object.assign(base, extras);
|
|
142
|
+
}
|
|
143
|
+
return base;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// ---------- Per-trace invariant checks ----------
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Check a single persisted trace entry for INV-1, INV-2, INV-3, INV-5.
|
|
150
|
+
* Pushes violations into the supplied array. Each violation carries
|
|
151
|
+
* session_id (when known) + turn (when known) so /mos:explain-decision
|
|
152
|
+
* and the guardian footer can pinpoint the offending row.
|
|
153
|
+
*/
|
|
154
|
+
function checkTraceEntry(trace, sessionId, fileName, violations) {
|
|
155
|
+
if (!trace || typeof trace !== 'object') return;
|
|
156
|
+
const turn = (typeof trace.turn === 'number') ? trace.turn : null;
|
|
157
|
+
const idCommon = {
|
|
158
|
+
session_id: sessionId,
|
|
159
|
+
file: fileName,
|
|
160
|
+
};
|
|
161
|
+
if (turn !== null) idCommon.turn = turn;
|
|
162
|
+
|
|
163
|
+
// INV-1 trace_missing_field. Use hasOwnProperty so explicit `null` /
|
|
164
|
+
// 0 / '' / false / [] do NOT trip the check (Section 8 sentinels are
|
|
165
|
+
// valid values).
|
|
166
|
+
for (const field of REQUIRED_TRACE_FIELDS) {
|
|
167
|
+
if (!Object.prototype.hasOwnProperty.call(trace, field)) {
|
|
168
|
+
violations.push(makeViolation(
|
|
169
|
+
'trace_missing_field',
|
|
170
|
+
'decision_trace missing required Section 8 field "' + field +
|
|
171
|
+
'" in session ' + sessionId +
|
|
172
|
+
(turn !== null ? ' turn ' + turn : ''),
|
|
173
|
+
Object.assign({ field: field, action_hint: 'review_decision_trace_emitter' },
|
|
174
|
+
idCommon)
|
|
175
|
+
));
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// INV-2 recommended_in_wrong_mode. RECOMMENDED marker may render only
|
|
180
|
+
// when tier_mode === 'mode_a' per Canon Part 3 Section 6.
|
|
181
|
+
const rendered = trace.brain_md_recommended_marker_rendered;
|
|
182
|
+
const tierMode = trace.brain_md_tier_mode;
|
|
183
|
+
if (rendered === true && tierMode !== 'mode_a' &&
|
|
184
|
+
VALID_TIER_MODES.indexOf(tierMode) !== -1) {
|
|
185
|
+
violations.push(makeViolation(
|
|
186
|
+
'recommended_in_wrong_mode',
|
|
187
|
+
'RECOMMENDED marker rendered while tier_mode="' + tierMode +
|
|
188
|
+
'" (Canon Part 3 Section 6 requires mode_a) in session ' +
|
|
189
|
+
sessionId + (turn !== null ? ' turn ' + turn : ''),
|
|
190
|
+
Object.assign({ tier_mode: tierMode, action_hint: 'audit_recommended_gate' },
|
|
191
|
+
idCommon)
|
|
192
|
+
));
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// INV-3 weight_clamp_breach. brain_md_weight_applied in [0.0, 1.0].
|
|
196
|
+
const weight = trace.brain_md_weight_applied;
|
|
197
|
+
if (isFiniteNumber(weight) && (weight < 0.0 || weight > 1.0)) {
|
|
198
|
+
violations.push(makeViolation(
|
|
199
|
+
'weight_clamp_breach',
|
|
200
|
+
'brain_md_weight_applied=' + weight + ' outside [0.0, 1.0] in session ' +
|
|
201
|
+
sessionId + (turn !== null ? ' turn ' + turn : ''),
|
|
202
|
+
Object.assign({ weight_applied: weight, action_hint: 'enforce_clamp_at_emitter' },
|
|
203
|
+
idCommon)
|
|
204
|
+
));
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// INV-5 unknown_verb_passed. Only check when CANONICAL_VERBS available
|
|
208
|
+
// AND fire_skill is a non-empty string (absent/null fire_skill is
|
|
209
|
+
// valid: the engine emits null when no skill is recommended).
|
|
210
|
+
const verbs = getCanonicalVerbs();
|
|
211
|
+
if (verbs !== null && typeof trace.fire_skill === 'string' &&
|
|
212
|
+
trace.fire_skill.length > 0 && verbs.indexOf(trace.fire_skill) === -1) {
|
|
213
|
+
violations.push(makeViolation(
|
|
214
|
+
'unknown_verb_passed',
|
|
215
|
+
'fire_skill="' + trace.fire_skill +
|
|
216
|
+
'" is not in Canon Part 3 vocabulary (10 frozen verbs) in session ' +
|
|
217
|
+
sessionId + (turn !== null ? ' turn ' + turn : ''),
|
|
218
|
+
Object.assign({ fire_skill: trace.fire_skill,
|
|
219
|
+
action_hint: 'route_through_canonicalizeVerb' }, idCommon)
|
|
220
|
+
));
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// ---------- Main validate() ----------
|
|
225
|
+
|
|
226
|
+
function validateRoom(roomDir) {
|
|
227
|
+
const violations = [];
|
|
228
|
+
const tracesDir = path.join(roomDir, '.mindrian', 'decision-traces');
|
|
229
|
+
const files = safeReadDir(tracesDir);
|
|
230
|
+
|
|
231
|
+
if (files === null) {
|
|
232
|
+
// INV: no decision-traces dir. This is the healthy fresh-room state;
|
|
233
|
+
// surface as info so /mos:explain-decision telemetry has something
|
|
234
|
+
// benign to report rather than a confusing silence.
|
|
235
|
+
violations.push(makeViolation(
|
|
236
|
+
'session_file_absent',
|
|
237
|
+
'No decision traces recorded yet (fresh room or pre-engine state).',
|
|
238
|
+
{ action_hint: 'none' }
|
|
239
|
+
));
|
|
240
|
+
return finalize(violations);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (files.length === 0) {
|
|
244
|
+
// Directory exists but is empty. Treat the same as absent for
|
|
245
|
+
// signaling purposes.
|
|
246
|
+
violations.push(makeViolation(
|
|
247
|
+
'session_file_absent',
|
|
248
|
+
'decision-traces directory present but contains no session files.',
|
|
249
|
+
{ action_hint: 'none' }
|
|
250
|
+
));
|
|
251
|
+
return finalize(violations);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
for (const fname of files) {
|
|
255
|
+
const fullPath = path.join(tracesDir, fname);
|
|
256
|
+
let raw;
|
|
257
|
+
try {
|
|
258
|
+
raw = fs.readFileSync(fullPath, 'utf8');
|
|
259
|
+
} catch (e) {
|
|
260
|
+
// Read failure is treated as malformed: the file exists but cannot
|
|
261
|
+
// be processed. Continue to the next sibling.
|
|
262
|
+
violations.push(makeViolation(
|
|
263
|
+
'trace_file_malformed',
|
|
264
|
+
'decision-traces file "' + fname + '" could not be read: ' +
|
|
265
|
+
(e && e.message ? e.message : String(e)),
|
|
266
|
+
{ file: fname, action_hint: 'inspect_file_permissions' }
|
|
267
|
+
));
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
let parsed;
|
|
271
|
+
try {
|
|
272
|
+
parsed = JSON.parse(raw);
|
|
273
|
+
} catch (e) {
|
|
274
|
+
violations.push(makeViolation(
|
|
275
|
+
'trace_file_malformed',
|
|
276
|
+
'decision-traces file "' + fname + '" is not valid JSON: ' +
|
|
277
|
+
(e && e.message ? e.message : String(e)),
|
|
278
|
+
{ file: fname, action_hint: 'rotate_or_remove_corrupt_trace' }
|
|
279
|
+
));
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
if (!parsed || typeof parsed !== 'object') {
|
|
283
|
+
violations.push(makeViolation(
|
|
284
|
+
'trace_file_malformed',
|
|
285
|
+
'decision-traces file "' + fname + '" did not parse to an object.',
|
|
286
|
+
{ file: fname, action_hint: 'rotate_or_remove_corrupt_trace' }
|
|
287
|
+
));
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
const sessionId = (typeof parsed.session_id === 'string' &&
|
|
291
|
+
parsed.session_id.length > 0) ? parsed.session_id : fname.replace(/\.json$/i, '');
|
|
292
|
+
const traces = Array.isArray(parsed.traces) ? parsed.traces : [];
|
|
293
|
+
for (const t of traces) {
|
|
294
|
+
checkTraceEntry(t, sessionId, fname, violations);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
return finalize(violations);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function finalize(violations) {
|
|
302
|
+
// Aggregate severity for guardian's per-validator summary line.
|
|
303
|
+
const order = ['info', 'warning', 'error', 'critical'];
|
|
304
|
+
let max = -1;
|
|
305
|
+
for (const v of violations) {
|
|
306
|
+
const i = order.indexOf(v.severity);
|
|
307
|
+
if (i > max) max = i;
|
|
308
|
+
}
|
|
309
|
+
return {
|
|
310
|
+
severity: max === -1 ? null : order[max],
|
|
311
|
+
violations: violations,
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// ---------- Exports ----------
|
|
316
|
+
|
|
317
|
+
module.exports = {
|
|
318
|
+
id: 'navigation-invariants',
|
|
319
|
+
severity_map: SEVERITY_MAP,
|
|
320
|
+
scope: 'room',
|
|
321
|
+
validate: function (sectionDirOrRoomDir, ctx) {
|
|
322
|
+
// Phase 88-13 contract: when scope === 'room' the guardian invokes
|
|
323
|
+
// validate(roomDir, ctx). For defensive symmetry with the other
|
|
324
|
+
// room-scoped validators (snapshot-integrity, queue-health,
|
|
325
|
+
// stale-lifecycle), prefer ctx.roomDir when available.
|
|
326
|
+
const roomDir = (ctx && typeof ctx.roomDir === 'string' && ctx.roomDir.length > 0)
|
|
327
|
+
? ctx.roomDir
|
|
328
|
+
: sectionDirOrRoomDir;
|
|
329
|
+
if (typeof roomDir !== 'string' || roomDir.length === 0) {
|
|
330
|
+
return { severity: null, violations: [] };
|
|
331
|
+
}
|
|
332
|
+
return validateRoom(roomDir);
|
|
333
|
+
},
|
|
334
|
+
// Internal exports for tests (not part of the registry contract; the
|
|
335
|
+
// guardian ignores extra keys):
|
|
336
|
+
__internal: {
|
|
337
|
+
REQUIRED_TRACE_FIELDS: REQUIRED_TRACE_FIELDS,
|
|
338
|
+
VALID_TIER_MODES: VALID_TIER_MODES,
|
|
339
|
+
},
|
|
340
|
+
};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026 Mindrian. BSL 1.1.
|
|
3
|
+
* Phase 88-13 MEM-GUARDIAN-QUEUE-01.
|
|
4
|
+
*
|
|
5
|
+
* Enforces size ceilings on the minto-debouncer queue
|
|
6
|
+
* (.mindrian/minto-queue.json shipped by 88-02). Without this validator,
|
|
7
|
+
* unbounded queue growth (drain never fires) accumulates silently for
|
|
8
|
+
* hundreds of sessions before anyone notices. This converts the silent
|
|
9
|
+
* growth into a visible session-start signal.
|
|
10
|
+
*
|
|
11
|
+
* Thresholds:
|
|
12
|
+
* entries < 500 healthy, no violation
|
|
13
|
+
* entries >= 500 && <= 999 warning queue_approaching_ceiling
|
|
14
|
+
* entries >= 1000 error queue_ceiling_exceeded +
|
|
15
|
+
* action_hint halt_enqueue_until_drained
|
|
16
|
+
*
|
|
17
|
+
* Emits at most ONE aggregate violation per invocation (not N per entry).
|
|
18
|
+
* Missing queue file -> no violation (healthy first-session state).
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
'use strict';
|
|
22
|
+
|
|
23
|
+
const fs = require('node:fs');
|
|
24
|
+
const path = require('node:path');
|
|
25
|
+
|
|
26
|
+
const SEVERITY_MAP = { critical: 3, error: 2, warning: 1, info: 0 };
|
|
27
|
+
const WARN_THRESHOLD = 500;
|
|
28
|
+
const ERROR_THRESHOLD = 1000;
|
|
29
|
+
const ROOM_SCOPE = '__room__';
|
|
30
|
+
|
|
31
|
+
function validateRoom(roomDir) {
|
|
32
|
+
const qp = path.join(roomDir, '.mindrian', 'minto-queue.json');
|
|
33
|
+
if (!fs.existsSync(qp)) {
|
|
34
|
+
return { severity: null, violations: [] };
|
|
35
|
+
}
|
|
36
|
+
let parsed;
|
|
37
|
+
try {
|
|
38
|
+
parsed = JSON.parse(fs.readFileSync(qp, 'utf8'));
|
|
39
|
+
} catch (_) {
|
|
40
|
+
// Malformed queue file is a silent-failure signal in its own right.
|
|
41
|
+
return {
|
|
42
|
+
severity: 'warning',
|
|
43
|
+
violations: [{
|
|
44
|
+
validator: 'queue-health',
|
|
45
|
+
category: 'queue_unparseable',
|
|
46
|
+
severity: 'warning',
|
|
47
|
+
message: 'minto-queue.json is unparseable; debouncer self-healed or writer crashed',
|
|
48
|
+
scope: ROOM_SCOPE,
|
|
49
|
+
}],
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
const entries = (parsed && Array.isArray(parsed.entries)) ? parsed.entries : [];
|
|
53
|
+
const count = entries.length;
|
|
54
|
+
if (count < WARN_THRESHOLD) {
|
|
55
|
+
return { severity: null, violations: [] };
|
|
56
|
+
}
|
|
57
|
+
if (count >= ERROR_THRESHOLD) {
|
|
58
|
+
return {
|
|
59
|
+
severity: 'error',
|
|
60
|
+
violations: [{
|
|
61
|
+
validator: 'queue-health',
|
|
62
|
+
category: 'queue_ceiling_exceeded',
|
|
63
|
+
severity: 'error',
|
|
64
|
+
message: 'minto-debouncer queue at ' + count +
|
|
65
|
+
' entries, ceiling ' + ERROR_THRESHOLD,
|
|
66
|
+
action_hint: 'halt_enqueue_until_drained',
|
|
67
|
+
count: count,
|
|
68
|
+
scope: ROOM_SCOPE,
|
|
69
|
+
}],
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
severity: 'warning',
|
|
74
|
+
violations: [{
|
|
75
|
+
validator: 'queue-health',
|
|
76
|
+
category: 'queue_approaching_ceiling',
|
|
77
|
+
severity: 'warning',
|
|
78
|
+
message: 'minto-debouncer queue at ' + count +
|
|
79
|
+
' entries, ceiling ' + ERROR_THRESHOLD,
|
|
80
|
+
action_hint: 'drain_soon',
|
|
81
|
+
count: count,
|
|
82
|
+
scope: ROOM_SCOPE,
|
|
83
|
+
}],
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
module.exports = {
|
|
88
|
+
id: 'queue-health',
|
|
89
|
+
severity_map: SEVERITY_MAP,
|
|
90
|
+
scope: 'room',
|
|
91
|
+
validate: function (sectionDirOrRoomDir, ctx) {
|
|
92
|
+
const roomDir = (ctx && ctx.roomDir) ? ctx.roomDir : sectionDirOrRoomDir;
|
|
93
|
+
return validateRoom(roomDir);
|
|
94
|
+
},
|
|
95
|
+
};
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026 Mindrian. BSL 1.1.
|
|
3
|
+
* Phase 88-13 MEM-GUARDIAN-SNAPSHOT-01.
|
|
4
|
+
*
|
|
5
|
+
* Detects partial session-snapshot.json produced by an on-stop walk that
|
|
6
|
+
* crashed mid-iteration before the atomic rename landed. Without this
|
|
7
|
+
* validator the drift stays silent for 20+ sessions (no visible
|
|
8
|
+
* TRIPLE_CONTEXT entry for the affected section, but user never sees why).
|
|
9
|
+
*
|
|
10
|
+
* Signals emitted:
|
|
11
|
+
* partial_snapshot warning per missing section, action_hint
|
|
12
|
+
* 'partial_snapshot_detected'
|
|
13
|
+
* snapshot_empty error when snapshot has zero sections but the
|
|
14
|
+
* room has at least one ROOM.md section on disk.
|
|
15
|
+
* Action hint 'rerun_on_stop'.
|
|
16
|
+
* (missing file) silent: no violation. Healthy first-session.
|
|
17
|
+
*
|
|
18
|
+
* Emits violations against a synthetic section key `__room__` so the
|
|
19
|
+
* guardian aggregator can surface them without tying them to a specific
|
|
20
|
+
* section (they are a room-wide health signal).
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
'use strict';
|
|
24
|
+
|
|
25
|
+
const fs = require('node:fs');
|
|
26
|
+
const path = require('node:path');
|
|
27
|
+
|
|
28
|
+
const SEVERITY_MAP = { critical: 3, error: 2, warning: 1, info: 0 };
|
|
29
|
+
const ROOM_SCOPE = '__room__';
|
|
30
|
+
|
|
31
|
+
function safeReadSections(roomDir) {
|
|
32
|
+
// Returns an array of section dir names that hold a ROOM.md, per the
|
|
33
|
+
// ICM Layer 0 identity invariant (CLAUDE.md decision #15).
|
|
34
|
+
try {
|
|
35
|
+
return fs.readdirSync(roomDir, { withFileTypes: true })
|
|
36
|
+
.filter(function (d) { return d.isDirectory() && d.name[0] !== '.'; })
|
|
37
|
+
.filter(function (d) {
|
|
38
|
+
try {
|
|
39
|
+
return fs.existsSync(path.join(roomDir, d.name, 'ROOM.md'));
|
|
40
|
+
} catch (_) { return false; }
|
|
41
|
+
})
|
|
42
|
+
.map(function (d) { return d.name; });
|
|
43
|
+
} catch (_) {
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function validateRoom(roomDir) {
|
|
49
|
+
const snapPath = path.join(roomDir, '.mindrian', 'session-snapshot.json');
|
|
50
|
+
if (!fs.existsSync(snapPath)) {
|
|
51
|
+
return { severity: null, violations: [] };
|
|
52
|
+
}
|
|
53
|
+
let parsed;
|
|
54
|
+
try {
|
|
55
|
+
const raw = fs.readFileSync(snapPath, 'utf8');
|
|
56
|
+
parsed = JSON.parse(raw);
|
|
57
|
+
} catch (_) {
|
|
58
|
+
// Malformed JSON surfaced as error (silent-to-loud conversion).
|
|
59
|
+
return {
|
|
60
|
+
severity: 'error',
|
|
61
|
+
violations: [{
|
|
62
|
+
validator: 'snapshot-integrity',
|
|
63
|
+
category: 'snapshot_unparseable',
|
|
64
|
+
severity: 'error',
|
|
65
|
+
message: 'session-snapshot.json is unparseable; on-stop likely crashed',
|
|
66
|
+
action_hint: 'rerun_on_stop',
|
|
67
|
+
scope: ROOM_SCOPE,
|
|
68
|
+
}],
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
const snapSections = (parsed && parsed.sections && typeof parsed.sections === 'object')
|
|
72
|
+
? Object.keys(parsed.sections)
|
|
73
|
+
: [];
|
|
74
|
+
const diskSections = safeReadSections(roomDir);
|
|
75
|
+
|
|
76
|
+
const violations = [];
|
|
77
|
+
if (snapSections.length === 0 && diskSections.length > 0) {
|
|
78
|
+
violations.push({
|
|
79
|
+
validator: 'snapshot-integrity',
|
|
80
|
+
category: 'snapshot_empty',
|
|
81
|
+
severity: 'error',
|
|
82
|
+
message: 'on-stop walk crashed or never ran: snapshot empty while room has ' +
|
|
83
|
+
diskSections.length + ' section' + (diskSections.length === 1 ? '' : 's'),
|
|
84
|
+
action_hint: 'rerun_on_stop',
|
|
85
|
+
scope: ROOM_SCOPE,
|
|
86
|
+
});
|
|
87
|
+
} else {
|
|
88
|
+
const snapSet = new Set(snapSections);
|
|
89
|
+
for (const d of diskSections) {
|
|
90
|
+
if (!snapSet.has(d)) {
|
|
91
|
+
violations.push({
|
|
92
|
+
validator: 'snapshot-integrity',
|
|
93
|
+
category: 'partial_snapshot',
|
|
94
|
+
severity: 'warning',
|
|
95
|
+
message: 'section "' + d + '" exists on disk but missing from session-snapshot.json',
|
|
96
|
+
action_hint: 'partial_snapshot_detected',
|
|
97
|
+
scope: ROOM_SCOPE,
|
|
98
|
+
section: d,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// Aggregate severity
|
|
104
|
+
let max = -1;
|
|
105
|
+
const order = ['info', 'warning', 'error', 'critical'];
|
|
106
|
+
for (const v of violations) {
|
|
107
|
+
const i = order.indexOf(v.severity);
|
|
108
|
+
if (i > max) max = i;
|
|
109
|
+
}
|
|
110
|
+
return {
|
|
111
|
+
severity: max === -1 ? null : order[max],
|
|
112
|
+
violations: violations,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
module.exports = {
|
|
117
|
+
id: 'snapshot-integrity',
|
|
118
|
+
severity_map: SEVERITY_MAP,
|
|
119
|
+
// Section-scoped validators get a sectionDir; this one is room-scoped so
|
|
120
|
+
// the guardian invokes it once per room (sectionDir parameter is ignored
|
|
121
|
+
// when context.scope === 'room'). The guardian honors a special
|
|
122
|
+
// `scope: 'room'` field so we do not duplicate work across N sections.
|
|
123
|
+
scope: 'room',
|
|
124
|
+
validate: function (sectionDirOrRoomDir, ctx) {
|
|
125
|
+
// The guardian always passes the room path when scope === 'room'.
|
|
126
|
+
const roomDir = (ctx && ctx.roomDir) ? ctx.roomDir : sectionDirOrRoomDir;
|
|
127
|
+
return validateRoom(roomDir);
|
|
128
|
+
},
|
|
129
|
+
};
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026 Mindrian. BSL 1.1.
|
|
3
|
+
* Phase 88-13 MEM-GUARDIAN-STALE-01.
|
|
4
|
+
*
|
|
5
|
+
* Re-validates every .mindrian/minto-stale.json entry (written by 88-06
|
|
6
|
+
* for sections whose MINTO couldn't regen) against the current MINTO
|
|
7
|
+
* state. A stale entry whose section now has a valid MINTO is a GHOST:
|
|
8
|
+
* the ledger lies. This validator emits a warning per ghost so the
|
|
9
|
+
* on-stop mode of the guardian can prune the ghost atomically. Without
|
|
10
|
+
* this, ghost entries linger forever and pollute session-start footers
|
|
11
|
+
* with false alarms.
|
|
12
|
+
*
|
|
13
|
+
* Signals:
|
|
14
|
+
* stale_ghost (warning) entry lists section X but invariants.validate(X)
|
|
15
|
+
* is now clean. Carries section name + action_hint
|
|
16
|
+
* 'prune_stale_entry'. Consumed by guardian on-stop
|
|
17
|
+
* mode to rewrite stale.json atomically.
|
|
18
|
+
* (MINTO still invalid) no new violation; real staleness is already
|
|
19
|
+
* surfaced by the stale.json consumer (88-07).
|
|
20
|
+
* (missing stale.json) no violation; healthy.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
'use strict';
|
|
24
|
+
|
|
25
|
+
const fs = require('node:fs');
|
|
26
|
+
const path = require('node:path');
|
|
27
|
+
|
|
28
|
+
const SEVERITY_MAP = { critical: 3, error: 2, warning: 1, info: 0 };
|
|
29
|
+
const ROOM_SCOPE = '__room__';
|
|
30
|
+
|
|
31
|
+
const { validate: invariantsValidate } = require('../../core/feynman-minto-invariants.cjs');
|
|
32
|
+
|
|
33
|
+
function validateRoom(roomDir) {
|
|
34
|
+
const stalePath = path.join(roomDir, '.mindrian', 'minto-stale.json');
|
|
35
|
+
if (!fs.existsSync(stalePath)) {
|
|
36
|
+
return { severity: null, violations: [] };
|
|
37
|
+
}
|
|
38
|
+
let parsed;
|
|
39
|
+
try {
|
|
40
|
+
parsed = JSON.parse(fs.readFileSync(stalePath, 'utf8'));
|
|
41
|
+
} catch (_) {
|
|
42
|
+
return {
|
|
43
|
+
severity: 'warning',
|
|
44
|
+
violations: [{
|
|
45
|
+
validator: 'stale-lifecycle',
|
|
46
|
+
category: 'stale_file_unparseable',
|
|
47
|
+
severity: 'warning',
|
|
48
|
+
message: 'minto-stale.json is unparseable',
|
|
49
|
+
scope: ROOM_SCOPE,
|
|
50
|
+
}],
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
const list = (parsed && Array.isArray(parsed.sections)) ? parsed.sections : [];
|
|
54
|
+
const violations = [];
|
|
55
|
+
// Reasons owned by the invariants module. Only these reasons are
|
|
56
|
+
// candidates for ghost detection via re-validation. Other reasons
|
|
57
|
+
// (never_generated, missing_timestamps, artifacts_newer_than_minto) are
|
|
58
|
+
// signaled by folder-memory.computeStale() independently of invariants
|
|
59
|
+
// state -- re-running invariants won't learn anything about them and
|
|
60
|
+
// pruning based on invariant cleanliness would erase real signals.
|
|
61
|
+
const INVARIANT_OWNED_REASONS = new Set(['invariant_violation', 'parse_failed']);
|
|
62
|
+
for (const entry of list) {
|
|
63
|
+
if (!entry || typeof entry !== 'object') continue;
|
|
64
|
+
const section = entry.section;
|
|
65
|
+
if (typeof section !== 'string' || section.length === 0) continue;
|
|
66
|
+
const reason = typeof entry.reason === 'string' ? entry.reason : '';
|
|
67
|
+
if (!INVARIANT_OWNED_REASONS.has(reason)) {
|
|
68
|
+
// Skip entries whose reason is not owned by the invariants module;
|
|
69
|
+
// folder-memory is the authoritative source for these, and pruning
|
|
70
|
+
// would erase valid staleness. These stay in stale.json until the
|
|
71
|
+
// originating producer (88-06 on-stop walk) removes them.
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const mintoPath = path.join(roomDir, section, 'MINTO.md');
|
|
75
|
+
if (!fs.existsSync(mintoPath)) continue;
|
|
76
|
+
let result;
|
|
77
|
+
try { result = invariantsValidate(mintoPath); }
|
|
78
|
+
catch (_) { continue; }
|
|
79
|
+
// Ghost condition: MINTO is fully invariant-clean. If ANY violation
|
|
80
|
+
// survives (including freshness/coherence warnings), the section is
|
|
81
|
+
// still stale and must NOT be pruned.
|
|
82
|
+
const violationsList = (result && result.violations) || [];
|
|
83
|
+
if (violationsList.length === 0) {
|
|
84
|
+
violations.push({
|
|
85
|
+
validator: 'stale-lifecycle',
|
|
86
|
+
category: 'stale_ghost',
|
|
87
|
+
severity: 'warning',
|
|
88
|
+
message: 'stale.json lists "' + section + '" (reason=' + reason +
|
|
89
|
+
') but MINTO is now invariant-clean',
|
|
90
|
+
action_hint: 'prune_stale_entry',
|
|
91
|
+
section: section,
|
|
92
|
+
scope: ROOM_SCOPE,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
let max = -1;
|
|
97
|
+
const order = ['info', 'warning', 'error', 'critical'];
|
|
98
|
+
for (const v of violations) {
|
|
99
|
+
const i = order.indexOf(v.severity);
|
|
100
|
+
if (i > max) max = i;
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
severity: max === -1 ? null : order[max],
|
|
104
|
+
violations: violations,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
module.exports = {
|
|
109
|
+
id: 'stale-lifecycle',
|
|
110
|
+
severity_map: SEVERITY_MAP,
|
|
111
|
+
scope: 'room',
|
|
112
|
+
validate: function (sectionDirOrRoomDir, ctx) {
|
|
113
|
+
const roomDir = (ctx && ctx.roomDir) ? ctx.roomDir : sectionDirOrRoomDir;
|
|
114
|
+
return validateRoom(roomDir);
|
|
115
|
+
},
|
|
116
|
+
};
|