@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,419 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /*
5
+ * Copyright (c) 2026 Mindrian. BSL 1.1.
6
+ *
7
+ * Phase 91-03 -- Skill Activation Router fixture tests
8
+ * =====================================================
9
+ * Exercises lib/core/skill-activation-router.cjs. The router composes
10
+ * navigation-engine.decide() output with the legacy (pre-91) file-state
11
+ * + env activation set into a single declarative activation decision
12
+ * that the UserPromptSubmit hook embeds into additionalContext.
13
+ *
14
+ * Canon Part 3 (Tri-Context Decision Gate): the closed 10-verb
15
+ * vocabulary is enforced on engine outputs. Unknown verbs are rejected
16
+ * with a trace note (canon_part_3_unknown_verb_rejected) instead of
17
+ * silently propagating, preventing a future plan from inventing a
18
+ * net-new verb behind canon review.
19
+ *
20
+ * Canon Part 7 (Reuse Before Build): legacy file-state + env activation
21
+ * is preserved byte-identical when the engine is silent. This module
22
+ * is a precedence layer on top, not a replacement.
23
+ *
24
+ * Test map (Tests 1-15 = router unit tests; Tests 16-17 = end-to-end
25
+ * integration through scripts/intent-classifier.cjs added in Task 2):
26
+ *
27
+ * 1. engine.fire_skill set + legacy populated -> source='engine'
28
+ * 2. engine.fire_skill null + suppress_skills set -> source='mixed'
29
+ * 3. engine null (timeout) + legacy populated -> source='legacy'
30
+ * 4. engine.fire_skill null + empty suppress -> source='legacy'
31
+ * 5. validateVerb('Run Methodology') === true (canonical hit)
32
+ * 6. validateVerb('run methodology') === true (case-insensitive)
33
+ * 7. validateVerb('Invent New Verb') === false (closed set)
34
+ * 8. unknown fire_skill -> falls through; trace note recorded
35
+ * 9. every canonical verb is accepted
36
+ * 10. empty legacy + null engine -> {[], [], 'legacy', ...}
37
+ * 11. contradictory fire vs suppress -> fire wins; trace note recorded
38
+ * 12. case-preservation: canonical casing in output (not user casing)
39
+ * 13. routeActivation(null, null) -> null-safe legacy fallback
40
+ * 14. non-array legacy -> defensive coercion
41
+ * 15. unknown verb + valid suppress -> mixed mode honored
42
+ * 16. integration: spawn intent-classifier with engine returning
43
+ * 'Run Methodology' -> additionalContext contains
44
+ * 'activated_skills: [Run Methodology]' + 'routing_source: engine'
45
+ * 17. integration: spawn intent-classifier with engine null ->
46
+ * additionalContext contains 'routing_source: legacy'
47
+ *
48
+ * Registered in lib/memory/run-feynman-tests.cjs.
49
+ */
50
+
51
+ const assert = require('node:assert/strict');
52
+ const fs = require('node:fs');
53
+ const path = require('node:path');
54
+ const os = require('node:os');
55
+ const { spawnSync } = require('node:child_process');
56
+
57
+ const REPO = path.resolve(__dirname, '..', '..');
58
+ const ROUTER_PATH = path.join(REPO, 'lib/core/skill-activation-router.cjs');
59
+ const SHARED_PATH = path.join(REPO, 'lib/core/navigation-engine-shared.cjs');
60
+ const CLASSIFIER_PATH = path.join(REPO, 'scripts/intent-classifier.cjs');
61
+
62
+ function requireRouter() {
63
+ // Lazy require so Task 1 RED can run before the file exists.
64
+ return require(ROUTER_PATH);
65
+ }
66
+
67
+ function requireShared() {
68
+ return require(SHARED_PATH);
69
+ }
70
+
71
+ // ---------- Test scaffolding ----------
72
+
73
+ let passed = 0;
74
+ let failed = 0;
75
+ function run(name, fn) {
76
+ try {
77
+ fn();
78
+ process.stdout.write('ok ' + name + '\n');
79
+ passed += 1;
80
+ } catch (err) {
81
+ process.stderr.write('FAIL ' + name + '\n');
82
+ process.stderr.write(String(err && err.stack ? err.stack : err) + '\n');
83
+ failed += 1;
84
+ }
85
+ }
86
+
87
+ // ---------- Fixture builders ----------
88
+
89
+ function makeEngineDecision(overrides) {
90
+ const base = {
91
+ fire_skill: null,
92
+ suppress_skills: [],
93
+ persona_updates: null,
94
+ offer_next_step: null,
95
+ decision_trace: {
96
+ icm_scope: null,
97
+ sql_signals: null,
98
+ minto_reasoning: null,
99
+ brain_patterns: null,
100
+ intent_persona: null,
101
+ chosen_rationale: '',
102
+ brain_md_tier_mode: 'mode_a',
103
+ brain_md_staleness: 'fresh',
104
+ brain_md_stale_reason: null,
105
+ brain_md_weight_applied: 1.0,
106
+ brain_md_recommended_confidence: 0.85,
107
+ brain_md_recommended_marker_rendered: true,
108
+ brain_md_sections_consumed: [],
109
+ brain_md_version: 1,
110
+ },
111
+ };
112
+ return Object.assign({}, base, overrides || {});
113
+ }
114
+
115
+ // =========================================================
116
+ // Task 1 -- Router unit tests (Tests 1-15)
117
+ // =========================================================
118
+
119
+ run('Test 1: engine.fire_skill set + legacy populated -> source=engine', () => {
120
+ const { routeActivation } = requireRouter();
121
+ const engine = makeEngineDecision({ fire_skill: 'Run Methodology' });
122
+ const legacy = ['room-passive', 'larry-personality'];
123
+ const out = routeActivation(engine, legacy);
124
+ assert.equal(out.source, 'engine');
125
+ assert.deepEqual(out.activated_skills, ['Run Methodology']);
126
+ assert.deepEqual(out.suppressed_skills, []);
127
+ assert.equal(out.reason, 'engine_fire_skill_set');
128
+ });
129
+
130
+ run('Test 2: engine.fire_skill null + suppress_skills set -> source=mixed', () => {
131
+ const { routeActivation } = requireRouter();
132
+ const engine = makeEngineDecision({
133
+ fire_skill: null,
134
+ suppress_skills: ['room-proactive'],
135
+ });
136
+ const legacy = ['room-passive', 'room-proactive'];
137
+ const out = routeActivation(engine, legacy);
138
+ assert.equal(out.source, 'mixed');
139
+ assert.deepEqual(out.activated_skills, ['room-passive']);
140
+ assert.deepEqual(out.suppressed_skills, ['room-proactive']);
141
+ });
142
+
143
+ run('Test 3: engine null (timeout) + legacy populated -> source=legacy', () => {
144
+ const { routeActivation } = requireRouter();
145
+ const out = routeActivation(null, ['room-passive']);
146
+ assert.equal(out.source, 'legacy');
147
+ assert.deepEqual(out.activated_skills, ['room-passive']);
148
+ assert.deepEqual(out.suppressed_skills, []);
149
+ });
150
+
151
+ run('Test 4: engine silent (fire_skill null + empty suppress) -> source=legacy', () => {
152
+ const { routeActivation } = requireRouter();
153
+ const engine = makeEngineDecision({ fire_skill: null, suppress_skills: [] });
154
+ const legacy = ['room-passive', 'context-engine'];
155
+ const out = routeActivation(engine, legacy);
156
+ assert.equal(out.source, 'legacy');
157
+ assert.deepEqual(out.activated_skills, ['room-passive', 'context-engine']);
158
+ assert.deepEqual(out.suppressed_skills, []);
159
+ });
160
+
161
+ run('Test 5: validateVerb(\'Run Methodology\') === true', () => {
162
+ const { validateVerb } = requireRouter();
163
+ assert.equal(validateVerb('Run Methodology'), true);
164
+ });
165
+
166
+ run('Test 6: validateVerb case-insensitive (\'run methodology\' === true)', () => {
167
+ const { validateVerb } = requireRouter();
168
+ assert.equal(validateVerb('run methodology'), true);
169
+ assert.equal(validateVerb('RUN METHODOLOGY'), true);
170
+ assert.equal(validateVerb('Run METHODOLOGY'), true);
171
+ });
172
+
173
+ run('Test 7: validateVerb(\'Invent New Verb\') === false (closed set)', () => {
174
+ const { validateVerb } = requireRouter();
175
+ assert.equal(validateVerb('Invent New Verb'), false);
176
+ assert.equal(validateVerb('Hack The Planet'), false);
177
+ assert.equal(validateVerb(''), false);
178
+ assert.equal(validateVerb(null), false);
179
+ assert.equal(validateVerb(undefined), false);
180
+ assert.equal(validateVerb(42), false);
181
+ });
182
+
183
+ run('Test 8: unknown fire_skill -> falls through to legacy; trace note recorded', () => {
184
+ const { routeActivation } = requireRouter();
185
+ const engine = makeEngineDecision({ fire_skill: 'Invent New Verb' });
186
+ const legacy = ['room-passive'];
187
+ const out = routeActivation(engine, legacy);
188
+ // Unknown verb is rejected; router falls through to legacy semantics.
189
+ assert.equal(out.source, 'legacy');
190
+ assert.deepEqual(out.activated_skills, ['room-passive']);
191
+ // Trace note must be recorded so /mos:explain-decision can surface
192
+ // the rejection (Canon Part 3 closed-vocab boundary visible).
193
+ assert.equal(Array.isArray(out.trace_notes), true);
194
+ assert.equal(
195
+ out.trace_notes.indexOf('canon_part_3_unknown_verb_rejected') !== -1,
196
+ true,
197
+ 'expected canon_part_3_unknown_verb_rejected in trace_notes; got ' +
198
+ JSON.stringify(out.trace_notes)
199
+ );
200
+ });
201
+
202
+ run('Test 9: all 10 canonical verbs accepted as fire_skill', () => {
203
+ const { routeActivation } = requireRouter();
204
+ const { CANONICAL_VERBS } = requireShared();
205
+ for (const verb of CANONICAL_VERBS) {
206
+ const engine = makeEngineDecision({ fire_skill: verb });
207
+ const out = routeActivation(engine, []);
208
+ assert.equal(out.source, 'engine', 'verb ' + verb + ' should fire');
209
+ assert.deepEqual(out.activated_skills, [verb]);
210
+ }
211
+ });
212
+
213
+ run('Test 10: empty legacy + null engine -> {[], [], legacy, ...}', () => {
214
+ const { routeActivation } = requireRouter();
215
+ const out = routeActivation(null, []);
216
+ assert.equal(out.source, 'legacy');
217
+ assert.deepEqual(out.activated_skills, []);
218
+ assert.deepEqual(out.suppressed_skills, []);
219
+ });
220
+
221
+ run('Test 11: contradictory fire vs suppress -> fire wins; trace note recorded', () => {
222
+ const { routeActivation } = requireRouter();
223
+ // engine fires Run Methodology AND lists Run Methodology in suppress.
224
+ // Router resolves: fire_skill wins; suppress entry for the fired skill
225
+ // is dropped; trace note records the contradiction.
226
+ const engine = makeEngineDecision({
227
+ fire_skill: 'Run Methodology',
228
+ suppress_skills: ['Run Methodology', 'room-proactive'],
229
+ });
230
+ const out = routeActivation(engine, []);
231
+ assert.equal(out.source, 'engine');
232
+ assert.deepEqual(out.activated_skills, ['Run Methodology']);
233
+ // Run Methodology is dropped from suppress; room-proactive remains.
234
+ assert.deepEqual(out.suppressed_skills, ['room-proactive']);
235
+ assert.equal(Array.isArray(out.trace_notes), true);
236
+ assert.equal(
237
+ out.trace_notes.indexOf('engine_contradictory_fire_vs_suppress_resolved') !== -1,
238
+ true,
239
+ 'expected engine_contradictory_fire_vs_suppress_resolved in trace_notes; got ' +
240
+ JSON.stringify(out.trace_notes)
241
+ );
242
+ });
243
+
244
+ run('Test 12: case-preservation in output uses canonical casing', () => {
245
+ const { routeActivation } = requireRouter();
246
+ // User-supplied casing 'devil\'s advocate' must be canonicalized to
247
+ // "Devil's Advocate" (the CANONICAL_VERBS entry).
248
+ const engine = makeEngineDecision({ fire_skill: "devil's advocate" });
249
+ const out = routeActivation(engine, []);
250
+ assert.equal(out.source, 'engine');
251
+ assert.deepEqual(out.activated_skills, ["Devil's Advocate"]);
252
+ });
253
+
254
+ run('Test 13: routeActivation(null, null) -> null-safe legacy fallback', () => {
255
+ const { routeActivation } = requireRouter();
256
+ const out = routeActivation(null, null);
257
+ assert.equal(out.source, 'legacy');
258
+ assert.deepEqual(out.activated_skills, []);
259
+ assert.deepEqual(out.suppressed_skills, []);
260
+ assert.equal(out.reason, 'null_inputs');
261
+ });
262
+
263
+ run('Test 14: non-array legacy -> defensive coercion to []', () => {
264
+ const { routeActivation } = requireRouter();
265
+ const out = routeActivation(null, 'not-an-array');
266
+ assert.equal(out.source, 'legacy');
267
+ assert.deepEqual(out.activated_skills, []);
268
+ });
269
+
270
+ run('Test 15: unknown verb + valid suppress -> mixed honored', () => {
271
+ const { routeActivation } = requireRouter();
272
+ const engine = makeEngineDecision({
273
+ fire_skill: 'Bogus Verb',
274
+ suppress_skills: ['room-proactive'],
275
+ });
276
+ const legacy = ['room-passive', 'room-proactive'];
277
+ const out = routeActivation(engine, legacy);
278
+ // Unknown fire_skill rejected; suppress still honored -> mixed mode.
279
+ assert.equal(out.source, 'mixed');
280
+ assert.deepEqual(out.activated_skills, ['room-passive']);
281
+ assert.deepEqual(out.suppressed_skills, ['room-proactive']);
282
+ assert.equal(Array.isArray(out.trace_notes), true);
283
+ assert.equal(
284
+ out.trace_notes.indexOf('canon_part_3_unknown_verb_rejected') !== -1,
285
+ true
286
+ );
287
+ });
288
+
289
+ // =========================================================
290
+ // Task 2 -- Integration tests (Tests 16-17)
291
+ // =========================================================
292
+ //
293
+ // These tests spawn scripts/intent-classifier.cjs end-to-end with a
294
+ // minimal Mindrian rooms fixture and verify the router output lands in
295
+ // the NAVIGATION DECISION block as 'activated_skills' + 'routing_source'
296
+ // lines. They use the existing MOS_NAV_TEST_* env-var stub mechanism
297
+ // for engine behavior simulation.
298
+ //
299
+ // Stub mechanism (Plan 91-02 patterns):
300
+ // - MOS_NAV_TEST_FIRE_SKILL=<verb> -> override engine fire_skill output
301
+ // - MOS_NAV_TEST_SUPPRESS_SKILLS=... -> override suppress_skills (csv)
302
+ // - When unset, engine runs normally.
303
+ //
304
+ // We cannot mock the engine via require.cache in a spawned subprocess,
305
+ // so the integration tests rely on env-var stubs that the classifier
306
+ // honors when present. Plan 91-02 already documented this pattern.
307
+
308
+ function makeRoomsFixture(label) {
309
+ const tmp = fs.mkdtempSync(path.join(os.tmpdir(), '91-03-' + label + '-'));
310
+ const root = path.join(tmp, 'MindrianRooms');
311
+ fs.mkdirSync(root, { recursive: true });
312
+ const roomDir = path.join(root, 'fixture-room');
313
+ fs.mkdirSync(roomDir, { recursive: true });
314
+ // Minimal STATE.md so tokenizer has something to fingerprint.
315
+ fs.writeFileSync(
316
+ path.join(roomDir, 'STATE.md'),
317
+ '---\nproject: fixture room\n---\n\n# Fixture Room\n'
318
+ );
319
+ // Section directory with a MINTO.md so resolveActiveSection finds one.
320
+ const sectionDir = path.join(roomDir, 'market-analysis');
321
+ fs.mkdirSync(sectionDir, { recursive: true });
322
+ fs.writeFileSync(
323
+ path.join(sectionDir, 'MINTO.md'),
324
+ '---\ngoverning_thought: Customers will pay\nreasoning_health_score: 0.6\n---\n\n# Market analysis\n'
325
+ );
326
+ fs.writeFileSync(
327
+ path.join(sectionDir, 'ROOM.md'),
328
+ '# market-analysis section\n'
329
+ );
330
+ // Registry.
331
+ const regDir = path.join(root, '.rooms');
332
+ fs.mkdirSync(regDir, { recursive: true });
333
+ fs.writeFileSync(
334
+ path.join(regDir, 'registry.json'),
335
+ JSON.stringify({ active: 'fixture-room', rooms: ['fixture-room'] }, null, 2)
336
+ );
337
+ return { tmp: tmp, root: root, roomDir: roomDir, sectionDir: sectionDir };
338
+ }
339
+
340
+ function runHook(rootEnv, extraEnv, prompt) {
341
+ const env = Object.assign({}, process.env, {
342
+ MINDRIAN_ROOMS_ROOT: rootEnv,
343
+ MINDRIAN_ROOMS_HOME: rootEnv,
344
+ MINDRIAN_COPILOT_INJECT_FINDINGS: '0',
345
+ }, extraEnv || {});
346
+ return spawnSync(process.execPath, [CLASSIFIER_PATH], {
347
+ input: JSON.stringify({ user_message: prompt || 'analyze market sizing' }),
348
+ env: env,
349
+ encoding: 'utf8',
350
+ timeout: 5000,
351
+ });
352
+ }
353
+
354
+ function classifierIntegrated() {
355
+ // Gate Tests 16-17 on the integration block being wired into
356
+ // intent-classifier.cjs (Task 2). Until then, skip them so RED of
357
+ // Task 1 only shows 15 unit tests.
358
+ const src = fs.readFileSync(CLASSIFIER_PATH, 'utf8');
359
+ return src.indexOf('skill-activation-router') !== -1;
360
+ }
361
+
362
+ if (classifierIntegrated()) {
363
+ run('Test 16: integration -- engine fire_skill -> activated_skills + routing_source=engine', () => {
364
+ const fix = makeRoomsFixture('t16');
365
+ try {
366
+ const res = runHook(fix.root, {
367
+ MOS_NAV_TEST_FIRE_SKILL: 'Run Methodology',
368
+ });
369
+ assert.equal(
370
+ res.status === 0,
371
+ true,
372
+ 'classifier exited non-zero: ' + res.status + '\nstderr: ' + (res.stderr || '')
373
+ );
374
+ const out = res.stdout || '';
375
+ // Engine block carries activated_skills line.
376
+ assert.equal(
377
+ out.indexOf('activated_skills: [Run Methodology]') !== -1,
378
+ true,
379
+ 'expected activated_skills line in stdout; got: ' + out
380
+ );
381
+ assert.equal(
382
+ out.indexOf('routing_source: engine') !== -1,
383
+ true,
384
+ 'expected routing_source: engine; got: ' + out
385
+ );
386
+ } finally {
387
+ fs.rmSync(fix.tmp, { recursive: true, force: true });
388
+ }
389
+ });
390
+
391
+ run('Test 17: integration -- engine null/silent -> routing_source=legacy', () => {
392
+ const fix = makeRoomsFixture('t17');
393
+ try {
394
+ const res = runHook(fix.root, {
395
+ // Force engine to return null fire_skill + empty suppress.
396
+ MOS_NAV_TEST_FIRE_SKILL: '__NULL__',
397
+ });
398
+ assert.equal(res.status === 0, true, 'classifier exit ' + res.status);
399
+ const out = res.stdout || '';
400
+ assert.equal(
401
+ out.indexOf('routing_source: legacy') !== -1,
402
+ true,
403
+ 'expected routing_source: legacy; got: ' + out
404
+ );
405
+ } finally {
406
+ fs.rmSync(fix.tmp, { recursive: true, force: true });
407
+ }
408
+ });
409
+ } else {
410
+ process.stdout.write(
411
+ 'skip Tests 16-17 (intent-classifier.cjs not yet integrated with router; gate clears in Task 2)\n'
412
+ );
413
+ }
414
+
415
+ // ---------- Summary ----------
416
+
417
+ const total = passed + failed;
418
+ process.stdout.write('\nskill-activation-router.test: ' + passed + '/' + total + ' passed\n');
419
+ process.exit(failed === 0 ? 0 : 1);