@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,515 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
* Copyright (c) 2026 Mindrian. BSL 1.1.
|
|
6
|
+
*
|
|
7
|
+
* Phase 91-08 -- Framework Chain Composer fixture tests
|
|
8
|
+
* ======================================================
|
|
9
|
+
* Exercises lib/core/framework-chain-composer.cjs. The composer parses
|
|
10
|
+
* BRAIN.md framework_chain_predictions section bodies (FEEDS_INTO edges
|
|
11
|
+
* authored by Phase 90-01 deriveSection) and proposes the next framework
|
|
12
|
+
* to run when the user just completed framework A.
|
|
13
|
+
*
|
|
14
|
+
* Canon Part 2 Engine 1 + Appendix E: framework chains power Act 1 to
|
|
15
|
+
* BONO Orchestration handoffs; FEEDS_INTO is the graph infrastructure.
|
|
16
|
+
*
|
|
17
|
+
* Canon Part 3 Section 6 RECOMMENDED gate: chain proposals respect the
|
|
18
|
+
* gate (Mode A + confidence >= 0.7 -> recommended_eligible:true). The
|
|
19
|
+
* gate result is consumed by offer-presenter.cjs (Plan 91-04).
|
|
20
|
+
*
|
|
21
|
+
* Canon Part 7 Reuse Before Build: FEEDS_INTO edges are existing graph
|
|
22
|
+
* infrastructure. This module CONSUMES them; it does not invent a chain
|
|
23
|
+
* representation.
|
|
24
|
+
*
|
|
25
|
+
* Canon Part 8 Graph Boundary: composer reads only the LOCAL BRAIN.md
|
|
26
|
+
* body via readQuadruple.brain.sections. NEVER queries Brain at engine
|
|
27
|
+
* time. The pre-derivation ran in Phase 90-01 inside the Plan 90-01
|
|
28
|
+
* chokepoint, hours before this code runs.
|
|
29
|
+
*
|
|
30
|
+
* Test map:
|
|
31
|
+
* Task 1 (Tests 1-15): parser + completion detection + chain proposal
|
|
32
|
+
* 1. parseFrameworkChainSection 4 FEEDS_INTO lines -> 4 edges
|
|
33
|
+
* 2. parseFrameworkChainSection (no signal) -> []
|
|
34
|
+
* 3. parseFrameworkChainSection format-tolerant (FEEDS_INTO + ->)
|
|
35
|
+
* 4. parseFrameworkChainSection missing confidence -> null edge.confidence
|
|
36
|
+
* 5. detectCompletedFramework via governing_thought match
|
|
37
|
+
* 6. detectCompletedFramework mtime fallback
|
|
38
|
+
* 7. detectCompletedFramework no signal -> null
|
|
39
|
+
* 8. proposeNextFramework happy path -> {next, confidence, source}
|
|
40
|
+
* 9. proposeNextFramework no outgoing edge -> null
|
|
41
|
+
* 10. proposeNextFramework confidence gating (<0.5 -> null)
|
|
42
|
+
* 11. proposeNextFramework tie-breaking by confidence desc
|
|
43
|
+
* 12. proposeNextFramework /mos: command mapping
|
|
44
|
+
* 13. proposeNextFramework grounding rule (reason has FEEDS_INTO + Brain + conf)
|
|
45
|
+
* 14. proposeNextFramework RECOMMENDED eligibility flag
|
|
46
|
+
* 15. proposeNextFramework empty edges -> null
|
|
47
|
+
*
|
|
48
|
+
* Task 2 (Tests 16-18): navigation-engine.cjs decide() integration
|
|
49
|
+
* 16. decide() with chain section + governing_thought -> offer_next_step
|
|
50
|
+
* non-null + reason contains 'FEEDS_INTO'
|
|
51
|
+
* 17. decide() Mode A confidence 0.85 -> recommended_eligible flag set
|
|
52
|
+
* in trace; offer-presenter would render RECOMMENDED marker
|
|
53
|
+
* 18. decide() user override path: turn 1 offers /mos:porter-five-forces;
|
|
54
|
+
* turn 2 userText invokes /mos:lean-canvas -> trace records
|
|
55
|
+
* REJECTED chain suggestion + offer-history outcome=ignored
|
|
56
|
+
*
|
|
57
|
+
* Registered in lib/memory/run-feynman-tests.cjs.
|
|
58
|
+
*/
|
|
59
|
+
|
|
60
|
+
const assert = require('node:assert/strict');
|
|
61
|
+
const fs = require('node:fs');
|
|
62
|
+
const path = require('node:path');
|
|
63
|
+
const os = require('node:os');
|
|
64
|
+
|
|
65
|
+
const REPO = path.resolve(__dirname, '..', '..');
|
|
66
|
+
const COMPOSER_PATH = path.join(REPO, 'lib/core/framework-chain-composer.cjs');
|
|
67
|
+
const ENGINE_PATH = path.join(REPO, 'lib/core/navigation-engine.cjs');
|
|
68
|
+
|
|
69
|
+
function requireComposer() {
|
|
70
|
+
return require(COMPOSER_PATH);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function requireEngine() {
|
|
74
|
+
return require(ENGINE_PATH);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// ---------- Test scaffolding ----------
|
|
78
|
+
|
|
79
|
+
let passed = 0;
|
|
80
|
+
let failed = 0;
|
|
81
|
+
function run(name, fn) {
|
|
82
|
+
try {
|
|
83
|
+
fn();
|
|
84
|
+
process.stdout.write('ok ' + name + '\n');
|
|
85
|
+
passed += 1;
|
|
86
|
+
} catch (err) {
|
|
87
|
+
process.stderr.write('FAIL ' + name + '\n');
|
|
88
|
+
process.stderr.write(String(err && err.stack ? err.stack : err) + '\n');
|
|
89
|
+
failed += 1;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// ---------- Section-body fixture helpers ----------
|
|
94
|
+
|
|
95
|
+
function makeChainSection(bodyText) {
|
|
96
|
+
if (bodyText === null) return null;
|
|
97
|
+
return { body: bodyText, tokens_estimate: Math.max(1, Math.ceil(bodyText.length / 4)) };
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const SAMPLE_4_LINES = [
|
|
101
|
+
'- SWOT Analysis FEEDS_INTO Porter Five Forces (confidence: 0.85, phase: early-market)',
|
|
102
|
+
'- Porter Five Forces FEEDS_INTO Value Chain Analysis (confidence: 0.78, phase: early-market)',
|
|
103
|
+
'- Business Model Canvas FEEDS_INTO Lean Canvas (confidence: 0.82, phase: thesis-build)',
|
|
104
|
+
'- Jobs-to-be-Done FEEDS_INTO Value Proposition Canvas (confidence: 0.90, phase: pre-opportunity)',
|
|
105
|
+
].join('\n');
|
|
106
|
+
|
|
107
|
+
// =========================================================
|
|
108
|
+
// Task 1 -- parser + completion detection + proposal (Tests 1..15)
|
|
109
|
+
// =========================================================
|
|
110
|
+
|
|
111
|
+
run('Test 1: parseFrameworkChainSection 4 FEEDS_INTO lines -> 4 edges', () => {
|
|
112
|
+
const { parseFrameworkChainSection } = requireComposer();
|
|
113
|
+
const section = makeChainSection(SAMPLE_4_LINES);
|
|
114
|
+
const edges = parseFrameworkChainSection(section);
|
|
115
|
+
assert.equal(Array.isArray(edges), true);
|
|
116
|
+
assert.equal(edges.length, 4, 'expected 4 edges; got ' + edges.length);
|
|
117
|
+
// Each edge has the four expected fields.
|
|
118
|
+
for (const e of edges) {
|
|
119
|
+
assert.equal(typeof e.from, 'string');
|
|
120
|
+
assert.equal(typeof e.to, 'string');
|
|
121
|
+
assert.equal(typeof e.confidence === 'number' || e.confidence === null, true);
|
|
122
|
+
// phase_indicator may be null when not present; in this fixture all
|
|
123
|
+
// four lines provide one.
|
|
124
|
+
assert.equal(typeof e.phase_indicator === 'string' || e.phase_indicator === null, true);
|
|
125
|
+
}
|
|
126
|
+
// Spot-check the first edge.
|
|
127
|
+
assert.equal(edges[0].from, 'SWOT Analysis');
|
|
128
|
+
assert.equal(edges[0].to, 'Porter Five Forces');
|
|
129
|
+
assert.equal(Math.abs(edges[0].confidence - 0.85) < 1e-9, true);
|
|
130
|
+
assert.equal(edges[0].phase_indicator, 'early-market');
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
run('Test 2: parseFrameworkChainSection (no signal) -> []', () => {
|
|
134
|
+
const { parseFrameworkChainSection } = requireComposer();
|
|
135
|
+
const section = makeChainSection('(no signal)');
|
|
136
|
+
const edges = parseFrameworkChainSection(section);
|
|
137
|
+
assert.equal(Array.isArray(edges), true);
|
|
138
|
+
assert.equal(edges.length, 0);
|
|
139
|
+
// Also null section.
|
|
140
|
+
assert.deepEqual(parseFrameworkChainSection(null), []);
|
|
141
|
+
// Also undefined.
|
|
142
|
+
assert.deepEqual(parseFrameworkChainSection(undefined), []);
|
|
143
|
+
// Also empty body.
|
|
144
|
+
assert.deepEqual(parseFrameworkChainSection({ body: '', tokens_estimate: 0 }), []);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
run('Test 3: parseFrameworkChainSection tolerant format (FEEDS_INTO + arrow)', () => {
|
|
148
|
+
const { parseFrameworkChainSection } = requireComposer();
|
|
149
|
+
// Mix: FEEDS_INTO form + arrow form. Arrow form drops the phase indicator.
|
|
150
|
+
const body = [
|
|
151
|
+
'- SWOT FEEDS_INTO Porter (confidence: 0.8)',
|
|
152
|
+
'- Lean Canvas -> Value Proposition Canvas (confidence: 0.7)',
|
|
153
|
+
].join('\n');
|
|
154
|
+
const edges = parseFrameworkChainSection(makeChainSection(body));
|
|
155
|
+
assert.equal(edges.length, 2, 'expected 2 edges; got ' + edges.length);
|
|
156
|
+
// Both should parse with valid confidence numbers.
|
|
157
|
+
assert.equal(typeof edges[0].confidence, 'number');
|
|
158
|
+
assert.equal(typeof edges[1].confidence, 'number');
|
|
159
|
+
// From/to extracted (whitespace-trimmed; case preserved).
|
|
160
|
+
assert.equal(edges[0].from, 'SWOT');
|
|
161
|
+
assert.equal(edges[0].to, 'Porter');
|
|
162
|
+
assert.equal(edges[1].from, 'Lean Canvas');
|
|
163
|
+
assert.equal(edges[1].to, 'Value Proposition Canvas');
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
run('Test 4: parseFrameworkChainSection missing confidence -> null edge.confidence (not filtered)', () => {
|
|
167
|
+
const { parseFrameworkChainSection } = requireComposer();
|
|
168
|
+
// Confidence absent. The edge MUST still parse so callers see the
|
|
169
|
+
// structural FEEDS_INTO relationship; downstream gating decides what
|
|
170
|
+
// to do with null confidence.
|
|
171
|
+
const body = '- SWOT Analysis FEEDS_INTO Porter Five Forces';
|
|
172
|
+
const edges = parseFrameworkChainSection(makeChainSection(body));
|
|
173
|
+
// Either the parser tolerantly emits an edge with null confidence,
|
|
174
|
+
// OR (acceptable) the parser drops it. The plan requires "not
|
|
175
|
+
// filtered", so we assert the edge survives.
|
|
176
|
+
assert.equal(edges.length >= 1, true,
|
|
177
|
+
'parser should preserve edge with missing confidence; got 0 edges');
|
|
178
|
+
const e = edges[0];
|
|
179
|
+
assert.equal(e.from, 'SWOT Analysis');
|
|
180
|
+
assert.equal(e.to, 'Porter Five Forces');
|
|
181
|
+
assert.equal(e.confidence, null);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
run('Test 5: detectCompletedFramework via governing_thought match', () => {
|
|
185
|
+
const { detectCompletedFramework } = requireComposer();
|
|
186
|
+
// Reasoning fixture contains "SWOT Analysis" in governing_thought.
|
|
187
|
+
const reasoning = {
|
|
188
|
+
exists: true,
|
|
189
|
+
governing_thought: 'After running our SWOT Analysis we identified two threats.',
|
|
190
|
+
reasoning_health_score: 0.8,
|
|
191
|
+
is_stale: false,
|
|
192
|
+
arguments: [],
|
|
193
|
+
};
|
|
194
|
+
const result = detectCompletedFramework('/tmp/nonexistent', '/tmp/nonexistent/section', reasoning);
|
|
195
|
+
assert.equal(result, 'SWOT Analysis',
|
|
196
|
+
'should detect SWOT Analysis from governing_thought; got: ' + result);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
run('Test 6: detectCompletedFramework mtime fallback', () => {
|
|
200
|
+
const { detectCompletedFramework } = requireComposer();
|
|
201
|
+
// Build a tmp section dir with a recently-touched file matching a
|
|
202
|
+
// framework slug. Reasoning is empty so the fallback path runs.
|
|
203
|
+
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'p91-08-mtime-'));
|
|
204
|
+
try {
|
|
205
|
+
const sectionDir = path.join(tmpRoot, 'market-analysis');
|
|
206
|
+
fs.mkdirSync(sectionDir, { recursive: true });
|
|
207
|
+
// File slug matching a known framework (lean-canvas).
|
|
208
|
+
fs.writeFileSync(path.join(sectionDir, 'lean-canvas.md'), '# Lean Canvas\n');
|
|
209
|
+
// Touch mtime so it's clearly within window.
|
|
210
|
+
const now = Date.now();
|
|
211
|
+
fs.utimesSync(path.join(sectionDir, 'lean-canvas.md'), now / 1000, now / 1000);
|
|
212
|
+
|
|
213
|
+
const reasoning = {
|
|
214
|
+
exists: true,
|
|
215
|
+
governing_thought: 'Some thought without any framework name in it.',
|
|
216
|
+
reasoning_health_score: 0.5,
|
|
217
|
+
is_stale: false,
|
|
218
|
+
arguments: [],
|
|
219
|
+
};
|
|
220
|
+
const result = detectCompletedFramework(tmpRoot, sectionDir, reasoning);
|
|
221
|
+
// Should match the lean-canvas slug -> 'Lean Canvas' (or any
|
|
222
|
+
// canonical name; here we accept any non-null match).
|
|
223
|
+
assert.equal(result !== null, true,
|
|
224
|
+
'mtime fallback should detect framework slug; got: ' + result);
|
|
225
|
+
assert.equal(/lean.?canvas/i.test(result), true,
|
|
226
|
+
'detected framework should reference Lean Canvas; got: ' + result);
|
|
227
|
+
} finally {
|
|
228
|
+
try { fs.rmSync(tmpRoot, { recursive: true, force: true }); } catch (_) {}
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
run('Test 7: detectCompletedFramework no signal -> null', () => {
|
|
233
|
+
const { detectCompletedFramework } = requireComposer();
|
|
234
|
+
// Empty reasoning + no section dir.
|
|
235
|
+
const reasoning = {
|
|
236
|
+
exists: true,
|
|
237
|
+
governing_thought: 'No framework names here, just prose about widgets.',
|
|
238
|
+
reasoning_health_score: 0.5,
|
|
239
|
+
is_stale: false,
|
|
240
|
+
arguments: [],
|
|
241
|
+
};
|
|
242
|
+
const result = detectCompletedFramework('/tmp/nonexistent-' + Date.now(), '/tmp/nonexistent-' + Date.now() + '/x', reasoning);
|
|
243
|
+
assert.equal(result, null);
|
|
244
|
+
// Also null reasoning.
|
|
245
|
+
assert.equal(detectCompletedFramework('/tmp/nope', '/tmp/nope/x', null), null);
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
run('Test 8: proposeNextFramework happy path', () => {
|
|
249
|
+
const { parseFrameworkChainSection, proposeNextFramework } = requireComposer();
|
|
250
|
+
const edges = parseFrameworkChainSection(makeChainSection(SAMPLE_4_LINES));
|
|
251
|
+
const out = proposeNextFramework('SWOT Analysis', edges);
|
|
252
|
+
assert.equal(out !== null, true);
|
|
253
|
+
assert.equal(out.next, 'Porter Five Forces');
|
|
254
|
+
assert.equal(Math.abs(out.confidence - 0.85) < 1e-9, true);
|
|
255
|
+
assert.equal(out.source, 'FEEDS_INTO');
|
|
256
|
+
assert.equal(out.phase_indicator, 'early-market');
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
run('Test 9: proposeNextFramework no outgoing edge -> null', () => {
|
|
260
|
+
const { parseFrameworkChainSection, proposeNextFramework } = requireComposer();
|
|
261
|
+
const edges = parseFrameworkChainSection(makeChainSection(SAMPLE_4_LINES));
|
|
262
|
+
// SAMPLE_4_LINES has no outgoing edge from "Random Framework".
|
|
263
|
+
const out = proposeNextFramework('Random Framework', edges);
|
|
264
|
+
assert.equal(out, null);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
run('Test 10: proposeNextFramework confidence gating (< 0.5 noise floor)', () => {
|
|
268
|
+
const { proposeNextFramework } = requireComposer();
|
|
269
|
+
// Manually-built edges with sub-0.5 confidence.
|
|
270
|
+
const lowEdges = [
|
|
271
|
+
{ from: 'SWOT', to: 'Porter', confidence: 0.4, phase_indicator: null },
|
|
272
|
+
];
|
|
273
|
+
const out = proposeNextFramework('SWOT', lowEdges);
|
|
274
|
+
assert.equal(out, null, 'sub-0.5 confidence must be filtered as noise; got: ' + JSON.stringify(out));
|
|
275
|
+
// Boundary: 0.5 is acceptable (it's the floor, not strictly less than).
|
|
276
|
+
// Either the implementation accepts 0.5 OR rejects it; we accept both
|
|
277
|
+
// behaviors but document the floor as < 0.5 = null.
|
|
278
|
+
const boundaryEdges = [
|
|
279
|
+
{ from: 'SWOT', to: 'Porter', confidence: 0.55, phase_indicator: null },
|
|
280
|
+
];
|
|
281
|
+
const boundaryOut = proposeNextFramework('SWOT', boundaryEdges);
|
|
282
|
+
assert.equal(boundaryOut !== null, true,
|
|
283
|
+
'0.55 confidence must propose; got: ' + JSON.stringify(boundaryOut));
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
run('Test 11: proposeNextFramework tie-breaking by confidence desc', () => {
|
|
287
|
+
const { proposeNextFramework } = requireComposer();
|
|
288
|
+
// Multiple edges from SWOT; engine returns the highest-confidence one.
|
|
289
|
+
const edges = [
|
|
290
|
+
{ from: 'SWOT', to: 'Lean Canvas', confidence: 0.7, phase_indicator: 'thesis' },
|
|
291
|
+
{ from: 'SWOT', to: 'Porter', confidence: 0.85, phase_indicator: 'early' },
|
|
292
|
+
{ from: 'SWOT', to: 'Value Chain', confidence: 0.6, phase_indicator: 'thesis' },
|
|
293
|
+
];
|
|
294
|
+
const out = proposeNextFramework('SWOT', edges);
|
|
295
|
+
assert.equal(out !== null, true);
|
|
296
|
+
assert.equal(out.next, 'Porter', 'highest-confidence edge wins; got: ' + out.next);
|
|
297
|
+
assert.equal(Math.abs(out.confidence - 0.85) < 1e-9, true);
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
run('Test 12: proposeNextFramework /mos: command mapping', () => {
|
|
301
|
+
const { proposeNextFramework } = requireComposer();
|
|
302
|
+
// 'Lean Canvas' has an existing /mos:lean-canvas command.
|
|
303
|
+
const knownEdges = [
|
|
304
|
+
{ from: 'Business Model Canvas', to: 'Lean Canvas', confidence: 0.82, phase_indicator: 'thesis' },
|
|
305
|
+
];
|
|
306
|
+
const known = proposeNextFramework('Business Model Canvas', knownEdges);
|
|
307
|
+
assert.equal(known !== null, true);
|
|
308
|
+
assert.equal(typeof known.command, 'string');
|
|
309
|
+
assert.equal(known.command.indexOf('/mos:') === 0, true,
|
|
310
|
+
'command must start with /mos:; got: ' + known.command);
|
|
311
|
+
// Unknown framework name falls back to /mos:beautiful-question or
|
|
312
|
+
// a slugified default. Either way the command MUST start with /mos:.
|
|
313
|
+
const unknownEdges = [
|
|
314
|
+
{ from: 'X', to: 'A Wholly Imaginary Framework', confidence: 0.8, phase_indicator: null },
|
|
315
|
+
];
|
|
316
|
+
const unknown = proposeNextFramework('X', unknownEdges);
|
|
317
|
+
assert.equal(unknown !== null, true);
|
|
318
|
+
assert.equal(unknown.command.indexOf('/mos:') === 0, true);
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
run('Test 13: proposeNextFramework grounding rule (FEEDS_INTO + Brain + confidence in reason)', () => {
|
|
322
|
+
const { proposeNextFramework } = requireComposer();
|
|
323
|
+
const edges = [
|
|
324
|
+
{ from: 'SWOT', to: 'Porter', confidence: 0.85, phase_indicator: 'early-market' },
|
|
325
|
+
];
|
|
326
|
+
const out = proposeNextFramework('SWOT', edges);
|
|
327
|
+
assert.equal(typeof out.reason, 'string');
|
|
328
|
+
assert.equal(/FEEDS_INTO/.test(out.reason), true,
|
|
329
|
+
'reason must reference FEEDS_INTO; got: ' + out.reason);
|
|
330
|
+
assert.equal(/Brain/i.test(out.reason), true,
|
|
331
|
+
'reason must reference Brain; got: ' + out.reason);
|
|
332
|
+
// Confidence number appears in the reason (either '0.85' or '0.8' fragment).
|
|
333
|
+
assert.equal(/0\.85|0\.8/.test(out.reason), true,
|
|
334
|
+
'reason must include confidence number; got: ' + out.reason);
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
run('Test 14: proposeNextFramework RECOMMENDED eligibility flag', () => {
|
|
338
|
+
const { proposeNextFramework } = requireComposer();
|
|
339
|
+
// 0.85 -> eligible.
|
|
340
|
+
const high = proposeNextFramework('SWOT', [
|
|
341
|
+
{ from: 'SWOT', to: 'Porter', confidence: 0.85, phase_indicator: null },
|
|
342
|
+
]);
|
|
343
|
+
assert.equal(high.recommended_eligible, true,
|
|
344
|
+
'0.85 confidence must mark recommended_eligible:true');
|
|
345
|
+
// 0.65 -> not eligible (between 0.5 noise floor and 0.7 recommended floor).
|
|
346
|
+
const mid = proposeNextFramework('SWOT', [
|
|
347
|
+
{ from: 'SWOT', to: 'Porter', confidence: 0.65, phase_indicator: null },
|
|
348
|
+
]);
|
|
349
|
+
assert.equal(mid.recommended_eligible, false,
|
|
350
|
+
'0.65 confidence must NOT mark recommended_eligible:true');
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
run('Test 15: proposeNextFramework empty edges -> null', () => {
|
|
354
|
+
const { proposeNextFramework } = requireComposer();
|
|
355
|
+
assert.equal(proposeNextFramework('SWOT', []), null);
|
|
356
|
+
assert.equal(proposeNextFramework('SWOT', null), null);
|
|
357
|
+
// Null completedFramework -> null.
|
|
358
|
+
assert.equal(proposeNextFramework(null, [
|
|
359
|
+
{ from: 'X', to: 'Y', confidence: 0.9, phase_indicator: null },
|
|
360
|
+
]), null);
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
// =========================================================
|
|
364
|
+
// Task 2 -- decide() integration (Tests 16..18)
|
|
365
|
+
// =========================================================
|
|
366
|
+
|
|
367
|
+
function makeBrainWithChain(chainBody, governingThought) {
|
|
368
|
+
return {
|
|
369
|
+
exists: true,
|
|
370
|
+
section: 'market-analysis',
|
|
371
|
+
brain_generated_at: '2026-04-27T12:00:00Z',
|
|
372
|
+
brain_graph_version: 1,
|
|
373
|
+
governing_thought_hash: 'sha256:fixture',
|
|
374
|
+
staleness: 'fresh',
|
|
375
|
+
stale_reason: null,
|
|
376
|
+
author: 'brain',
|
|
377
|
+
confidence_baseline: 0.5,
|
|
378
|
+
parse_failed: false,
|
|
379
|
+
sections: {
|
|
380
|
+
pattern_matches: null,
|
|
381
|
+
framework_chain_predictions: chainBody !== null ? makeChainSection(chainBody) : null,
|
|
382
|
+
cross_domain_analogies: null,
|
|
383
|
+
wicked_indicators: null,
|
|
384
|
+
unfilled_opportunity_matches: null,
|
|
385
|
+
assessment_thinking_chain_position: null,
|
|
386
|
+
problemtype_classification: null,
|
|
387
|
+
flagged_contradictions_xroom: null,
|
|
388
|
+
hsi_signals: null,
|
|
389
|
+
},
|
|
390
|
+
flagged_weaknesses: [],
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
function makeQuadrupleWithChain(chainBody, governingThought) {
|
|
395
|
+
return {
|
|
396
|
+
room: { exists: true, identity_text: 'fixture', references: [] },
|
|
397
|
+
state: { exists: true, artifact_count: 1, completeness_score: 0.5 },
|
|
398
|
+
reasoning: {
|
|
399
|
+
exists: true,
|
|
400
|
+
governing_thought: governingThought,
|
|
401
|
+
reasoning_health_score: 0.7,
|
|
402
|
+
is_stale: false,
|
|
403
|
+
arguments: [],
|
|
404
|
+
},
|
|
405
|
+
brain: makeBrainWithChain(chainBody, governingThought),
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
run('Test 16: decide() with chain + governing_thought -> offer_next_step with FEEDS_INTO reason', () => {
|
|
410
|
+
const { decide } = requireEngine();
|
|
411
|
+
const quadruple = makeQuadrupleWithChain(
|
|
412
|
+
SAMPLE_4_LINES,
|
|
413
|
+
'After our SWOT Analysis we found two key threats and one opportunity.'
|
|
414
|
+
);
|
|
415
|
+
const out = decide(
|
|
416
|
+
{ sectionPath: '/tmp/fixture', sessionId: 's1' },
|
|
417
|
+
{
|
|
418
|
+
quadruple: quadruple,
|
|
419
|
+
brainAvailable: true,
|
|
420
|
+
userPersona: null,
|
|
421
|
+
intentSignal: null,
|
|
422
|
+
}
|
|
423
|
+
);
|
|
424
|
+
// Engine should compose a chain offer: SWOT -> Porter (the highest-conf
|
|
425
|
+
// outgoing edge from SWOT in SAMPLE_4_LINES).
|
|
426
|
+
assert.equal(out.offer_next_step !== null, true,
|
|
427
|
+
'expected non-null offer_next_step; trace: ' + (out.decision_trace.chosen_rationale || ''));
|
|
428
|
+
assert.equal(typeof out.offer_next_step.command, 'string');
|
|
429
|
+
assert.equal(out.offer_next_step.command.indexOf('/mos:') === 0, true);
|
|
430
|
+
assert.equal(/FEEDS_INTO/.test(out.offer_next_step.reason), true,
|
|
431
|
+
'offer reason must reference FEEDS_INTO; got: ' + out.offer_next_step.reason);
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
run('Test 17: decide() Mode A confidence 0.85 chain -> recommended_eligible flag in trace', () => {
|
|
435
|
+
const { decide } = requireEngine();
|
|
436
|
+
const quadruple = makeQuadrupleWithChain(
|
|
437
|
+
SAMPLE_4_LINES,
|
|
438
|
+
'We just completed a SWOT Analysis review with the team.'
|
|
439
|
+
);
|
|
440
|
+
const out = decide(
|
|
441
|
+
{ sectionPath: '/tmp/fixture', sessionId: 's1' },
|
|
442
|
+
{
|
|
443
|
+
quadruple: quadruple,
|
|
444
|
+
brainAvailable: true,
|
|
445
|
+
userPersona: null,
|
|
446
|
+
intentSignal: null,
|
|
447
|
+
}
|
|
448
|
+
);
|
|
449
|
+
// The chain proposal sets a recommended_eligible flag in decision_trace
|
|
450
|
+
// OR sets brain_md_recommended_marker_rendered when the chain confidence
|
|
451
|
+
// qualifies and Mode A holds. Either field signals offer-presenter to
|
|
452
|
+
// render the marker.
|
|
453
|
+
const trace = out.decision_trace;
|
|
454
|
+
const eligible =
|
|
455
|
+
trace.brain_md_recommended_marker_rendered === true ||
|
|
456
|
+
(trace.chain_recommended_eligible === true);
|
|
457
|
+
assert.equal(eligible, true,
|
|
458
|
+
'Mode A + chain conf 0.85 must mark eligibility; trace: ' + JSON.stringify(trace));
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
run('Test 18: decide() user override path: turn 1 offer; turn 2 different command -> REJECTED chain trace', () => {
|
|
462
|
+
const { decide } = requireEngine();
|
|
463
|
+
// Turn 1: chain proposes /mos:porter-five-forces (or similar slug from
|
|
464
|
+
// Porter Five Forces). Engine writes trace.brain_patterns including
|
|
465
|
+
// category 'framework_chain_proposal' OR sets offer_next_step with
|
|
466
|
+
// chain context.
|
|
467
|
+
const turn1Quad = makeQuadrupleWithChain(
|
|
468
|
+
SAMPLE_4_LINES,
|
|
469
|
+
'After our SWOT Analysis we identified threats.'
|
|
470
|
+
);
|
|
471
|
+
const turn1 = decide(
|
|
472
|
+
{ sectionPath: '/tmp/fixture', sessionId: 's1', userText: '' },
|
|
473
|
+
{
|
|
474
|
+
quadruple: turn1Quad,
|
|
475
|
+
brainAvailable: true,
|
|
476
|
+
userPersona: null,
|
|
477
|
+
intentSignal: null,
|
|
478
|
+
}
|
|
479
|
+
);
|
|
480
|
+
assert.equal(turn1.offer_next_step !== null, true,
|
|
481
|
+
'turn 1 must produce a chain offer; trace: ' + turn1.decision_trace.chosen_rationale);
|
|
482
|
+
const turn1Command = turn1.offer_next_step.command;
|
|
483
|
+
|
|
484
|
+
// Turn 2: user invokes a DIFFERENT /mos: command. Engine should record
|
|
485
|
+
// this as REJECTED chain suggestion in decision_trace.
|
|
486
|
+
const turn2 = decide(
|
|
487
|
+
{
|
|
488
|
+
sectionPath: '/tmp/fixture',
|
|
489
|
+
sessionId: 's1',
|
|
490
|
+
userText: '/mos:lean-canvas help me with my lean canvas instead',
|
|
491
|
+
},
|
|
492
|
+
{
|
|
493
|
+
quadruple: turn1Quad,
|
|
494
|
+
brainAvailable: true,
|
|
495
|
+
userPersona: null,
|
|
496
|
+
intentSignal: null,
|
|
497
|
+
lastTurnOffer: { command: turn1Command, reason: turn1.offer_next_step.reason },
|
|
498
|
+
}
|
|
499
|
+
);
|
|
500
|
+
// The override is captured either in chosen_rationale or in a dedicated
|
|
501
|
+
// trace field. Both are acceptable -- /mos:explain-decision can read
|
|
502
|
+
// either. We assert at least one path is present.
|
|
503
|
+
const rationale = turn2.decision_trace.chosen_rationale || '';
|
|
504
|
+
const hasOverride =
|
|
505
|
+
/REJECTED chain suggestion/i.test(rationale) ||
|
|
506
|
+
turn2.decision_trace.chain_override_recorded === true;
|
|
507
|
+
assert.equal(hasOverride, true,
|
|
508
|
+
'turn 2 must record REJECTED chain suggestion; rationale: ' + rationale);
|
|
509
|
+
});
|
|
510
|
+
|
|
511
|
+
// ---------- Suite footer ----------
|
|
512
|
+
|
|
513
|
+
const total = passed + failed;
|
|
514
|
+
process.stdout.write('\nframework-chain-composer: ' + passed + '/' + total + ' passed\n');
|
|
515
|
+
process.exit(failed === 0 ? 0 : 1);
|