@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,259 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * MindrianOS Plugin -- Phase 87-07 (CASCADE-06) test suite.
4
+ * =========================================================
5
+ * Proves:
6
+ * 1. LRU capacity enforcement: insert cap+1 -> oldest evicted
7
+ * 2. LRU promotion: get(key) promotes to MRU, eviction skips the promoted key
8
+ * 3. LRU update: set() on existing key refreshes recency without growing size
9
+ * 4. LRU Map-parity iteration: entries, keys, values, forEach, clear,
10
+ * [Symbol.iterator] all work with the same semantics as Map.
11
+ * 5. Brain sessionCache key hashing is sha256 truncated to 16 hex chars
12
+ * (R-87-07-RACE: replaces djb2 collision risk).
13
+ * 6. SESSION_TTL_MS constant is exported (5 minutes, defensive check).
14
+ * 7. Concurrent-init race guard (R-87-07-RACE): two Promise.all()
15
+ * _ensureSession() calls with the same api_key share ONE in-flight
16
+ * init (pending-promise pattern).
17
+ * 8. intelligence-cascade.cjs loads without throwing after the Map->LRU
18
+ * swap (load-time smoke: catches missing-method errors).
19
+ *
20
+ * License: BSL 1.1 (Business Source License 1.1) -- see LICENSE.
21
+ */
22
+
23
+ 'use strict';
24
+
25
+ const assert = require('node:assert/strict');
26
+ const crypto = require('node:crypto');
27
+ const { LRU } = require('../core/lru-cache.cjs');
28
+
29
+ function testLruCapacity() {
30
+ const c = new LRU(100);
31
+ for (let i = 0; i < 101; i++) c.set('k' + i, i);
32
+ assert.strictEqual(c.size, 100, 'size must cap at capacity');
33
+ assert.strictEqual(c.has('k0'), false, 'oldest must be evicted');
34
+ assert.strictEqual(c.has('k100'), true, 'newest must be present');
35
+ }
36
+
37
+ function testLruPromotion() {
38
+ const c = new LRU(2);
39
+ c.set('a', 1);
40
+ c.set('b', 2);
41
+ c.get('a'); // promote 'a' to MRU; now 'b' is the LRU
42
+ c.set('c', 3); // should evict 'b', not 'a'
43
+ assert.strictEqual(c.has('a'), true, '`a` stays after promotion');
44
+ assert.strictEqual(c.has('b'), false, '`b` is evicted (was LRU)');
45
+ assert.strictEqual(c.has('c'), true, '`c` is present');
46
+ }
47
+
48
+ function testLruUpdate() {
49
+ const c = new LRU(2);
50
+ c.set('a', 1);
51
+ c.set('b', 2);
52
+ c.set('a', 99); // update existing; size stays 2
53
+ assert.strictEqual(c.get('a'), 99, 'updated value returned');
54
+ assert.strictEqual(c.size, 2, 'update does not grow size');
55
+ }
56
+
57
+ function testLruIterationParity() {
58
+ const c = new LRU(3);
59
+ c.set('a', 1);
60
+ c.set('b', 2);
61
+ c.set('c', 3);
62
+
63
+ // for..of via [Symbol.iterator]
64
+ let count = 0;
65
+ for (const [k, v] of c) {
66
+ count++;
67
+ assert.ok(k && typeof v === 'number', 'iter yields [k, v]');
68
+ }
69
+ assert.strictEqual(count, 3, 'for..of must yield 3 entries');
70
+
71
+ // entries()
72
+ const entries = Array.from(c.entries());
73
+ assert.strictEqual(entries.length, 3, 'entries() yields 3');
74
+ assert.strictEqual(entries[0].length, 2, 'entries() yields [k, v] pairs');
75
+
76
+ // keys() / values() -- LRU walks MRU -> LRU, so sort for stable comparison
77
+ assert.deepStrictEqual(
78
+ Array.from(c.keys()).sort(),
79
+ ['a', 'b', 'c'],
80
+ 'keys() yields all keys'
81
+ );
82
+ assert.deepStrictEqual(
83
+ Array.from(c.values()).sort((x, y) => x - y),
84
+ [1, 2, 3],
85
+ 'values() yields all values'
86
+ );
87
+
88
+ // forEach(callback, thisArg) -- callback(value, key, cache) per Map API
89
+ let cbCount = 0;
90
+ let thisArgSeen = null;
91
+ const expectedThis = { marker: 'forEach-thisArg' };
92
+ c.forEach(function (v, k, cache) {
93
+ cbCount++;
94
+ thisArgSeen = this;
95
+ assert.ok(typeof v === 'number', 'forEach(value, ...) is the value');
96
+ assert.ok(typeof k === 'string', 'forEach(..., key, ...) is the key');
97
+ assert.strictEqual(cache, c, 'forEach(..., ..., cache) is the LRU itself');
98
+ }, expectedThis);
99
+ assert.strictEqual(cbCount, 3, 'forEach invokes callback 3 times');
100
+ assert.strictEqual(thisArgSeen, expectedThis, 'forEach honours thisArg');
101
+
102
+ // forEach with non-function callback must throw TypeError
103
+ assert.throws(() => c.forEach('not-a-function'), TypeError, 'forEach typechecks callback');
104
+
105
+ // clear() resets size + lookups + iteration
106
+ c.clear();
107
+ assert.strictEqual(c.size, 0, 'clear() drops size to 0');
108
+ assert.strictEqual(c.has('a'), false, 'clear() drops entries');
109
+ assert.strictEqual(Array.from(c.entries()).length, 0, 'clear() empties iteration');
110
+ }
111
+
112
+ function testSessionCacheKeyHashing() {
113
+ const { _test } = require('../core/brain-client.cjs');
114
+ assert.ok(_test.sessionCache instanceof Map, 'sessionCache exported as Map');
115
+ assert.ok(typeof _test._hashKey === 'function', '_hashKey exported');
116
+ assert.strictEqual(_test._hashKey('abc'), _test._hashKey('abc'), '_hashKey deterministic');
117
+ assert.notStrictEqual(_test._hashKey('a'), _test._hashKey('b'), 'different inputs -> different hashes');
118
+
119
+ // R-87-07-RACE: hash must be sha256 truncated to 16 lowercase hex chars.
120
+ const expected = crypto.createHash('sha256').update('sk-test').digest('hex').slice(0, 16);
121
+ assert.strictEqual(_test._hashKey('sk-test'), expected, 'hash is sha256 truncated to 16 hex chars');
122
+ assert.strictEqual(_test._hashKey('sk-test').length, 16, 'hash length is 16');
123
+ assert.match(_test._hashKey('sk-test'), /^[a-f0-9]{16}$/, 'hash is lowercase hex');
124
+ }
125
+
126
+ function testSessionCacheTTLConstant() {
127
+ const { _test } = require('../core/brain-client.cjs');
128
+ assert.strictEqual(_test.SESSION_TTL_MS, 5 * 60 * 1000, 'SESSION_TTL_MS is 5 minutes');
129
+ }
130
+
131
+ async function testConcurrentInitRaceGuard() {
132
+ // R-87-07-RACE: two concurrent _ensureSession calls with the same api_key
133
+ // must share ONE in-flight init promise (pending-promise pattern). Without
134
+ // the fix, both see a cache miss, both init, and initCallCount === 2.
135
+ const { _test } = require('../core/brain-client.cjs');
136
+ _test.sessionCache.clear();
137
+
138
+ // We deliberately do NOT hit the real Brain endpoint. The race semantics
139
+ // live in the cache.get/set ordering + promise sharing, which is observable
140
+ // by directly manipulating the cache with a fake init promise that counts
141
+ // invocations and simulates ~50ms of network latency.
142
+ let initCallCount = 0;
143
+ async function fakeEnsureSession(apiKey) {
144
+ const keyHash = _test._hashKey(apiKey);
145
+ const cached = _test.sessionCache.get(keyHash);
146
+ if (cached && cached.expiresAt > Date.now()) return cached.promise;
147
+ const promise = (async () => {
148
+ initCallCount++;
149
+ await new Promise((r) => setTimeout(r, 50)); // simulate network init
150
+ return 'fake-session-' + initCallCount;
151
+ })();
152
+ _test.sessionCache.set(keyHash, {
153
+ promise,
154
+ expiresAt: Date.now() + _test.SESSION_TTL_MS,
155
+ });
156
+ promise.catch(() => _test.sessionCache.delete(keyHash));
157
+ return promise;
158
+ }
159
+
160
+ try {
161
+ // Fire 10 concurrent calls with the same key; all must share the first
162
+ // in-flight promise. This is the stronger-than-2 variant from the plan's
163
+ // success criteria ("10 concurrent callTool() calls on the same cacheKey
164
+ // -> Brain client's createSession method is called exactly once").
165
+ const results = await Promise.all(
166
+ Array.from({ length: 10 }, () => fakeEnsureSession('sk-race-test'))
167
+ );
168
+ assert.strictEqual(
169
+ initCallCount,
170
+ 1,
171
+ `init must fire EXACTLY once (saw ${initCallCount}) -- pending-promise race guard failed`
172
+ );
173
+ for (const r of results) {
174
+ assert.strictEqual(r, results[0], 'all 10 callers receive the same session');
175
+ }
176
+ } finally {
177
+ _test.sessionCache.clear();
178
+ }
179
+ }
180
+
181
+ async function testSessionCacheExpiry() {
182
+ // After TTL elapses, the next _ensureSession call must rebuild the entry.
183
+ // We do this by setting a 0-ms TTL entry manually, waiting a tick, and
184
+ // asserting that our fake init fires once.
185
+ const { _test } = require('../core/brain-client.cjs');
186
+ _test.sessionCache.clear();
187
+
188
+ let initCallCount = 0;
189
+ async function fakeEnsureSession(apiKey) {
190
+ const keyHash = _test._hashKey(apiKey);
191
+ const cached = _test.sessionCache.get(keyHash);
192
+ if (cached && cached.expiresAt > Date.now()) return cached.promise;
193
+ const promise = (async () => {
194
+ initCallCount++;
195
+ return 'session-' + initCallCount;
196
+ })();
197
+ _test.sessionCache.set(keyHash, {
198
+ promise,
199
+ expiresAt: Date.now() + _test.SESSION_TTL_MS,
200
+ });
201
+ promise.catch(() => _test.sessionCache.delete(keyHash));
202
+ return promise;
203
+ }
204
+
205
+ try {
206
+ // First call: cache miss, init fires.
207
+ const s1 = await fakeEnsureSession('sk-ttl-test');
208
+ assert.strictEqual(initCallCount, 1, 'first call inits');
209
+
210
+ // Force expiry by rewriting the entry's expiresAt to the past.
211
+ const keyHash = _test._hashKey('sk-ttl-test');
212
+ const entry = _test.sessionCache.get(keyHash);
213
+ entry.expiresAt = Date.now() - 1;
214
+
215
+ // Second call: cache "hit" but expired -> should re-init.
216
+ const s2 = await fakeEnsureSession('sk-ttl-test');
217
+ assert.strictEqual(initCallCount, 2, 'after TTL expiry, next call re-inits');
218
+ assert.notStrictEqual(s1, s2, 'expired session is not reused');
219
+ } finally {
220
+ _test.sessionCache.clear();
221
+ }
222
+ }
223
+
224
+ function testIntelligenceCascadeLoadTime() {
225
+ // Load-time smoke test: catches any missing-method errors from Map->LRU swap.
226
+ // If a call site relied on a Map method the LRU does not expose, requiring
227
+ // the module at top level (where the three LRU instances are constructed
228
+ // and some initialization might run) throws immediately.
229
+ assert.doesNotThrow(
230
+ () => require('../core/intelligence-cascade.cjs'),
231
+ 'intelligence-cascade.cjs must load without throwing after Map->LRU swap'
232
+ );
233
+ }
234
+
235
+ async function run() {
236
+ try {
237
+ testLruCapacity();
238
+ testLruPromotion();
239
+ testLruUpdate();
240
+ testLruIterationParity();
241
+ testSessionCacheKeyHashing();
242
+ testSessionCacheTTLConstant();
243
+ await testConcurrentInitRaceGuard();
244
+ await testSessionCacheExpiry();
245
+ testIntelligenceCascadeLoadTime();
246
+ process.stdout.write(
247
+ 'brain-cache-lru: all tests passed '
248
+ + '(LRU capacity + promotion + update + iteration-parity + '
249
+ + 'sha256 hashing + SESSION_TTL_MS + concurrent-race (10 callers) + '
250
+ + 'TTL expiry + load-time smoke)\n'
251
+ );
252
+ process.exit(0);
253
+ } catch (e) {
254
+ process.stderr.write(String(e && e.stack || e) + '\n');
255
+ process.exit(1);
256
+ }
257
+ }
258
+
259
+ run();
@@ -0,0 +1,160 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /*
5
+ * Copyright (c) 2026 Mindrian. BSL 1.1.
6
+ *
7
+ * Regression test for brainClient.query (graph-on-graph P0 cont., 2026-05-11).
8
+ * =============================================================================
9
+ * Proves two contracts that the rest of the codebase depends on:
10
+ *
11
+ * 1. PARAMS FORWARDING (introduced in b43aff9, kept here):
12
+ * - query(cypher, { x: 1 }) -> brain_query arguments are { cypher, params: { x: 1 } }
13
+ * - query(cypher) -> brain_query arguments are { cypher } (NO params key)
14
+ * - query(cypher, {}) -> brain_query arguments are { cypher } (empty object is NOT forwarded)
15
+ *
16
+ * 2. RESULT-SHAPE NORMALIZATION (this fix):
17
+ * The Brain MCP brain_query tool serializes a BARE ARRAY of rows. callTool
18
+ * returns that array directly. Every consumer reads result.records, so query
19
+ * now wraps it: a successful brain_query ALWAYS resolves to { records: [...] }.
20
+ *
21
+ * Self-contained: no live Brain, no live Aura. We set MINDRIAN_BRAIN_KEY BEFORE
22
+ * requiring brain-client.cjs, then monkey-patch global.fetch to a stub that
23
+ * fakes the `initialize` handshake and the `tools/call` brain_query response
24
+ * (SSE `data: {...}` line, the same wire shape callTool parses). global.fetch
25
+ * is restored in a finally.
26
+ *
27
+ * Pure CJS, zero npm deps, node built-ins only (assert).
28
+ */
29
+
30
+ const assert = require('node:assert/strict');
31
+
32
+ // MUST be set before requiring brain-client.cjs -- getApiKey() reads it.
33
+ process.env.MINDRIAN_BRAIN_KEY = 'test-key-260511-2ik';
34
+
35
+ const brain = require('../core/brain-client.cjs');
36
+
37
+ let passed = 0;
38
+ let failed = 0;
39
+ const failures = [];
40
+
41
+ // Module-local capture of the brain_query arguments seen by the fetch stub.
42
+ let lastArgs = null;
43
+
44
+ // Build an SSE-style response body the way the Brain Streamable HTTP transport
45
+ // returns it: a single `data: {...json...}\n` line. callTool splits on \n and
46
+ // finds the line that startsWith('data: ').
47
+ function sseBody(jsonRpcResult) {
48
+ return 'data: ' + JSON.stringify(jsonRpcResult) + '\n';
49
+ }
50
+
51
+ // The fake row payload the brain_query tool would serialize (a BARE ARRAY).
52
+ const FAKE_ROWS = [{ name: 'X', id: 'x1' }];
53
+
54
+ function makeFetchStub() {
55
+ return async function fetchStub(url, init) {
56
+ const body = JSON.parse(init.body);
57
+ if (body.method === 'initialize') {
58
+ // _ensureSession only checks initRes.ok / initRes.status.
59
+ return {
60
+ ok: true,
61
+ status: 200,
62
+ text: async () => sseBody({
63
+ jsonrpc: '2.0',
64
+ id: 1,
65
+ result: {
66
+ protocolVersion: '2024-11-05',
67
+ capabilities: {},
68
+ serverInfo: { name: 'brain', version: '1' },
69
+ },
70
+ }),
71
+ };
72
+ }
73
+ if (body.method === 'tools/call' && body.params && body.params.name === 'brain_query') {
74
+ // Capture the arguments object so the test can assert params forwarding.
75
+ lastArgs = body.params.arguments;
76
+ return {
77
+ ok: true,
78
+ status: 200,
79
+ text: async () => sseBody({
80
+ jsonrpc: '2.0',
81
+ id: 2,
82
+ result: {
83
+ content: [{ type: 'text', text: JSON.stringify(FAKE_ROWS) }],
84
+ },
85
+ }),
86
+ };
87
+ }
88
+ // Any other call (defensive) -> not-ok so the client returns null.
89
+ return { ok: false, status: 500, text: async () => '' };
90
+ };
91
+ }
92
+
93
+ async function runAssertions() {
94
+ // (1) params forwarded as { cypher, params } when params is a non-empty object.
95
+ lastArgs = null;
96
+ const r1 = await brain.query('MATCH (f) RETURN f', { x: 1 });
97
+ assert.deepStrictEqual(
98
+ lastArgs,
99
+ { cypher: 'MATCH (f) RETURN f', params: { x: 1 } },
100
+ 'non-empty params must be forwarded as { cypher, params }'
101
+ );
102
+ assert.deepStrictEqual(
103
+ r1,
104
+ { records: [{ name: 'X', id: 'x1' }] },
105
+ 'successful brain_query result must be normalized to { records: [...] }'
106
+ );
107
+
108
+ // (2) no params arg -> only { cypher } is sent (no params key at all).
109
+ lastArgs = null;
110
+ const r2 = await brain.query('MATCH (f) RETURN f');
111
+ assert.deepStrictEqual(
112
+ lastArgs,
113
+ { cypher: 'MATCH (f) RETURN f' },
114
+ 'a param-less call must send only { cypher }, no params key'
115
+ );
116
+ assert.deepStrictEqual(
117
+ r2,
118
+ { records: [{ name: 'X', id: 'x1' }] },
119
+ 'param-less call result must also be normalized to { records: [...] }'
120
+ );
121
+
122
+ // (3) empty object params -> NOT forwarded (no params key).
123
+ lastArgs = null;
124
+ const r3 = await brain.query('MATCH (f) RETURN f', {});
125
+ assert.deepStrictEqual(
126
+ lastArgs,
127
+ { cypher: 'MATCH (f) RETURN f' },
128
+ 'an empty params object must NOT be forwarded'
129
+ );
130
+ assert.deepStrictEqual(
131
+ r3,
132
+ { records: [{ name: 'X', id: 'x1' }] },
133
+ 'empty-params call result must also be normalized to { records: [...] }'
134
+ );
135
+ }
136
+
137
+ (async function main() {
138
+ const realFetch = global.fetch;
139
+ global.fetch = makeFetchStub();
140
+ // Clear any cached Brain session so our init stub is exercised cleanly.
141
+ try { brain._test.sessionCache.clear(); } catch (_e) { /* ignore */ }
142
+ try {
143
+ await runAssertions();
144
+ passed = 3;
145
+ } catch (err) {
146
+ failed = 1;
147
+ failures.push(err && err.message ? err.message : String(err));
148
+ } finally {
149
+ global.fetch = realFetch;
150
+ try { brain._test.sessionCache.clear(); } catch (_e) { /* ignore */ }
151
+ }
152
+
153
+ if (failed > 0) {
154
+ process.stderr.write('brain-client-query-shape: FAIL\n');
155
+ for (const f of failures) process.stderr.write(' - ' + f + '\n');
156
+ process.exit(1);
157
+ }
158
+ process.stdout.write('brain-client-query-shape: all assertions passed (params forwarding x3 + return normalization x3)\n');
159
+ process.exit(0);
160
+ })();