@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.
Files changed (597) hide show
  1. package/.claude-plugin/plugin.json +21 -0
  2. package/.mcp.json +9 -0
  3. package/CHANGELOG.md +3333 -0
  4. package/LICENSE +123 -0
  5. package/README.md +673 -0
  6. package/agents/brain-query.md +80 -0
  7. package/agents/framework-runner.md +237 -0
  8. package/agents/grading.md +188 -0
  9. package/agents/investor.md +128 -0
  10. package/agents/larry-extended.md +135 -0
  11. package/agents/opportunity-scanner.md +91 -0
  12. package/agents/persona-analyst.md +132 -0
  13. package/agents/research.md +89 -0
  14. package/agents/reverse-salient-agent.md +27 -0
  15. package/bin/cli.js +142 -0
  16. package/bin/mindrian-mcp-server.cjs +182 -0
  17. package/bin/mindrian-tools.cjs +765 -0
  18. package/commands/act.md +439 -0
  19. package/commands/admin.md +404 -0
  20. package/commands/analyze-needs.md +42 -0
  21. package/commands/analyze-systems.md +39 -0
  22. package/commands/analyze-timing.md +42 -0
  23. package/commands/auto-explore.md +64 -0
  24. package/commands/beautiful-question.md +40 -0
  25. package/commands/brain-derive.md +78 -0
  26. package/commands/build-knowledge.md +42 -0
  27. package/commands/build-thesis.md +46 -0
  28. package/commands/causal.md +234 -0
  29. package/commands/challenge-assumptions.md +33 -0
  30. package/commands/compare-ventures.md +83 -0
  31. package/commands/dashboard.md +110 -0
  32. package/commands/deep-grade.md +82 -0
  33. package/commands/diagnose.md +58 -0
  34. package/commands/diagnostics.md +151 -0
  35. package/commands/doctor.md +151 -0
  36. package/commands/dominant-designs.md +40 -0
  37. package/commands/explain-decision.md +87 -0
  38. package/commands/explore-domains.md +42 -0
  39. package/commands/explore-futures.md +40 -0
  40. package/commands/explore-trends.md +42 -0
  41. package/commands/export.md +103 -0
  42. package/commands/file-meeting.md +724 -0
  43. package/commands/find-analogies.md +188 -0
  44. package/commands/find-bottlenecks.md +62 -0
  45. package/commands/find-connections.md +76 -0
  46. package/commands/funding.md +81 -0
  47. package/commands/grade.md +203 -0
  48. package/commands/graph.md +128 -0
  49. package/commands/hat-briefing.md +125 -0
  50. package/commands/heal.md +196 -0
  51. package/commands/help.md +399 -0
  52. package/commands/hmi-status.md +172 -0
  53. package/commands/jtbd.md +241 -0
  54. package/commands/leadership.md +73 -0
  55. package/commands/lean-canvas.md +40 -0
  56. package/commands/macro-trends.md +40 -0
  57. package/commands/map-unknowns.md +40 -0
  58. package/commands/memory.md +173 -0
  59. package/commands/models.md +175 -0
  60. package/commands/mos-reason.md +285 -0
  61. package/commands/mullins.md +120 -0
  62. package/commands/new-project.md +481 -0
  63. package/commands/onboard.md +434 -0
  64. package/commands/operator.md +149 -0
  65. package/commands/opportunities.md +144 -0
  66. package/commands/organize.md +497 -0
  67. package/commands/persona.md +198 -0
  68. package/commands/pipeline.md +112 -0
  69. package/commands/present.md +91 -0
  70. package/commands/publish.md +201 -0
  71. package/commands/query.md +124 -0
  72. package/commands/radar.md +72 -0
  73. package/commands/reanalyze.md +91 -0
  74. package/commands/research.md +196 -0
  75. package/commands/room.md +352 -0
  76. package/commands/rooms.md +598 -0
  77. package/commands/root-cause.md +40 -0
  78. package/commands/rs-experts.md +85 -0
  79. package/commands/rs-explain.md +100 -0
  80. package/commands/rs-fetch.md +94 -0
  81. package/commands/rs-thesis.md +85 -0
  82. package/commands/scenario-plan.md +40 -0
  83. package/commands/scheduled-tasks.md +285 -0
  84. package/commands/score-innovation.md +43 -0
  85. package/commands/scout.md +239 -0
  86. package/commands/setup.md +618 -0
  87. package/commands/snapshot.md +147 -0
  88. package/commands/speakers.md +84 -0
  89. package/commands/splash.md +28 -0
  90. package/commands/status.md +75 -0
  91. package/commands/structure-argument.md +42 -0
  92. package/commands/suggest-next.md +80 -0
  93. package/commands/systems-thinking.md +40 -0
  94. package/commands/think-hats.md +42 -0
  95. package/commands/update.md +181 -0
  96. package/commands/user-needs.md +40 -0
  97. package/commands/validate.md +40 -0
  98. package/commands/value-proposition.md +61 -0
  99. package/commands/vault.md +180 -0
  100. package/commands/visualize.md +52 -0
  101. package/commands/whitespace.md +507 -0
  102. package/commands/wiki.md +69 -0
  103. package/hooks/hooks.json +381 -0
  104. package/hooks/run-hook.cmd +64 -0
  105. package/lib/__init__.py +0 -0
  106. package/lib/__pycache__/__init__.cpython-312.pyc +0 -0
  107. package/lib/agents/auto-explore-agent.cjs +1043 -0
  108. package/lib/agents/reverse-salient-agent.cjs +679 -0
  109. package/lib/agents/tension-hook-agent.cjs +544 -0
  110. package/lib/brain/ROOM.md +44 -0
  111. package/lib/brain/chain-recommender.cjs +301 -0
  112. package/lib/chat/chat-context.js +185 -0
  113. package/lib/chat/chat-panel.js +721 -0
  114. package/lib/chat/fabric-chat.cjs +288 -0
  115. package/lib/chat/generative-tools.js +219 -0
  116. package/lib/conversation/ROOM.md +39 -0
  117. package/lib/conversation/classifier-rules.json +38 -0
  118. package/lib/conversation/classifier.cjs +264 -0
  119. package/lib/conversation/operator.cjs +287 -0
  120. package/lib/copy/115-spec-strings.cjs +55 -0
  121. package/lib/core/__init__.py +0 -0
  122. package/lib/core/__nav-stub.cjs +14 -0
  123. package/lib/core/__pycache__/__init__.cpython-312.pyc +0 -0
  124. package/lib/core/__pycache__/rs-math.cpython-312.pyc +0 -0
  125. package/lib/core/__pycache__/rs_cache.cpython-312.pyc +0 -0
  126. package/lib/core/__pycache__/rs_corpus.cpython-312.pyc +0 -0
  127. package/lib/core/__pycache__/rs_hybrid.cpython-312.pyc +0 -0
  128. package/lib/core/__pycache__/rs_math.cpython-312.pyc +0 -0
  129. package/lib/core/__pycache__/rs_rooms.cpython-312.pyc +0 -0
  130. package/lib/core/artifact-id.cjs +148 -0
  131. package/lib/core/asset-ops.cjs +151 -0
  132. package/lib/core/auto-commit-throttle.cjs +129 -0
  133. package/lib/core/bearer-token.cjs +199 -0
  134. package/lib/core/brain-client.cjs +865 -0
  135. package/lib/core/brain-derivation-prompts.cjs +326 -0
  136. package/lib/core/brain-derivation-queue.cjs +431 -0
  137. package/lib/core/brain-derivation.cjs +580 -0
  138. package/lib/core/brain-md-schema.cjs +528 -0
  139. package/lib/core/brain-md-staleness.cjs +357 -0
  140. package/lib/core/brain-response-sanitize.cjs +188 -0
  141. package/lib/core/bridge-writer.cjs +477 -0
  142. package/lib/core/chat-context-builder.cjs +253 -0
  143. package/lib/core/cross-room-aggregator.cjs +762 -0
  144. package/lib/core/daily-briefing.cjs +438 -0
  145. package/lib/core/decision-capture.cjs +618 -0
  146. package/lib/core/deep-links.cjs +82 -0
  147. package/lib/core/dispatch-optimizer.cjs +354 -0
  148. package/lib/core/dual-path-detector.cjs +84 -0
  149. package/lib/core/dual-path-detector.test.cjs +334 -0
  150. package/lib/core/exports-log.cjs +79 -0
  151. package/lib/core/feynman-minto-invariants.cjs +605 -0
  152. package/lib/core/folder-memory-async.cjs +338 -0
  153. package/lib/core/folder-memory-shared.cjs +890 -0
  154. package/lib/core/folder-memory.cjs +416 -0
  155. package/lib/core/framework-chain-composer.cjs +411 -0
  156. package/lib/core/frontmatter-schemas.cjs +330 -0
  157. package/lib/core/git-ops.cjs +141 -0
  158. package/lib/core/graph-ops.cjs +258 -0
  159. package/lib/core/hat-persistence.cjs +362 -0
  160. package/lib/core/index.cjs +60 -0
  161. package/lib/core/integration-registry.cjs +232 -0
  162. package/lib/core/intelligence-cascade.cjs +661 -0
  163. package/lib/core/lazygraph-ops.cjs +1057 -0
  164. package/lib/core/lru-cache.cjs +139 -0
  165. package/lib/core/mcp-profiles.cjs +182 -0
  166. package/lib/core/meeting-ops.cjs +54 -0
  167. package/lib/core/memory-ops.cjs +600 -0
  168. package/lib/core/migrations/ROOM.md +33 -0
  169. package/lib/core/migrations/phase-109-nodes-provenance.cjs +339 -0
  170. package/lib/core/migrations/phase-109-session-focus.cjs +99 -0
  171. package/lib/core/model-profiles.cjs +246 -0
  172. package/lib/core/mullins-scaffold.cjs +160 -0
  173. package/lib/core/nav-dial.cjs +316 -0
  174. package/lib/core/navigation/ROOM.md +15 -0
  175. package/lib/core/navigation/explanation.cjs +43 -0
  176. package/lib/core/navigation/focus.cjs +135 -0
  177. package/lib/core/navigation/ingestion.cjs +82 -0
  178. package/lib/core/navigation/insights.cjs +350 -0
  179. package/lib/core/navigation/memory-events.cjs +118 -0
  180. package/lib/core/navigation/neighborhood.cjs +78 -0
  181. package/lib/core/navigation/packet.cjs +182 -0
  182. package/lib/core/navigation/room-home.cjs +127 -0
  183. package/lib/core/navigation/transitions.cjs +82 -0
  184. package/lib/core/navigation-engine-shared.cjs +242 -0
  185. package/lib/core/navigation-engine.cjs +664 -0
  186. package/lib/core/navigation.cjs +60 -0
  187. package/lib/core/nl-graph-queries.cjs +164 -0
  188. package/lib/core/offer-presenter.cjs +406 -0
  189. package/lib/core/opportunity-extractor.cjs +183 -0
  190. package/lib/core/opportunity-ops.cjs +1371 -0
  191. package/lib/core/persona-ops.cjs +537 -0
  192. package/lib/core/persona-taxonomy.cjs +190 -0
  193. package/lib/core/platform-gates.cjs +120 -0
  194. package/lib/core/platform.cjs +257 -0
  195. package/lib/core/proactive-intelligence.cjs +528 -0
  196. package/lib/core/problem-type-router.cjs +315 -0
  197. package/lib/core/reasoning-ops.cjs +639 -0
  198. package/lib/core/reverse-salient-persona-suffix.cjs +115 -0
  199. package/lib/core/room-classifier-strict-mode.cjs +229 -0
  200. package/lib/core/room-db.cjs +127 -0
  201. package/lib/core/room-ops-async.cjs +92 -0
  202. package/lib/core/room-ops-shared.cjs +64 -0
  203. package/lib/core/room-ops-sync.cjs +70 -0
  204. package/lib/core/room-ops.cjs +32 -0
  205. package/lib/core/room-type-detector.cjs +386 -0
  206. package/lib/core/rs-brain-substrate-prompts.cjs +129 -0
  207. package/lib/core/rs-brain-substrate.cjs +570 -0
  208. package/lib/core/rs-breakthrough-scorer.cjs +255 -0
  209. package/lib/core/rs-canon-violations.cjs +82 -0
  210. package/lib/core/rs-chain-feeder.cjs +343 -0
  211. package/lib/core/rs-commercial-assessor.cjs +280 -0
  212. package/lib/core/rs-differential-scorer.cjs +376 -0
  213. package/lib/core/rs-domain-analyzer.cjs +385 -0
  214. package/lib/core/rs-egress-prompts.cjs +113 -0
  215. package/lib/core/rs-egress-telemetry.cjs +225 -0
  216. package/lib/core/rs-egress-violations.cjs +53 -0
  217. package/lib/core/rs-expert-mapper.cjs +467 -0
  218. package/lib/core/rs-fetcher-academic.cjs +697 -0
  219. package/lib/core/rs-fetcher-experts.cjs +314 -0
  220. package/lib/core/rs-fetcher-industry.cjs +731 -0
  221. package/lib/core/rs-fetcher-patents.cjs +564 -0
  222. package/lib/core/rs-innovation-classifier.cjs +194 -0
  223. package/lib/core/rs-mind-map.cjs +656 -0
  224. package/lib/core/rs-neo4j-writer.cjs +388 -0
  225. package/lib/core/rs-nl-to-query.cjs +425 -0
  226. package/lib/core/rs-pinecone-bridge.cjs +303 -0
  227. package/lib/core/rs-preprocessor.cjs +350 -0
  228. package/lib/core/rs-query-matrix.cjs +316 -0
  229. package/lib/core/rs-query-to-text.cjs +438 -0
  230. package/lib/core/rs-sqlite-mirror.cjs +443 -0
  231. package/lib/core/rs-thesis-generator.cjs +188 -0
  232. package/lib/core/rs_cache.py +479 -0
  233. package/lib/core/rs_corpus.py +468 -0
  234. package/lib/core/rs_hybrid.py +586 -0
  235. package/lib/core/rs_math.py +287 -0
  236. package/lib/core/rs_rooms.py +193 -0
  237. package/lib/core/scheduled-scanner.cjs +463 -0
  238. package/lib/core/scratchpad-ops.cjs +201 -0
  239. package/lib/core/section-8-trace-schema.cjs +138 -0
  240. package/lib/core/section-registry.cjs +111 -0
  241. package/lib/core/session-state.cjs +144 -0
  242. package/lib/core/shallow-doc-parser.cjs +174 -0
  243. package/lib/core/shallow-doc-parser.test.cjs +226 -0
  244. package/lib/core/skill-activation-router.cjs +284 -0
  245. package/lib/core/state-ops.cjs +46 -0
  246. package/lib/core/statusline-cache.cjs +266 -0
  247. package/lib/core/token-estimator.cjs +348 -0
  248. package/lib/core/user-archetype.cjs +239 -0
  249. package/lib/core/user-md-ops.cjs +524 -0
  250. package/lib/core/visual-ops.cjs +624 -0
  251. package/lib/core/write-lock.cjs +149 -0
  252. package/lib/graph/canvas-graph.js +467 -0
  253. package/lib/graph/constellation-config.cjs +299 -0
  254. package/lib/graph/graph-detail-panel.js +165 -0
  255. package/lib/hmi/ROOM.md +47 -0
  256. package/lib/hmi/across-session-memory.cjs +604 -0
  257. package/lib/hmi/cross-room-memory.cjs +575 -0
  258. package/lib/hmi/decoy-tier.cjs +395 -0
  259. package/lib/hmi/jtbd-classifier.cjs +219 -0
  260. package/lib/hmi/jtbd-state.cjs +199 -0
  261. package/lib/hmi/jtbd-taxonomy.json +392 -0
  262. package/lib/hmi/selector-dispatcher.cjs +546 -0
  263. package/lib/hmi/selector-telemetry.cjs +263 -0
  264. package/lib/hmi/shape-f0-renderer.cjs +139 -0
  265. package/lib/hmi/shape-f1-fallback.cjs +80 -0
  266. package/lib/hmi/shape-f1-renderer.cjs +138 -0
  267. package/lib/hmi/shape-f2-renderer.cjs +132 -0
  268. package/lib/hmi/shape-f3-renderer.cjs +66 -0
  269. package/lib/hmi/shape-f4-renderer.cjs +72 -0
  270. package/lib/hmi/shape-f5-renderer.cjs +155 -0
  271. package/lib/hmi/shape-f6-plan-review-renderer.cjs +312 -0
  272. package/lib/hmi/shape-f6-renderer.cjs +144 -0
  273. package/lib/hmi/shape-g-renderer.cjs +219 -0
  274. package/lib/hmi/shape-h-renderer.cjs +222 -0
  275. package/lib/hmi/tier-check.cjs +63 -0
  276. package/lib/import/PRECONDITIONS.md +41 -0
  277. package/lib/import/branding.cjs +210 -0
  278. package/lib/import/branding.test.cjs +235 -0
  279. package/lib/import/classifications-sync.cjs +104 -0
  280. package/lib/import/classifications-sync.test.cjs +129 -0
  281. package/lib/import/enricher.cjs +296 -0
  282. package/lib/import/enricher.test.cjs +273 -0
  283. package/lib/import/integration.test.cjs +376 -0
  284. package/lib/import/manifest.cjs +129 -0
  285. package/lib/import/manifest.schema.json +185 -0
  286. package/lib/import/manifest.test.cjs +123 -0
  287. package/lib/import/meeting-detector.cjs +92 -0
  288. package/lib/import/meeting-detector.test.cjs +100 -0
  289. package/lib/import/person-detector.cjs +229 -0
  290. package/lib/import/person-detector.test.cjs +149 -0
  291. package/lib/import/report.cjs +186 -0
  292. package/lib/import/report.test.cjs +186 -0
  293. package/lib/import/room-md-scaffolder.cjs +49 -0
  294. package/lib/import/router.cjs +224 -0
  295. package/lib/import/router.test.cjs +356 -0
  296. package/lib/import/run-all-tests.cjs +36 -0
  297. package/lib/import/smoke-test.cjs +213 -0
  298. package/lib/import/smoke-test.test.cjs +148 -0
  299. package/lib/import/test-fixtures/collision-vault/preexisting-room/STATE.md +8 -0
  300. package/lib/import/test-fixtures/collision-vault/preexisting-room/problem-definition/onboarding/onboarding.md +7 -0
  301. package/lib/import/test-fixtures/collision-vault/source/onboarding.md +5 -0
  302. package/lib/import/test-fixtures/obsidian-vault/.obsidian/workspace.json +1 -0
  303. package/lib/import/test-fixtures/obsidian-vault/notes/with-wikilinks.md +4 -0
  304. package/lib/import/test-fixtures/tiny-vault/notes/2026-01-15-team-sync.md +9 -0
  305. package/lib/import/test-fixtures/tiny-vault/notes/empty.md +3 -0
  306. package/lib/import/test-fixtures/tiny-vault/notes/onboarding.md +5 -0
  307. package/lib/import/test-fixtures/tiny-vault/notes/pricing.md +5 -0
  308. package/lib/import/test-fixtures/tiny-vault/notes/random.md +4 -0
  309. package/lib/import/undo.test.cjs +199 -0
  310. package/lib/import/vault-scanner.cjs +105 -0
  311. package/lib/import/vault-scanner.test.cjs +67 -0
  312. package/lib/mcp/app-html/dashboard.html +316 -0
  313. package/lib/mcp/app-html/graph.html +428 -0
  314. package/lib/mcp/app-html/mindrian-platform.html +1841 -0
  315. package/lib/mcp/app-html/wiki.html +383 -0
  316. package/lib/mcp/app-views.cjs +322 -0
  317. package/lib/mcp/brain-router.cjs +418 -0
  318. package/lib/mcp/capability-registry.cjs +62 -0
  319. package/lib/mcp/larry-context.cjs +46 -0
  320. package/lib/mcp/larry-server-instructions.md +114 -0
  321. package/lib/mcp/pipeline-state.cjs +275 -0
  322. package/lib/mcp/prompts.cjs +302 -0
  323. package/lib/mcp/resources.cjs +227 -0
  324. package/lib/mcp/session-catchup.cjs +327 -0
  325. package/lib/mcp/surface-detect.cjs +75 -0
  326. package/lib/mcp/tool-router.cjs +1034 -0
  327. package/lib/memory/aaak-compress.cjs +403 -0
  328. package/lib/memory/aaak-compress.test.cjs +288 -0
  329. package/lib/memory/async-artifact-auto-commit.test.cjs +223 -0
  330. package/lib/memory/bearer-token.test.cjs +315 -0
  331. package/lib/memory/brain-cache-lru.test.cjs +259 -0
  332. package/lib/memory/brain-client-query-shape.test.cjs +160 -0
  333. package/lib/memory/brain-derivation-graceful-degradation.test.cjs +1019 -0
  334. package/lib/memory/brain-derivation-queue.test.cjs +539 -0
  335. package/lib/memory/brain-derivation.test.cjs +634 -0
  336. package/lib/memory/brain-derive-command.test.cjs +534 -0
  337. package/lib/memory/brain-md-invariants-validator.test.cjs +704 -0
  338. package/lib/memory/brain-md-schema.test.cjs +467 -0
  339. package/lib/memory/brain-md-staleness.test.cjs +525 -0
  340. package/lib/memory/brain-server-resolution.test.cjs +314 -0
  341. package/lib/memory/chain-recommender.test.cjs +233 -0
  342. package/lib/memory/chat-context.test.cjs +128 -0
  343. package/lib/memory/command-registry.test.cjs +220 -0
  344. package/lib/memory/cross-room-aggregator.test.cjs +909 -0
  345. package/lib/memory/dashboard-server.test.cjs +256 -0
  346. package/lib/memory/debouncer-drain-at-prompt.test.cjs +389 -0
  347. package/lib/memory/decision-capture.test.cjs +632 -0
  348. package/lib/memory/decision-capture.worker.cjs +70 -0
  349. package/lib/memory/explain-decision-command.test.cjs +521 -0
  350. package/lib/memory/explain-decision-footer.test.cjs +316 -0
  351. package/lib/memory/explored-materials-store.cjs +392 -0
  352. package/lib/memory/feynman-minto-guardian.test.cjs +736 -0
  353. package/lib/memory/feynman-minto-invariants.test.cjs +511 -0
  354. package/lib/memory/feynman-prompts-drift.test.cjs +144 -0
  355. package/lib/memory/feynman-prompts.cjs +151 -0
  356. package/lib/memory/feynman-prompts.test.cjs +96 -0
  357. package/lib/memory/folder-memory-quadruple.test.cjs +548 -0
  358. package/lib/memory/folder-memory.test.cjs +503 -0
  359. package/lib/memory/framework-chain-composer.test.cjs +515 -0
  360. package/lib/memory/frontmatter-schema-validator.test.cjs +290 -0
  361. package/lib/memory/heal-command.test.cjs +604 -0
  362. package/lib/memory/index-artifact-transaction.test.cjs +333 -0
  363. package/lib/memory/lazygraph-rs-discoveries-view.test.cjs +122 -0
  364. package/lib/memory/mcp-input-validation.test.cjs +240 -0
  365. package/lib/memory/mcp-server-brain-deps.test.cjs +270 -0
  366. package/lib/memory/mcp-stack-fallback.test.cjs +433 -0
  367. package/lib/memory/minto-debouncer.test.cjs +407 -0
  368. package/lib/memory/minto-debouncer.worker.cjs +46 -0
  369. package/lib/memory/minto-migration-v88.test.cjs +265 -0
  370. package/lib/memory/minto-schema-v88.test.cjs +390 -0
  371. package/lib/memory/mos-status-renderer.test.cjs +631 -0
  372. package/lib/memory/narrative-schema.cjs +376 -0
  373. package/lib/memory/narrative-schema.test.cjs +209 -0
  374. package/lib/memory/nav-dial.test.cjs +414 -0
  375. package/lib/memory/navigation-engine-core.test.cjs +722 -0
  376. package/lib/memory/navigation-invariants.test.cjs +483 -0
  377. package/lib/memory/offer-presenter.test.cjs +554 -0
  378. package/lib/memory/on-stop-snapshot.test.cjs +404 -0
  379. package/lib/memory/pending-tension-store.cjs +373 -0
  380. package/lib/memory/post-compact-reinjection.test.cjs +854 -0
  381. package/lib/memory/post-write-triple.test.cjs +317 -0
  382. package/lib/memory/pre-compact-snapshot.test.cjs +495 -0
  383. package/lib/memory/problem-type-router.test.cjs +656 -0
  384. package/lib/memory/query-efficiency-telemetry.test.cjs +370 -0
  385. package/lib/memory/recompile-room-references.test.cjs +392 -0
  386. package/lib/memory/recompile-room-references.worker.cjs +42 -0
  387. package/lib/memory/record-decision-dual-write.test.cjs +454 -0
  388. package/lib/memory/room-classifier-strict-mode.test.cjs +417 -0
  389. package/lib/memory/room-minto-hook.test.cjs +398 -0
  390. package/lib/memory/rs-discovery-engine.test.cjs +323 -0
  391. package/lib/memory/run-feynman-tests.cjs +1247 -0
  392. package/lib/memory/security-trifecta.test.cjs +312 -0
  393. package/lib/memory/session-start-brain-staleness.test.cjs +363 -0
  394. package/lib/memory/session-start-triple-injection.test.cjs +514 -0
  395. package/lib/memory/sessionstart-banner-formatter.cjs +318 -0
  396. package/lib/memory/sessionstart-minto-banner.test.cjs +373 -0
  397. package/lib/memory/skill-activation-router.test.cjs +419 -0
  398. package/lib/memory/stamp-artifact-write.test.cjs +304 -0
  399. package/lib/memory/statusline-active-room.test.cjs +315 -0
  400. package/lib/memory/statusline-minto-segment.test.cjs +292 -0
  401. package/lib/memory/sync-async-entry-points.test.cjs +204 -0
  402. package/lib/memory/test-bridge-writer-enhanced.cjs +452 -0
  403. package/lib/memory/test-rs-brain-substrate-shape.cjs +529 -0
  404. package/lib/memory/test-rs-brain-substrate.cjs +636 -0
  405. package/lib/memory/test-rs-breakthrough-scorer.cjs +375 -0
  406. package/lib/memory/test-rs-canon-violations.cjs +218 -0
  407. package/lib/memory/test-rs-chain-feeder-core.cjs +344 -0
  408. package/lib/memory/test-rs-chain-feeder-skill-spawn.cjs +297 -0
  409. package/lib/memory/test-rs-commercial-assessor.cjs +385 -0
  410. package/lib/memory/test-rs-differential-scorer.cjs +480 -0
  411. package/lib/memory/test-rs-discovery-engine.cjs +603 -0
  412. package/lib/memory/test-rs-domain-analyzer.cjs +492 -0
  413. package/lib/memory/test-rs-egress-primitives.cjs +420 -0
  414. package/lib/memory/test-rs-expert-mapper.cjs +547 -0
  415. package/lib/memory/test-rs-explain-command.cjs +443 -0
  416. package/lib/memory/test-rs-fetcher-academic.cjs +848 -0
  417. package/lib/memory/test-rs-fetcher-experts.cjs +496 -0
  418. package/lib/memory/test-rs-fetcher-industry.cjs +702 -0
  419. package/lib/memory/test-rs-fetcher-patents.cjs +674 -0
  420. package/lib/memory/test-rs-innovation-classifier.cjs +301 -0
  421. package/lib/memory/test-rs-mind-map.cjs +646 -0
  422. package/lib/memory/test-rs-neo4j-writer.cjs +518 -0
  423. package/lib/memory/test-rs-nl-to-query.cjs +449 -0
  424. package/lib/memory/test-rs-pinecone-bridge.cjs +277 -0
  425. package/lib/memory/test-rs-preprocessor.cjs +433 -0
  426. package/lib/memory/test-rs-query-matrix.cjs +391 -0
  427. package/lib/memory/test-rs-query-to-text.cjs +551 -0
  428. package/lib/memory/test-rs-sqlite-mirror.cjs +649 -0
  429. package/lib/memory/test-rs-thesis-generator.cjs +360 -0
  430. package/lib/memory/triple-context-formatter.cjs +473 -0
  431. package/lib/memory/triple-context-formatter.test.cjs +442 -0
  432. package/lib/memory/user-md-persona.test.cjs +565 -0
  433. package/lib/memory/userpromptsubmit-integration.test.cjs +690 -0
  434. package/lib/memory/validators/README.md +157 -0
  435. package/lib/memory/validators/brain-md-invariants.cjs +475 -0
  436. package/lib/memory/validators/brain-substrate-invariants.cjs +285 -0
  437. package/lib/memory/validators/external-academic-invariants.cjs +249 -0
  438. package/lib/memory/validators/external-industry-invariants.cjs +271 -0
  439. package/lib/memory/validators/external-patents-invariants.cjs +266 -0
  440. package/lib/memory/validators/minto-invariants.cjs +62 -0
  441. package/lib/memory/validators/navigation-invariants.cjs +340 -0
  442. package/lib/memory/validators/queue-health.cjs +95 -0
  443. package/lib/memory/validators/snapshot-integrity.cjs +129 -0
  444. package/lib/memory/validators/stale-lifecycle.cjs +116 -0
  445. package/lib/memory/vault-section-minto-generator-atomic.test.cjs +556 -0
  446. package/lib/memory/vault-section-minto-generator-atomic.worker.cjs +73 -0
  447. package/lib/memory/write-lock-atomic.test.cjs +137 -0
  448. package/lib/memory/write-lock-atomic.worker.cjs +55 -0
  449. package/lib/parity/check-parity.cjs +83 -0
  450. package/lib/presentation/presentation-server.cjs +101 -0
  451. package/lib/presentation/presentation-watcher.cjs +123 -0
  452. package/lib/quickview/hub-server.cjs +719 -0
  453. package/lib/quickview/server.cjs +533 -0
  454. package/lib/render/JTBD-PALETTES.md +145 -0
  455. package/lib/render/ROOM.md +59 -0
  456. package/lib/render/render-v2.cjs +486 -0
  457. package/lib/render/render-v2.test.cjs +267 -0
  458. package/lib/render/render.cjs +65 -0
  459. package/lib/state/ROOM.md +46 -0
  460. package/lib/state/state-md-parser.cjs +215 -0
  461. package/lib/statusline/ROOM.md +38 -0
  462. package/lib/statusline/banner-suppression.cjs +50 -0
  463. package/lib/statusline/surface-detect.cjs +85 -0
  464. package/lib/update-bootstrap.sh.template +145 -0
  465. package/lib/vault/frontmatter-schema.cjs +297 -0
  466. package/lib/vault/room-scanner.cjs +352 -0
  467. package/lib/vault/wikilink-builder.cjs +231 -0
  468. package/lib/vault/wikilink-builder.test.cjs +182 -0
  469. package/lib/wiki/graph-links.cjs +281 -0
  470. package/lib/wiki/page-renderer.cjs +229 -0
  471. package/lib/wiki/wiki-chat.cjs +81 -0
  472. package/lib/wiki/wiki-layout.cjs +1459 -0
  473. package/lib/wiki/wiki-search.cjs +142 -0
  474. package/lib/wiki/wiki-server.cjs +678 -0
  475. package/lib/wiki/wiki-watcher.cjs +105 -0
  476. package/lib/workflow/ROOM.md +47 -0
  477. package/lib/workflow/command-resolver.cjs +155 -0
  478. package/lib/workflow/command-resolver.test.cjs +235 -0
  479. package/package.json +44 -0
  480. package/pipelines/analogy/01-decompose.md +80 -0
  481. package/pipelines/analogy/02-abstract.md +87 -0
  482. package/pipelines/analogy/03-search.md +135 -0
  483. package/pipelines/analogy/04-transfer.md +101 -0
  484. package/pipelines/analogy/05-validate.md +106 -0
  485. package/pipelines/analogy/CHAIN.md +56 -0
  486. package/pipelines/discovery/01-explore-domains.md +44 -0
  487. package/pipelines/discovery/02-think-hats.md +50 -0
  488. package/pipelines/discovery/03-analyze-needs.md +54 -0
  489. package/pipelines/discovery/CHAIN.md +37 -0
  490. package/pipelines/thesis/01-structure-argument.md +45 -0
  491. package/pipelines/thesis/02-challenge-assumptions.md +48 -0
  492. package/pipelines/thesis/03-build-thesis.md +54 -0
  493. package/pipelines/thesis/CHAIN.md +37 -0
  494. package/references/brain/causal-directives.md +91 -0
  495. package/references/brain/causal-enrichment.cypher +165 -0
  496. package/references/brain/command-triggers-schema.md +226 -0
  497. package/references/brain/graph-architecture.md +317 -0
  498. package/references/brain/query-patterns.md +460 -0
  499. package/references/brain/room-hierarchy-schema.md +218 -0
  500. package/references/brain/schema.md +76 -0
  501. package/references/capability-radar/capabilities-index.md +241 -0
  502. package/references/capability-radar/changelog-cache.md +81 -0
  503. package/references/causal/causal-schema.md +103 -0
  504. package/references/design/email-template-standard.md +155 -0
  505. package/references/design/graph-visualization-standard.md +178 -0
  506. package/references/document-generation.md +179 -0
  507. package/references/hsi/HSI-TOOLS-REFERENCE.md +222 -0
  508. package/references/import-config.md +141 -0
  509. package/references/integrations/detection-patterns.md +101 -0
  510. package/references/meeting/artifact-template.md +377 -0
  511. package/references/meeting/cross-meeting-intelligence.md +216 -0
  512. package/references/meeting/cross-relationship-patterns.md +202 -0
  513. package/references/meeting/live-join-interface.md +244 -0
  514. package/references/meeting/section-mapping.md +192 -0
  515. package/references/meeting/segment-classification.md +258 -0
  516. package/references/meeting/speaker-profile-template.md +219 -0
  517. package/references/meeting/summary-template.md +348 -0
  518. package/references/meeting/transcript-patterns.md +226 -0
  519. package/references/methodology/analyze-needs.md +135 -0
  520. package/references/methodology/analyze-systems.md +121 -0
  521. package/references/methodology/analyze-timing.md +149 -0
  522. package/references/methodology/beautiful-question.md +109 -0
  523. package/references/methodology/build-knowledge.md +161 -0
  524. package/references/methodology/build-thesis.md +237 -0
  525. package/references/methodology/challenge-assumptions.md +127 -0
  526. package/references/methodology/diagnose.md +169 -0
  527. package/references/methodology/dominant-designs.md +212 -0
  528. package/references/methodology/explore-domains.md +147 -0
  529. package/references/methodology/explore-futures.md +163 -0
  530. package/references/methodology/explore-trends.md +129 -0
  531. package/references/methodology/find-bottlenecks.md +131 -0
  532. package/references/methodology/grade.md +211 -0
  533. package/references/methodology/index.md +97 -0
  534. package/references/methodology/leadership.md +200 -0
  535. package/references/methodology/lean-canvas.md +116 -0
  536. package/references/methodology/macro-trends.md +192 -0
  537. package/references/methodology/map-unknowns.md +137 -0
  538. package/references/methodology/mullins-7-domains.md +104 -0
  539. package/references/methodology/problem-types.md +65 -0
  540. package/references/methodology/root-cause.md +178 -0
  541. package/references/methodology/sapphire-encoding.md +355 -0
  542. package/references/methodology/scenario-plan.md +178 -0
  543. package/references/methodology/score-innovation.md +154 -0
  544. package/references/methodology/structure-argument.md +158 -0
  545. package/references/methodology/systems-thinking.md +159 -0
  546. package/references/methodology/think-hats.md +147 -0
  547. package/references/methodology/triz-matrix.json +751 -0
  548. package/references/methodology/triz-principles.md +501 -0
  549. package/references/methodology/user-needs.md +199 -0
  550. package/references/methodology/validate.md +163 -0
  551. package/references/methodology/value-proposition.md +244 -0
  552. package/references/opportunities/funding-lifecycle.md +103 -0
  553. package/references/opportunities/grant-api-patterns.md +99 -0
  554. package/references/opportunities/opportunity-template.md +84 -0
  555. package/references/personality/assessment-philosophy.md +72 -0
  556. package/references/personality/lexicon.md +100 -0
  557. package/references/personality/persona-chains.md +56 -0
  558. package/references/personality/pws-lexicon-full.md +499 -0
  559. package/references/personality/voice-dna.md +156 -0
  560. package/references/personas/hat-perspectives.md +76 -0
  561. package/references/personas/persona-template.md +63 -0
  562. package/references/pipeline/act-output-contract.md +88 -0
  563. package/references/pipeline/chains-index.md +39 -0
  564. package/references/pws-profile-generation.md +79 -0
  565. package/references/reasoning/reasoning-schema.md +143 -0
  566. package/references/reasoning/reasoning-template.md +68 -0
  567. package/references/reasoning/run-template.md +38 -0
  568. package/references/research/RESEARCH_14_CLAUDE_CODE_SOURCE_ARCHITECTURE.md +209 -0
  569. package/references/research/RESEARCH_15_V1.8_OPTIMIZATION_JTBD.md +375 -0
  570. package/references/research/RESEARCH_16_NATIVE_FIRST_PLUGIN_ARCHITECTURE.md +575 -0
  571. package/references/research/RESEARCH_17_MCP_UI_FRAMEWORKS.md +272 -0
  572. package/references/taxonomy/TAXONOMY.md +192 -0
  573. package/references/templates/MINTO.md +36 -0
  574. package/references/user-research/2026-04-05-leah-lawrence-session.md +202 -0
  575. package/references/vault-kit/README.md +35 -0
  576. package/references/vault-kit/app.json +12 -0
  577. package/references/vault-kit/appearance.json +12 -0
  578. package/references/vault-kit/graph.json +35 -0
  579. package/references/vault-kit/snippets/mindrian-destijl.css +297 -0
  580. package/references/vault-kit/templates/new-artifact.md +37 -0
  581. package/references/vault-kit/templates/new-meeting-note.md +35 -0
  582. package/references/vault-kit/templates/new-team-profile.md +29 -0
  583. package/references/vault-kit/templates/new-xref.md +35 -0
  584. package/references/visual/symbol-system.md +151 -0
  585. package/skills/MOSDeckEngine/SKILL.md +325 -0
  586. package/skills/brain-connector/SKILL.md +114 -0
  587. package/skills/context-engine/SKILL.md +147 -0
  588. package/skills/conversation-mode/SKILL.md +102 -0
  589. package/skills/larry-personality/SKILL.md +219 -0
  590. package/skills/larry-personality/framework-chains.md +92 -0
  591. package/skills/larry-personality/mode-engine.md +185 -0
  592. package/skills/mullins-scaffold/SKILL.md +61 -0
  593. package/skills/mullins-scaffold/scaffold.json +146 -0
  594. package/skills/pws-methodology/SKILL.md +49 -0
  595. package/skills/room-passive/SKILL.md +165 -0
  596. package/skills/room-proactive/SKILL.md +250 -0
  597. package/skills/ui-system/SKILL.md +277 -0
@@ -0,0 +1,115 @@
1
+ /*
2
+ * Copyright (c) 2026 Mindrian. BSL 1.1.
3
+ *
4
+ * Phase 89-07 Wave 2 -- ReverseSalientAgent persona suffix.
5
+ *
6
+ * Maps Phase 115 USER.md role_blend -> persona-aware F.0 header suffix.
7
+ * 7 canonical role keys + 2 aliases + default fallback.
8
+ *
9
+ * Lex tie-break per Phase 115 D-AMEND-04 (agents/larry-extended.md lines 78-100):
10
+ * 1. Filter to canonical keys with positive numeric weight
11
+ * 2. Sort filtered keys alphabetically
12
+ * 3. Walk in sorted order, keep highest-weight; on ties, alphabetical earlier wins
13
+ * 4. Any error / no canonical match / all-zero weights -> default
14
+ *
15
+ * Editorial copy (SCOPE B Section 6 of 89-07-RESEARCH.md, confidence: LOW):
16
+ * founder -> 'shipping risk'
17
+ * researcher -> 'evidence gap'
18
+ * researcher_ind -> 'evidence gap' (functionally a researcher persona)
19
+ * founder_grant -> 'submission risk' (grant-specific founder)
20
+ * investor -> 'thesis fragility'
21
+ * operator -> 'execution gap'
22
+ * mentor -> 'coaching wedge'
23
+ * domain_expert -> 'physical-reality friction'
24
+ * student -> 'understanding gap'
25
+ * default -> 'lagging component'
26
+ *
27
+ * Wording is tunable post-empathy-audit per RESEARCH Confidence: LOW caveat.
28
+ * Final copy is subject to revision after the beta.4 empathy audit, at which
29
+ * point both this module and any consumer test would be updated together.
30
+ *
31
+ * Pure CJS, zero dependencies, never throws.
32
+ */
33
+
34
+ 'use strict';
35
+
36
+ // Frozen suffix map. 9 keys + default = 10 entries.
37
+ const PERSONA_SUFFIX = Object.freeze({
38
+ founder: 'shipping risk',
39
+ researcher: 'evidence gap',
40
+ researcher_ind: 'evidence gap',
41
+ founder_grant: 'submission risk',
42
+ investor: 'thesis fragility',
43
+ operator: 'execution gap',
44
+ mentor: 'coaching wedge',
45
+ domain_expert: 'physical-reality friction',
46
+ student: 'understanding gap',
47
+ default: 'lagging component',
48
+ });
49
+
50
+ // Frozen canonical key list. Order is alphabetical (matches lex tie-break
51
+ // expectation in tests). 9 canonical + 'default' = 10 entries.
52
+ const CANONICAL_KEYS = Object.freeze([
53
+ 'default',
54
+ 'domain_expert',
55
+ 'founder',
56
+ 'founder_grant',
57
+ 'investor',
58
+ 'mentor',
59
+ 'operator',
60
+ 'researcher',
61
+ 'researcher_ind',
62
+ 'student',
63
+ ]);
64
+
65
+ /**
66
+ * Pick the persona suffix string for a USER.md role_blend object.
67
+ *
68
+ * @param {object|null|undefined} roleBlend
69
+ * { founder?: number, researcher?: number, ... } per Phase 115 schema.
70
+ * @returns {string} One of the PERSONA_SUFFIX values; 'lagging component' on
71
+ * any failure / cold-start / empty / all-zero / unknown-key.
72
+ */
73
+ function suffixFor(roleBlend) {
74
+ try {
75
+ // Reject non-object, null, undefined, primitives.
76
+ if (roleBlend === null || roleBlend === undefined) return PERSONA_SUFFIX.default;
77
+ if (typeof roleBlend !== 'object') return PERSONA_SUFFIX.default;
78
+ // Arrays pass typeof === 'object' but their numeric-index keys never match
79
+ // CANONICAL_KEYS so they fall through to default. We document this rather
80
+ // than special-case Array.isArray(...) since the filter step handles it.
81
+
82
+ const keys = Object.keys(roleBlend);
83
+ if (keys.length === 0) return PERSONA_SUFFIX.default;
84
+
85
+ // Canonical-only candidates with positive numeric weight; lex tie-break by
86
+ // walking sorted keys (alphabetical earlier wins on ties because we keep
87
+ // strict > comparison and the earlier key was assigned first).
88
+ const canonicalSorted = keys
89
+ .filter((k) => CANONICAL_KEYS.indexOf(k) !== -1)
90
+ .sort();
91
+
92
+ let best = null;
93
+ let bestWeight = 0;
94
+ for (const k of canonicalSorted) {
95
+ const w = roleBlend[k];
96
+ if (typeof w === 'number' && Number.isFinite(w) && w > bestWeight) {
97
+ best = k;
98
+ bestWeight = w;
99
+ }
100
+ }
101
+ if (best === null || bestWeight <= 0) return PERSONA_SUFFIX.default;
102
+ // Reliability fence: if PERSONA_SUFFIX somehow lacks the canonical key
103
+ // (shouldn't be possible since CANONICAL_KEYS and PERSONA_SUFFIX are
104
+ // co-frozen at module load), fall through to default.
105
+ return PERSONA_SUFFIX[best] || PERSONA_SUFFIX.default;
106
+ } catch (_e) {
107
+ return PERSONA_SUFFIX.default;
108
+ }
109
+ }
110
+
111
+ module.exports = {
112
+ suffixFor: suffixFor,
113
+ PERSONA_SUFFIX: PERSONA_SUFFIX,
114
+ CANONICAL_KEYS: CANONICAL_KEYS,
115
+ };
@@ -0,0 +1,229 @@
1
+ /*
2
+ * Copyright (c) 2026 Mindrian. BSL 1.1.
3
+ * (Business Source License 1.1; SPDX BUSL-1.1; see LICENSE.)
4
+ *
5
+ * Phase 94-06 -- Room classifier strict-mode override
6
+ *
7
+ * Pure-function detector that resolves three unambiguous user-input
8
+ * patterns directly to a registered room, bypassing the similarity
9
+ * heuristic in scripts/intent-classifier.cjs:
10
+ *
11
+ * 1. Numeric position 'switch to 8' or '8' -> registry[N-1]
12
+ * 2. Explicit slug 'curriculum-redesign-fall-2026' -> exact slug
13
+ * '/mos:rooms <slug>'
14
+ * 3. Quoted exact name '"Beta"' / '"Curriculum Redesign"' -> name OR slug
15
+ *
16
+ * First match wins (numeric, then slug, then quoted). When NO pattern
17
+ * matches, returns null and the classifier falls through to its existing
18
+ * similarity heuristic. The override is forward-additive: similarity
19
+ * heuristic is unchanged.
20
+ *
21
+ * Canon Part 3 (10-verb vocabulary preserved): strict-mode is a routing
22
+ * OVERRIDE, not a new verb. The 10 canonical verbs in
23
+ * lib/core/navigation-engine-shared.cjs are untouched.
24
+ *
25
+ * Canon Part 4 (every choice is graph data): when the override fires,
26
+ * the caller emits a Section-8 decision-trace edge with
27
+ * routing_source: 'strict_mode' so /mos:explain-decision can attribute
28
+ * the resolution.
29
+ *
30
+ * Canon Part 7 (reuse before build): extends scripts/intent-classifier.cjs
31
+ * by composition (separate helper module imported by the classifier),
32
+ * NOT by replacing the existing similarity heuristic. The justification
33
+ * bar for net-new capability is met: strict-mode handles cases the
34
+ * similarity heuristic cannot disambiguate (numeric position has no
35
+ * token overlap; explicit slug should never be misrouted; quoted exact
36
+ * name is the user's clearest signal).
37
+ *
38
+ * Lawrence Aronhime reproducer fence (2026-04-28 38-min live test):
39
+ * with two rooms loaded ('core-power-isolation' +
40
+ * 'curriculum-redesign-fall-2026'), Lawrence's four utterances kept
41
+ * resolving to the WRONG room. Plan 94-06 fences callouts 1 (numeric),
42
+ * 2 (slug-form), and 4 (slash command) via this module. Callout 3
43
+ * ('the curriculum room', natural language) is known-deferred to
44
+ * v1.11.3 because it requires a natural-language intent layer.
45
+ *
46
+ * Pure CJS, zero npm deps. Never throws.
47
+ */
48
+ 'use strict';
49
+
50
+ // ---------- Routing source constant ----------
51
+
52
+ // Section-8 decision-trace edge value when this layer fires. Forward-
53
+ // additive per Phase 91 invariant: existing routing_source values
54
+ // ('engine' | 'legacy' | 'mixed' | 'classifier') are unaffected.
55
+ const STRICT_MODE_ROUTING_SOURCE = 'strict_mode';
56
+
57
+ // ---------- Pattern regexes ----------
58
+
59
+ // Numeric: 'switch to 8' or '8' or 'go to 5' or 'jump to 3' or
60
+ // 'move to 2'. Bounded to a small synonym set so we don't accidentally
61
+ // match prose like 'jump 3 hoops' (no 'to' keyword).
62
+ const NUMERIC_PATTERN = /^(?:(?:switch|go|jump|move)\s+to\s+)?(\d+)$/i;
63
+
64
+ // Explicit slug: lowercase letters, digits, hyphens. 3-80 chars total.
65
+ // Starts AND ends with alphanumeric (no leading/trailing hyphen).
66
+ // Optional '/mos:rooms ' prefix to honor the canonical command form.
67
+ const SLUG_PATTERN = /^(?:\/mos:rooms\s+)?([a-z0-9][a-z0-9-]{1,78}[a-z0-9])$/;
68
+
69
+ // Quoted: any quoted span (single or double). The captured inner text
70
+ // is the candidate room name OR slug.
71
+ const QUOTED_PATTERN = /^['"]([^'"]+)['"]$/;
72
+
73
+ // ---------- Registry parsing ----------
74
+
75
+ /**
76
+ * parseRegistryRooms(reg) -> [{slug, name, path?}]
77
+ *
78
+ * Normalize the registry rooms field into a deterministic array of room
79
+ * records. Tolerates the array form, the object form, and the legacy
80
+ * string-only form. Preserves insertion order so 1-indexed numeric
81
+ * position is deterministic.
82
+ */
83
+ function parseRegistryRooms(reg) {
84
+ if (!reg || !reg.rooms) return [];
85
+ const out = [];
86
+ if (Array.isArray(reg.rooms)) {
87
+ for (const r of reg.rooms) {
88
+ if (typeof r === 'string') {
89
+ out.push({ slug: r, name: r });
90
+ } else if (r && typeof r === 'object') {
91
+ const slug = (typeof r.slug === 'string' && r.slug)
92
+ ? r.slug
93
+ : (typeof r.name === 'string' ? r.name : null);
94
+ if (!slug) continue;
95
+ const name = (typeof r.name === 'string' && r.name) ? r.name : slug;
96
+ out.push({ slug: slug, name: name, path: r.path || null });
97
+ }
98
+ }
99
+ return out;
100
+ }
101
+ if (typeof reg.rooms === 'object') {
102
+ // Object form: keys are slugs; values are metadata objects. Order
103
+ // is the JSON insertion order (V8 preserves; per ES2015 spec for
104
+ // string keys). 1-indexed numeric position resolves to
105
+ // Object.keys(...)[N-1].
106
+ for (const slug of Object.keys(reg.rooms)) {
107
+ const meta = reg.rooms[slug];
108
+ const name = (meta && typeof meta.venture_name === 'string' && meta.venture_name)
109
+ ? meta.venture_name
110
+ : (meta && typeof meta.name === 'string' && meta.name ? meta.name : slug);
111
+ out.push({
112
+ slug: slug,
113
+ name: name,
114
+ path: (meta && typeof meta.path === 'string') ? meta.path : null,
115
+ });
116
+ }
117
+ return out;
118
+ }
119
+ return [];
120
+ }
121
+
122
+ // ---------- Strict-mode detector ----------
123
+
124
+ /**
125
+ * detectStrictMode(prompt, registry) -> {slug, name, pattern, routing_source} | null
126
+ *
127
+ * Pure function. Tries the three strict-mode patterns in precedence
128
+ * order and returns the first match. Returns null when no pattern
129
+ * applies (caller falls through to similarity heuristic).
130
+ *
131
+ * Never throws. Defensive on registry shape (array OR object form).
132
+ *
133
+ * @param {string} prompt
134
+ * @param {object} registry
135
+ * @returns {{slug:string, name:string, pattern:string, routing_source:string} | null}
136
+ */
137
+ function detectStrictMode(prompt, registry) {
138
+ if (typeof prompt !== 'string') return null;
139
+ const trimmed = prompt.trim();
140
+ if (!trimmed) return null;
141
+
142
+ const rooms = parseRegistryRooms(registry);
143
+ if (rooms.length === 0) return null;
144
+
145
+ // Pattern 1: numeric (1-indexed registry position).
146
+ const numMatch = trimmed.match(NUMERIC_PATTERN);
147
+ if (numMatch) {
148
+ const idx = parseInt(numMatch[1], 10) - 1;
149
+ if (idx >= 0 && idx < rooms.length) {
150
+ const r = rooms[idx];
151
+ return {
152
+ slug: r.slug,
153
+ name: r.name,
154
+ path: r.path,
155
+ pattern: 'numeric',
156
+ routing_source: STRICT_MODE_ROUTING_SOURCE,
157
+ input: prompt,
158
+ };
159
+ }
160
+ // Numeric pattern matched syntactically but index out of bounds.
161
+ // Return null so the similarity heuristic gets a turn.
162
+ return null;
163
+ }
164
+
165
+ // Pattern 2: explicit slug (case-sensitive against registry slugs).
166
+ const slugMatch = trimmed.match(SLUG_PATTERN);
167
+ if (slugMatch) {
168
+ const candidate = slugMatch[1];
169
+ for (const r of rooms) {
170
+ if (r.slug === candidate) {
171
+ return {
172
+ slug: r.slug,
173
+ name: r.name,
174
+ path: r.path,
175
+ pattern: 'slug',
176
+ routing_source: STRICT_MODE_ROUTING_SOURCE,
177
+ input: prompt,
178
+ };
179
+ }
180
+ }
181
+ // Pattern matched but slug not registered. Fall through to
182
+ // pattern 3 / similarity (do NOT short-circuit; the slug form
183
+ // may also be a quoted-or-natural-language input that happens
184
+ // to look slug-like).
185
+ }
186
+
187
+ // Pattern 3: quoted exact name OR slug. Single OR double quote span.
188
+ // Name match is case-insensitive; slug match is case-insensitive too
189
+ // (slugs in registry are lowercase by convention but user may type
190
+ // 'Curriculum-Redesign-Fall-2026' with title case).
191
+ const quoteMatch = trimmed.match(QUOTED_PATTERN);
192
+ if (quoteMatch) {
193
+ const candidate = quoteMatch[1];
194
+ const candidateLower = candidate.toLowerCase();
195
+ for (const r of rooms) {
196
+ if (r.slug === candidate
197
+ || (typeof r.name === 'string' && r.name === candidate)
198
+ || (typeof r.name === 'string' && r.name.toLowerCase() === candidateLower)
199
+ || r.slug.toLowerCase() === candidateLower) {
200
+ return {
201
+ slug: r.slug,
202
+ name: r.name,
203
+ path: r.path,
204
+ pattern: 'quoted',
205
+ routing_source: STRICT_MODE_ROUTING_SOURCE,
206
+ input: prompt,
207
+ };
208
+ }
209
+ }
210
+ // Pattern matched but no name/slug matches. Fall through.
211
+ }
212
+
213
+ return null;
214
+ }
215
+
216
+ // ---------- Exports ----------
217
+
218
+ module.exports = {
219
+ detectStrictMode: detectStrictMode,
220
+ parseRegistryRooms: parseRegistryRooms,
221
+ STRICT_MODE_ROUTING_SOURCE: STRICT_MODE_ROUTING_SOURCE,
222
+ // Pattern regexes are exported for downstream tooling that wants to
223
+ // reuse the canonical patterns (e.g. /mos:explain-decision rendering
224
+ // or future natural-language layer that wants to disambiguate from
225
+ // strict-mode patterns).
226
+ NUMERIC_PATTERN: NUMERIC_PATTERN,
227
+ SLUG_PATTERN: SLUG_PATTERN,
228
+ QUOTED_PATTERN: QUOTED_PATTERN,
229
+ };
@@ -0,0 +1,127 @@
1
+ 'use strict';
2
+ // Composition entry point for room.db. Phase 109 chains two idempotent migrations
3
+ // after the existing schema init: nodes-provenance (Plan 109-01) then session_focus
4
+ // (Plan 109-02).
5
+ //
6
+ // Phase 109-02 contract change (parallel-worktree merge surface):
7
+ // openRoomDb is now SYNCHRONOUS and returns the bare node:sqlite DatabaseSync
8
+ // handle (not the legacy { db, conn } async tuple). Pre-Phase-109 callers that
9
+ // did `const handle = await openRoomDb(roomDir); handle.db.prepare(...)` need to
10
+ // either:
11
+ // (a) drop the await and use the returned db directly, or
12
+ // (b) call the openGraph low-level API directly.
13
+ // The async tuple shape was a leak from lazygraph-ops.cjs openGraph(); the
14
+ // navigation API (Plan 109-04) and all 109-* helpers consume the bare db.
15
+ // Plan 109-01's nodes-provenance migration was authored against the same
16
+ // sync contract; the orchestrator merges both 109-01 and 109-02 worktrees
17
+ // onto the same single-line migration chain shown below.
18
+ //
19
+ // Phase 109-06 addition: runtime soft-defense audit log per RESEARCH section 3.3.
20
+ // When openRoomDb is called from outside the navigation/* allow-list, we append
21
+ // one JSONL line to ~/.mindrian/telemetry/navigation-bypass.jsonl. Defensive
22
+ // (never throws). LOCAL only (Canon Part 8). sha256-hashed room slug. Mirrors
23
+ // Phase 88.1-16 query-efficiency telemetry pattern. Opt-out via env var
24
+ // MINDRIAN_DISABLE_BYPASS_AUDIT=1.
25
+
26
+ const path = require('node:path');
27
+ const fs = require('node:fs');
28
+ const os = require('node:os');
29
+ const crypto = require('node:crypto');
30
+ const { DatabaseSync } = require('node:sqlite');
31
+ const lazygraph = require('./lazygraph-ops.cjs');
32
+ const memory = require('./memory-ops.cjs');
33
+ const { runMigration: runPhase109SessionFocus } = require('./migrations/phase-109-session-focus.cjs');
34
+
35
+ // Plan 109-01 migration is loaded best-effort. In a parallel worktree where
36
+ // 109-01 has not yet shipped, the require will throw MODULE_NOT_FOUND and we
37
+ // fall back to the 109-02 migration's defensive ensureProvenanceColumns()
38
+ // backfill (which is a strict subset of the 109-01 schema work). Once 109-01
39
+ // merges, this loader resolves and the canonical migration runs first.
40
+ let runPhase109NodesProvenance = null;
41
+ try {
42
+ runPhase109NodesProvenance = require('./migrations/phase-109-nodes-provenance.cjs').runMigration;
43
+ } catch (_e) {
44
+ // 109-01 not present in this worktree; 109-02 migration handles its own
45
+ // FK target schema needs additively.
46
+ }
47
+
48
+ // Phase 109-06 runtime soft-defense. Inspect Error().stack to find the first
49
+ // frame outside this file. If that frame is NOT inside the navigation allow-list,
50
+ // append one JSONL line to ~/.mindrian/telemetry/navigation-bypass.jsonl with
51
+ // scalar fields only (timestamp, caller path, sha256 room hash). Defensive at
52
+ // every step: try/catch swallow, stack-parse failures default to 'unknown'.
53
+ function auditBypassIfNeeded(roomDir) {
54
+ if (process.env.MINDRIAN_DISABLE_BYPASS_AUDIT === '1') return;
55
+ let callerFile = 'unknown';
56
+ try {
57
+ const stack = (new Error()).stack.split('\n');
58
+ // Walk frames after the Error constructor. Skip any frame whose file is
59
+ // room-db.cjs itself (this function + openRoomDb wrapper).
60
+ for (let i = 1; i < Math.min(stack.length, 12); i++) {
61
+ const frame = stack[i];
62
+ // Match either '(path:line:col)' or 'at path:line:col' shapes.
63
+ const m = frame.match(/\(([^)]+):\d+:\d+\)/) || frame.match(/at\s+(.+):\d+:\d+/);
64
+ if (m && m[1] && !/room-db\.cjs$/.test(m[1])) {
65
+ callerFile = m[1];
66
+ break;
67
+ }
68
+ }
69
+ } catch (_) { /* swallow */ }
70
+ const normalized = callerFile.replace(/\\/g, '/');
71
+ // Allow-list mirrors the pre-commit hook list. No JSONL write for legitimate
72
+ // navigation/* + tests + migration scripts callers.
73
+ if (
74
+ normalized.includes('/lib/core/navigation/') ||
75
+ normalized.endsWith('/lib/core/navigation.cjs') ||
76
+ /[\\/]tests[\\/]/.test(callerFile) ||
77
+ /[\\/]scripts[\\/]migrate-/.test(callerFile) ||
78
+ /[\\/]lib[\\/]core[\\/]migrations[\\/]/.test(callerFile)
79
+ ) {
80
+ return;
81
+ }
82
+ try {
83
+ const dir = path.join(os.homedir(), '.mindrian', 'telemetry');
84
+ fs.mkdirSync(dir, { recursive: true });
85
+ const sha = crypto.createHash('sha256').update(String(roomDir || '')).digest('hex').slice(0, 16);
86
+ const line = JSON.stringify({ ts: Date.now(), caller: callerFile, room_hash: sha }) + '\n';
87
+ fs.appendFileSync(path.join(dir, 'navigation-bypass.jsonl'), line);
88
+ } catch (_) { /* never throw */ }
89
+ }
90
+
91
+ function openRoomDb(roomDir) {
92
+ // Soft-defense MUST be first so the caller is detected even when downstream
93
+ // schema init throws. Defensive (never throws) per Canon Part 8.
94
+ auditBypassIfNeeded(roomDir);
95
+ const resolved = path.resolve(roomDir);
96
+ const dbDir = path.join(resolved, '.mindrian');
97
+ const dbPath = path.join(dbDir, 'room.db');
98
+ fs.mkdirSync(dbDir, { recursive: true });
99
+ const db = new DatabaseSync(dbPath);
100
+ db.exec('PRAGMA journal_mode = WAL');
101
+ db.exec('PRAGMA foreign_keys = ON');
102
+ // Init lazygraph schema (nodes + edges + indices) sync via the same call
103
+ // the async wrapper makes internally.
104
+ lazygraph.initSchema(db);
105
+ // Init memory schema (identity / facts / sessions / fragments / assumptions / etc).
106
+ memory.initMemorySchema(db);
107
+ // Phase 109 migrations in order: nodes provenance first (109-01), then
108
+ // session_focus (109-02). Both are idempotent via identity sentinels.
109
+ if (runPhase109NodesProvenance) {
110
+ runPhase109NodesProvenance(db);
111
+ }
112
+ runPhase109SessionFocus(db);
113
+ return db;
114
+ }
115
+
116
+ function closeRoomDb(handle) {
117
+ // Tolerant: accept either bare DatabaseSync (current contract) or the legacy
118
+ // { db, conn } shape during the merge cycle.
119
+ const db = handle && handle.db ? handle.db : handle;
120
+ try {
121
+ db.close();
122
+ } catch (_e) {
123
+ // already closed; ignore
124
+ }
125
+ }
126
+
127
+ module.exports = { openRoomDb, closeRoomDb };
@@ -0,0 +1,92 @@
1
+ /**
2
+ * MindrianOS Plugin -- Room Ops (ASYNC entry point)
3
+ * ==================================================
4
+ * execFile (promisified via util.promisify) variants of the public room-ops
5
+ * surface. Import this from MCP tool-router and any caller that returns a
6
+ * Promise to the MCP runtime.
7
+ *
8
+ * NEVER call from CLI scripts that expect synchronous semantics -- use
9
+ * room-ops-sync.cjs. Key-set parity between sync and async is enforced by
10
+ * lib/memory/sync-async-entry-points.test.cjs.
11
+ *
12
+ * Phase 87-04 sync/async split (CASCADE-06). Eliminates the MCP blocking
13
+ * I/O footgun: env branching inside a single module made it too easy to
14
+ * ship synchronous subprocess I/O into the MCP handler path on accident.
15
+ *
16
+ * License: BSL 1.1 (Business Source License 1.1) -- see LICENSE.
17
+ */
18
+
19
+ 'use strict';
20
+
21
+ const path = require('path');
22
+ const util = require('util');
23
+ const { execFile } = require('child_process');
24
+ const execFileAsync = util.promisify(execFile);
25
+ const { discoverSections } = require('./section-registry.cjs');
26
+ const { resolveRoom: resolveRoomShared } = require('./room-ops-shared.cjs');
27
+
28
+ const SCRIPTS_DIR = path.resolve(__dirname, '../../scripts');
29
+
30
+ /**
31
+ * List discovered sections with metadata (async).
32
+ * Wraps the pure synchronous discoverSections() call in an async shape for
33
+ * API symmetry with room-ops-sync.cjs.
34
+ * @param {string} roomDir - Path to room directory
35
+ * @returns {Promise<{ sections: Array, core_count: number, extended_count: number }>}
36
+ */
37
+ async function listSections(roomDir) {
38
+ const resolved = path.resolve(roomDir);
39
+ const discovery = discoverSections(resolved);
40
+
41
+ const sections = discovery.all.map(name => {
42
+ const meta = discovery.getMeta(name);
43
+ return {
44
+ name,
45
+ type: meta.type,
46
+ label: meta.label,
47
+ color: meta.color,
48
+ };
49
+ });
50
+
51
+ return {
52
+ sections,
53
+ core_count: discovery.core.length,
54
+ extended_count: discovery.extended.length,
55
+ };
56
+ }
57
+
58
+ /**
59
+ * Run analyze-room script against a room directory (async).
60
+ * Uses execFile (promisified via util.promisify) rather than the blocking
61
+ * subprocess API, so the MCP handler loop stays non-blocking.
62
+ * @param {string} roomDir - Path to room directory
63
+ * @returns {Promise<string>} Raw script output
64
+ */
65
+ async function analyzeRoom(roomDir) {
66
+ const resolved = path.resolve(roomDir);
67
+ const scriptPath = path.join(SCRIPTS_DIR, 'analyze-room');
68
+ try {
69
+ const { stdout } = await execFileAsync('bash', [scriptPath, resolved], {
70
+ timeout: 10000,
71
+ maxBuffer: 10 * 1024 * 1024,
72
+ encoding: 'utf-8',
73
+ });
74
+ return stdout;
75
+ } catch (e) {
76
+ throw new Error(`analyze-room failed: ${e.message}`);
77
+ }
78
+ }
79
+
80
+ /**
81
+ * Resolve the active room directory path (async wrapper around the pure
82
+ * shared implementation). Wrapped in an async function for signature parity
83
+ * with the other async exports and to keep the test's AsyncFunction assertion
84
+ * uniform across every exported function name.
85
+ * @param {string} workDir - Workspace root directory
86
+ * @returns {Promise<string|null>}
87
+ */
88
+ async function resolveRoom(workDir) {
89
+ return resolveRoomShared(workDir);
90
+ }
91
+
92
+ module.exports = { listSections, analyzeRoom, resolveRoom };
@@ -0,0 +1,64 @@
1
+ /**
2
+ * MindrianOS Plugin -- Room Ops (shared pure logic)
3
+ * ==================================================
4
+ * Pure helpers with NO child_process I/O. Both room-ops-sync.cjs and
5
+ * room-ops-async.cjs import from this file. If you need to add a helper
6
+ * that calls execSync or execFile, put it in the sync or async entry
7
+ * point, not here.
8
+ *
9
+ * Phase 87-04 sync/async split (CASCADE-06). Eliminates the env-branching
10
+ * footgun (R4) by making the sync/async contract a require-time choice.
11
+ *
12
+ * License: BSL 1.1 (Business Source License 1.1) -- see LICENSE.
13
+ */
14
+
15
+ 'use strict';
16
+
17
+ const path = require('path');
18
+ const fs = require('fs');
19
+
20
+ /**
21
+ * Trivial path helper kept here for symmetry with future shared utilities.
22
+ * Pure string/fs-path math; no I/O.
23
+ * @param {string} roomDir
24
+ * @returns {string}
25
+ */
26
+ function resolveRoomPath(roomDir) {
27
+ return path.resolve(roomDir);
28
+ }
29
+
30
+ /**
31
+ * Resolve the active room directory path.
32
+ *
33
+ * Strategy 1: Read .rooms/registry.json and follow `active` -> rooms[active].path
34
+ * Strategy 2: Fall back to the legacy `room/` directory
35
+ *
36
+ * Pure fs + JSON logic, no child_process. Shared between sync and async
37
+ * entry points (both re-export this function under its original name).
38
+ *
39
+ * @param {string} workDir - Workspace root directory
40
+ * @returns {string|null} Absolute room path, or null if no room found
41
+ */
42
+ function resolveRoom(workDir) {
43
+ const resolved = path.resolve(workDir);
44
+ const registryPath = path.join(resolved, '.rooms', 'registry.json');
45
+
46
+ // Strategy 1: Registry
47
+ if (fs.existsSync(registryPath)) {
48
+ try {
49
+ const reg = JSON.parse(fs.readFileSync(registryPath, 'utf8'));
50
+ if (reg.active && reg.rooms && reg.rooms[reg.active]) {
51
+ const roomPath = path.resolve(resolved, reg.rooms[reg.active].path);
52
+ if (fs.existsSync(roomPath)) return roomPath;
53
+ }
54
+ } catch (_e) { /* fall through to legacy */ }
55
+ }
56
+
57
+ // Strategy 2: Legacy
58
+ const legacy = path.join(resolved, 'room');
59
+ if (fs.existsSync(legacy)) return legacy;
60
+
61
+ return null;
62
+ }
63
+
64
+ module.exports = { resolveRoomPath, resolveRoom };