@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,656 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /*
5
+ * Copyright (c) 2026 Mindrian. BSL 1.1.
6
+ *
7
+ * Phase 91-07 -- Problem-Type Router fixture tests
8
+ * =================================================
9
+ * Exercises lib/core/problem-type-router.cjs. The router parses BRAIN.md
10
+ * problemtype_classification + wicked_indicators section bodies and
11
+ * returns canonical 4-type routing recommendations (UDP / IDP / WDP /
12
+ * unknown) with wicked escalation per Canon Appendix E rule R4.
13
+ *
14
+ * Canon Part 2 Appendix E (Team Composition R4): wicked problem
15
+ * (8-10 wickedness score) escalates to soft-systems family.
16
+ *
17
+ * Canon Part 3 (10-verb closed vocabulary): every recommended skill
18
+ * maps to one of the canonical verbs (Run Methodology / Reformulate /
19
+ * Spawn Sub-Agent / Navigate Graph / Devil's Advocate / Scenario Plan /
20
+ * Synthesize / Bank Opportunity / Defer / Free-Text).
21
+ *
22
+ * Canon Part 8 (Graph Boundary): ProblemType is a generic enum, not
23
+ * user content. The router never reads BRAIN.md directly; it only
24
+ * consumes already-parsed section bodies from readQuadruple.
25
+ *
26
+ * Test map:
27
+ * Task 1 (Tests 1-18): parser + 4-type routing + wicked escalation
28
+ * 1. parseProblemTypeSection happy-path UDP + confidence 0.85
29
+ * 2. parseProblemTypeSection (no signal) -> null
30
+ * 3. parseProblemTypeSection type-only (no confidence) -> tolerant
31
+ * 4. parseProblemTypeSection out-of-range confidence -> null
32
+ * 5. parseProblemTypeSection unknown type 'FOO' -> {type: unknown}
33
+ * 6. routeByProblemType('UDP', 0.85) -> exploration skills
34
+ * 7. routeByProblemType('IDP', 0.8) -> definition-seeking skills
35
+ * 8. routeByProblemType('WDP', 0.9) -> execution skills
36
+ * 9. routeByProblemType('unknown', null) -> empty + fallback reason
37
+ * 10. routeByProblemType(null, null) -> same as unknown
38
+ * 11. detectWickedEscalation(null) -> false
39
+ * 12. detectWickedEscalation(score 7) -> false
40
+ * 13. detectWickedEscalation(score 8) -> true
41
+ * 14. detectWickedEscalation(score 10) -> true
42
+ * 15. applyWickedOverride sets wicked_override:true + Appendix E R4
43
+ * 16. Canon Part 3 10-verb traceability across all routing tables
44
+ * 17. Low-confidence routing reason annotation
45
+ * 18. Suppress_skills array invariant + null-safe shape
46
+ *
47
+ * Task 2 (Tests 19-21): navigation-engine.cjs decide() integration
48
+ * 19. decide() with IDP fixture surfaces routing in chosen_rationale
49
+ * 20. decide() with wicked_score 9 surfaces wicked escalation
50
+ * 21. decide() with tier_0 (absent BRAIN.md) -- no regression
51
+ *
52
+ * Task 3 (Tests 22-24): brain-client.isAvailable() upgrade
53
+ * 22. Brain reachable + IDP fresh -> mode_a
54
+ * 23. Brain unreachable + brain_offline -> mode_b; routing still works
55
+ * 24. brain-client require failure -> brainAvailable=false; no throw
56
+ *
57
+ * Registered in lib/memory/run-feynman-tests.cjs.
58
+ */
59
+
60
+ const assert = require('node:assert/strict');
61
+ const fs = require('node:fs');
62
+ const path = require('node:path');
63
+ const os = require('node:os');
64
+ const { spawnSync } = require('node:child_process');
65
+
66
+ const REPO = path.resolve(__dirname, '..', '..');
67
+ const ROUTER_PATH = path.join(REPO, 'lib/core/problem-type-router.cjs');
68
+ const ENGINE_PATH = path.join(REPO, 'lib/core/navigation-engine.cjs');
69
+ const SHARED_PATH = path.join(REPO, 'lib/core/navigation-engine-shared.cjs');
70
+ const CLASSIFIER_PATH = path.join(REPO, 'scripts/intent-classifier.cjs');
71
+
72
+ function requireRouter() {
73
+ return require(ROUTER_PATH);
74
+ }
75
+
76
+ function requireEngine() {
77
+ return require(ENGINE_PATH);
78
+ }
79
+
80
+ function requireShared() {
81
+ return require(SHARED_PATH);
82
+ }
83
+
84
+ // ---------- Test scaffolding ----------
85
+
86
+ let passed = 0;
87
+ let failed = 0;
88
+ function run(name, fn) {
89
+ try {
90
+ fn();
91
+ process.stdout.write('ok ' + name + '\n');
92
+ passed += 1;
93
+ } catch (err) {
94
+ process.stderr.write('FAIL ' + name + '\n');
95
+ process.stderr.write(String(err && err.stack ? err.stack : err) + '\n');
96
+ failed += 1;
97
+ }
98
+ }
99
+
100
+ // ---------- Section-body fixture helpers ----------
101
+
102
+ function makeProblemTypeSection(bodyText) {
103
+ if (bodyText === null) return null;
104
+ return { body: bodyText, tokens_estimate: Math.max(1, Math.ceil(bodyText.length / 4)) };
105
+ }
106
+
107
+ function makeWickedSection(score) {
108
+ if (score === null) return null;
109
+ return {
110
+ body: '- wicked_score: ' + score + '\n- rationale: fixture',
111
+ tokens_estimate: 8,
112
+ };
113
+ }
114
+
115
+ // =========================================================
116
+ // Task 1 -- parser + routing tables (Tests 1..18)
117
+ // =========================================================
118
+
119
+ run('Test 1: parseProblemTypeSection happy-path UDP + confidence 0.85', () => {
120
+ const { parseProblemTypeSection } = requireRouter();
121
+ const section = makeProblemTypeSection('- type: UDP\n- confidence: 0.85\n- rationale: fixture');
122
+ const out = parseProblemTypeSection(section);
123
+ assert.equal(out.type, 'UDP');
124
+ assert.equal(Math.abs(out.confidence - 0.85) < 1e-9, true);
125
+ });
126
+
127
+ run('Test 2: parseProblemTypeSection (no signal) -> null', () => {
128
+ const { parseProblemTypeSection } = requireRouter();
129
+ const section = makeProblemTypeSection('(no signal)');
130
+ const out = parseProblemTypeSection(section);
131
+ assert.equal(out, null);
132
+ });
133
+
134
+ run('Test 3: parseProblemTypeSection type-only -> tolerant {type, confidence:null}', () => {
135
+ const { parseProblemTypeSection } = requireRouter();
136
+ const section = makeProblemTypeSection('- type: UDP');
137
+ const out = parseProblemTypeSection(section);
138
+ assert.equal(out.type, 'UDP');
139
+ assert.equal(out.confidence, null);
140
+ });
141
+
142
+ run('Test 4: parseProblemTypeSection out-of-range confidence rejected', () => {
143
+ const { parseProblemTypeSection } = requireRouter();
144
+ // > 1 rejected
145
+ const section1 = makeProblemTypeSection('- type: UDP\n- confidence: 1.5');
146
+ const out1 = parseProblemTypeSection(section1);
147
+ assert.equal(out1.type, 'UDP');
148
+ assert.equal(out1.confidence, null,
149
+ 'confidence > 1 must be null; got ' + out1.confidence);
150
+ // 0.0 and 1.0 edge cases ARE permitted.
151
+ const section2 = makeProblemTypeSection('- type: WDP\n- confidence: 1.0');
152
+ const out2 = parseProblemTypeSection(section2);
153
+ assert.equal(out2.confidence, 1.0);
154
+ const section3 = makeProblemTypeSection('- type: WDP\n- confidence: 0.0');
155
+ const out3 = parseProblemTypeSection(section3);
156
+ assert.equal(out3.confidence, 0.0);
157
+ });
158
+
159
+ run('Test 5: parseProblemTypeSection unknown type FOO -> {type: unknown}', () => {
160
+ const { parseProblemTypeSection } = requireRouter();
161
+ const section = makeProblemTypeSection('- type: FOO\n- confidence: 0.5');
162
+ const out = parseProblemTypeSection(section);
163
+ assert.equal(out.type, 'unknown');
164
+ assert.equal(out.confidence, 0.5);
165
+ });
166
+
167
+ run('Test 6: routeByProblemType(UDP, 0.85) -> exploration skills', () => {
168
+ const { routeByProblemType } = requireRouter();
169
+ const out = routeByProblemType('UDP', 0.85);
170
+ assert.deepEqual(out.recommended_skills, [
171
+ 'explore-domains',
172
+ 'beautiful-question',
173
+ 'whitespace',
174
+ 'find-analogies',
175
+ 'find-connections',
176
+ ]);
177
+ assert.deepEqual(out.suppressed_skills, []);
178
+ assert.equal(/Undefined/i.test(out.reason), true);
179
+ assert.equal(/exploration/i.test(out.reason), true);
180
+ assert.equal(out.wicked_override, false);
181
+ });
182
+
183
+ run('Test 7: routeByProblemType(IDP, 0.8) -> definition-seeking skills', () => {
184
+ const { routeByProblemType } = requireRouter();
185
+ const out = routeByProblemType('IDP', 0.8);
186
+ assert.deepEqual(out.recommended_skills, [
187
+ 'beautiful-question',
188
+ 'structure-argument',
189
+ 'mullins',
190
+ 'lean-canvas',
191
+ 'map-unknowns',
192
+ ]);
193
+ assert.equal(/Ill-Defined/i.test(out.reason), true);
194
+ assert.equal(/definition/i.test(out.reason), true);
195
+ });
196
+
197
+ run('Test 8: routeByProblemType(WDP, 0.9) -> execution skills', () => {
198
+ const { routeByProblemType } = requireRouter();
199
+ const out = routeByProblemType('WDP', 0.9);
200
+ assert.deepEqual(out.recommended_skills, [
201
+ 'grade',
202
+ 'deep-grade',
203
+ 'score-innovation',
204
+ 'build-thesis',
205
+ 'challenge-assumptions',
206
+ ]);
207
+ assert.equal(/Well-Defined/i.test(out.reason), true);
208
+ assert.equal(/execution/i.test(out.reason), true);
209
+ });
210
+
211
+ run('Test 9: routeByProblemType(unknown, null) -> empty + fallback reason', () => {
212
+ const { routeByProblemType } = requireRouter();
213
+ const out = routeByProblemType('unknown', null);
214
+ assert.deepEqual(out.recommended_skills, []);
215
+ assert.deepEqual(out.suppressed_skills, []);
216
+ assert.equal(/unavailable|fallback/i.test(out.reason), true);
217
+ });
218
+
219
+ run('Test 10: routeByProblemType(null, null) -> same as unknown case', () => {
220
+ const { routeByProblemType } = requireRouter();
221
+ const out = routeByProblemType(null, null);
222
+ assert.deepEqual(out.recommended_skills, []);
223
+ assert.deepEqual(out.suppressed_skills, []);
224
+ assert.equal(/unavailable|fallback/i.test(out.reason), true);
225
+ });
226
+
227
+ run('Test 11: detectWickedEscalation(null) -> false', () => {
228
+ const { detectWickedEscalation } = requireRouter();
229
+ assert.equal(detectWickedEscalation(null), false);
230
+ });
231
+
232
+ run('Test 12: detectWickedEscalation(score 7) -> false', () => {
233
+ const { detectWickedEscalation } = requireRouter();
234
+ const section = makeWickedSection(7);
235
+ assert.equal(detectWickedEscalation(section), false);
236
+ });
237
+
238
+ run('Test 13: detectWickedEscalation(score 8) -> true', () => {
239
+ const { detectWickedEscalation } = requireRouter();
240
+ const section = makeWickedSection(8);
241
+ assert.equal(detectWickedEscalation(section), true);
242
+ });
243
+
244
+ run('Test 14: detectWickedEscalation(score 10) -> true', () => {
245
+ const { detectWickedEscalation } = requireRouter();
246
+ const section = makeWickedSection(10);
247
+ assert.equal(detectWickedEscalation(section), true);
248
+ });
249
+
250
+ run('Test 15: applyWickedOverride sets wicked_override:true + Canon Appendix E R4', () => {
251
+ const { routeByProblemType, applyWickedOverride } = requireRouter();
252
+ const base = routeByProblemType('IDP', 0.8);
253
+ const out = applyWickedOverride(base);
254
+ assert.equal(out.wicked_override, true);
255
+ // Wicked override skills per Canon Appendix E R4 family.
256
+ assert.deepEqual(out.recommended_skills, [
257
+ 'challenge-assumptions',
258
+ 'find-bottlenecks',
259
+ 'scenario-plan',
260
+ 'explore-futures',
261
+ ]);
262
+ assert.equal(/Wicked|Appendix E R4/i.test(out.reason), true);
263
+ assert.equal(/Canon Appendix E R4/.test(out.reason), true,
264
+ 'Wicked override reason must cite Canon Appendix E R4 explicitly; got: ' + out.reason);
265
+ });
266
+
267
+ run('Test 16: Canon Part 3 10-verb traceability across routing tables', () => {
268
+ const { TYPE_VERB_MAPPING, WICKED_VERB_MAPPING } = requireRouter();
269
+ const { CANONICAL_VERBS } = requireShared();
270
+ const canonSet = new Set(CANONICAL_VERBS);
271
+ // Every type table maps each skill to a canonical verb.
272
+ for (const typeKey of Object.keys(TYPE_VERB_MAPPING)) {
273
+ const skills = TYPE_VERB_MAPPING[typeKey];
274
+ for (const entry of skills) {
275
+ assert.equal(canonSet.has(entry.verb), true,
276
+ typeKey + ' skill ' + entry.skill + ' verb ' + entry.verb + ' not in CANONICAL_VERBS');
277
+ }
278
+ }
279
+ // Wicked table also maps to canonical verbs.
280
+ for (const entry of WICKED_VERB_MAPPING) {
281
+ assert.equal(canonSet.has(entry.verb), true,
282
+ 'Wicked skill ' + entry.skill + ' verb ' + entry.verb + ' not in CANONICAL_VERBS');
283
+ }
284
+ });
285
+
286
+ run('Test 17: Low-confidence (< 0.5) routing reason annotation', () => {
287
+ const { routeByProblemType } = requireRouter();
288
+ // High-conf reason has no low-conf marker.
289
+ const high = routeByProblemType('UDP', 0.85);
290
+ assert.equal(/low confidence/i.test(high.reason), false);
291
+ // Low-conf reason carries the marker.
292
+ const low = routeByProblemType('UDP', 0.2);
293
+ assert.equal(/low confidence/i.test(low.reason), true);
294
+ // Skills still surface (caller decides whether to weight down).
295
+ assert.equal(low.recommended_skills.length > 0, true);
296
+ });
297
+
298
+ run('Test 18: routeByProblemType output shape invariants (suppressed_skills array; wicked_override bool)', () => {
299
+ const { routeByProblemType, applyWickedOverride } = requireRouter();
300
+ for (const t of ['UDP', 'IDP', 'WDP', 'unknown', null]) {
301
+ const out = routeByProblemType(t, 0.5);
302
+ assert.equal(Array.isArray(out.recommended_skills), true);
303
+ assert.equal(Array.isArray(out.suppressed_skills), true);
304
+ assert.equal(typeof out.reason, 'string');
305
+ assert.equal(typeof out.wicked_override, 'boolean');
306
+ assert.equal(out.wicked_override, false,
307
+ 'baseline routing must not set wicked_override');
308
+ const wicked = applyWickedOverride(out);
309
+ assert.equal(Array.isArray(wicked.recommended_skills), true);
310
+ assert.equal(wicked.wicked_override, true);
311
+ }
312
+ });
313
+
314
+ // =========================================================
315
+ // Task 2 -- decide() integration (Tests 19..21)
316
+ // =========================================================
317
+
318
+ function makeBrainWithProblemType(typeBody, wickedScore) {
319
+ return {
320
+ exists: true,
321
+ section: 'market-analysis',
322
+ brain_generated_at: '2026-04-27T12:00:00Z',
323
+ brain_graph_version: 1,
324
+ governing_thought_hash: 'sha256:fixture',
325
+ staleness: 'fresh',
326
+ stale_reason: null,
327
+ author: 'brain',
328
+ confidence_baseline: 0.5,
329
+ parse_failed: false,
330
+ sections: {
331
+ pattern_matches: null,
332
+ framework_chain_predictions: null,
333
+ cross_domain_analogies: null,
334
+ wicked_indicators: wickedScore !== null ? makeWickedSection(wickedScore) : null,
335
+ unfilled_opportunity_matches: null,
336
+ assessment_thinking_chain_position: null,
337
+ problemtype_classification: typeBody !== null ? makeProblemTypeSection(typeBody) : null,
338
+ flagged_contradictions_xroom: null,
339
+ hsi_signals: null,
340
+ },
341
+ flagged_weaknesses: [],
342
+ };
343
+ }
344
+
345
+ function makeQuadruple(brain) {
346
+ return {
347
+ room: { exists: true, identity_text: 'fixture', references: [] },
348
+ state: { exists: true, artifact_count: 1, completeness_score: 0.5 },
349
+ reasoning: {
350
+ exists: true,
351
+ governing_thought: 'fixture thought',
352
+ reasoning_health_score: 0.7,
353
+ is_stale: false,
354
+ arguments: [],
355
+ },
356
+ brain: brain,
357
+ };
358
+ }
359
+
360
+ run('Test 19: decide() with IDP classification surfaces routing in chosen_rationale', () => {
361
+ const { decide } = requireEngine();
362
+ const brain = makeBrainWithProblemType('- type: IDP\n- confidence: 0.8', null);
363
+ const out = decide(
364
+ { sectionPath: '/tmp/fixture', sessionId: 's1' },
365
+ {
366
+ quadruple: makeQuadruple(brain),
367
+ brainAvailable: true,
368
+ userPersona: null,
369
+ intentSignal: null,
370
+ }
371
+ );
372
+ // chosen_rationale must reference IDP and definition-seeking routing.
373
+ const rationale = out.decision_trace.chosen_rationale || '';
374
+ assert.equal(/IDP/i.test(rationale), true,
375
+ 'chosen_rationale must reference IDP; got: ' + rationale);
376
+ assert.equal(/definition|Ill-Defined/i.test(rationale), true,
377
+ 'chosen_rationale must reference definition-seeking; got: ' + rationale);
378
+ });
379
+
380
+ run('Test 20: decide() with wicked_score 9 surfaces wicked escalation in rationale', () => {
381
+ const { decide } = requireEngine();
382
+ // Wicked override applies regardless of base type. Provide IDP + wicked_score 9.
383
+ const brain = makeBrainWithProblemType('- type: IDP\n- confidence: 0.8', 9);
384
+ const out = decide(
385
+ { sectionPath: '/tmp/fixture', sessionId: 's1' },
386
+ {
387
+ quadruple: makeQuadruple(brain),
388
+ brainAvailable: true,
389
+ userPersona: null,
390
+ intentSignal: null,
391
+ }
392
+ );
393
+ const rationale = out.decision_trace.chosen_rationale || '';
394
+ assert.equal(/wicked|Appendix E R4/i.test(rationale), true,
395
+ 'wicked rationale must reference wicked escalation; got: ' + rationale);
396
+ });
397
+
398
+ run('Test 21: decide() with tier_0 (absent BRAIN.md) -- no regression', () => {
399
+ const { decide } = requireEngine();
400
+ // No brain -> tier_0; problem-type routing contributes nothing.
401
+ const quadruple = {
402
+ room: { exists: true, identity_text: 'fx', references: [] },
403
+ state: { exists: true, artifact_count: 0, completeness_score: 0 },
404
+ reasoning: { exists: false, governing_thought: null, reasoning_health_score: 0, is_stale: true, arguments: [] },
405
+ brain: null,
406
+ };
407
+ const out = decide(
408
+ { sectionPath: '/tmp/fixture', sessionId: 's1' },
409
+ {
410
+ quadruple: quadruple,
411
+ brainAvailable: false,
412
+ userPersona: null,
413
+ intentSignal: null,
414
+ }
415
+ );
416
+ assert.equal(out.decision_trace.brain_md_tier_mode, 'tier_0');
417
+ // Engine never throws and never claims a problem-type rationale when brain
418
+ // is absent.
419
+ const rationale = out.decision_trace.chosen_rationale || '';
420
+ assert.equal(/IDP|UDP|WDP/i.test(rationale), false,
421
+ 'tier_0 rationale must NOT cite problem-type when brain is absent; got: ' + rationale);
422
+ });
423
+
424
+ // =========================================================
425
+ // Task 3 -- brain-client.isAvailable() upgrade (Tests 22..24)
426
+ // =========================================================
427
+
428
+ // Tests 22-24 spawn the classifier in a child process with mocked
429
+ // brain-client modules. We use require-cache injection in a tiny harness
430
+ // script to simulate isAvailable returning true / false / module-missing.
431
+
432
+ function runClassifierWithBrainMock(opts) {
433
+ // opts.brainAvailableValue: true | false | 'throw' | 'absent' (don't replace)
434
+ // opts.brainMd: optional BRAIN.md content to plant in the section
435
+ // opts.userMd: optional USER.md content
436
+ const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'p91-07-mock-'));
437
+ try {
438
+ const roomsRoot = path.join(tmpRoot, 'MindrianRooms');
439
+ const roomDir = path.join(roomsRoot, 'fixture-room');
440
+ const sectionDir = path.join(roomDir, 'market-analysis');
441
+ fs.mkdirSync(sectionDir, { recursive: true });
442
+ fs.mkdirSync(path.join(roomsRoot, '.rooms'), { recursive: true });
443
+ fs.writeFileSync(
444
+ path.join(roomsRoot, '.rooms', 'registry.json'),
445
+ JSON.stringify({ active: 'fixture-room', rooms: { 'fixture-room': {} } }, null, 2)
446
+ );
447
+ fs.writeFileSync(
448
+ path.join(roomDir, 'STATE.md'),
449
+ '---\nproject: fixture\n---\n\n# STATE\n'
450
+ );
451
+ fs.writeFileSync(
452
+ path.join(roomDir, 'ROOM.md'),
453
+ '---\nname: fixture-room\n---\n\n# Fixture\n'
454
+ );
455
+ fs.writeFileSync(
456
+ path.join(sectionDir, 'ROOM.md'),
457
+ '---\nname: market-analysis\n---\n\n# Market Analysis\n'
458
+ );
459
+ fs.writeFileSync(
460
+ path.join(sectionDir, 'MINTO.md'),
461
+ '---\nfm_version: 88\ngoverning_thought: Customers will pay for X\nlast_generated_at: 2026-04-27T12:00:00Z\nlast_artifact_write_seen_at: 2026-04-27T11:00:00Z\nreasoning_health_score: 0.8\nflagged_weaknesses: []\ndecision_log: []\n---\n\n# MINTO\n'
462
+ );
463
+ if (opts.brainMd !== undefined) {
464
+ fs.writeFileSync(path.join(sectionDir, 'BRAIN.md'), opts.brainMd);
465
+ }
466
+ // Active section pointer
467
+ fs.mkdirSync(path.join(roomDir, '.mindrian'), { recursive: true });
468
+ fs.writeFileSync(
469
+ path.join(roomDir, '.mindrian', 'active-section.json'),
470
+ JSON.stringify({ section: 'market-analysis' })
471
+ );
472
+
473
+ // Build a tiny mock harness that replaces brain-client in require.cache
474
+ // before invoking the classifier.
475
+ const harness = `'use strict';
476
+ const Module = require('module');
477
+ const path = require('path');
478
+ const realResolve = Module._resolveFilename;
479
+ Module._resolveFilename = function(request, parent, isMain, options) {
480
+ if (typeof request === 'string' && request.indexOf('brain-client.cjs') !== -1) {
481
+ if (${JSON.stringify(opts.brainAvailableValue)} === 'absent') {
482
+ // Trigger MODULE_NOT_FOUND
483
+ const e = new Error("Cannot find module '" + request + "'");
484
+ e.code = 'MODULE_NOT_FOUND';
485
+ throw e;
486
+ }
487
+ }
488
+ return realResolve.call(this, request, parent, isMain, options);
489
+ };
490
+ // Pre-populate require.cache for brain-client with a mock that responds
491
+ // according to the value flag.
492
+ const realBrainPath = ${JSON.stringify(path.join(REPO, 'lib/core/brain-client.cjs'))};
493
+ if (${JSON.stringify(opts.brainAvailableValue)} === 'throw') {
494
+ require.cache[realBrainPath] = {
495
+ id: realBrainPath, filename: realBrainPath, loaded: true,
496
+ exports: { isAvailable: function() { throw new Error('mock-throw'); } },
497
+ };
498
+ } else if (${JSON.stringify(opts.brainAvailableValue)} === true) {
499
+ require.cache[realBrainPath] = {
500
+ id: realBrainPath, filename: realBrainPath, loaded: true,
501
+ exports: { isAvailable: function() { return true; }, schema: function() { return {}; } },
502
+ };
503
+ } else if (${JSON.stringify(opts.brainAvailableValue)} === false) {
504
+ require.cache[realBrainPath] = {
505
+ id: realBrainPath, filename: realBrainPath, loaded: true,
506
+ exports: { isAvailable: function() { return false; } },
507
+ };
508
+ }
509
+ // Now run the classifier. It reads stdin -- we feed via process.stdin manually.
510
+ process.env.MINDRIAN_ROOMS_ROOT = ${JSON.stringify(roomsRoot)};
511
+ process.env.CLAUDE_SESSION_ID = 'mock-session-22';
512
+ require(${JSON.stringify(CLASSIFIER_PATH)});
513
+ `;
514
+ const harnessPath = path.join(tmpRoot, 'harness.cjs');
515
+ fs.writeFileSync(harnessPath, harness);
516
+
517
+ const res = spawnSync(process.execPath, [harnessPath], {
518
+ input: 'tell me about market sizing',
519
+ encoding: 'utf8',
520
+ timeout: 10000,
521
+ env: Object.assign({}, process.env, {
522
+ MINDRIAN_ROOMS_ROOT: roomsRoot,
523
+ CLAUDE_SESSION_ID: 'mock-session-22',
524
+ MINDRIAN_COPILOT_INJECT_FINDINGS: '0',
525
+ }),
526
+ });
527
+ return {
528
+ stdout: res.stdout || '',
529
+ stderr: res.stderr || '',
530
+ status: res.status,
531
+ tmpRoot: tmpRoot,
532
+ roomDir: roomDir,
533
+ sectionDir: sectionDir,
534
+ };
535
+ } finally {
536
+ // Best-effort cleanup; tests inspect the trace inline before this fires.
537
+ }
538
+ }
539
+
540
+ run('Test 22: Brain reachable (isAvailable -> true) + fresh BRAIN.md IDP -> mode_a', () => {
541
+ // BRAIN.md fixture for IDP at confidence 0.8.
542
+ const brainMd =
543
+ '---\n' +
544
+ 'fm_version: 90\n' +
545
+ 'brain_generated_at: 2026-04-27T11:00:00Z\n' +
546
+ 'brain_graph_version: 1\n' +
547
+ 'governing_thought_hash: sha256:fixture\n' +
548
+ 'staleness: fresh\n' +
549
+ 'stale_reason: null\n' +
550
+ 'author: brain\n' +
551
+ 'confidence_baseline: 0.5\n' +
552
+ 'flagged_weaknesses: []\n' +
553
+ '---\n\n' +
554
+ '# BRAIN.md\n\n' +
555
+ '## ProblemType Classification\n\n' +
556
+ '- type: IDP\n' +
557
+ '- confidence: 0.8\n' +
558
+ '- rationale: fixture\n';
559
+ const result = runClassifierWithBrainMock({
560
+ brainAvailableValue: true,
561
+ brainMd: brainMd,
562
+ });
563
+ // The classifier should have written a decision-trace JSON file.
564
+ const tracePath = path.join(result.roomDir, '.mindrian', 'decision-traces', 'mock-session-22.json');
565
+ assert.equal(fs.existsSync(tracePath), true,
566
+ 'decision-trace must exist; stderr: ' + result.stderr);
567
+ const data = JSON.parse(fs.readFileSync(tracePath, 'utf8'));
568
+ assert.equal(Array.isArray(data.traces), true);
569
+ assert.equal(data.traces.length >= 1, true);
570
+ const last = data.traces[data.traces.length - 1];
571
+ // Brain reachable + fresh BRAIN.md -> mode_a.
572
+ assert.equal(last.brain_md_tier_mode, 'mode_a',
573
+ 'expected mode_a; got ' + last.brain_md_tier_mode + '; stderr: ' + result.stderr);
574
+ });
575
+
576
+ run('Test 23: Brain unreachable (isAvailable -> false) + brain_offline -> mode_b; routing still works locally', () => {
577
+ // BRAIN.md fixture for IDP, marked stale with brain_offline reason.
578
+ const brainMd =
579
+ '---\n' +
580
+ 'fm_version: 90\n' +
581
+ 'brain_generated_at: 2026-04-27T11:00:00Z\n' +
582
+ 'brain_graph_version: 1\n' +
583
+ 'governing_thought_hash: sha256:fixture\n' +
584
+ 'staleness: stale\n' +
585
+ 'stale_reason: brain_offline\n' +
586
+ 'author: brain\n' +
587
+ 'confidence_baseline: 0.5\n' +
588
+ 'flagged_weaknesses: []\n' +
589
+ '---\n\n' +
590
+ '# BRAIN.md\n\n' +
591
+ '## ProblemType Classification\n\n' +
592
+ '- type: IDP\n' +
593
+ '- confidence: 0.8\n';
594
+ const result = runClassifierWithBrainMock({
595
+ brainAvailableValue: false,
596
+ brainMd: brainMd,
597
+ });
598
+ const tracePath = path.join(result.roomDir, '.mindrian', 'decision-traces', 'mock-session-22.json');
599
+ assert.equal(fs.existsSync(tracePath), true,
600
+ 'decision-trace must exist; stderr: ' + result.stderr);
601
+ const data = JSON.parse(fs.readFileSync(tracePath, 'utf8'));
602
+ const last = data.traces[data.traces.length - 1];
603
+ // Brain unreachable + brain_offline -> mode_b per Phase 90 contract.
604
+ assert.equal(last.brain_md_tier_mode, 'mode_b',
605
+ 'expected mode_b; got ' + last.brain_md_tier_mode + '; stderr: ' + result.stderr);
606
+ // RECOMMENDED never rendered in mode_b.
607
+ assert.equal(last.brain_md_recommended_marker_rendered, false);
608
+ // Local problem-type routing still contributes (rationale should mention IDP).
609
+ const rationale = last.chosen_rationale || '';
610
+ assert.equal(/IDP/i.test(rationale), true,
611
+ 'mode_b should still surface local IDP routing; got: ' + rationale);
612
+ });
613
+
614
+ run('Test 24: brain-client require failure -> brainAvailable=false; no throw', () => {
615
+ // brainAvailableValue: 'throw' will inject a module that throws on isAvailable.
616
+ // The intent-classifier must catch and default to brainAvailable=false.
617
+ const brainMd =
618
+ '---\n' +
619
+ 'fm_version: 90\n' +
620
+ 'brain_generated_at: 2026-04-27T11:00:00Z\n' +
621
+ 'brain_graph_version: 1\n' +
622
+ 'governing_thought_hash: sha256:fixture\n' +
623
+ 'staleness: stale\n' +
624
+ 'stale_reason: brain_offline\n' +
625
+ 'author: brain\n' +
626
+ 'confidence_baseline: 0.5\n' +
627
+ 'flagged_weaknesses: []\n' +
628
+ '---\n\n' +
629
+ '# BRAIN.md\n\n' +
630
+ '## ProblemType Classification\n\n' +
631
+ '- type: WDP\n' +
632
+ '- confidence: 0.7\n';
633
+ const result = runClassifierWithBrainMock({
634
+ brainAvailableValue: 'throw',
635
+ brainMd: brainMd,
636
+ });
637
+ // Classifier must NOT crash; exit 0 (advisory).
638
+ assert.equal(result.status, 0,
639
+ 'classifier must exit 0 even when brain-client throws; got ' + result.status + '; stderr: ' + result.stderr);
640
+ const tracePath = path.join(result.roomDir, '.mindrian', 'decision-traces', 'mock-session-22.json');
641
+ assert.equal(fs.existsSync(tracePath), true);
642
+ const data = JSON.parse(fs.readFileSync(tracePath, 'utf8'));
643
+ const last = data.traces[data.traces.length - 1];
644
+ // brainAvailable defaults false -> mode_b (BRAIN.md is brain_offline) or tier_0.
645
+ assert.equal(last.brain_md_tier_mode === 'mode_b' || last.brain_md_tier_mode === 'tier_0', true,
646
+ 'expected mode_b/tier_0 when isAvailable throws; got ' + last.brain_md_tier_mode);
647
+ });
648
+
649
+ // =========================================================
650
+ // Suite tail
651
+ // =========================================================
652
+
653
+ process.stdout.write(
654
+ '\nProblem-Type Router tests: ' + passed + '/' + (passed + failed) + ' passed\n'
655
+ );
656
+ process.exit(failed === 0 ? 0 : 1);