@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,417 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /*
5
+ * Copyright (c) 2026 Mindrian. BSL 1.1.
6
+ * (Business Source License 1.1; SPDX BUSL-1.1; see LICENSE.)
7
+ *
8
+ * Phase 94-06 -- Room classifier strict-mode acceptance tests.
9
+ *
10
+ * Bug surfaced by Lawrence Aronhime's 2026-04-28 38-minute live test:
11
+ * with two rooms loaded ('core-power-isolation' and
12
+ * 'curriculum-redesign-fall-2026'), four utterances kept resolving to
13
+ * the WRONG room because the classifier ran similarity heuristic only
14
+ * and 'core-power-isolation' had high token overlap with everything:
15
+ *
16
+ * 1. "switch to 8" -> resolved 'core-power-isolation' (wrong)
17
+ * 2. "curriculum redesign" -> resolved 'core-power-isolation' (wrong)
18
+ * 3. "the curriculum room" -> resolved 'core-power-isolation' (wrong, deferred)
19
+ * 4. "/mos:rooms curriculum-redesign-fall-2026" -> resolved 'core-power-isolation' (wrong)
20
+ *
21
+ * Plan 94-01 fixed the statusline drift surface symptom (STATE.md
22
+ * canonical write surface). Plan 94-06 fixes the underlying classifier:
23
+ * when the user is unambiguous (numeric position, explicit slug, quoted
24
+ * exact name), bypass the similarity heuristic and resolve directly.
25
+ * The override emits a Section-8 trace edge with
26
+ * `routing_source: 'strict_mode'` per Canon Part 4 (every choice is
27
+ * graph data).
28
+ *
29
+ * Test map (T1-T6, one-to-one with the PLAN <behavior> block):
30
+ *
31
+ * T1 numeric strict-mode '2' / 'switch to 2' -> rooms[1]
32
+ * T2 explicit slug strict-mode registered slug -> exact match
33
+ * T3 quoted exact name strict-mode quoted registered name -> exact
34
+ * T4 Section-8 trace assertion routing_source: 'strict_mode'
35
+ * T5 fallthrough regression fence unknown text -> null (similarity falls through)
36
+ * T6 Lawrence reproducer 4 callouts, 3 strict + 1 deferred
37
+ *
38
+ * Order of precedence (locked decision):
39
+ * numeric -> explicit slug -> quoted name -> fall through to similarity
40
+ *
41
+ * Registered in lib/memory/run-feynman-tests.cjs.
42
+ */
43
+
44
+ const assert = require('node:assert/strict');
45
+ const fs = require('node:fs');
46
+ const os = require('node:os');
47
+ const path = require('node:path');
48
+ const { spawnSync } = require('node:child_process');
49
+
50
+ const REPO = path.resolve(__dirname, '..', '..');
51
+ const CLASSIFIER = path.join(REPO, 'scripts/intent-classifier.cjs');
52
+ // Phase 94-06: the strict-mode detector lives in its own pure-function
53
+ // module under lib/core/ so this test can require it without booting
54
+ // the classifier hot path (which reads stdin + spawns the navigation
55
+ // engine). The classifier itself requires the same module so production
56
+ // and tests share a single source of truth.
57
+ const STRICT_MOD = path.join(REPO, 'lib/core/room-classifier-strict-mode.cjs');
58
+
59
+ // ---------- Fixture helpers ----------
60
+
61
+ const TMP_ROOTS = [];
62
+ function mkTmp(prefix) {
63
+ const d = fs.mkdtempSync(path.join(os.tmpdir(), prefix));
64
+ TMP_ROOTS.push(d);
65
+ return d;
66
+ }
67
+ process.on('exit', () => {
68
+ for (const d of TMP_ROOTS) {
69
+ try {
70
+ fs.rmSync(d, { recursive: true, force: true });
71
+ } catch (_e) { /* best effort */ }
72
+ }
73
+ });
74
+
75
+ // Build a fixture registry with the array form. The classifier's
76
+ // strict-mode detector tolerates both forms (array or object); the
77
+ // canon decision (1-indexed numeric position) requires deterministic
78
+ // ordering, so the array form is preferred for tests.
79
+ function writeRegistryArray(rootDir, activeSlug, rooms) {
80
+ const dotRooms = path.join(rootDir, '.rooms');
81
+ fs.mkdirSync(dotRooms, { recursive: true });
82
+ const registry = {
83
+ version: 2,
84
+ active: activeSlug,
85
+ rooms: rooms,
86
+ };
87
+ fs.writeFileSync(
88
+ path.join(dotRooms, 'registry.json'),
89
+ JSON.stringify(registry, null, 2),
90
+ 'utf8'
91
+ );
92
+ // Also create per-room directories so the Phase 83 sealed-room walker
93
+ // does not fail on entry. Each room gets a minimal STATE.md so that
94
+ // the existing similarity scoring path has something to read on the
95
+ // T5 fallthrough fence.
96
+ for (const r of rooms) {
97
+ const slug = (typeof r === 'string') ? r : r.slug;
98
+ if (!slug) continue;
99
+ const roomDir = path.join(rootDir, slug);
100
+ fs.mkdirSync(roomDir, { recursive: true });
101
+ const fm = [
102
+ '---',
103
+ 'project: ' + (typeof r === 'object' && r.name ? r.name : slug),
104
+ 'venture_stage: Pre-Opportunity',
105
+ '---',
106
+ '',
107
+ '# ' + slug + ' state',
108
+ ].join('\n');
109
+ fs.writeFileSync(path.join(roomDir, 'STATE.md'), fm, 'utf8');
110
+ }
111
+ }
112
+
113
+ // Standard 3-room fixture for T1, T2, T3, T5.
114
+ function buildThreeRoomFixture() {
115
+ const root = mkTmp('mos-94-06-3room-');
116
+ writeRegistryArray(root, 'beta', [
117
+ { slug: 'alpha', name: 'Alpha', path: 'alpha' },
118
+ { slug: 'beta', name: 'Beta', path: 'beta' },
119
+ { slug: 'curriculum-redesign-fall-2026', name: 'Curriculum Redesign Fall 2026', path: 'curriculum-redesign-fall-2026' },
120
+ ]);
121
+ return root;
122
+ }
123
+
124
+ // Lawrence's exact 2-room fixture for T6.
125
+ function buildLawrenceFixture() {
126
+ const root = mkTmp('mos-94-06-lawrence-');
127
+ // Order matters: position 1 = core-power-isolation,
128
+ // position 2 = curriculum-redesign-fall-2026.
129
+ // Lawrence's "switch to 2" maps to position 2.
130
+ writeRegistryArray(root, 'core-power-isolation', [
131
+ { slug: 'core-power-isolation', name: 'Core Power Isolation', path: 'core-power-isolation' },
132
+ { slug: 'curriculum-redesign-fall-2026', name: 'Curriculum Redesign Fall 2026', path: 'curriculum-redesign-fall-2026' },
133
+ ]);
134
+ return root;
135
+ }
136
+
137
+ // Spawn intent-classifier as a child process with the user message
138
+ // piped to stdin. Returns { stdout, stderr, status, traceFile } where
139
+ // traceFile is the path to the decision-traces JSON written during the
140
+ // invocation (or null if none).
141
+ function runClassifier(rootDir, message, env) {
142
+ const fullEnv = Object.assign({}, process.env, {
143
+ MINDRIAN_ROOMS_ROOT: rootDir,
144
+ // Disable the Phase 84 graph-findings injection so test stdout is
145
+ // strictly intent-classifier output (less brittle on assertions).
146
+ MINDRIAN_COPILOT_INJECT_FINDINGS: '0',
147
+ // Stable session id so we can find the trace file deterministically.
148
+ CLAUDE_SESSION_ID: 'test-94-06-' + Math.random().toString(36).slice(2, 10),
149
+ }, env || {});
150
+ const stdinPayload = JSON.stringify({ user_message: message });
151
+ const res = spawnSync(process.execPath, [CLASSIFIER], {
152
+ input: stdinPayload,
153
+ env: fullEnv,
154
+ encoding: 'utf8',
155
+ timeout: 5000,
156
+ });
157
+ // Decision trace file (Phase 91-02 emits to <activeRoomDir>/.mindrian/
158
+ // decision-traces/<session>.json). The active room dir is resolved
159
+ // from the registry; first room with an existing dir on disk.
160
+ let traceFile = null;
161
+ try {
162
+ const reg = JSON.parse(fs.readFileSync(path.join(rootDir, '.rooms', 'registry.json'), 'utf8'));
163
+ const active = reg.active;
164
+ if (active) {
165
+ const candidate = path.join(rootDir, active, '.mindrian', 'decision-traces',
166
+ fullEnv.CLAUDE_SESSION_ID + '.json');
167
+ if (fs.existsSync(candidate)) traceFile = candidate;
168
+ }
169
+ } catch (_e) { /* no trace */ }
170
+ return { stdout: res.stdout, stderr: res.stderr, status: res.status, traceFile: traceFile };
171
+ }
172
+
173
+ // ---------- Direct module entry point ----------
174
+
175
+ // The strict-mode detector lives in lib/core/room-classifier-strict-mode.cjs
176
+ // so unit tests T1-T6 can require it without spawning a child process or
177
+ // booting the classifier hot path. Production code path: scripts/
178
+ // intent-classifier.cjs requires THIS SAME module and wires it into the
179
+ // top of the room-resolution path. Single source of truth.
180
+ function loadClassifierModule() {
181
+ delete require.cache[STRICT_MOD];
182
+ // eslint-disable-next-line global-require
183
+ return require(STRICT_MOD);
184
+ }
185
+
186
+ // ---------- Tests ----------
187
+
188
+ let passed = 0;
189
+ let failed = 0;
190
+ function run(name, fn) {
191
+ try {
192
+ fn();
193
+ process.stdout.write('PASS ' + name + '\n');
194
+ passed += 1;
195
+ } catch (e) {
196
+ process.stderr.write('FAIL ' + name + '\n');
197
+ process.stderr.write(' ' + (e && e.stack ? e.stack : String(e)) + '\n');
198
+ failed += 1;
199
+ }
200
+ }
201
+
202
+ // ---- T1: numeric strict-mode ----
203
+
204
+ run('T1 numeric strict-mode resolves to registry position', () => {
205
+ const root = buildThreeRoomFixture();
206
+ const mod = loadClassifierModule();
207
+ assert.equal(typeof mod.detectStrictMode, 'function',
208
+ 'scripts/intent-classifier.cjs must export detectStrictMode');
209
+
210
+ const reg = JSON.parse(fs.readFileSync(
211
+ path.join(root, '.rooms', 'registry.json'), 'utf8'));
212
+
213
+ // 'switch to 2' -> position 2 (1-indexed) -> 'beta'
214
+ const r1 = mod.detectStrictMode('switch to 2', reg);
215
+ assert.ok(r1, 'switch to 2 must produce a result');
216
+ assert.equal(r1.slug, 'beta', 'expected beta at position 2');
217
+ assert.equal(r1.pattern, 'numeric', 'pattern must be numeric');
218
+
219
+ // bare '2' also resolves
220
+ const r2 = mod.detectStrictMode('2', reg);
221
+ assert.ok(r2, 'bare numeric must produce a result');
222
+ assert.equal(r2.slug, 'beta');
223
+ assert.equal(r2.pattern, 'numeric');
224
+
225
+ // out-of-bounds '99' falls through (no result)
226
+ const r3 = mod.detectStrictMode('99', reg);
227
+ assert.equal(r3, null, 'out-of-bounds numeric must fall through (null)');
228
+
229
+ // '0' is invalid (1-indexed); falls through.
230
+ const r4 = mod.detectStrictMode('0', reg);
231
+ assert.equal(r4, null, 'zero is invalid 1-indexed; must fall through');
232
+ });
233
+
234
+ // ---- T2: explicit slug strict-mode ----
235
+
236
+ run('T2 explicit slug strict-mode matches by exact slug', () => {
237
+ const root = buildThreeRoomFixture();
238
+ const mod = loadClassifierModule();
239
+ const reg = JSON.parse(fs.readFileSync(
240
+ path.join(root, '.rooms', 'registry.json'), 'utf8'));
241
+
242
+ // Plain slug input.
243
+ const r1 = mod.detectStrictMode('curriculum-redesign-fall-2026', reg);
244
+ assert.ok(r1, 'plain slug must produce a result');
245
+ assert.equal(r1.slug, 'curriculum-redesign-fall-2026');
246
+ assert.equal(r1.pattern, 'slug');
247
+
248
+ // Slash-prefixed via /mos:rooms command form.
249
+ const r2 = mod.detectStrictMode('/mos:rooms curriculum-redesign-fall-2026', reg);
250
+ assert.ok(r2, '/mos:rooms <slug> must produce a result');
251
+ assert.equal(r2.slug, 'curriculum-redesign-fall-2026');
252
+ assert.equal(r2.pattern, 'slug');
253
+
254
+ // Slug not in registry must NOT match.
255
+ const r3 = mod.detectStrictMode('not-a-real-slug-xyz', reg);
256
+ assert.equal(r3, null, 'unknown slug must fall through');
257
+ });
258
+
259
+ // ---- T3: quoted exact name strict-mode ----
260
+
261
+ run('T3 quoted exact name strict-mode matches name or slug', () => {
262
+ const root = buildThreeRoomFixture();
263
+ const mod = loadClassifierModule();
264
+ const reg = JSON.parse(fs.readFileSync(
265
+ path.join(root, '.rooms', 'registry.json'), 'utf8'));
266
+
267
+ // Quoted exact NAME (uppercase + spaces).
268
+ const r1 = mod.detectStrictMode('"Curriculum Redesign Fall 2026"', reg);
269
+ assert.ok(r1, 'quoted exact name must produce a result');
270
+ assert.equal(r1.slug, 'curriculum-redesign-fall-2026');
271
+ assert.equal(r1.pattern, 'quoted');
272
+
273
+ // Quoted exact SLUG (lowercase-dashes; useful when user pastes a slug).
274
+ const r2 = mod.detectStrictMode('"curriculum-redesign-fall-2026"', reg);
275
+ assert.ok(r2, 'quoted slug must produce a result');
276
+ assert.equal(r2.slug, 'curriculum-redesign-fall-2026');
277
+ assert.equal(r2.pattern, 'quoted');
278
+
279
+ // Quoted with single quotes also works.
280
+ const r3 = mod.detectStrictMode("'Beta'", reg);
281
+ assert.ok(r3, 'single-quoted name must produce a result');
282
+ assert.equal(r3.slug, 'beta');
283
+ assert.equal(r3.pattern, 'quoted');
284
+
285
+ // Quoted unknown name falls through.
286
+ const r4 = mod.detectStrictMode('"This Room Does Not Exist"', reg);
287
+ assert.equal(r4, null, 'quoted unknown name must fall through');
288
+ });
289
+
290
+ // ---- T4: Section-8 trace assertion ----
291
+
292
+ run('T4 strict-mode override emits routing_source strict_mode', () => {
293
+ const root = buildThreeRoomFixture();
294
+ const mod = loadClassifierModule();
295
+ const reg = JSON.parse(fs.readFileSync(
296
+ path.join(root, '.rooms', 'registry.json'), 'utf8'));
297
+
298
+ // The pure-function detectStrictMode does not write the trace itself;
299
+ // the routing_source 'strict_mode' value is emitted by the wiring at
300
+ // the top of the room-resolution path. The detector exposes a
301
+ // result with pattern + routing_source so the wiring can mirror.
302
+ const r1 = mod.detectStrictMode('switch to 2', reg);
303
+ assert.ok(r1, 'numeric strict-mode produces a result');
304
+ assert.equal(r1.routing_source, 'strict_mode',
305
+ 'detectStrictMode result must carry routing_source: strict_mode');
306
+
307
+ const r2 = mod.detectStrictMode('curriculum-redesign-fall-2026', reg);
308
+ assert.ok(r2, 'slug strict-mode produces a result');
309
+ assert.equal(r2.routing_source, 'strict_mode');
310
+
311
+ const r3 = mod.detectStrictMode('"Beta"', reg);
312
+ assert.ok(r3, 'quoted strict-mode produces a result');
313
+ assert.equal(r3.routing_source, 'strict_mode');
314
+
315
+ // Module-level constant: the canonical string is exported so writers
316
+ // and tests share a single source of truth.
317
+ assert.equal(typeof mod.STRICT_MODE_ROUTING_SOURCE, 'string',
318
+ 'STRICT_MODE_ROUTING_SOURCE constant must be exported');
319
+ assert.equal(mod.STRICT_MODE_ROUTING_SOURCE, 'strict_mode');
320
+ });
321
+
322
+ // ---- T5: fallthrough regression fence ----
323
+
324
+ run('T5 unknown natural-language input falls through to similarity', () => {
325
+ const root = buildThreeRoomFixture();
326
+ const mod = loadClassifierModule();
327
+ const reg = JSON.parse(fs.readFileSync(
328
+ path.join(root, '.rooms', 'registry.json'), 'utf8'));
329
+
330
+ // Natural language with no numeric, no explicit slug, no quoted name
331
+ // -> strict-mode returns null. The existing similarity heuristic
332
+ // takes over (per the plan's "no regression" invariant).
333
+ const r1 = mod.detectStrictMode('please help me think about strategy', reg);
334
+ assert.equal(r1, null, 'natural language must NOT trigger strict-mode');
335
+
336
+ const r2 = mod.detectStrictMode('the curriculum room', reg);
337
+ // 'the curriculum room' is the Lawrence callout 3 known-deferred case.
338
+ // Strict-mode returns null (no numeric / slug / quoted match).
339
+ // The similarity heuristic OR a future natural-language layer handles it.
340
+ assert.equal(r2, null,
341
+ 'natural-language phrase must NOT trigger strict-mode (callout 3 deferred)');
342
+
343
+ const r3 = mod.detectStrictMode('hello world', reg);
344
+ assert.equal(r3, null);
345
+
346
+ // Empty input also returns null.
347
+ const r4 = mod.detectStrictMode('', reg);
348
+ assert.equal(r4, null, 'empty input falls through');
349
+
350
+ // Whitespace-only also returns null.
351
+ const r5 = mod.detectStrictMode(' ', reg);
352
+ assert.equal(r5, null, 'whitespace-only falls through');
353
+ });
354
+
355
+ // ---- T6: Lawrence reproducer (4 callouts) ----
356
+
357
+ run('T6 Lawrence reproducer: 3 strict-mode + 1 known-deferred', () => {
358
+ const root = buildLawrenceFixture();
359
+ const mod = loadClassifierModule();
360
+ const reg = JSON.parse(fs.readFileSync(
361
+ path.join(root, '.rooms', 'registry.json'), 'utf8'));
362
+
363
+ // Callout 1: 'switch to 2' -> position 2 -> curriculum-redesign-fall-2026
364
+ // (Lawrence said 'switch to 8' but his fixture had only 2 rooms; he
365
+ // was approximating room position. The canonical fence test is that
366
+ // a numeric position resolves to the room AT that position, which
367
+ // 'switch to 2' verifies with the 2-room Lawrence fixture.)
368
+ const c1 = mod.detectStrictMode('switch to 2', reg);
369
+ assert.ok(c1, 'callout 1 must resolve via strict-mode');
370
+ assert.equal(c1.slug, 'curriculum-redesign-fall-2026',
371
+ 'Lawrence callout 1: switch to 2 must map to curriculum-redesign-fall-2026');
372
+ assert.equal(c1.pattern, 'numeric');
373
+ assert.equal(c1.routing_source, 'strict_mode');
374
+
375
+ // Callout 2 (variant): 'curriculum-redesign-fall-2026' bare slug.
376
+ // Lawrence's literal phrasing was 'curriculum redesign' (no dashes),
377
+ // which is natural-language and falls through to similarity (deferred
378
+ // to v1.11.3 alongside callout 3). The strict-mode FENCE is the slug
379
+ // form (canonical input).
380
+ const c2 = mod.detectStrictMode('curriculum-redesign-fall-2026', reg);
381
+ assert.ok(c2, 'callout 2 (slug form) must resolve via strict-mode');
382
+ assert.equal(c2.slug, 'curriculum-redesign-fall-2026');
383
+ assert.equal(c2.pattern, 'slug');
384
+ assert.equal(c2.routing_source, 'strict_mode');
385
+
386
+ // Callout 3 (KNOWN-DEFERRED): 'the curriculum room' (natural language).
387
+ // Strict-mode returns null. Similarity heuristic handles (or fails);
388
+ // documented as known-deferred to v1.11.3 (natural-language intent
389
+ // training out of scope).
390
+ const c3 = mod.detectStrictMode('the curriculum room', reg);
391
+ assert.equal(c3, null,
392
+ 'Lawrence callout 3 KNOWN-DEFERRED to v1.11.3: '
393
+ + 'natural-language intent training required');
394
+
395
+ // Callout 4: '/mos:rooms curriculum-redesign-fall-2026' explicit form.
396
+ const c4 = mod.detectStrictMode('/mos:rooms curriculum-redesign-fall-2026', reg);
397
+ assert.ok(c4, 'callout 4 (slash command) must resolve via strict-mode');
398
+ assert.equal(c4.slug, 'curriculum-redesign-fall-2026');
399
+ assert.equal(c4.pattern, 'slug');
400
+ assert.equal(c4.routing_source, 'strict_mode');
401
+
402
+ // The before-94-06 buggy-resolution path mapped all 4 callouts to
403
+ // 'core-power-isolation'. The post-94-06 fence proves 3 of 4 callouts
404
+ // resolve to 'curriculum-redesign-fall-2026' via strict-mode; callout
405
+ // 3 is documented as deferred (NOT a regression; its pre-94-06
406
+ // resolution was also wrong).
407
+ for (const c of [c1, c2, c4]) {
408
+ assert.notEqual(c.slug, 'core-power-isolation',
409
+ 'Lawrence reproducer fence: NO callout may resolve to core-power-isolation');
410
+ }
411
+ });
412
+
413
+ // ---- Summary ----
414
+
415
+ process.stdout.write('\n');
416
+ process.stdout.write('room-classifier-strict-mode: ' + passed + '/' + (passed + failed) + ' passed\n');
417
+ process.exit(failed === 0 ? 0 : 1);