@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,534 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /*
5
+ * Copyright (c) 2026 Mindrian. BSL 1.1.
6
+ *
7
+ * Phase 90-07 Task 1 -- brain-derive-command.cjs fixture tests (12 cases)
8
+ * ======================================================================
9
+ * 12 tests across the /mos:brain-derive dispatcher. Exercises the 4
10
+ * invocation modes (single section, --all, --cross-room, --dry-run)
11
+ * plus graceful-degradation paths (Brain offline from start,
12
+ * rate-limit mid-batch, invalid section, no active room, schema-gate
13
+ * rejection on one section) plus streaming-progress surfacing and
14
+ * the Shape E Action Report rendering contract.
15
+ *
16
+ * Mocking strategy:
17
+ * - Install a mock brain-client.cjs in require.cache for isAvailable()
18
+ * control (Canon Part 8 proxy: no real Brain traffic ever fires
19
+ * during tests).
20
+ * - Install a mock brain-derivation.cjs in require.cache with a
21
+ * deriveSection stub that returns programmable results and records
22
+ * every invocation into an audit array. Forces determinism without
23
+ * touching real Brain / real filesystem derivations.
24
+ * - Override MINDRIAN_ROOMS_ROOT + create a tmp registry.json so the
25
+ * dispatcher's resolveActiveRoom() resolves into a fixture room
26
+ * under the tmp tree instead of the real ~/MindrianRooms registry.
27
+ *
28
+ * The mock approach mirrors Plan 90-01 (brain-derivation.test.cjs) and
29
+ * Plan 90-02 (brain-derivation-queue.test.cjs): override require.cache
30
+ * entries BEFORE requiring the module under test; reset between tests.
31
+ *
32
+ * Pure node built-ins: fs, os, path, assert, child_process (spawnSync
33
+ * for streaming progress stdout capture). No npm deps.
34
+ */
35
+
36
+ const assert = require('node:assert/strict');
37
+ const fs = require('node:fs');
38
+ const os = require('node:os');
39
+ const path = require('node:path');
40
+ const { spawnSync } = require('node:child_process');
41
+
42
+ const REPO_ROOT = path.resolve(__dirname, '..', '..');
43
+ const DISPATCHER_PATH = path.join(REPO_ROOT, 'scripts', 'brain-derive-command.cjs');
44
+
45
+ // ---------- Tmp workspace helpers ----------
46
+
47
+ const TMP_ROOTS = [];
48
+ function makeTmpRoot(tag) {
49
+ const r = fs.mkdtempSync(path.join(os.tmpdir(), 'brain-derive-cmd-' + tag + '-'));
50
+ TMP_ROOTS.push(r);
51
+ return r;
52
+ }
53
+ process.on('exit', function () {
54
+ for (const r of TMP_ROOTS) {
55
+ try { fs.rmSync(r, { recursive: true, force: true }); } catch (_e) { /* best effort */ }
56
+ }
57
+ });
58
+
59
+ function writeFile(p, body) {
60
+ fs.mkdirSync(path.dirname(p), { recursive: true });
61
+ fs.writeFileSync(p, body, 'utf8');
62
+ }
63
+
64
+ // ---------- Fixture builder: registry + room + sections ----------
65
+ //
66
+ // Build a tmp MindrianRooms dir with a registry.json pointing to one
67
+ // active room that has N sections, each with a minimal ROOM.md +
68
+ // MINTO.md so the dispatcher's resolveTargetSections() finds them.
69
+
70
+ function buildFixtureRooms(opts) {
71
+ opts = opts || {};
72
+ const roomsRoot = makeTmpRoot('rooms');
73
+ const sectionsCount = opts.sections == null ? 3 : opts.sections;
74
+ const roomSlug = opts.room_slug || 'fixture-room';
75
+ const roomPath = path.join(roomsRoot, roomSlug);
76
+ fs.mkdirSync(roomPath, { recursive: true });
77
+
78
+ // Room-level ROOM.md.
79
+ writeFile(path.join(roomPath, 'ROOM.md'), [
80
+ '---',
81
+ 'name: "' + roomSlug + '"',
82
+ 'kind: room',
83
+ '---',
84
+ '',
85
+ '# ' + roomSlug,
86
+ '',
87
+ ].join('\n'));
88
+
89
+ // Sections. Each has ROOM.md + MINTO.md so readTriple finds them.
90
+ const sectionNames = opts.section_names || (function () {
91
+ const base = ['market-analysis', 'problem-definition', 'competitive-analysis',
92
+ 'team-execution', 'solution-design', 'business-model',
93
+ 'legal-ip', 'financial-model', 'go-to-market'];
94
+ return base.slice(0, sectionsCount);
95
+ })();
96
+ for (const sec of sectionNames) {
97
+ const sp = path.join(roomPath, sec);
98
+ fs.mkdirSync(sp, { recursive: true });
99
+ writeFile(path.join(sp, 'ROOM.md'), [
100
+ '---',
101
+ 'name: "' + sec + '"',
102
+ 'kind: section',
103
+ '---',
104
+ '',
105
+ '# ' + sec,
106
+ '',
107
+ ].join('\n'));
108
+ writeFile(path.join(sp, 'MINTO.md'), [
109
+ '---',
110
+ 'schema_version: 88',
111
+ 'version: 1',
112
+ 'section: "' + sec + '"',
113
+ 'last_generated_at: "2026-04-20T00:00:00Z"',
114
+ 'last_artifact_write_seen_at: "2026-04-20T00:00:00Z"',
115
+ 'arguments_count: 4',
116
+ 'evidence_density: 0.6',
117
+ 'mece_status: pass',
118
+ 'reasoning_health_score: 0.7',
119
+ 'flagged_weaknesses: []',
120
+ 'decision_log: []',
121
+ '---',
122
+ '',
123
+ '## Governing Thought',
124
+ '',
125
+ 'The venture validates its primary hypothesis within 90 days.',
126
+ '',
127
+ ].join('\n'));
128
+ }
129
+
130
+ // Registry.
131
+ if (!opts.no_registry) {
132
+ const rooms = {};
133
+ rooms[roomSlug] = { path: roomSlug, venture_name: roomSlug, status: 'active' };
134
+ const reg = {
135
+ version: 2,
136
+ root: roomsRoot,
137
+ active: opts.active == null ? roomSlug : opts.active,
138
+ rooms: rooms,
139
+ };
140
+ writeFile(path.join(roomsRoot, '.rooms', 'registry.json'), JSON.stringify(reg, null, 2));
141
+ }
142
+
143
+ return { roomsRoot: roomsRoot, roomPath: roomPath, roomSlug: roomSlug, sectionNames: sectionNames };
144
+ }
145
+
146
+ // ---------- Dispatcher module loader (mock-enabled) ----------
147
+ //
148
+ // Returns {dispatcher, audit}. Audit tracks every deriveSection call +
149
+ // every brain-client isAvailable() call. Mock is installed in
150
+ // require.cache BEFORE the dispatcher module is required so its top-
151
+ // level require() picks up the stubs.
152
+
153
+ function loadDispatcherWithMocks(opts) {
154
+ opts = opts || {};
155
+ const audit = {
156
+ derive_calls: [],
157
+ isAvailable_calls: 0,
158
+ };
159
+
160
+ // Mock brain-client.
161
+ const bcPath = require.resolve('../core/brain-client.cjs');
162
+ delete require.cache[bcPath];
163
+ require.cache[bcPath] = {
164
+ id: bcPath,
165
+ filename: bcPath,
166
+ loaded: true,
167
+ exports: {
168
+ isAvailable: function () {
169
+ audit.isAvailable_calls += 1;
170
+ if (typeof opts.isAvailableFn === 'function') {
171
+ return opts.isAvailableFn(audit.isAvailable_calls);
172
+ }
173
+ return opts.isAvailable === undefined ? true : opts.isAvailable;
174
+ },
175
+ schema: async function () { return { brain_graph_version: 1 }; },
176
+ query: async function () { return { records: [] }; },
177
+ search: async function () { return { matches: [] }; },
178
+ },
179
+ };
180
+
181
+ // Mock brain-derivation.cjs deriveSection.
182
+ const bdPath = require.resolve('../core/brain-derivation.cjs');
183
+ delete require.cache[bdPath];
184
+ const realExports = opts.useRealBrainDerivation ? require('../core/brain-derivation.cjs') : {};
185
+ require.cache[bdPath] = {
186
+ id: bdPath,
187
+ filename: bdPath,
188
+ loaded: true,
189
+ exports: Object.assign({}, realExports, {
190
+ deriveSection: async function (roomPath, section, options) {
191
+ const rec = { roomPath: roomPath, section: section, options: options || {} };
192
+ audit.derive_calls.push(rec);
193
+ if (typeof opts.deriveFn === 'function') {
194
+ return opts.deriveFn(rec, audit.derive_calls.length);
195
+ }
196
+ return { success: true, brain_md_path: path.join(roomPath, section, 'BRAIN.md'), violations: [], cost_tokens: 540 };
197
+ },
198
+ SECTION_BUILDERS: realExports.SECTION_BUILDERS || [],
199
+ }),
200
+ };
201
+
202
+ // Fresh require of dispatcher.
203
+ const dispPath = require.resolve('../../scripts/brain-derive-command.cjs');
204
+ delete require.cache[dispPath];
205
+ const dispatcher = require('../../scripts/brain-derive-command.cjs');
206
+ return { dispatcher: dispatcher, audit: audit };
207
+ }
208
+
209
+ function resetModuleCache() {
210
+ for (const modPath of [
211
+ require.resolve('../core/brain-client.cjs'),
212
+ require.resolve('../core/brain-derivation.cjs'),
213
+ ]) {
214
+ delete require.cache[modPath];
215
+ }
216
+ try {
217
+ const dispPath = require.resolve('../../scripts/brain-derive-command.cjs');
218
+ delete require.cache[dispPath];
219
+ } catch (_e) { /* file may not exist yet during early RED phase */ }
220
+ }
221
+
222
+ // ---------- Test runner ----------
223
+
224
+ let passed = 0;
225
+ let failed = 0;
226
+
227
+ async function runAsync(name, fn) {
228
+ try {
229
+ resetModuleCache();
230
+ await fn();
231
+ passed += 1;
232
+ process.stdout.write(' ok ' + name + '\n');
233
+ } catch (err) {
234
+ failed += 1;
235
+ process.stderr.write(' FAIL ' + name + '\n');
236
+ process.stderr.write(' ' + (err && err.stack ? err.stack : err) + '\n');
237
+ }
238
+ }
239
+
240
+ // ---------- 12 tests ----------
241
+
242
+ async function main() {
243
+
244
+ // Test 01: single section happy path.
245
+ await runAsync('Test 01: single section happy path -> deriveSection called once; report lists 1 derived', async function () {
246
+ const { roomsRoot, roomSlug } = buildFixtureRooms({ sections: 3 });
247
+ const { dispatcher, audit } = loadDispatcherWithMocks({});
248
+ const result = await dispatcher.dispatch({
249
+ section: 'market-analysis',
250
+ all: false,
251
+ crossRoom: false,
252
+ dryRun: false,
253
+ _rooms_root_override: roomsRoot,
254
+ });
255
+ assert.equal(audit.derive_calls.length, 1, 'expected 1 deriveSection call');
256
+ assert.equal(audit.derive_calls[0].section, 'market-analysis');
257
+ assert.equal(result.summary.sections_derived, 1);
258
+ assert.equal(result.summary.sections_requested, 1);
259
+ assert.equal(result.exit_code, 0);
260
+ // Shape E rendering contains required labels.
261
+ const rendered = dispatcher.renderShapeE(result.summary);
262
+ assert.ok(/Sections derived/.test(rendered), 'Shape E must contain "Sections derived" label');
263
+ assert.ok(/market-analysis/.test(rendered), 'Shape E must contain section name');
264
+ });
265
+
266
+ // Test 02: --all with 3 active sections.
267
+ await runAsync('Test 02: --all with 3 active sections -> deriveSection called 3x; report lists 3 derived', async function () {
268
+ const { roomsRoot } = buildFixtureRooms({ sections: 3 });
269
+ const { dispatcher, audit } = loadDispatcherWithMocks({});
270
+ const result = await dispatcher.dispatch({
271
+ section: null,
272
+ all: true,
273
+ crossRoom: false,
274
+ dryRun: false,
275
+ _rooms_root_override: roomsRoot,
276
+ });
277
+ assert.equal(audit.derive_calls.length, 3, 'expected 3 deriveSection calls; got ' + audit.derive_calls.length);
278
+ assert.equal(result.summary.sections_derived, 3);
279
+ assert.equal(result.summary.sections_requested, 3);
280
+ assert.equal(result.exit_code, 0);
281
+ // Every derive call should have cross_room_scan !== true.
282
+ for (const c of audit.derive_calls) {
283
+ assert.notEqual(c.options.cross_room_scan, true, 'cross_room_scan must be false/undefined without --cross-room');
284
+ }
285
+ });
286
+
287
+ // Test 03: --cross-room flag -> deriveSection called with options.cross_room_scan:true.
288
+ await runAsync('Test 03: --cross-room -> deriveSection called with options.cross_room_scan:true', async function () {
289
+ const { roomsRoot } = buildFixtureRooms({ sections: 2 });
290
+ const { dispatcher, audit } = loadDispatcherWithMocks({});
291
+ const result = await dispatcher.dispatch({
292
+ section: 'market-analysis',
293
+ all: false,
294
+ crossRoom: true,
295
+ dryRun: false,
296
+ _rooms_root_override: roomsRoot,
297
+ });
298
+ assert.equal(audit.derive_calls.length, 1);
299
+ assert.equal(audit.derive_calls[0].options.cross_room_scan, true,
300
+ 'cross_room_scan must be true when --cross-room flag is set');
301
+ assert.equal(result.summary.sections_derived, 1);
302
+ assert.equal(result.summary.cross_room_enabled, true);
303
+ });
304
+
305
+ // Test 04: --dry-run -> zero deriveSection calls.
306
+ await runAsync('Test 04: --dry-run -> zero deriveSection calls; zero writes; report shows estimated cost', async function () {
307
+ const { roomsRoot } = buildFixtureRooms({ sections: 3 });
308
+ const { dispatcher, audit } = loadDispatcherWithMocks({});
309
+ const result = await dispatcher.dispatch({
310
+ section: null,
311
+ all: true,
312
+ crossRoom: false,
313
+ dryRun: true,
314
+ _rooms_root_override: roomsRoot,
315
+ });
316
+ assert.equal(audit.derive_calls.length, 0, 'dry-run must NOT invoke deriveSection');
317
+ assert.equal(result.summary.dry_run, true);
318
+ assert.ok(result.summary.cost_tokens_estimated > 0, 'dry-run must report an estimated cost');
319
+ assert.equal(result.exit_code, 0);
320
+ // Shape E should mark as dry-run.
321
+ const rendered = dispatcher.renderShapeE(result.summary);
322
+ assert.ok(/DRY[-\s]?RUN|dry[-\s]?run|dry run/i.test(rendered), 'Shape E must mark dry-run');
323
+ });
324
+
325
+ // Test 05: Brain offline from start -> 0 derived; single-line message.
326
+ await runAsync('Test 05: Brain offline from start -> 0 sections derived; single-line message', async function () {
327
+ const { roomsRoot } = buildFixtureRooms({ sections: 3 });
328
+ const { dispatcher, audit } = loadDispatcherWithMocks({ isAvailable: false });
329
+ const result = await dispatcher.dispatch({
330
+ section: null,
331
+ all: true,
332
+ crossRoom: false,
333
+ dryRun: false,
334
+ _rooms_root_override: roomsRoot,
335
+ });
336
+ assert.equal(audit.derive_calls.length, 0, 'Brain-offline must skip all deriveSection calls');
337
+ assert.equal(result.summary.sections_derived, 0);
338
+ assert.equal(result.summary.brain_offline_from_start, true);
339
+ assert.equal(result.exit_code, 0, 'Brain offline is soft-fail exit 0, not error');
340
+ });
341
+
342
+ // Test 06: rate-limited mid-batch.
343
+ await runAsync('Test 06: rate-limited mid-batch -> N derived, remainder skipped with reason rate_limited', async function () {
344
+ const { roomsRoot } = buildFixtureRooms({ sections: 7 });
345
+ const { dispatcher, audit } = loadDispatcherWithMocks({
346
+ deriveFn: function (rec, callIndex) {
347
+ if (callIndex >= 3) {
348
+ // Third call onwards returns rate_limited.
349
+ return { success: false, reason: 'rate_limited', cost_tokens: 0, violations: [] };
350
+ }
351
+ return { success: true, brain_md_path: path.join(rec.roomPath, rec.section, 'BRAIN.md'), violations: [], cost_tokens: 540 };
352
+ },
353
+ });
354
+ const result = await dispatcher.dispatch({
355
+ section: null,
356
+ all: true,
357
+ crossRoom: false,
358
+ dryRun: false,
359
+ _rooms_root_override: roomsRoot,
360
+ });
361
+ // After rate_limited result on call 3, remaining calls should be skipped without invoking deriveSection.
362
+ // Expected pattern: calls 1 and 2 derived, call 3 hits rate_limited, calls 4-7 skipped.
363
+ assert.ok(audit.derive_calls.length <= 4,
364
+ 'after rate_limited, no more deriveSection should fire; got ' + audit.derive_calls.length + ' calls');
365
+ assert.equal(result.summary.sections_derived, 2);
366
+ assert.ok(result.summary.brain_offline_sections >= 4,
367
+ 'remaining 4+ sections must be categorized as brain_offline/rate_limited skip; got ' + result.summary.brain_offline_sections);
368
+ assert.equal(result.summary.rate_limited, true);
369
+ });
370
+
371
+ // Test 07: invalid section name -> exit 1.
372
+ await runAsync('Test 07: invalid section name -> exit 1 with error message', async function () {
373
+ const { roomsRoot } = buildFixtureRooms({ sections: 2 });
374
+ const { dispatcher, audit } = loadDispatcherWithMocks({});
375
+ const result = await dispatcher.dispatch({
376
+ section: 'nonexistent-section-xyz',
377
+ all: false,
378
+ crossRoom: false,
379
+ dryRun: false,
380
+ _rooms_root_override: roomsRoot,
381
+ });
382
+ assert.equal(audit.derive_calls.length, 0);
383
+ assert.equal(result.exit_code, 1);
384
+ assert.ok(result.error_message, 'must produce an error message');
385
+ assert.ok(/invalid|unknown|not found|does not exist/i.test(result.error_message),
386
+ 'error message should indicate invalid section: ' + result.error_message);
387
+ });
388
+
389
+ // Test 08: no active room -> exit 1.
390
+ await runAsync('Test 08: no active room -> exit 1 with error message', async function () {
391
+ // Build a tmp rooms root without a registry.
392
+ const roomsRoot = makeTmpRoot('no-registry');
393
+ const { dispatcher, audit } = loadDispatcherWithMocks({});
394
+ const result = await dispatcher.dispatch({
395
+ section: null,
396
+ all: true,
397
+ crossRoom: false,
398
+ dryRun: false,
399
+ _rooms_root_override: roomsRoot,
400
+ });
401
+ assert.equal(audit.derive_calls.length, 0);
402
+ assert.equal(result.exit_code, 1);
403
+ assert.ok(result.error_message);
404
+ assert.ok(/no active room|no registry|switch/i.test(result.error_message),
405
+ 'error message should indicate missing active room: ' + result.error_message);
406
+ });
407
+
408
+ // Test 09: schema gate rejection on one section.
409
+ await runAsync('Test 09: schema gate rejection on one section -> report lists failed; others still derived', async function () {
410
+ const { roomsRoot } = buildFixtureRooms({ sections: 3 });
411
+ const { dispatcher, audit } = loadDispatcherWithMocks({
412
+ deriveFn: function (rec, callIndex) {
413
+ if (callIndex === 2) {
414
+ return {
415
+ success: false,
416
+ reason: 'schema_rejected',
417
+ violations: [{ category: 'schema', severity: 'error', message: 'author field missing' }],
418
+ cost_tokens: 60,
419
+ };
420
+ }
421
+ return { success: true, brain_md_path: path.join(rec.roomPath, rec.section, 'BRAIN.md'), violations: [], cost_tokens: 540 };
422
+ },
423
+ });
424
+ const result = await dispatcher.dispatch({
425
+ section: null,
426
+ all: true,
427
+ crossRoom: false,
428
+ dryRun: false,
429
+ _rooms_root_override: roomsRoot,
430
+ });
431
+ assert.equal(audit.derive_calls.length, 3, 'all 3 sections must still be attempted despite 1 schema failure');
432
+ assert.equal(result.summary.sections_derived, 2);
433
+ assert.equal(result.summary.schema_gate_failed, 1);
434
+ assert.equal(result.exit_code, 0);
435
+ // Rendered report should include the failed section.
436
+ const rendered = dispatcher.renderShapeE(result.summary);
437
+ assert.ok(/schema|failed/i.test(rendered), 'Shape E must surface schema gate failure');
438
+ });
439
+
440
+ // Test 10: 7-section --all with streaming progress.
441
+ await runAsync('Test 10: 7-section --all with streaming progress -> stderr shows [1/7] through [7/7]', async function () {
442
+ const { roomsRoot, roomPath } = buildFixtureRooms({ sections: 7 });
443
+ // Write a minimal stub that invokes the dispatcher via CLI so we capture real stderr stream.
444
+ // We invoke main() directly via spawnSync to capture stderr in-process style.
445
+ const cliScript = [
446
+ '"use strict";',
447
+ // Mock brain-client.
448
+ 'const Module = require("module");',
449
+ 'const origResolve = Module._resolve_filename || Module._resolveFilename;',
450
+ 'const origLoad = Module._load;',
451
+ 'Module._load = function (request, parent, isMain) {',
452
+ ' if (request.endsWith("brain-client.cjs") || request.indexOf("brain-client") !== -1 && request.indexOf("core") !== -1) {',
453
+ ' return { isAvailable: function () { return true; }, schema: async function () { return { brain_graph_version: 1 }; }, query: async function () { return { records: [] }; }, search: async function () { return { matches: [] }; } };',
454
+ ' }',
455
+ ' if (request.endsWith("brain-derivation.cjs") && request.indexOf("prompts") === -1) {',
456
+ ' return { deriveSection: async function (roomPath, section) { return { success: true, brain_md_path: roomPath + "/" + section + "/BRAIN.md", violations: [], cost_tokens: 540 }; }, SECTION_BUILDERS: [] };',
457
+ ' }',
458
+ ' return origLoad.apply(this, arguments);',
459
+ '};',
460
+ 'process.env.MINDRIAN_ROOMS_ROOT = ' + JSON.stringify(roomsRoot) + ';',
461
+ 'process.argv = [process.argv[0], ' + JSON.stringify(DISPATCHER_PATH) + ', "--all"];',
462
+ 'require(' + JSON.stringify(DISPATCHER_PATH) + ').main();',
463
+ ].join('\n');
464
+ const tmpRunner = path.join(makeTmpRoot('runner'), 'run.js');
465
+ writeFile(tmpRunner, cliScript);
466
+ const res = spawnSync(process.execPath, [tmpRunner], { encoding: 'utf8' });
467
+ const combined = (res.stdout || '') + '\n' + (res.stderr || '');
468
+ // Expect per-section progress lines [N/7]. We tolerate [1/7] through [7/7] appearing on stderr.
469
+ let progressHits = 0;
470
+ for (let i = 1; i <= 7; i++) {
471
+ if (combined.indexOf('[' + i + '/7]') !== -1) progressHits += 1;
472
+ }
473
+ assert.ok(progressHits >= 7,
474
+ 'expected 7 streaming progress lines [N/7]; found ' + progressHits + '\nOUTPUT:\n' + combined);
475
+ // Shape E final report must also appear.
476
+ assert.ok(/Sections derived/i.test(combined) || /BRAIN DERIVATION/i.test(combined),
477
+ 'final Shape E report must render after progress: ' + combined.slice(0, 500));
478
+ });
479
+
480
+ // Test 11: performance -- 3-section --all in under 15s with stubbed Brain.
481
+ await runAsync('Test 11: 3-section --all performance budget < 15s stubbed', async function () {
482
+ const { roomsRoot } = buildFixtureRooms({ sections: 3 });
483
+ const { dispatcher, audit } = loadDispatcherWithMocks({});
484
+ const t0 = Date.now();
485
+ const result = await dispatcher.dispatch({
486
+ section: null,
487
+ all: true,
488
+ crossRoom: false,
489
+ dryRun: false,
490
+ _rooms_root_override: roomsRoot,
491
+ });
492
+ const dt = Date.now() - t0;
493
+ assert.ok(dt < 15000, '3-section --all must complete in < 15s; took ' + dt + 'ms');
494
+ assert.equal(result.summary.sections_derived, 3);
495
+ });
496
+
497
+ // Test 12: Shape E format assertion.
498
+ await runAsync('Test 12: Shape E format contract -- counts + section list + action footer', async function () {
499
+ const { roomsRoot } = buildFixtureRooms({ sections: 2 });
500
+ const { dispatcher, audit } = loadDispatcherWithMocks({});
501
+ const result = await dispatcher.dispatch({
502
+ section: null,
503
+ all: true,
504
+ crossRoom: false,
505
+ dryRun: false,
506
+ _rooms_root_override: roomsRoot,
507
+ });
508
+ const rendered = dispatcher.renderShapeE(result.summary);
509
+ // Required labels per plan interface spec.
510
+ assert.ok(/BRAIN DERIVATION RESULTS/i.test(rendered), 'header');
511
+ assert.ok(/Sections derived/i.test(rendered), 'sections count row');
512
+ assert.ok(/Schema gates|schema/i.test(rendered), 'schema gates row');
513
+ assert.ok(/Cross-room|cross[- ]?room/i.test(rendered), 'cross-room row');
514
+ assert.ok(/Brain offline|offline/i.test(rendered), 'brain offline row');
515
+ assert.ok(/Cost tokens|cost/i.test(rendered), 'cost tokens row');
516
+ // PER SECTION block present and lists section names.
517
+ assert.ok(/PER SECTION|per section/i.test(rendered), 'per-section block header');
518
+ assert.ok(/market-analysis|problem-definition/.test(rendered), 'per-section lists known section');
519
+ // NEXT action footer present.
520
+ assert.ok(/NEXT|next/i.test(rendered), 'next/action footer block');
521
+ // ZERO em-dashes anywhere in rendered output (Canon hard rule).
522
+ assert.ok(rendered.indexOf('\u2014') === -1, 'Shape E must contain zero em-dashes');
523
+ assert.equal(result.summary.sections_derived, 2);
524
+ });
525
+
526
+ // ---------- Summary ----------
527
+ process.stdout.write('\n' + passed + '/' + (passed + failed) + ' passed\n');
528
+ if (failed > 0) process.exit(1);
529
+ }
530
+
531
+ main().catch(function (err) {
532
+ process.stderr.write('UNCAUGHT: ' + (err && err.stack ? err.stack : err) + '\n');
533
+ process.exit(1);
534
+ });