@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,618 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026 Mindrian. BSL 1.1.
|
|
3
|
+
*
|
|
4
|
+
* Phase 88-10 -- decision-capture persistence module
|
|
5
|
+
* ===================================================
|
|
6
|
+
* Per-section decision persistence. Writes APPROVE/REJECT/DEFER
|
|
7
|
+
* decisions to the owning section's Feynman-MINTO.md frontmatter
|
|
8
|
+
* decision_log field. When the log exceeds 20 entries, older entries
|
|
9
|
+
* archive to .mindrian/decision-archive/YYYY-MM/<section>.jsonl
|
|
10
|
+
* (partitioned by the ARCHIVED entry's timestamp, not the current
|
|
11
|
+
* time). Read-optimized path for 88-07 session-start TRIPLE_CONTEXT
|
|
12
|
+
* injection (paired with Phase 88-01 folder-memory.readDecisionLog).
|
|
13
|
+
*
|
|
14
|
+
* Usage example:
|
|
15
|
+
* const { recordDecision, readDecisionLog } = require('./decision-capture.cjs');
|
|
16
|
+
* const r = recordDecision(roomPath, 'market-analysis', {
|
|
17
|
+
* session_id: 'sess-2026-04-19-xyz',
|
|
18
|
+
* timestamp: new Date().toISOString(),
|
|
19
|
+
* action: 'flag_tam_staleness',
|
|
20
|
+
* user_response: 'defer',
|
|
21
|
+
* reason: 'Q3 refresh required',
|
|
22
|
+
* });
|
|
23
|
+
* // r: { success, violations?, archived? }
|
|
24
|
+
*
|
|
25
|
+
* Composes with:
|
|
26
|
+
* - Phase 87-02 (lib/core/write-lock.cjs) -- acquireLock around the
|
|
27
|
+
* MINTO mutation so cross-producer renames serialize cleanly.
|
|
28
|
+
* - Phase 88-00 (lib/memory/narrative-schema.cjs) --
|
|
29
|
+
* validateDecisionLogEntry is the single chokepoint for per-entry
|
|
30
|
+
* schema enforcement before we append.
|
|
31
|
+
* - Phase 88-00-B (lib/core/feynman-minto-invariants.cjs) -- post-write
|
|
32
|
+
* validation; critical severity aborts and restores the previous
|
|
33
|
+
* MINTO.md byte-for-byte.
|
|
34
|
+
* - Phase 88-04-B (scripts/vault-section-minto-generator.cjs) --
|
|
35
|
+
* atomic openSync 'wx' + fsync + rename pattern reused here.
|
|
36
|
+
*
|
|
37
|
+
* The decision_log field is preserved across regen via the 88-00 schema
|
|
38
|
+
* contract (read-before-write preservation inside the generator). That
|
|
39
|
+
* contract is tested independently in Test 11 of the acceptance suite.
|
|
40
|
+
*
|
|
41
|
+
* Pure CJS, node built-ins only, zero npm dependencies. Three-surface
|
|
42
|
+
* compatible (CLI hook, Desktop MCP handler, Cowork shared runner).
|
|
43
|
+
*
|
|
44
|
+
* License: BSL 1.1.
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
'use strict';
|
|
48
|
+
|
|
49
|
+
const fs = require('node:fs');
|
|
50
|
+
const path = require('node:path');
|
|
51
|
+
|
|
52
|
+
const narrativeSchema = require('../memory/narrative-schema.cjs');
|
|
53
|
+
const writeLock = require('./write-lock.cjs');
|
|
54
|
+
const feynmanMintoInvariants = require('./feynman-minto-invariants.cjs');
|
|
55
|
+
|
|
56
|
+
const MAX_DECISION_LOG = 20;
|
|
57
|
+
|
|
58
|
+
// ---------- Helpers ----------
|
|
59
|
+
|
|
60
|
+
function safeReadSync(p) {
|
|
61
|
+
try {
|
|
62
|
+
return fs.readFileSync(p, 'utf8');
|
|
63
|
+
} catch (_e) {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function stripQuote(s) {
|
|
69
|
+
if (typeof s !== 'string') return s;
|
|
70
|
+
const t = s.trim();
|
|
71
|
+
if (
|
|
72
|
+
(t.startsWith('"') && t.endsWith('"')) ||
|
|
73
|
+
(t.startsWith("'") && t.endsWith("'"))
|
|
74
|
+
) return t.slice(1, -1);
|
|
75
|
+
return t;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function quote(v) {
|
|
79
|
+
// Minimal safe YAML double-quote: escape backslashes + inner quotes.
|
|
80
|
+
const s = String(v).replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
81
|
+
return '"' + s + '"';
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Narrow-dialect frontmatter parser scoped to this module: pulls every
|
|
85
|
+
// top-level key + the decision_log block-style object array. Copy of the
|
|
86
|
+
// 88-00 generator readPreservedV88Fields() approach with enough surface
|
|
87
|
+
// to rebuild the full frontmatter back (we need to preserve unknown
|
|
88
|
+
// keys byte-for-byte when we re-emit). Zero new deps.
|
|
89
|
+
function parseFrontmatter(fmText) {
|
|
90
|
+
const lines = fmText.split(/\r?\n/);
|
|
91
|
+
// We return an ordered list of "items": either {kind:'scalar', key, raw}
|
|
92
|
+
// or {kind:'emptyArray', key} or {kind:'decisionLog', entries} or
|
|
93
|
+
// {kind:'blockList', key, items[]} or {kind:'blank', raw}.
|
|
94
|
+
// On re-emit we preserve the exact raw line for scalar items so unknown
|
|
95
|
+
// keys (schema_version, status, etc.) survive mutation byte-for-byte.
|
|
96
|
+
const items = [];
|
|
97
|
+
let i = 0;
|
|
98
|
+
while (i < lines.length) {
|
|
99
|
+
const line = lines[i];
|
|
100
|
+
if (/^\s*$/.test(line)) {
|
|
101
|
+
items.push({ kind: 'blank', raw: line });
|
|
102
|
+
i += 1;
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
const scalarM = line.match(/^([A-Za-z_][A-Za-z0-9_-]*):\s*(.*)$/);
|
|
106
|
+
if (!scalarM) {
|
|
107
|
+
// Non-conforming line -- preserve verbatim.
|
|
108
|
+
items.push({ kind: 'blank', raw: line });
|
|
109
|
+
i += 1;
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
const key = scalarM[1];
|
|
113
|
+
const rest = scalarM[2];
|
|
114
|
+
|
|
115
|
+
if (rest.trim().length > 0) {
|
|
116
|
+
// Inline scalar or flow-style array.
|
|
117
|
+
items.push({ kind: 'scalar', key: key, raw: line });
|
|
118
|
+
i += 1;
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Block follows -- either string-list or object-list.
|
|
123
|
+
// Look ahead: peek at next non-blank line.
|
|
124
|
+
let j = i + 1;
|
|
125
|
+
while (j < lines.length && /^\s*$/.test(lines[j])) j += 1;
|
|
126
|
+
if (j >= lines.length) {
|
|
127
|
+
items.push({ kind: 'emptyBlock', key: key, raw: line });
|
|
128
|
+
i = j;
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
const peek = lines[j];
|
|
132
|
+
if (!/^\s+-\s/.test(peek)) {
|
|
133
|
+
// Not a list -- treat as orphan empty.
|
|
134
|
+
items.push({ kind: 'emptyBlock', key: key, raw: line });
|
|
135
|
+
i = j;
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Block list. Determine string-list vs object-list from first item.
|
|
140
|
+
const objHead = peek.match(
|
|
141
|
+
/^\s+-\s+([A-Za-z_][A-Za-z0-9_-]*):\s*(.*)$/
|
|
142
|
+
);
|
|
143
|
+
const strItem = peek.match(/^\s+-\s+(.*)$/);
|
|
144
|
+
const isObjectList = !!objHead;
|
|
145
|
+
if (isObjectList) {
|
|
146
|
+
// Consume object list.
|
|
147
|
+
const entries = [];
|
|
148
|
+
i = j;
|
|
149
|
+
let current = null;
|
|
150
|
+
while (i < lines.length) {
|
|
151
|
+
const row = lines[i];
|
|
152
|
+
if (/^\s*$/.test(row)) { i += 1; continue; }
|
|
153
|
+
if (/^[A-Za-z_]/.test(row)) break;
|
|
154
|
+
const head = row.match(
|
|
155
|
+
/^\s+-\s+([A-Za-z_][A-Za-z0-9_-]*):\s*(.*)$/
|
|
156
|
+
);
|
|
157
|
+
if (head) {
|
|
158
|
+
if (current) entries.push(current);
|
|
159
|
+
current = {};
|
|
160
|
+
current[head[1]] = stripQuote(head[2]);
|
|
161
|
+
i += 1;
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
const cont = row.match(
|
|
165
|
+
/^\s+([A-Za-z_][A-Za-z0-9_-]*):\s*(.*)$/
|
|
166
|
+
);
|
|
167
|
+
if (cont && current) {
|
|
168
|
+
current[cont[1]] = stripQuote(cont[2]);
|
|
169
|
+
i += 1;
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
if (current) entries.push(current);
|
|
175
|
+
items.push({ kind: 'objectList', key: key, entries: entries });
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
// String list.
|
|
179
|
+
const strItems = [];
|
|
180
|
+
i = j;
|
|
181
|
+
while (i < lines.length) {
|
|
182
|
+
const row = lines[i];
|
|
183
|
+
if (/^\s*$/.test(row)) { i += 1; continue; }
|
|
184
|
+
if (/^[A-Za-z_]/.test(row)) break;
|
|
185
|
+
const s = row.match(/^\s+-\s+(.*)$/);
|
|
186
|
+
if (s) {
|
|
187
|
+
strItems.push(stripQuote(s[1]));
|
|
188
|
+
i += 1;
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
break;
|
|
192
|
+
}
|
|
193
|
+
items.push({ kind: 'stringList', key: key, items: strItems });
|
|
194
|
+
}
|
|
195
|
+
return items;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function emitFrontmatter(items) {
|
|
199
|
+
const out = [];
|
|
200
|
+
for (const it of items) {
|
|
201
|
+
if (it.kind === 'blank') {
|
|
202
|
+
out.push(it.raw);
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
if (it.kind === 'scalar' || it.kind === 'emptyBlock') {
|
|
206
|
+
out.push(it.raw);
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
if (it.kind === 'stringList') {
|
|
210
|
+
if (it.items.length === 0) {
|
|
211
|
+
out.push(it.key + ': []');
|
|
212
|
+
} else {
|
|
213
|
+
out.push(it.key + ':');
|
|
214
|
+
for (const v of it.items) out.push(' - ' + quote(v));
|
|
215
|
+
}
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
if (it.kind === 'objectList') {
|
|
219
|
+
if (it.entries.length === 0) {
|
|
220
|
+
out.push(it.key + ': []');
|
|
221
|
+
} else {
|
|
222
|
+
out.push(it.key + ':');
|
|
223
|
+
for (const entry of it.entries) {
|
|
224
|
+
const keys = Object.keys(entry);
|
|
225
|
+
if (keys.length === 0) continue;
|
|
226
|
+
// session_id first if present (canonical ordering mirrors the
|
|
227
|
+
// 88-00 generator renderV88FrontmatterLines decision_log shape).
|
|
228
|
+
const ordered = [];
|
|
229
|
+
if ('session_id' in entry) ordered.push('session_id');
|
|
230
|
+
for (const k of keys) {
|
|
231
|
+
if (k !== 'session_id') ordered.push(k);
|
|
232
|
+
}
|
|
233
|
+
ordered.forEach(function (k, idx) {
|
|
234
|
+
const prefix = idx === 0 ? ' - ' : ' ';
|
|
235
|
+
out.push(prefix + k + ': ' + quote(entry[k]));
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return out.join('\n');
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Extract the decision_log entries from a parsed frontmatter items array.
|
|
246
|
+
// Returns the current array + index (so we can replace it in place).
|
|
247
|
+
function findDecisionLog(items) {
|
|
248
|
+
for (let i = 0; i < items.length; i++) {
|
|
249
|
+
const it = items[i];
|
|
250
|
+
if ((it.kind === 'objectList' || it.kind === 'stringList') && it.key === 'decision_log') {
|
|
251
|
+
return { idx: i, entries: Array.isArray(it.entries) ? it.entries.slice() : [] };
|
|
252
|
+
}
|
|
253
|
+
if ((it.kind === 'scalar' || it.kind === 'emptyBlock') && it.key === 'decision_log') {
|
|
254
|
+
// Inline empty array: `decision_log: []`
|
|
255
|
+
return { idx: i, entries: [] };
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
return { idx: -1, entries: [] };
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Replace (or insert) the decision_log block in the items array.
|
|
262
|
+
function setDecisionLog(items, idx, entries) {
|
|
263
|
+
const newItem = { kind: 'objectList', key: 'decision_log', entries: entries };
|
|
264
|
+
if (idx === -1) {
|
|
265
|
+
// Not present: insert before the last blank-at-end (if any) so the
|
|
266
|
+
// output trails cleanly. Simplest: append.
|
|
267
|
+
items.push(newItem);
|
|
268
|
+
} else {
|
|
269
|
+
items[idx] = newItem;
|
|
270
|
+
}
|
|
271
|
+
return items;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// ---------- Archive helpers ----------
|
|
275
|
+
|
|
276
|
+
// Derive YYYY-MM partition from an ISO-8601 timestamp. Returns null if the
|
|
277
|
+
// timestamp is malformed (should never happen: entries are validated
|
|
278
|
+
// before they enter the decision_log).
|
|
279
|
+
function archiveMonth(isoTimestamp) {
|
|
280
|
+
if (typeof isoTimestamp !== 'string' || isoTimestamp.length < 7) return null;
|
|
281
|
+
return isoTimestamp.slice(0, 7);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// Archive filename from a section. URL-encode every character that is
|
|
285
|
+
// unsafe across Linux, macOS, Windows filesystems so special-char
|
|
286
|
+
// sections (spaces, unicode, slashes) still work. We keep it simple:
|
|
287
|
+
// encodeURIComponent covers all known hazards.
|
|
288
|
+
function archiveBasename(section) {
|
|
289
|
+
// Preserve dashes, which are filesystem-safe and readable.
|
|
290
|
+
return encodeURIComponent(section).replace(/%2D/gi, '-') + '.jsonl';
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function archiveEntry(roomPath, section, entry) {
|
|
294
|
+
const yyyyMM = archiveMonth(entry.timestamp);
|
|
295
|
+
if (!yyyyMM) {
|
|
296
|
+
throw new Error(
|
|
297
|
+
'decision-capture: cannot derive archive partition from timestamp ' +
|
|
298
|
+
JSON.stringify(entry.timestamp)
|
|
299
|
+
);
|
|
300
|
+
}
|
|
301
|
+
const archiveDir = path.join(
|
|
302
|
+
roomPath,
|
|
303
|
+
'.mindrian',
|
|
304
|
+
'decision-archive',
|
|
305
|
+
yyyyMM
|
|
306
|
+
);
|
|
307
|
+
fs.mkdirSync(archiveDir, { recursive: true });
|
|
308
|
+
const archivePath = path.join(archiveDir, archiveBasename(section));
|
|
309
|
+
// appendFileSync is atomic for small lines per POSIX for O_APPEND writes;
|
|
310
|
+
// we still wrap in try/catch to surface filesystem errors cleanly.
|
|
311
|
+
fs.appendFileSync(archivePath, JSON.stringify(entry) + '\n');
|
|
312
|
+
return archivePath;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// ---------- Atomic MINTO mutation ----------
|
|
316
|
+
|
|
317
|
+
// Rewrite MINTO.md with the updated decision_log, preserving all other
|
|
318
|
+
// frontmatter keys and the body byte-for-byte. Uses the openSync('wx') +
|
|
319
|
+
// fsync + rename pattern from Phase 88-04-B (same atomic-write contract,
|
|
320
|
+
// scoped locally to this module to avoid cross-requiring the generator).
|
|
321
|
+
function atomicRewriteMintoWithDecisionLog(mintoPath, updatedEntries, roomPath) {
|
|
322
|
+
const raw = safeReadSync(mintoPath);
|
|
323
|
+
if (raw === null) {
|
|
324
|
+
return {
|
|
325
|
+
success: false,
|
|
326
|
+
violations: [{
|
|
327
|
+
category: 'existence',
|
|
328
|
+
severity: 'error',
|
|
329
|
+
message: 'no_minto',
|
|
330
|
+
}],
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
const fm = raw.match(/^(---\r?\n)([\s\S]*?)(\r?\n---\r?\n)([\s\S]*)$/);
|
|
334
|
+
if (!fm) {
|
|
335
|
+
return {
|
|
336
|
+
success: false,
|
|
337
|
+
violations: [{
|
|
338
|
+
category: 'schema',
|
|
339
|
+
severity: 'error',
|
|
340
|
+
message: 'frontmatter-parse-failed',
|
|
341
|
+
}],
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
const header = fm[1];
|
|
345
|
+
const fmText = fm[2];
|
|
346
|
+
const tail = fm[3];
|
|
347
|
+
const body = fm[4];
|
|
348
|
+
|
|
349
|
+
const items = parseFrontmatter(fmText);
|
|
350
|
+
const cur = findDecisionLog(items);
|
|
351
|
+
setDecisionLog(items, cur.idx, updatedEntries);
|
|
352
|
+
const newFmText = emitFrontmatter(items);
|
|
353
|
+
const newContent = header + newFmText + tail + body;
|
|
354
|
+
|
|
355
|
+
// Atomic write sequence (Phase 88-04-B pattern):
|
|
356
|
+
// openSync('wx') + writeSync + fsyncSync + closeSync
|
|
357
|
+
// + invariants.validate(tmp) (warning-tolerant, critical-blocks)
|
|
358
|
+
// + acquireLock + renameSync + releaseLock
|
|
359
|
+
const tmpPath = mintoPath + '.tmp.' + process.pid + '.minto';
|
|
360
|
+
let fd;
|
|
361
|
+
try {
|
|
362
|
+
fd = fs.openSync(tmpPath, 'wx');
|
|
363
|
+
} catch (e) {
|
|
364
|
+
if (e.code === 'EEXIST') {
|
|
365
|
+
// Stale tmp from a prior mid-write crash owned by the same pid
|
|
366
|
+
// slot. Clean and retry once.
|
|
367
|
+
try { fs.unlinkSync(tmpPath); } catch (_) {}
|
|
368
|
+
fd = fs.openSync(tmpPath, 'wx');
|
|
369
|
+
} else {
|
|
370
|
+
throw e;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
try {
|
|
374
|
+
fs.writeSync(fd, newContent);
|
|
375
|
+
fs.fsyncSync(fd);
|
|
376
|
+
} finally {
|
|
377
|
+
try { fs.closeSync(fd); } catch (_) {}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// Post-write invariants validation. Critical severity aborts and
|
|
381
|
+
// restores the previous MINTO.md byte-for-byte (by unlinking the tmp).
|
|
382
|
+
let validation;
|
|
383
|
+
try {
|
|
384
|
+
validation = feynmanMintoInvariants.validate(tmpPath);
|
|
385
|
+
} catch (_e) {
|
|
386
|
+
validation = { valid: true, violations: [], severity: null };
|
|
387
|
+
}
|
|
388
|
+
const SEV = feynmanMintoInvariants.SEVERITY;
|
|
389
|
+
const isCritical = validation.violations.some(function (v) {
|
|
390
|
+
return v.severity === SEV.CRITICAL;
|
|
391
|
+
});
|
|
392
|
+
if (isCritical) {
|
|
393
|
+
try { fs.unlinkSync(tmpPath); } catch (_) {}
|
|
394
|
+
return {
|
|
395
|
+
success: false,
|
|
396
|
+
violations: validation.violations,
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// Atomic publish under the Phase 87-02 write-lock. Retry on contention
|
|
401
|
+
// with exponential backoff + half-jitter (mirrors 88-04-B pattern).
|
|
402
|
+
const LOCK_RETRIES = 12;
|
|
403
|
+
const LOCK_BASE_MS = 25;
|
|
404
|
+
const LOCK_CAP_MS = 1600;
|
|
405
|
+
let locked = false;
|
|
406
|
+
let lockErr = null;
|
|
407
|
+
for (let attempt = 0; attempt < LOCK_RETRIES; attempt++) {
|
|
408
|
+
try {
|
|
409
|
+
writeLock.acquireLock(roomPath);
|
|
410
|
+
locked = true;
|
|
411
|
+
lockErr = null;
|
|
412
|
+
break;
|
|
413
|
+
} catch (e) {
|
|
414
|
+
lockErr = e;
|
|
415
|
+
const backoff = Math.min(
|
|
416
|
+
LOCK_CAP_MS,
|
|
417
|
+
LOCK_BASE_MS * Math.pow(2, attempt)
|
|
418
|
+
);
|
|
419
|
+
const sleep = Math.floor(backoff / 2 + Math.random() * (backoff / 2));
|
|
420
|
+
const end = Date.now() + sleep;
|
|
421
|
+
while (Date.now() < end) { /* busy-wait */ }
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
if (!locked) {
|
|
425
|
+
try { fs.unlinkSync(tmpPath); } catch (_) {}
|
|
426
|
+
return {
|
|
427
|
+
success: false,
|
|
428
|
+
violations: [{
|
|
429
|
+
category: 'atomicity',
|
|
430
|
+
severity: 'error',
|
|
431
|
+
message: 'write-lock acquire failed after ' + LOCK_RETRIES +
|
|
432
|
+
' retries: ' + (lockErr && lockErr.message || lockErr),
|
|
433
|
+
}],
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
try {
|
|
438
|
+
fs.renameSync(tmpPath, mintoPath);
|
|
439
|
+
} finally {
|
|
440
|
+
try { writeLock.releaseLock(roomPath); } catch (_) {}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
return { success: true, violations: validation.violations };
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
// ---------- Public API ----------
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* recordDecision(roomPath, section, decision)
|
|
450
|
+
*
|
|
451
|
+
* Append a decision to the section's MINTO.md frontmatter decision_log.
|
|
452
|
+
* Enforces the 20-entry cap; older entries archive to
|
|
453
|
+
* `<roomPath>/.mindrian/decision-archive/YYYY-MM/<section>.jsonl`
|
|
454
|
+
* partitioned by the ARCHIVED entry's timestamp (not the current time).
|
|
455
|
+
*
|
|
456
|
+
* Returns:
|
|
457
|
+
* { success: true, violations: [], archived: {count, archivePaths[]} | null }
|
|
458
|
+
* { success: false, violations: [...] }
|
|
459
|
+
*/
|
|
460
|
+
function recordDecision(roomPath, section, decision) {
|
|
461
|
+
// --- Validate entry shape ---
|
|
462
|
+
const v = narrativeSchema.validateDecisionLogEntry(decision);
|
|
463
|
+
if (!v.valid) {
|
|
464
|
+
return {
|
|
465
|
+
success: false,
|
|
466
|
+
violations: v.errors.map(function (msg) {
|
|
467
|
+
return { category: 'schema', severity: 'error', message: msg };
|
|
468
|
+
}),
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
const mintoPath = path.join(roomPath, section, 'MINTO.md');
|
|
473
|
+
if (!fs.existsSync(mintoPath)) {
|
|
474
|
+
// This plan does NOT create MINTO.md from scratch. 88-13 guardian
|
|
475
|
+
// will enqueue regen when it sees an empty section with a decision
|
|
476
|
+
// request. Surface the gap so the caller can route to the debouncer.
|
|
477
|
+
return {
|
|
478
|
+
success: false,
|
|
479
|
+
violations: [{
|
|
480
|
+
category: 'existence',
|
|
481
|
+
severity: 'error',
|
|
482
|
+
message: 'no_minto',
|
|
483
|
+
}],
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
// --- Acquire write-lock around the read-modify-write cycle ---
|
|
488
|
+
// The atomic rewriter acquires its own lock around the rename. We also
|
|
489
|
+
// hold a SEPARATE lock around the read-modify-write so two processes
|
|
490
|
+
// cannot both read the same decision_log, append disjoint entries, and
|
|
491
|
+
// then race their writes (last-writer-wins would lose one entry).
|
|
492
|
+
//
|
|
493
|
+
// Retry with exponential backoff so concurrent producers converge
|
|
494
|
+
// without starvation (Phase 88-02/88-04-B backoff pattern).
|
|
495
|
+
const LOCK_RETRIES = 12;
|
|
496
|
+
const LOCK_BASE_MS = 25;
|
|
497
|
+
const LOCK_CAP_MS = 1600;
|
|
498
|
+
let outerLocked = false;
|
|
499
|
+
let outerErr = null;
|
|
500
|
+
for (let attempt = 0; attempt < LOCK_RETRIES; attempt++) {
|
|
501
|
+
try {
|
|
502
|
+
writeLock.acquireLock(roomPath);
|
|
503
|
+
outerLocked = true;
|
|
504
|
+
outerErr = null;
|
|
505
|
+
break;
|
|
506
|
+
} catch (e) {
|
|
507
|
+
outerErr = e;
|
|
508
|
+
const backoff = Math.min(
|
|
509
|
+
LOCK_CAP_MS,
|
|
510
|
+
LOCK_BASE_MS * Math.pow(2, attempt)
|
|
511
|
+
);
|
|
512
|
+
const sleep = Math.floor(backoff / 2 + Math.random() * (backoff / 2));
|
|
513
|
+
const end = Date.now() + sleep;
|
|
514
|
+
while (Date.now() < end) { /* busy-wait */ }
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
if (!outerLocked) {
|
|
518
|
+
return {
|
|
519
|
+
success: false,
|
|
520
|
+
violations: [{
|
|
521
|
+
category: 'atomicity',
|
|
522
|
+
severity: 'error',
|
|
523
|
+
message: 'decision-capture: outer write-lock acquire failed: ' +
|
|
524
|
+
(outerErr && outerErr.message || outerErr),
|
|
525
|
+
}],
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
try {
|
|
530
|
+
// --- Read current decision_log ---
|
|
531
|
+
const currentLog = readDecisionLogInternal(mintoPath);
|
|
532
|
+
const newLog = currentLog.concat([decision]);
|
|
533
|
+
|
|
534
|
+
// --- Cap + archive ---
|
|
535
|
+
let archivedCount = 0;
|
|
536
|
+
const archivePaths = [];
|
|
537
|
+
while (newLog.length > MAX_DECISION_LOG) {
|
|
538
|
+
const oldest = newLog.shift();
|
|
539
|
+
try {
|
|
540
|
+
const ap = archiveEntry(roomPath, section, oldest);
|
|
541
|
+
archivedCount += 1;
|
|
542
|
+
archivePaths.push(ap);
|
|
543
|
+
} catch (e) {
|
|
544
|
+
return {
|
|
545
|
+
success: false,
|
|
546
|
+
violations: [{
|
|
547
|
+
category: 'atomicity',
|
|
548
|
+
severity: 'error',
|
|
549
|
+
message: 'archive write failed: ' + (e && e.message || e),
|
|
550
|
+
}],
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
// --- Atomic MINTO rewrite ---
|
|
556
|
+
// The rewriter acquires its OWN lock around the rename; our outer
|
|
557
|
+
// lock guarantees atomic read-modify-write but the acquireLock call
|
|
558
|
+
// inside atomicRewriteMintoWithDecisionLog sees we already own the
|
|
559
|
+
// lock (same PID) and re-acquires cleanly (write-lock.cjs same-pid
|
|
560
|
+
// re-acquire is an overwrite, not a throw).
|
|
561
|
+
const writeResult = atomicRewriteMintoWithDecisionLog(
|
|
562
|
+
mintoPath,
|
|
563
|
+
newLog,
|
|
564
|
+
roomPath
|
|
565
|
+
);
|
|
566
|
+
if (!writeResult.success) {
|
|
567
|
+
// Atomic rewrite failed -- the archived entries are already on
|
|
568
|
+
// disk. That is acceptable: archival is append-only (JSONL) and
|
|
569
|
+
// the caller retries the write. The MINTO decision_log will
|
|
570
|
+
// re-converge on next successful call.
|
|
571
|
+
return writeResult;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
return {
|
|
575
|
+
success: true,
|
|
576
|
+
violations: writeResult.violations || [],
|
|
577
|
+
archived: archivedCount > 0
|
|
578
|
+
? { count: archivedCount, archivePaths: archivePaths }
|
|
579
|
+
: null,
|
|
580
|
+
};
|
|
581
|
+
} finally {
|
|
582
|
+
try { writeLock.releaseLock(roomPath); } catch (_) {}
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
// Internal helper: read decision_log directly from a MINTO path without
|
|
587
|
+
// going through folder-memory (avoids cross-require + lets us parse the
|
|
588
|
+
// exact block-style dialect we emit).
|
|
589
|
+
function readDecisionLogInternal(mintoPath) {
|
|
590
|
+
const raw = safeReadSync(mintoPath);
|
|
591
|
+
if (raw === null) return [];
|
|
592
|
+
const fm = raw.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n/);
|
|
593
|
+
if (!fm) return [];
|
|
594
|
+
const items = parseFrontmatter(fm[1]);
|
|
595
|
+
const found = findDecisionLog(items);
|
|
596
|
+
return found.entries;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
/**
|
|
600
|
+
* readDecisionLog(roomPath, section)
|
|
601
|
+
*
|
|
602
|
+
* Returns the current decision_log (Array) from the section's MINTO.md
|
|
603
|
+
* frontmatter. Never throws. Returns [] when MINTO is missing or lacks
|
|
604
|
+
* the field (pre-88-00 file not yet migrated).
|
|
605
|
+
*
|
|
606
|
+
* Does NOT read the archive. The archive is for dedicated full-history
|
|
607
|
+
* consumers (not needed for 88-07 session-start injection, which only
|
|
608
|
+
* consumes the current-section window).
|
|
609
|
+
*/
|
|
610
|
+
function readDecisionLog(roomPath, section) {
|
|
611
|
+
const mintoPath = path.join(roomPath, section, 'MINTO.md');
|
|
612
|
+
return readDecisionLogInternal(mintoPath);
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
module.exports = {
|
|
616
|
+
recordDecision: recordDecision,
|
|
617
|
+
readDecisionLog: readDecisionLog,
|
|
618
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* deep-links.cjs -- Deep Link Protocol for MindrianOS
|
|
5
|
+
*
|
|
6
|
+
* Generates claude-cli:// URLs for room-to-room navigation,
|
|
7
|
+
* dashboard-to-CLI handoff, and section-specific deep links.
|
|
8
|
+
*
|
|
9
|
+
* Protocol: claude-cli://open?cwd={path}&q={command}
|
|
10
|
+
* Security: ASCII control char rejection, path <=4096 chars, query <=5000 chars
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const path = require('path');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Generate a deep link URL for a room path and optional command.
|
|
17
|
+
* @param {string} roomPath - Absolute path to room directory
|
|
18
|
+
* @param {string} [command] - Optional /mos: command to execute on open
|
|
19
|
+
* @returns {string} claude-cli:// URL
|
|
20
|
+
*/
|
|
21
|
+
function generateDeepLink(roomPath, command) {
|
|
22
|
+
const cwd = path.resolve(roomPath);
|
|
23
|
+
if (cwd.length > 4096) {
|
|
24
|
+
throw new Error('Room path exceeds 4096 character limit');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const encodedCwd = encodeURIComponent(cwd);
|
|
28
|
+
|
|
29
|
+
if (!command) {
|
|
30
|
+
return `claude-cli://open?cwd=${encodedCwd}`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const q = command.length > 5000 ? command.slice(0, 5000) : command;
|
|
34
|
+
const encodedQ = encodeURIComponent(q);
|
|
35
|
+
return `claude-cli://open?cwd=${encodedCwd}&q=${encodedQ}`;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Generate a deep link to a specific room section.
|
|
40
|
+
* @param {string} roomPath - Absolute path to room directory
|
|
41
|
+
* @param {string} section - Section name (e.g., 'problem-definition')
|
|
42
|
+
* @returns {string} claude-cli:// URL that opens the room and navigates to section
|
|
43
|
+
*/
|
|
44
|
+
function generateSectionLink(roomPath, section) {
|
|
45
|
+
return generateDeepLink(roomPath, `/mos:room ${section}`);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Generate a deep link to the room dashboard.
|
|
50
|
+
* @param {string} roomPath - Absolute path to room directory
|
|
51
|
+
* @returns {string} claude-cli:// URL that opens the dashboard
|
|
52
|
+
*/
|
|
53
|
+
function generateDashboardLink(roomPath) {
|
|
54
|
+
return generateDeepLink(roomPath, '/mos:dashboard');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Generate a deep link to the room wiki.
|
|
59
|
+
* @param {string} roomPath - Absolute path to room directory
|
|
60
|
+
* @returns {string} claude-cli:// URL that opens the wiki
|
|
61
|
+
*/
|
|
62
|
+
function generateWikiLink(roomPath) {
|
|
63
|
+
return generateDeepLink(roomPath, '/mos:wiki');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Generate a deep link for a specific methodology command.
|
|
68
|
+
* @param {string} roomPath - Absolute path to room directory
|
|
69
|
+
* @param {string} methodology - Methodology name (e.g., 'find-analogies')
|
|
70
|
+
* @returns {string} claude-cli:// URL
|
|
71
|
+
*/
|
|
72
|
+
function generateMethodologyLink(roomPath, methodology) {
|
|
73
|
+
return generateDeepLink(roomPath, `/mos:${methodology}`);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
module.exports = {
|
|
77
|
+
generateDeepLink,
|
|
78
|
+
generateSectionLink,
|
|
79
|
+
generateDashboardLink,
|
|
80
|
+
generateWikiLink,
|
|
81
|
+
generateMethodologyLink,
|
|
82
|
+
};
|