@mindrian_os/install 1.13.0-beta.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (597) hide show
  1. package/.claude-plugin/plugin.json +21 -0
  2. package/.mcp.json +9 -0
  3. package/CHANGELOG.md +3333 -0
  4. package/LICENSE +123 -0
  5. package/README.md +673 -0
  6. package/agents/brain-query.md +80 -0
  7. package/agents/framework-runner.md +237 -0
  8. package/agents/grading.md +188 -0
  9. package/agents/investor.md +128 -0
  10. package/agents/larry-extended.md +135 -0
  11. package/agents/opportunity-scanner.md +91 -0
  12. package/agents/persona-analyst.md +132 -0
  13. package/agents/research.md +89 -0
  14. package/agents/reverse-salient-agent.md +27 -0
  15. package/bin/cli.js +142 -0
  16. package/bin/mindrian-mcp-server.cjs +182 -0
  17. package/bin/mindrian-tools.cjs +765 -0
  18. package/commands/act.md +439 -0
  19. package/commands/admin.md +404 -0
  20. package/commands/analyze-needs.md +42 -0
  21. package/commands/analyze-systems.md +39 -0
  22. package/commands/analyze-timing.md +42 -0
  23. package/commands/auto-explore.md +64 -0
  24. package/commands/beautiful-question.md +40 -0
  25. package/commands/brain-derive.md +78 -0
  26. package/commands/build-knowledge.md +42 -0
  27. package/commands/build-thesis.md +46 -0
  28. package/commands/causal.md +234 -0
  29. package/commands/challenge-assumptions.md +33 -0
  30. package/commands/compare-ventures.md +83 -0
  31. package/commands/dashboard.md +110 -0
  32. package/commands/deep-grade.md +82 -0
  33. package/commands/diagnose.md +58 -0
  34. package/commands/diagnostics.md +151 -0
  35. package/commands/doctor.md +151 -0
  36. package/commands/dominant-designs.md +40 -0
  37. package/commands/explain-decision.md +87 -0
  38. package/commands/explore-domains.md +42 -0
  39. package/commands/explore-futures.md +40 -0
  40. package/commands/explore-trends.md +42 -0
  41. package/commands/export.md +103 -0
  42. package/commands/file-meeting.md +724 -0
  43. package/commands/find-analogies.md +188 -0
  44. package/commands/find-bottlenecks.md +62 -0
  45. package/commands/find-connections.md +76 -0
  46. package/commands/funding.md +81 -0
  47. package/commands/grade.md +203 -0
  48. package/commands/graph.md +128 -0
  49. package/commands/hat-briefing.md +125 -0
  50. package/commands/heal.md +196 -0
  51. package/commands/help.md +399 -0
  52. package/commands/hmi-status.md +172 -0
  53. package/commands/jtbd.md +241 -0
  54. package/commands/leadership.md +73 -0
  55. package/commands/lean-canvas.md +40 -0
  56. package/commands/macro-trends.md +40 -0
  57. package/commands/map-unknowns.md +40 -0
  58. package/commands/memory.md +173 -0
  59. package/commands/models.md +175 -0
  60. package/commands/mos-reason.md +285 -0
  61. package/commands/mullins.md +120 -0
  62. package/commands/new-project.md +481 -0
  63. package/commands/onboard.md +434 -0
  64. package/commands/operator.md +149 -0
  65. package/commands/opportunities.md +144 -0
  66. package/commands/organize.md +497 -0
  67. package/commands/persona.md +198 -0
  68. package/commands/pipeline.md +112 -0
  69. package/commands/present.md +91 -0
  70. package/commands/publish.md +201 -0
  71. package/commands/query.md +124 -0
  72. package/commands/radar.md +72 -0
  73. package/commands/reanalyze.md +91 -0
  74. package/commands/research.md +196 -0
  75. package/commands/room.md +352 -0
  76. package/commands/rooms.md +598 -0
  77. package/commands/root-cause.md +40 -0
  78. package/commands/rs-experts.md +85 -0
  79. package/commands/rs-explain.md +100 -0
  80. package/commands/rs-fetch.md +94 -0
  81. package/commands/rs-thesis.md +85 -0
  82. package/commands/scenario-plan.md +40 -0
  83. package/commands/scheduled-tasks.md +285 -0
  84. package/commands/score-innovation.md +43 -0
  85. package/commands/scout.md +239 -0
  86. package/commands/setup.md +618 -0
  87. package/commands/snapshot.md +147 -0
  88. package/commands/speakers.md +84 -0
  89. package/commands/splash.md +28 -0
  90. package/commands/status.md +75 -0
  91. package/commands/structure-argument.md +42 -0
  92. package/commands/suggest-next.md +80 -0
  93. package/commands/systems-thinking.md +40 -0
  94. package/commands/think-hats.md +42 -0
  95. package/commands/update.md +181 -0
  96. package/commands/user-needs.md +40 -0
  97. package/commands/validate.md +40 -0
  98. package/commands/value-proposition.md +61 -0
  99. package/commands/vault.md +180 -0
  100. package/commands/visualize.md +52 -0
  101. package/commands/whitespace.md +507 -0
  102. package/commands/wiki.md +69 -0
  103. package/hooks/hooks.json +381 -0
  104. package/hooks/run-hook.cmd +64 -0
  105. package/lib/__init__.py +0 -0
  106. package/lib/__pycache__/__init__.cpython-312.pyc +0 -0
  107. package/lib/agents/auto-explore-agent.cjs +1043 -0
  108. package/lib/agents/reverse-salient-agent.cjs +679 -0
  109. package/lib/agents/tension-hook-agent.cjs +544 -0
  110. package/lib/brain/ROOM.md +44 -0
  111. package/lib/brain/chain-recommender.cjs +301 -0
  112. package/lib/chat/chat-context.js +185 -0
  113. package/lib/chat/chat-panel.js +721 -0
  114. package/lib/chat/fabric-chat.cjs +288 -0
  115. package/lib/chat/generative-tools.js +219 -0
  116. package/lib/conversation/ROOM.md +39 -0
  117. package/lib/conversation/classifier-rules.json +38 -0
  118. package/lib/conversation/classifier.cjs +264 -0
  119. package/lib/conversation/operator.cjs +287 -0
  120. package/lib/copy/115-spec-strings.cjs +55 -0
  121. package/lib/core/__init__.py +0 -0
  122. package/lib/core/__nav-stub.cjs +14 -0
  123. package/lib/core/__pycache__/__init__.cpython-312.pyc +0 -0
  124. package/lib/core/__pycache__/rs-math.cpython-312.pyc +0 -0
  125. package/lib/core/__pycache__/rs_cache.cpython-312.pyc +0 -0
  126. package/lib/core/__pycache__/rs_corpus.cpython-312.pyc +0 -0
  127. package/lib/core/__pycache__/rs_hybrid.cpython-312.pyc +0 -0
  128. package/lib/core/__pycache__/rs_math.cpython-312.pyc +0 -0
  129. package/lib/core/__pycache__/rs_rooms.cpython-312.pyc +0 -0
  130. package/lib/core/artifact-id.cjs +148 -0
  131. package/lib/core/asset-ops.cjs +151 -0
  132. package/lib/core/auto-commit-throttle.cjs +129 -0
  133. package/lib/core/bearer-token.cjs +199 -0
  134. package/lib/core/brain-client.cjs +865 -0
  135. package/lib/core/brain-derivation-prompts.cjs +326 -0
  136. package/lib/core/brain-derivation-queue.cjs +431 -0
  137. package/lib/core/brain-derivation.cjs +580 -0
  138. package/lib/core/brain-md-schema.cjs +528 -0
  139. package/lib/core/brain-md-staleness.cjs +357 -0
  140. package/lib/core/brain-response-sanitize.cjs +188 -0
  141. package/lib/core/bridge-writer.cjs +477 -0
  142. package/lib/core/chat-context-builder.cjs +253 -0
  143. package/lib/core/cross-room-aggregator.cjs +762 -0
  144. package/lib/core/daily-briefing.cjs +438 -0
  145. package/lib/core/decision-capture.cjs +618 -0
  146. package/lib/core/deep-links.cjs +82 -0
  147. package/lib/core/dispatch-optimizer.cjs +354 -0
  148. package/lib/core/dual-path-detector.cjs +84 -0
  149. package/lib/core/dual-path-detector.test.cjs +334 -0
  150. package/lib/core/exports-log.cjs +79 -0
  151. package/lib/core/feynman-minto-invariants.cjs +605 -0
  152. package/lib/core/folder-memory-async.cjs +338 -0
  153. package/lib/core/folder-memory-shared.cjs +890 -0
  154. package/lib/core/folder-memory.cjs +416 -0
  155. package/lib/core/framework-chain-composer.cjs +411 -0
  156. package/lib/core/frontmatter-schemas.cjs +330 -0
  157. package/lib/core/git-ops.cjs +141 -0
  158. package/lib/core/graph-ops.cjs +258 -0
  159. package/lib/core/hat-persistence.cjs +362 -0
  160. package/lib/core/index.cjs +60 -0
  161. package/lib/core/integration-registry.cjs +232 -0
  162. package/lib/core/intelligence-cascade.cjs +661 -0
  163. package/lib/core/lazygraph-ops.cjs +1057 -0
  164. package/lib/core/lru-cache.cjs +139 -0
  165. package/lib/core/mcp-profiles.cjs +182 -0
  166. package/lib/core/meeting-ops.cjs +54 -0
  167. package/lib/core/memory-ops.cjs +600 -0
  168. package/lib/core/migrations/ROOM.md +33 -0
  169. package/lib/core/migrations/phase-109-nodes-provenance.cjs +339 -0
  170. package/lib/core/migrations/phase-109-session-focus.cjs +99 -0
  171. package/lib/core/model-profiles.cjs +246 -0
  172. package/lib/core/mullins-scaffold.cjs +160 -0
  173. package/lib/core/nav-dial.cjs +316 -0
  174. package/lib/core/navigation/ROOM.md +15 -0
  175. package/lib/core/navigation/explanation.cjs +43 -0
  176. package/lib/core/navigation/focus.cjs +135 -0
  177. package/lib/core/navigation/ingestion.cjs +82 -0
  178. package/lib/core/navigation/insights.cjs +350 -0
  179. package/lib/core/navigation/memory-events.cjs +118 -0
  180. package/lib/core/navigation/neighborhood.cjs +78 -0
  181. package/lib/core/navigation/packet.cjs +182 -0
  182. package/lib/core/navigation/room-home.cjs +127 -0
  183. package/lib/core/navigation/transitions.cjs +82 -0
  184. package/lib/core/navigation-engine-shared.cjs +242 -0
  185. package/lib/core/navigation-engine.cjs +664 -0
  186. package/lib/core/navigation.cjs +60 -0
  187. package/lib/core/nl-graph-queries.cjs +164 -0
  188. package/lib/core/offer-presenter.cjs +406 -0
  189. package/lib/core/opportunity-extractor.cjs +183 -0
  190. package/lib/core/opportunity-ops.cjs +1371 -0
  191. package/lib/core/persona-ops.cjs +537 -0
  192. package/lib/core/persona-taxonomy.cjs +190 -0
  193. package/lib/core/platform-gates.cjs +120 -0
  194. package/lib/core/platform.cjs +257 -0
  195. package/lib/core/proactive-intelligence.cjs +528 -0
  196. package/lib/core/problem-type-router.cjs +315 -0
  197. package/lib/core/reasoning-ops.cjs +639 -0
  198. package/lib/core/reverse-salient-persona-suffix.cjs +115 -0
  199. package/lib/core/room-classifier-strict-mode.cjs +229 -0
  200. package/lib/core/room-db.cjs +127 -0
  201. package/lib/core/room-ops-async.cjs +92 -0
  202. package/lib/core/room-ops-shared.cjs +64 -0
  203. package/lib/core/room-ops-sync.cjs +70 -0
  204. package/lib/core/room-ops.cjs +32 -0
  205. package/lib/core/room-type-detector.cjs +386 -0
  206. package/lib/core/rs-brain-substrate-prompts.cjs +129 -0
  207. package/lib/core/rs-brain-substrate.cjs +570 -0
  208. package/lib/core/rs-breakthrough-scorer.cjs +255 -0
  209. package/lib/core/rs-canon-violations.cjs +82 -0
  210. package/lib/core/rs-chain-feeder.cjs +343 -0
  211. package/lib/core/rs-commercial-assessor.cjs +280 -0
  212. package/lib/core/rs-differential-scorer.cjs +376 -0
  213. package/lib/core/rs-domain-analyzer.cjs +385 -0
  214. package/lib/core/rs-egress-prompts.cjs +113 -0
  215. package/lib/core/rs-egress-telemetry.cjs +225 -0
  216. package/lib/core/rs-egress-violations.cjs +53 -0
  217. package/lib/core/rs-expert-mapper.cjs +467 -0
  218. package/lib/core/rs-fetcher-academic.cjs +697 -0
  219. package/lib/core/rs-fetcher-experts.cjs +314 -0
  220. package/lib/core/rs-fetcher-industry.cjs +731 -0
  221. package/lib/core/rs-fetcher-patents.cjs +564 -0
  222. package/lib/core/rs-innovation-classifier.cjs +194 -0
  223. package/lib/core/rs-mind-map.cjs +656 -0
  224. package/lib/core/rs-neo4j-writer.cjs +388 -0
  225. package/lib/core/rs-nl-to-query.cjs +425 -0
  226. package/lib/core/rs-pinecone-bridge.cjs +303 -0
  227. package/lib/core/rs-preprocessor.cjs +350 -0
  228. package/lib/core/rs-query-matrix.cjs +316 -0
  229. package/lib/core/rs-query-to-text.cjs +438 -0
  230. package/lib/core/rs-sqlite-mirror.cjs +443 -0
  231. package/lib/core/rs-thesis-generator.cjs +188 -0
  232. package/lib/core/rs_cache.py +479 -0
  233. package/lib/core/rs_corpus.py +468 -0
  234. package/lib/core/rs_hybrid.py +586 -0
  235. package/lib/core/rs_math.py +287 -0
  236. package/lib/core/rs_rooms.py +193 -0
  237. package/lib/core/scheduled-scanner.cjs +463 -0
  238. package/lib/core/scratchpad-ops.cjs +201 -0
  239. package/lib/core/section-8-trace-schema.cjs +138 -0
  240. package/lib/core/section-registry.cjs +111 -0
  241. package/lib/core/session-state.cjs +144 -0
  242. package/lib/core/shallow-doc-parser.cjs +174 -0
  243. package/lib/core/shallow-doc-parser.test.cjs +226 -0
  244. package/lib/core/skill-activation-router.cjs +284 -0
  245. package/lib/core/state-ops.cjs +46 -0
  246. package/lib/core/statusline-cache.cjs +266 -0
  247. package/lib/core/token-estimator.cjs +348 -0
  248. package/lib/core/user-archetype.cjs +239 -0
  249. package/lib/core/user-md-ops.cjs +524 -0
  250. package/lib/core/visual-ops.cjs +624 -0
  251. package/lib/core/write-lock.cjs +149 -0
  252. package/lib/graph/canvas-graph.js +467 -0
  253. package/lib/graph/constellation-config.cjs +299 -0
  254. package/lib/graph/graph-detail-panel.js +165 -0
  255. package/lib/hmi/ROOM.md +47 -0
  256. package/lib/hmi/across-session-memory.cjs +604 -0
  257. package/lib/hmi/cross-room-memory.cjs +575 -0
  258. package/lib/hmi/decoy-tier.cjs +395 -0
  259. package/lib/hmi/jtbd-classifier.cjs +219 -0
  260. package/lib/hmi/jtbd-state.cjs +199 -0
  261. package/lib/hmi/jtbd-taxonomy.json +392 -0
  262. package/lib/hmi/selector-dispatcher.cjs +546 -0
  263. package/lib/hmi/selector-telemetry.cjs +263 -0
  264. package/lib/hmi/shape-f0-renderer.cjs +139 -0
  265. package/lib/hmi/shape-f1-fallback.cjs +80 -0
  266. package/lib/hmi/shape-f1-renderer.cjs +138 -0
  267. package/lib/hmi/shape-f2-renderer.cjs +132 -0
  268. package/lib/hmi/shape-f3-renderer.cjs +66 -0
  269. package/lib/hmi/shape-f4-renderer.cjs +72 -0
  270. package/lib/hmi/shape-f5-renderer.cjs +155 -0
  271. package/lib/hmi/shape-f6-plan-review-renderer.cjs +312 -0
  272. package/lib/hmi/shape-f6-renderer.cjs +144 -0
  273. package/lib/hmi/shape-g-renderer.cjs +219 -0
  274. package/lib/hmi/shape-h-renderer.cjs +222 -0
  275. package/lib/hmi/tier-check.cjs +63 -0
  276. package/lib/import/PRECONDITIONS.md +41 -0
  277. package/lib/import/branding.cjs +210 -0
  278. package/lib/import/branding.test.cjs +235 -0
  279. package/lib/import/classifications-sync.cjs +104 -0
  280. package/lib/import/classifications-sync.test.cjs +129 -0
  281. package/lib/import/enricher.cjs +296 -0
  282. package/lib/import/enricher.test.cjs +273 -0
  283. package/lib/import/integration.test.cjs +376 -0
  284. package/lib/import/manifest.cjs +129 -0
  285. package/lib/import/manifest.schema.json +185 -0
  286. package/lib/import/manifest.test.cjs +123 -0
  287. package/lib/import/meeting-detector.cjs +92 -0
  288. package/lib/import/meeting-detector.test.cjs +100 -0
  289. package/lib/import/person-detector.cjs +229 -0
  290. package/lib/import/person-detector.test.cjs +149 -0
  291. package/lib/import/report.cjs +186 -0
  292. package/lib/import/report.test.cjs +186 -0
  293. package/lib/import/room-md-scaffolder.cjs +49 -0
  294. package/lib/import/router.cjs +224 -0
  295. package/lib/import/router.test.cjs +356 -0
  296. package/lib/import/run-all-tests.cjs +36 -0
  297. package/lib/import/smoke-test.cjs +213 -0
  298. package/lib/import/smoke-test.test.cjs +148 -0
  299. package/lib/import/test-fixtures/collision-vault/preexisting-room/STATE.md +8 -0
  300. package/lib/import/test-fixtures/collision-vault/preexisting-room/problem-definition/onboarding/onboarding.md +7 -0
  301. package/lib/import/test-fixtures/collision-vault/source/onboarding.md +5 -0
  302. package/lib/import/test-fixtures/obsidian-vault/.obsidian/workspace.json +1 -0
  303. package/lib/import/test-fixtures/obsidian-vault/notes/with-wikilinks.md +4 -0
  304. package/lib/import/test-fixtures/tiny-vault/notes/2026-01-15-team-sync.md +9 -0
  305. package/lib/import/test-fixtures/tiny-vault/notes/empty.md +3 -0
  306. package/lib/import/test-fixtures/tiny-vault/notes/onboarding.md +5 -0
  307. package/lib/import/test-fixtures/tiny-vault/notes/pricing.md +5 -0
  308. package/lib/import/test-fixtures/tiny-vault/notes/random.md +4 -0
  309. package/lib/import/undo.test.cjs +199 -0
  310. package/lib/import/vault-scanner.cjs +105 -0
  311. package/lib/import/vault-scanner.test.cjs +67 -0
  312. package/lib/mcp/app-html/dashboard.html +316 -0
  313. package/lib/mcp/app-html/graph.html +428 -0
  314. package/lib/mcp/app-html/mindrian-platform.html +1841 -0
  315. package/lib/mcp/app-html/wiki.html +383 -0
  316. package/lib/mcp/app-views.cjs +322 -0
  317. package/lib/mcp/brain-router.cjs +418 -0
  318. package/lib/mcp/capability-registry.cjs +62 -0
  319. package/lib/mcp/larry-context.cjs +46 -0
  320. package/lib/mcp/larry-server-instructions.md +114 -0
  321. package/lib/mcp/pipeline-state.cjs +275 -0
  322. package/lib/mcp/prompts.cjs +302 -0
  323. package/lib/mcp/resources.cjs +227 -0
  324. package/lib/mcp/session-catchup.cjs +327 -0
  325. package/lib/mcp/surface-detect.cjs +75 -0
  326. package/lib/mcp/tool-router.cjs +1034 -0
  327. package/lib/memory/aaak-compress.cjs +403 -0
  328. package/lib/memory/aaak-compress.test.cjs +288 -0
  329. package/lib/memory/async-artifact-auto-commit.test.cjs +223 -0
  330. package/lib/memory/bearer-token.test.cjs +315 -0
  331. package/lib/memory/brain-cache-lru.test.cjs +259 -0
  332. package/lib/memory/brain-client-query-shape.test.cjs +160 -0
  333. package/lib/memory/brain-derivation-graceful-degradation.test.cjs +1019 -0
  334. package/lib/memory/brain-derivation-queue.test.cjs +539 -0
  335. package/lib/memory/brain-derivation.test.cjs +634 -0
  336. package/lib/memory/brain-derive-command.test.cjs +534 -0
  337. package/lib/memory/brain-md-invariants-validator.test.cjs +704 -0
  338. package/lib/memory/brain-md-schema.test.cjs +467 -0
  339. package/lib/memory/brain-md-staleness.test.cjs +525 -0
  340. package/lib/memory/brain-server-resolution.test.cjs +314 -0
  341. package/lib/memory/chain-recommender.test.cjs +233 -0
  342. package/lib/memory/chat-context.test.cjs +128 -0
  343. package/lib/memory/command-registry.test.cjs +220 -0
  344. package/lib/memory/cross-room-aggregator.test.cjs +909 -0
  345. package/lib/memory/dashboard-server.test.cjs +256 -0
  346. package/lib/memory/debouncer-drain-at-prompt.test.cjs +389 -0
  347. package/lib/memory/decision-capture.test.cjs +632 -0
  348. package/lib/memory/decision-capture.worker.cjs +70 -0
  349. package/lib/memory/explain-decision-command.test.cjs +521 -0
  350. package/lib/memory/explain-decision-footer.test.cjs +316 -0
  351. package/lib/memory/explored-materials-store.cjs +392 -0
  352. package/lib/memory/feynman-minto-guardian.test.cjs +736 -0
  353. package/lib/memory/feynman-minto-invariants.test.cjs +511 -0
  354. package/lib/memory/feynman-prompts-drift.test.cjs +144 -0
  355. package/lib/memory/feynman-prompts.cjs +151 -0
  356. package/lib/memory/feynman-prompts.test.cjs +96 -0
  357. package/lib/memory/folder-memory-quadruple.test.cjs +548 -0
  358. package/lib/memory/folder-memory.test.cjs +503 -0
  359. package/lib/memory/framework-chain-composer.test.cjs +515 -0
  360. package/lib/memory/frontmatter-schema-validator.test.cjs +290 -0
  361. package/lib/memory/heal-command.test.cjs +604 -0
  362. package/lib/memory/index-artifact-transaction.test.cjs +333 -0
  363. package/lib/memory/lazygraph-rs-discoveries-view.test.cjs +122 -0
  364. package/lib/memory/mcp-input-validation.test.cjs +240 -0
  365. package/lib/memory/mcp-server-brain-deps.test.cjs +270 -0
  366. package/lib/memory/mcp-stack-fallback.test.cjs +433 -0
  367. package/lib/memory/minto-debouncer.test.cjs +407 -0
  368. package/lib/memory/minto-debouncer.worker.cjs +46 -0
  369. package/lib/memory/minto-migration-v88.test.cjs +265 -0
  370. package/lib/memory/minto-schema-v88.test.cjs +390 -0
  371. package/lib/memory/mos-status-renderer.test.cjs +631 -0
  372. package/lib/memory/narrative-schema.cjs +376 -0
  373. package/lib/memory/narrative-schema.test.cjs +209 -0
  374. package/lib/memory/nav-dial.test.cjs +414 -0
  375. package/lib/memory/navigation-engine-core.test.cjs +722 -0
  376. package/lib/memory/navigation-invariants.test.cjs +483 -0
  377. package/lib/memory/offer-presenter.test.cjs +554 -0
  378. package/lib/memory/on-stop-snapshot.test.cjs +404 -0
  379. package/lib/memory/pending-tension-store.cjs +373 -0
  380. package/lib/memory/post-compact-reinjection.test.cjs +854 -0
  381. package/lib/memory/post-write-triple.test.cjs +317 -0
  382. package/lib/memory/pre-compact-snapshot.test.cjs +495 -0
  383. package/lib/memory/problem-type-router.test.cjs +656 -0
  384. package/lib/memory/query-efficiency-telemetry.test.cjs +370 -0
  385. package/lib/memory/recompile-room-references.test.cjs +392 -0
  386. package/lib/memory/recompile-room-references.worker.cjs +42 -0
  387. package/lib/memory/record-decision-dual-write.test.cjs +454 -0
  388. package/lib/memory/room-classifier-strict-mode.test.cjs +417 -0
  389. package/lib/memory/room-minto-hook.test.cjs +398 -0
  390. package/lib/memory/rs-discovery-engine.test.cjs +323 -0
  391. package/lib/memory/run-feynman-tests.cjs +1247 -0
  392. package/lib/memory/security-trifecta.test.cjs +312 -0
  393. package/lib/memory/session-start-brain-staleness.test.cjs +363 -0
  394. package/lib/memory/session-start-triple-injection.test.cjs +514 -0
  395. package/lib/memory/sessionstart-banner-formatter.cjs +318 -0
  396. package/lib/memory/sessionstart-minto-banner.test.cjs +373 -0
  397. package/lib/memory/skill-activation-router.test.cjs +419 -0
  398. package/lib/memory/stamp-artifact-write.test.cjs +304 -0
  399. package/lib/memory/statusline-active-room.test.cjs +315 -0
  400. package/lib/memory/statusline-minto-segment.test.cjs +292 -0
  401. package/lib/memory/sync-async-entry-points.test.cjs +204 -0
  402. package/lib/memory/test-bridge-writer-enhanced.cjs +452 -0
  403. package/lib/memory/test-rs-brain-substrate-shape.cjs +529 -0
  404. package/lib/memory/test-rs-brain-substrate.cjs +636 -0
  405. package/lib/memory/test-rs-breakthrough-scorer.cjs +375 -0
  406. package/lib/memory/test-rs-canon-violations.cjs +218 -0
  407. package/lib/memory/test-rs-chain-feeder-core.cjs +344 -0
  408. package/lib/memory/test-rs-chain-feeder-skill-spawn.cjs +297 -0
  409. package/lib/memory/test-rs-commercial-assessor.cjs +385 -0
  410. package/lib/memory/test-rs-differential-scorer.cjs +480 -0
  411. package/lib/memory/test-rs-discovery-engine.cjs +603 -0
  412. package/lib/memory/test-rs-domain-analyzer.cjs +492 -0
  413. package/lib/memory/test-rs-egress-primitives.cjs +420 -0
  414. package/lib/memory/test-rs-expert-mapper.cjs +547 -0
  415. package/lib/memory/test-rs-explain-command.cjs +443 -0
  416. package/lib/memory/test-rs-fetcher-academic.cjs +848 -0
  417. package/lib/memory/test-rs-fetcher-experts.cjs +496 -0
  418. package/lib/memory/test-rs-fetcher-industry.cjs +702 -0
  419. package/lib/memory/test-rs-fetcher-patents.cjs +674 -0
  420. package/lib/memory/test-rs-innovation-classifier.cjs +301 -0
  421. package/lib/memory/test-rs-mind-map.cjs +646 -0
  422. package/lib/memory/test-rs-neo4j-writer.cjs +518 -0
  423. package/lib/memory/test-rs-nl-to-query.cjs +449 -0
  424. package/lib/memory/test-rs-pinecone-bridge.cjs +277 -0
  425. package/lib/memory/test-rs-preprocessor.cjs +433 -0
  426. package/lib/memory/test-rs-query-matrix.cjs +391 -0
  427. package/lib/memory/test-rs-query-to-text.cjs +551 -0
  428. package/lib/memory/test-rs-sqlite-mirror.cjs +649 -0
  429. package/lib/memory/test-rs-thesis-generator.cjs +360 -0
  430. package/lib/memory/triple-context-formatter.cjs +473 -0
  431. package/lib/memory/triple-context-formatter.test.cjs +442 -0
  432. package/lib/memory/user-md-persona.test.cjs +565 -0
  433. package/lib/memory/userpromptsubmit-integration.test.cjs +690 -0
  434. package/lib/memory/validators/README.md +157 -0
  435. package/lib/memory/validators/brain-md-invariants.cjs +475 -0
  436. package/lib/memory/validators/brain-substrate-invariants.cjs +285 -0
  437. package/lib/memory/validators/external-academic-invariants.cjs +249 -0
  438. package/lib/memory/validators/external-industry-invariants.cjs +271 -0
  439. package/lib/memory/validators/external-patents-invariants.cjs +266 -0
  440. package/lib/memory/validators/minto-invariants.cjs +62 -0
  441. package/lib/memory/validators/navigation-invariants.cjs +340 -0
  442. package/lib/memory/validators/queue-health.cjs +95 -0
  443. package/lib/memory/validators/snapshot-integrity.cjs +129 -0
  444. package/lib/memory/validators/stale-lifecycle.cjs +116 -0
  445. package/lib/memory/vault-section-minto-generator-atomic.test.cjs +556 -0
  446. package/lib/memory/vault-section-minto-generator-atomic.worker.cjs +73 -0
  447. package/lib/memory/write-lock-atomic.test.cjs +137 -0
  448. package/lib/memory/write-lock-atomic.worker.cjs +55 -0
  449. package/lib/parity/check-parity.cjs +83 -0
  450. package/lib/presentation/presentation-server.cjs +101 -0
  451. package/lib/presentation/presentation-watcher.cjs +123 -0
  452. package/lib/quickview/hub-server.cjs +719 -0
  453. package/lib/quickview/server.cjs +533 -0
  454. package/lib/render/JTBD-PALETTES.md +145 -0
  455. package/lib/render/ROOM.md +59 -0
  456. package/lib/render/render-v2.cjs +486 -0
  457. package/lib/render/render-v2.test.cjs +267 -0
  458. package/lib/render/render.cjs +65 -0
  459. package/lib/state/ROOM.md +46 -0
  460. package/lib/state/state-md-parser.cjs +215 -0
  461. package/lib/statusline/ROOM.md +38 -0
  462. package/lib/statusline/banner-suppression.cjs +50 -0
  463. package/lib/statusline/surface-detect.cjs +85 -0
  464. package/lib/update-bootstrap.sh.template +145 -0
  465. package/lib/vault/frontmatter-schema.cjs +297 -0
  466. package/lib/vault/room-scanner.cjs +352 -0
  467. package/lib/vault/wikilink-builder.cjs +231 -0
  468. package/lib/vault/wikilink-builder.test.cjs +182 -0
  469. package/lib/wiki/graph-links.cjs +281 -0
  470. package/lib/wiki/page-renderer.cjs +229 -0
  471. package/lib/wiki/wiki-chat.cjs +81 -0
  472. package/lib/wiki/wiki-layout.cjs +1459 -0
  473. package/lib/wiki/wiki-search.cjs +142 -0
  474. package/lib/wiki/wiki-server.cjs +678 -0
  475. package/lib/wiki/wiki-watcher.cjs +105 -0
  476. package/lib/workflow/ROOM.md +47 -0
  477. package/lib/workflow/command-resolver.cjs +155 -0
  478. package/lib/workflow/command-resolver.test.cjs +235 -0
  479. package/package.json +44 -0
  480. package/pipelines/analogy/01-decompose.md +80 -0
  481. package/pipelines/analogy/02-abstract.md +87 -0
  482. package/pipelines/analogy/03-search.md +135 -0
  483. package/pipelines/analogy/04-transfer.md +101 -0
  484. package/pipelines/analogy/05-validate.md +106 -0
  485. package/pipelines/analogy/CHAIN.md +56 -0
  486. package/pipelines/discovery/01-explore-domains.md +44 -0
  487. package/pipelines/discovery/02-think-hats.md +50 -0
  488. package/pipelines/discovery/03-analyze-needs.md +54 -0
  489. package/pipelines/discovery/CHAIN.md +37 -0
  490. package/pipelines/thesis/01-structure-argument.md +45 -0
  491. package/pipelines/thesis/02-challenge-assumptions.md +48 -0
  492. package/pipelines/thesis/03-build-thesis.md +54 -0
  493. package/pipelines/thesis/CHAIN.md +37 -0
  494. package/references/brain/causal-directives.md +91 -0
  495. package/references/brain/causal-enrichment.cypher +165 -0
  496. package/references/brain/command-triggers-schema.md +226 -0
  497. package/references/brain/graph-architecture.md +317 -0
  498. package/references/brain/query-patterns.md +460 -0
  499. package/references/brain/room-hierarchy-schema.md +218 -0
  500. package/references/brain/schema.md +76 -0
  501. package/references/capability-radar/capabilities-index.md +241 -0
  502. package/references/capability-radar/changelog-cache.md +81 -0
  503. package/references/causal/causal-schema.md +103 -0
  504. package/references/design/email-template-standard.md +155 -0
  505. package/references/design/graph-visualization-standard.md +178 -0
  506. package/references/document-generation.md +179 -0
  507. package/references/hsi/HSI-TOOLS-REFERENCE.md +222 -0
  508. package/references/import-config.md +141 -0
  509. package/references/integrations/detection-patterns.md +101 -0
  510. package/references/meeting/artifact-template.md +377 -0
  511. package/references/meeting/cross-meeting-intelligence.md +216 -0
  512. package/references/meeting/cross-relationship-patterns.md +202 -0
  513. package/references/meeting/live-join-interface.md +244 -0
  514. package/references/meeting/section-mapping.md +192 -0
  515. package/references/meeting/segment-classification.md +258 -0
  516. package/references/meeting/speaker-profile-template.md +219 -0
  517. package/references/meeting/summary-template.md +348 -0
  518. package/references/meeting/transcript-patterns.md +226 -0
  519. package/references/methodology/analyze-needs.md +135 -0
  520. package/references/methodology/analyze-systems.md +121 -0
  521. package/references/methodology/analyze-timing.md +149 -0
  522. package/references/methodology/beautiful-question.md +109 -0
  523. package/references/methodology/build-knowledge.md +161 -0
  524. package/references/methodology/build-thesis.md +237 -0
  525. package/references/methodology/challenge-assumptions.md +127 -0
  526. package/references/methodology/diagnose.md +169 -0
  527. package/references/methodology/dominant-designs.md +212 -0
  528. package/references/methodology/explore-domains.md +147 -0
  529. package/references/methodology/explore-futures.md +163 -0
  530. package/references/methodology/explore-trends.md +129 -0
  531. package/references/methodology/find-bottlenecks.md +131 -0
  532. package/references/methodology/grade.md +211 -0
  533. package/references/methodology/index.md +97 -0
  534. package/references/methodology/leadership.md +200 -0
  535. package/references/methodology/lean-canvas.md +116 -0
  536. package/references/methodology/macro-trends.md +192 -0
  537. package/references/methodology/map-unknowns.md +137 -0
  538. package/references/methodology/mullins-7-domains.md +104 -0
  539. package/references/methodology/problem-types.md +65 -0
  540. package/references/methodology/root-cause.md +178 -0
  541. package/references/methodology/sapphire-encoding.md +355 -0
  542. package/references/methodology/scenario-plan.md +178 -0
  543. package/references/methodology/score-innovation.md +154 -0
  544. package/references/methodology/structure-argument.md +158 -0
  545. package/references/methodology/systems-thinking.md +159 -0
  546. package/references/methodology/think-hats.md +147 -0
  547. package/references/methodology/triz-matrix.json +751 -0
  548. package/references/methodology/triz-principles.md +501 -0
  549. package/references/methodology/user-needs.md +199 -0
  550. package/references/methodology/validate.md +163 -0
  551. package/references/methodology/value-proposition.md +244 -0
  552. package/references/opportunities/funding-lifecycle.md +103 -0
  553. package/references/opportunities/grant-api-patterns.md +99 -0
  554. package/references/opportunities/opportunity-template.md +84 -0
  555. package/references/personality/assessment-philosophy.md +72 -0
  556. package/references/personality/lexicon.md +100 -0
  557. package/references/personality/persona-chains.md +56 -0
  558. package/references/personality/pws-lexicon-full.md +499 -0
  559. package/references/personality/voice-dna.md +156 -0
  560. package/references/personas/hat-perspectives.md +76 -0
  561. package/references/personas/persona-template.md +63 -0
  562. package/references/pipeline/act-output-contract.md +88 -0
  563. package/references/pipeline/chains-index.md +39 -0
  564. package/references/pws-profile-generation.md +79 -0
  565. package/references/reasoning/reasoning-schema.md +143 -0
  566. package/references/reasoning/reasoning-template.md +68 -0
  567. package/references/reasoning/run-template.md +38 -0
  568. package/references/research/RESEARCH_14_CLAUDE_CODE_SOURCE_ARCHITECTURE.md +209 -0
  569. package/references/research/RESEARCH_15_V1.8_OPTIMIZATION_JTBD.md +375 -0
  570. package/references/research/RESEARCH_16_NATIVE_FIRST_PLUGIN_ARCHITECTURE.md +575 -0
  571. package/references/research/RESEARCH_17_MCP_UI_FRAMEWORKS.md +272 -0
  572. package/references/taxonomy/TAXONOMY.md +192 -0
  573. package/references/templates/MINTO.md +36 -0
  574. package/references/user-research/2026-04-05-leah-lawrence-session.md +202 -0
  575. package/references/vault-kit/README.md +35 -0
  576. package/references/vault-kit/app.json +12 -0
  577. package/references/vault-kit/appearance.json +12 -0
  578. package/references/vault-kit/graph.json +35 -0
  579. package/references/vault-kit/snippets/mindrian-destijl.css +297 -0
  580. package/references/vault-kit/templates/new-artifact.md +37 -0
  581. package/references/vault-kit/templates/new-meeting-note.md +35 -0
  582. package/references/vault-kit/templates/new-team-profile.md +29 -0
  583. package/references/vault-kit/templates/new-xref.md +35 -0
  584. package/references/visual/symbol-system.md +151 -0
  585. package/skills/MOSDeckEngine/SKILL.md +325 -0
  586. package/skills/brain-connector/SKILL.md +114 -0
  587. package/skills/context-engine/SKILL.md +147 -0
  588. package/skills/conversation-mode/SKILL.md +102 -0
  589. package/skills/larry-personality/SKILL.md +219 -0
  590. package/skills/larry-personality/framework-chains.md +92 -0
  591. package/skills/larry-personality/mode-engine.md +185 -0
  592. package/skills/mullins-scaffold/SKILL.md +61 -0
  593. package/skills/mullins-scaffold/scaffold.json +146 -0
  594. package/skills/pws-methodology/SKILL.md +49 -0
  595. package/skills/room-passive/SKILL.md +165 -0
  596. package/skills/room-proactive/SKILL.md +250 -0
  597. package/skills/ui-system/SKILL.md +277 -0
@@ -0,0 +1,656 @@
1
+ /*
2
+ * Copyright (c) 2026 Mindrian. BSL 1.1.
3
+ * Phase 89.3 Plan 03 -- 5-branch Cytoscape mind-map generator.
4
+ *
5
+ * renderMindMap(query_filter, opts) is the read-side companion to the
6
+ * dual-tier writers (rs-neo4j-writer.cjs Plan 89.3-01 and
7
+ * rs-sqlite-mirror.cjs Plan 89.3-02). It reads from the active tier
8
+ * (Aura via opts.driver OR room.db via opts.roomDir) and emits a
9
+ * Cytoscape-compatible JSON payload split into 5 branches PLUS a
10
+ * standalone HTML wrapper.
11
+ *
12
+ * The 5 branches (per kickoff section 5):
13
+ * 1. Direct Intersections lsa > 0.6 AND bert > 0.6
14
+ * 2. Structural Transfer classification = structural_transfer
15
+ * 3. Semantic Implementation classification = semantic_implementation
16
+ * 4. Discovered RS ReverseSalient nodes
17
+ * 5. Innovation Ecosystem Innovation + Paper + Author + Institution slice
18
+ *
19
+ * Tier dispatch is transparent. Caller passes opts.tier explicitly OR
20
+ * the module auto-detects: if opts.driver looks like a neo4j-driver
21
+ * Driver, use Aura; if opts.roomDir is a string, use SQLite. If neither
22
+ * is provided, throws TypeError with a clear message so the caller
23
+ * can fix the call site.
24
+ *
25
+ * Canon Part 7 (Reuse Before Build):
26
+ * - Reuses lazygraph.openGraph + closeGraph (no new SQLite wrapper)
27
+ * - Reuses dashboard/index.html cytoscape@3.33.1 CDN URL byte-for-byte
28
+ * (NO new runtime dependency; no build step)
29
+ * - Shares ExternalEgressViolation + auditQueryObject with 89.2 fetchers
30
+ *
31
+ * Canon Part 8 (Graph Boundary -- defense-in-depth on the DISPLAY surface):
32
+ * the data source is trusted (user's OWN graph), but the rendered HTML
33
+ * wrapper may be shared, exported to the dashboard, or cached. Therefore
34
+ * auditQueryObject scans the FINAL HTML before return; on any
35
+ * FORBIDDEN_PATTERNS hit it throws ExternalEgressViolation with
36
+ * meta.surface = 'rs-mind-map-html' so the caller knows precisely which
37
+ * surface tripped the guard. Result is NEVER returned on audit failure.
38
+ *
39
+ * Pure CJS, zero npm deps, node built-ins only (no fetch, no http).
40
+ */
41
+ 'use strict';
42
+
43
+ const { ExternalEgressViolation } = require('./rs-egress-violations.cjs');
44
+ const { auditQueryObject } = require('./rs-egress-prompts.cjs');
45
+ const lazygraph = require('./lazygraph-ops.cjs');
46
+
47
+ const SURFACE = 'rs-mind-map-html';
48
+ const SCHEMA_VERSION = '1.0';
49
+
50
+ // The 5 canonical branches (kickoff section 5). Frozen so callers cannot
51
+ // mutate the canonical list and downstream renderers can rely on the
52
+ // fixed key set.
53
+ const BRANCHES = Object.freeze([
54
+ 'Direct Intersections',
55
+ 'Structural Transfer',
56
+ 'Semantic Implementation',
57
+ 'Discovered RS',
58
+ 'Innovation Ecosystem',
59
+ ]);
60
+
61
+ // De Stijl-derived per-branch colors. Frozen for the same reason as
62
+ // BRANCHES. The HTML wrapper emits these as inline styles in the
63
+ // legend block; the Cytoscape style block also references them via
64
+ // node-data lookup at render time.
65
+ const BRANCH_COLORS = Object.freeze({
66
+ 'Direct Intersections': '#ff0000',
67
+ 'Structural Transfer': '#0000ff',
68
+ 'Semantic Implementation': '#999933',
69
+ 'Discovered RS': '#000000',
70
+ 'Innovation Ecosystem': '#666666',
71
+ });
72
+
73
+ // Cytoscape CDN URL: byte-identical to dashboard/index.html line 22.
74
+ // Canon Part 7 reuse: do NOT bump this version independently of the
75
+ // dashboard. If/when the dashboard upgrades, this constant moves with it.
76
+ const CYTOSCAPE_CDN_URL = 'https://unpkg.com/cytoscape@3.33.1/dist/cytoscape.min.js';
77
+
78
+ // ---------- detectTier ----------
79
+ //
80
+ // Resolution order:
81
+ // 1. opts.tier explicit ('aura' or 'sqlite') -- caller wins
82
+ // 2. opts.driver with .session function -- Tier 1 (Aura)
83
+ // 3. opts.roomDir string -- Tier 0 (SQLite)
84
+ // 4. nothing -- TypeError (fail loud, fail early)
85
+
86
+ async function detectTier(opts) {
87
+ if (opts && (opts.tier === 'aura' || opts.tier === 'sqlite')) return opts.tier;
88
+ if (opts && opts.driver && typeof opts.driver.session === 'function') return 'aura';
89
+ if (opts && typeof opts.roomDir === 'string' && opts.roomDir.length > 0) return 'sqlite';
90
+ throw new TypeError(
91
+ 'rs-mind-map: opts.tier OR opts.driver OR opts.roomDir required'
92
+ );
93
+ }
94
+
95
+ // ---------- safeJsonParse ----------
96
+ //
97
+ // Defensive: SQLite properties column is JSON-stringified. Bad JSON
98
+ // (corrupted row, manual SQL edit) returns an empty object so the
99
+ // renderer keeps moving. We never throw on malformed JSON because that
100
+ // would make ONE corrupted row block the entire mind map.
101
+
102
+ function safeJsonParse(s) {
103
+ if (typeof s !== 'string' || s.length === 0) return {};
104
+ try { return JSON.parse(s); } catch (_e) { return {}; }
105
+ }
106
+
107
+ // ---------- buildLabel ----------
108
+ //
109
+ // Cytoscape nodes need a human-readable label. Falls back gracefully
110
+ // through several property paths because different node types carry
111
+ // the human-friendly name in different fields.
112
+
113
+ function buildLabel(props, type) {
114
+ if (!props || typeof props !== 'object') return type || 'node';
115
+ if (typeof props.title === 'string' && props.title.length > 0) return props.title;
116
+ if (typeof props.name === 'string' && props.name.length > 0) return props.name;
117
+ if (typeof props.thesis === 'string' && props.thesis.length > 0) {
118
+ return props.thesis.slice(0, 60);
119
+ }
120
+ if (typeof props.query_concept === 'string' && props.query_concept.length > 0) {
121
+ return props.query_concept;
122
+ }
123
+ return type || 'node';
124
+ }
125
+
126
+ // ---------- toCytoscapeNode ----------
127
+ //
128
+ // Convert a (id, type, properties, branch) tuple into the Cytoscape
129
+ // elements format: { data: { id, label, type, branch } }. Properties
130
+ // are NOT spread into data (only label + type + branch + id) because
131
+ // the rendered HTML must not echo arbitrary user content into the
132
+ // node data block; the audit later catches any leak that does sneak
133
+ // through, but minimizing the surface is defense-in-depth design.
134
+
135
+ function toCytoscapeNode(id, type, properties, branch) {
136
+ return {
137
+ data: {
138
+ id: id,
139
+ label: buildLabel(properties, type),
140
+ type: type,
141
+ branch: branch,
142
+ },
143
+ };
144
+ }
145
+
146
+ function toCytoscapeEdge(id, source, target, type, branch) {
147
+ return {
148
+ data: {
149
+ id: id,
150
+ source: source,
151
+ target: target,
152
+ label: type,
153
+ branch: branch,
154
+ },
155
+ };
156
+ }
157
+
158
+ // ---------- readSqliteBranches ----------
159
+ //
160
+ // Tier 0 read path. Opens the room.db via lazygraph.openGraph and runs
161
+ // 5 SELECT queries -- one per branch. Returns:
162
+ // { branches: { '...': {nodes, edges}, ... }, total_nodes, total_edges }
163
+ //
164
+ // The branches map carries Cytoscape-formatted nodes + edges per
165
+ // branch (renderMindMap wraps the unified result later).
166
+
167
+ async function readSqliteBranches(roomDir, queryFilter) {
168
+ const handle = await lazygraph.openGraph(roomDir);
169
+ const conn = handle.conn;
170
+ const branches = {
171
+ 'Direct Intersections': { nodes: [], edges: [] },
172
+ 'Structural Transfer': { nodes: [], edges: [] },
173
+ 'Semantic Implementation': { nodes: [], edges: [] },
174
+ 'Discovered RS': { nodes: [], edges: [] },
175
+ 'Innovation Ecosystem': { nodes: [], edges: [] },
176
+ };
177
+ let total_nodes = 0;
178
+ let total_edges = 0;
179
+
180
+ try {
181
+ // Branch 1: Direct Intersections (lsa > 0.6 AND bert > 0.6)
182
+ if (shouldEmitBranch('Direct Intersections', queryFilter)) {
183
+ const rows = conn.prepare(
184
+ 'SELECT id, type, properties FROM nodes ' +
185
+ 'WHERE type = ? ' +
186
+ 'AND CAST(json_extract(properties, ?) AS REAL) > 0.6 ' +
187
+ 'AND CAST(json_extract(properties, ?) AS REAL) > 0.6'
188
+ ).all('RSDiscovery', '$.lsa', '$.bert');
189
+ for (const r of rows) {
190
+ const props = safeJsonParse(r.properties);
191
+ branches['Direct Intersections'].nodes.push(
192
+ toCytoscapeNode(r.id, r.type, props, 'Direct Intersections')
193
+ );
194
+ }
195
+ }
196
+
197
+ // Branch 2: Structural Transfer
198
+ if (shouldEmitBranch('Structural Transfer', queryFilter)) {
199
+ const rows = conn.prepare(
200
+ 'SELECT id, type, properties FROM nodes ' +
201
+ 'WHERE type = ? ' +
202
+ 'AND json_extract(properties, ?) = ?'
203
+ ).all('RSDiscovery', '$.classification', 'structural_transfer');
204
+ for (const r of rows) {
205
+ const props = safeJsonParse(r.properties);
206
+ branches['Structural Transfer'].nodes.push(
207
+ toCytoscapeNode(r.id, r.type, props, 'Structural Transfer')
208
+ );
209
+ }
210
+ }
211
+
212
+ // Branch 3: Semantic Implementation
213
+ if (shouldEmitBranch('Semantic Implementation', queryFilter)) {
214
+ const rows = conn.prepare(
215
+ 'SELECT id, type, properties FROM nodes ' +
216
+ 'WHERE type = ? ' +
217
+ 'AND json_extract(properties, ?) = ?'
218
+ ).all('RSDiscovery', '$.classification', 'semantic_implementation');
219
+ for (const r of rows) {
220
+ const props = safeJsonParse(r.properties);
221
+ branches['Semantic Implementation'].nodes.push(
222
+ toCytoscapeNode(r.id, r.type, props, 'Semantic Implementation')
223
+ );
224
+ }
225
+ }
226
+
227
+ // Branch 4: Discovered RS (ReverseSalient nodes)
228
+ if (shouldEmitBranch('Discovered RS', queryFilter)) {
229
+ const rows = conn.prepare(
230
+ 'SELECT id, type, properties FROM nodes WHERE type = ?'
231
+ ).all('ReverseSalient');
232
+ for (const r of rows) {
233
+ const props = safeJsonParse(r.properties);
234
+ branches['Discovered RS'].nodes.push(
235
+ toCytoscapeNode(r.id, r.type, props, 'Discovered RS')
236
+ );
237
+ }
238
+ }
239
+
240
+ // Branch 5: Innovation Ecosystem (Innovation + Paper + Author + Institution)
241
+ if (shouldEmitBranch('Innovation Ecosystem', queryFilter)) {
242
+ const ECO_TYPES = ['Innovation', 'Paper', 'Author', 'Institution'];
243
+ const placeholders = ECO_TYPES.map(function () { return '?'; }).join(',');
244
+ const rows = conn.prepare(
245
+ 'SELECT id, type, properties FROM nodes WHERE type IN (' + placeholders + ')'
246
+ ).all.apply(conn.prepare(
247
+ 'SELECT id, type, properties FROM nodes WHERE type IN (' + placeholders + ')'
248
+ ), ECO_TYPES);
249
+ for (const r of rows) {
250
+ const props = safeJsonParse(r.properties);
251
+ branches['Innovation Ecosystem'].nodes.push(
252
+ toCytoscapeNode(r.id, r.type, props, 'Innovation Ecosystem')
253
+ );
254
+ }
255
+ // Edges within the ecosystem.
256
+ const ECO_EDGE_TYPES = ['DERIVED_FROM', 'AUTHORED_BY', 'AFFILIATED_WITH', 'ENABLES'];
257
+ const edgePlaceholders = ECO_EDGE_TYPES.map(function () { return '?'; }).join(',');
258
+ const edgeRows = conn.prepare(
259
+ 'SELECT source, target, type, properties FROM edges WHERE type IN (' + edgePlaceholders + ')'
260
+ ).all.apply(conn.prepare(
261
+ 'SELECT source, target, type, properties FROM edges WHERE type IN (' + edgePlaceholders + ')'
262
+ ), ECO_EDGE_TYPES);
263
+ for (const r of edgeRows) {
264
+ branches['Innovation Ecosystem'].edges.push(
265
+ toCytoscapeEdge(
266
+ r.source + '__' + r.type + '__' + r.target,
267
+ r.source, r.target, r.type, 'Innovation Ecosystem'
268
+ )
269
+ );
270
+ }
271
+ }
272
+
273
+ // Compute total_nodes + total_edges from the FULL graph (for
274
+ // metadata; not branch-filtered because metadata reflects the
275
+ // raw graph state).
276
+ total_nodes = conn.prepare('SELECT COUNT(*) AS n FROM nodes').get().n;
277
+ total_edges = conn.prepare('SELECT COUNT(*) AS n FROM edges').get().n;
278
+ } finally {
279
+ try { await lazygraph.closeGraph(handle.db); } catch (_e) { /* best effort */ }
280
+ }
281
+
282
+ return { branches: branches, total_nodes: total_nodes, total_edges: total_edges };
283
+ }
284
+
285
+ // ---------- readAuraBranches ----------
286
+ //
287
+ // Tier 1 read path. Opens an Aura session via opts.driver and runs 5
288
+ // Cypher MATCH queries -- one per branch. The neo4j-driver Result has
289
+ // .records[] where each record exposes .get(name) returning the matched
290
+ // node (which itself has .properties, .labels, .identity).
291
+ //
292
+ // Multi-hop traversal is reserved for the Innovation Ecosystem branch
293
+ // because that is where the cross-table value concentrates (per kickoff
294
+ // section 5).
295
+
296
+ async function readAuraBranches(driver, queryFilter) {
297
+ const session = driver.session();
298
+ const branches = {
299
+ 'Direct Intersections': { nodes: [], edges: [] },
300
+ 'Structural Transfer': { nodes: [], edges: [] },
301
+ 'Semantic Implementation': { nodes: [], edges: [] },
302
+ 'Discovered RS': { nodes: [], edges: [] },
303
+ 'Innovation Ecosystem': { nodes: [], edges: [] },
304
+ };
305
+ let total_nodes = 0;
306
+ let total_edges = 0;
307
+
308
+ try {
309
+ // Branch 1: Direct Intersections
310
+ if (shouldEmitBranch('Direct Intersections', queryFilter)) {
311
+ const r = await session.run(
312
+ 'MATCH (d:RSDiscovery) WHERE d.lsa > 0.6 AND d.bert > 0.6 RETURN d'
313
+ );
314
+ for (const rec of r.records || []) {
315
+ const node = rec.get('d');
316
+ const id = recordNodeId(node, rec);
317
+ const props = (node && node.properties) || {};
318
+ branches['Direct Intersections'].nodes.push(
319
+ toCytoscapeNode(id, 'RSDiscovery', props, 'Direct Intersections')
320
+ );
321
+ total_nodes += 1;
322
+ }
323
+ } else {
324
+ // Still call run so the dispatch counter matches the 5-branch contract.
325
+ await session.run('MATCH (d:RSDiscovery) WHERE false RETURN d');
326
+ }
327
+
328
+ // Branch 2: Structural Transfer
329
+ if (shouldEmitBranch('Structural Transfer', queryFilter)) {
330
+ const r = await session.run(
331
+ 'MATCH (d:RSDiscovery) WHERE d.classification = "structural_transfer" RETURN d'
332
+ );
333
+ for (const rec of r.records || []) {
334
+ const node = rec.get('d');
335
+ const id = recordNodeId(node, rec);
336
+ const props = (node && node.properties) || {};
337
+ branches['Structural Transfer'].nodes.push(
338
+ toCytoscapeNode(id, 'RSDiscovery', props, 'Structural Transfer')
339
+ );
340
+ total_nodes += 1;
341
+ }
342
+ } else {
343
+ await session.run('MATCH (d:RSDiscovery) WHERE false RETURN d');
344
+ }
345
+
346
+ // Branch 3: Semantic Implementation
347
+ if (shouldEmitBranch('Semantic Implementation', queryFilter)) {
348
+ const r = await session.run(
349
+ 'MATCH (d:RSDiscovery) WHERE d.classification = "semantic_implementation" RETURN d'
350
+ );
351
+ for (const rec of r.records || []) {
352
+ const node = rec.get('d');
353
+ const id = recordNodeId(node, rec);
354
+ const props = (node && node.properties) || {};
355
+ branches['Semantic Implementation'].nodes.push(
356
+ toCytoscapeNode(id, 'RSDiscovery', props, 'Semantic Implementation')
357
+ );
358
+ total_nodes += 1;
359
+ }
360
+ } else {
361
+ await session.run('MATCH (d:RSDiscovery) WHERE false RETURN d');
362
+ }
363
+
364
+ // Branch 4: Discovered RS
365
+ if (shouldEmitBranch('Discovered RS', queryFilter)) {
366
+ const r = await session.run('MATCH (rs:ReverseSalient) RETURN rs');
367
+ for (const rec of r.records || []) {
368
+ const node = rec.get('rs');
369
+ const id = recordNodeId(node, rec);
370
+ const props = (node && node.properties) || {};
371
+ branches['Discovered RS'].nodes.push(
372
+ toCytoscapeNode(id, 'ReverseSalient', props, 'Discovered RS')
373
+ );
374
+ total_nodes += 1;
375
+ }
376
+ } else {
377
+ await session.run('MATCH (rs:ReverseSalient) WHERE false RETURN rs');
378
+ }
379
+
380
+ // Branch 5: Innovation Ecosystem (multi-hop where Aura adds value).
381
+ // Real Aura multi-hop queries return the same node many times across
382
+ // rows (one row per traversal path); we dedupe by id within this
383
+ // branch so the Cytoscape elements array stays unique. dedupeAndCombine
384
+ // dedupes across branches but the per-branch nodes[] is what callers
385
+ // commonly read directly, so the dedup must happen here too.
386
+ if (shouldEmitBranch('Innovation Ecosystem', queryFilter)) {
387
+ const r = await session.run(
388
+ 'MATCH (i:Innovation) ' +
389
+ 'OPTIONAL MATCH (i)<-[:ENABLES]-(d:RSDiscovery)-[:DERIVED_FROM]->(p:Paper)-[:AUTHORED_BY]->(a:Author)-[:AFFILIATED_WITH]->(inst:Institution) ' +
390
+ 'RETURN i, p, a, inst'
391
+ );
392
+ const seen = new Set();
393
+ for (const rec of r.records || []) {
394
+ for (const key of ['i', 'p', 'a', 'inst']) {
395
+ let node;
396
+ try { node = rec.get(key); } catch (_e) { node = null; }
397
+ if (!node) continue;
398
+ const id = recordNodeId(node, rec);
399
+ if (seen.has(id)) continue;
400
+ seen.add(id);
401
+ const labels = (node.labels && node.labels.length > 0) ? node.labels : [keyToLabel(key)];
402
+ const type = labels[0];
403
+ const props = (node && node.properties) || {};
404
+ branches['Innovation Ecosystem'].nodes.push(
405
+ toCytoscapeNode(id, type, props, 'Innovation Ecosystem')
406
+ );
407
+ total_nodes += 1;
408
+ }
409
+ }
410
+ } else {
411
+ await session.run('MATCH (i:Innovation) WHERE false RETURN i');
412
+ }
413
+ } finally {
414
+ try { await session.close(); } catch (_e) { /* best effort */ }
415
+ }
416
+
417
+ return { branches: branches, total_nodes: total_nodes, total_edges: total_edges };
418
+ }
419
+
420
+ function keyToLabel(key) {
421
+ if (key === 'i') return 'Innovation';
422
+ if (key === 'p') return 'Paper';
423
+ if (key === 'a') return 'Author';
424
+ if (key === 'inst') return 'Institution';
425
+ if (key === 'd') return 'RSDiscovery';
426
+ if (key === 'rs') return 'ReverseSalient';
427
+ return 'Unknown';
428
+ }
429
+
430
+ function recordNodeId(node, rec) {
431
+ if (node && node.identity && typeof node.identity.low === 'number') {
432
+ return 'aura-' + node.identity.low;
433
+ }
434
+ if (node && node.properties && typeof node.properties.id === 'string') {
435
+ return node.properties.id;
436
+ }
437
+ return 'aura-unknown-' + Math.floor(Math.random() * 1e6);
438
+ }
439
+
440
+ // ---------- shouldEmitBranch ----------
441
+ //
442
+ // query_filter.branch (string) limits the output to a single branch.
443
+ // All other branches return empty arrays. Absence of branch filter
444
+ // means emit all 5.
445
+
446
+ function shouldEmitBranch(branch, queryFilter) {
447
+ if (!queryFilter || typeof queryFilter !== 'object') return true;
448
+ if (typeof queryFilter.branch !== 'string' || queryFilter.branch.length === 0) return true;
449
+ return queryFilter.branch === branch;
450
+ }
451
+
452
+ // ---------- dedupeAndCombine ----------
453
+ //
454
+ // Flatten the 5 branches into a single elements.{nodes, edges}
455
+ // object, deduping by id. Cytoscape requires unique element ids;
456
+ // the same node may appear in more than one branch (for example a
457
+ // hybrid-classified RSDiscovery that crosses thresholds), so dedup
458
+ // is required.
459
+
460
+ function dedupeAndCombine(branches) {
461
+ const nodeMap = new Map();
462
+ const edgeMap = new Map();
463
+ for (const branch of Object.keys(branches)) {
464
+ const payload = branches[branch] || { nodes: [], edges: [] };
465
+ for (const n of payload.nodes) {
466
+ if (n && n.data && n.data.id && !nodeMap.has(n.data.id)) nodeMap.set(n.data.id, n);
467
+ }
468
+ for (const e of payload.edges) {
469
+ if (e && e.data && e.data.id && !edgeMap.has(e.data.id)) edgeMap.set(e.data.id, e);
470
+ }
471
+ }
472
+ return {
473
+ nodes: Array.from(nodeMap.values()),
474
+ edges: Array.from(edgeMap.values()),
475
+ };
476
+ }
477
+
478
+ // ---------- buildHtmlWrapper ----------
479
+ //
480
+ // Standalone HTML wrapper. Uses the existing dashboard cytoscape@3.33.1
481
+ // CDN pattern (Canon Part 7 reuse; no new runtime dependency). The
482
+ // elements array is JSON-serialized inline so the wrapper opens in
483
+ // any browser without a backing server. Legend block is inline-styled
484
+ // so the file works as a single self-contained artifact.
485
+
486
+ function buildHtmlWrapper(graph) {
487
+ const elementsJson = JSON.stringify(graph.elements || { nodes: [], edges: [] });
488
+ const colorsJson = JSON.stringify(graph.branch_colors || BRANCH_COLORS);
489
+ const branchesJson = JSON.stringify(graph.branches || {});
490
+
491
+ // Legend rows: one per branch with the canonical color swatch.
492
+ const legendRows = BRANCHES.map(function (b) {
493
+ return '<div><span style="display:inline-block;width:12px;height:12px;background:' +
494
+ BRANCH_COLORS[b] + ';margin-right:6px;border:1px solid #000;"></span>' +
495
+ escapeHtml(b) + '</div>';
496
+ }).join('\n ');
497
+
498
+ return '<!DOCTYPE html>\n' +
499
+ '<html lang="en">\n' +
500
+ '<head>\n' +
501
+ ' <meta charset="UTF-8">\n' +
502
+ ' <title>RS Mind Map: 5-Branch View</title>\n' +
503
+ ' <script src="' + CYTOSCAPE_CDN_URL + '"></script>\n' +
504
+ ' <style>\n' +
505
+ ' body { margin: 0; font-family: monospace; background: #ffffff; color: #000000; }\n' +
506
+ ' #cy { width: 100vw; height: 100vh; }\n' +
507
+ ' .legend { position: absolute; top: 10px; left: 10px; background: #ffffff; border: 2px solid #000000; padding: 10px; z-index: 10; }\n' +
508
+ ' .legend strong { display: block; margin-bottom: 6px; }\n' +
509
+ ' </style>\n' +
510
+ '</head>\n' +
511
+ '<body>\n' +
512
+ ' <div id="cy"></div>\n' +
513
+ ' <div class="legend">\n' +
514
+ ' <strong>Branches</strong>\n' +
515
+ ' ' + legendRows + '\n' +
516
+ ' </div>\n' +
517
+ ' <script>\n' +
518
+ ' var elements = ' + elementsJson + ';\n' +
519
+ ' var branchColors = ' + colorsJson + ';\n' +
520
+ ' var branches = ' + branchesJson + ';\n' +
521
+ ' var cy = cytoscape({\n' +
522
+ ' container: document.getElementById(\'cy\'),\n' +
523
+ ' elements: [].concat(elements.nodes || [], elements.edges || []),\n' +
524
+ ' style: [\n' +
525
+ ' { selector: \'node\', style: { label: \'data(label)\', \'background-color\': function (ele) { return branchColors[ele.data(\'branch\')] || \'#999999\'; }, \'font-size\': 9, color: \'#000000\', \'text-valign\': \'bottom\', \'text-margin-y\': 6 } },\n' +
526
+ ' { selector: \'edge\', style: { label: \'data(label)\', \'line-color\': function (ele) { return branchColors[ele.data(\'branch\')] || \'#999999\'; }, \'target-arrow-color\': function (ele) { return branchColors[ele.data(\'branch\')] || \'#999999\'; }, \'target-arrow-shape\': \'triangle\', \'curve-style\': \'bezier\', \'font-size\': 7 } }\n' +
527
+ ' ],\n' +
528
+ ' layout: { name: \'cose\', animate: false, padding: 30 }\n' +
529
+ ' });\n' +
530
+ ' </script>\n' +
531
+ '</body>\n' +
532
+ '</html>\n';
533
+ }
534
+
535
+ // ---------- escapeHtml ----------
536
+ //
537
+ // Minimal HTML entity escape for the legend labels. We escape the
538
+ // branch names even though they are constants because future Canon
539
+ // amendments may extend BRANCHES with caller-supplied names; defense
540
+ // in depth.
541
+
542
+ function escapeHtml(s) {
543
+ if (typeof s !== 'string') return '';
544
+ return s.replace(/&/g, '&amp;')
545
+ .replace(/</g, '&lt;')
546
+ .replace(/>/g, '&gt;')
547
+ .replace(/"/g, '&quot;')
548
+ .replace(/'/g, '&#39;');
549
+ }
550
+
551
+ // ---------- renderMindMap ----------
552
+ //
553
+ // The public entry point. Orchestration:
554
+ // 1. Resolve tier (throws TypeError if neither driver nor roomDir provided)
555
+ // 2. Validate tier-specific opts
556
+ // 3. Read raw branches from active tier (Tier 0 SQLite or Tier 1 Aura)
557
+ // 4. Force all 5 branch keys to be present (empty arrays for missing branches)
558
+ // 5. Compute combined elements (deduped by id)
559
+ // 6. Build metadata (tier, branch_counts, totals, schema_version)
560
+ // 7. Build HTML wrapper
561
+ // 8. Canon Part 8 defense-in-depth: auditQueryObject on FINAL HTML
562
+ // (throws ExternalEgressViolation on any FORBIDDEN_PATTERNS hit;
563
+ // result is NEVER returned)
564
+ // 9. Return assembled result with html_wrapper attached
565
+
566
+ async function renderMindMap(query_filter, opts) {
567
+ opts = opts || {};
568
+ const queryFilter = (query_filter && typeof query_filter === 'object') ? query_filter : {};
569
+ const tier = await detectTier(opts);
570
+
571
+ let raw;
572
+ if (tier === 'sqlite') {
573
+ if (typeof opts.roomDir !== 'string' || opts.roomDir.length === 0) {
574
+ throw new TypeError('rs-mind-map: opts.roomDir required for sqlite tier');
575
+ }
576
+ raw = await readSqliteBranches(opts.roomDir, queryFilter);
577
+ } else {
578
+ if (!opts.driver || typeof opts.driver.session !== 'function') {
579
+ throw new TypeError('rs-mind-map: opts.driver required for aura tier');
580
+ }
581
+ raw = await readAuraBranches(opts.driver, queryFilter);
582
+ }
583
+
584
+ // Normalize: every branch key MUST be present in output (empty arrays
585
+ // for missing). Downstream renderers (dashboard, /mos:rs-mind-map)
586
+ // rely on the fixed key set.
587
+ const branches = {};
588
+ for (const b of BRANCHES) {
589
+ branches[b] = raw.branches[b] || { nodes: [], edges: [] };
590
+ }
591
+
592
+ const elements = dedupeAndCombine(branches);
593
+
594
+ const branch_counts = {};
595
+ for (const b of BRANCHES) branch_counts[b] = branches[b].nodes.length;
596
+
597
+ const result = {
598
+ branches: branches,
599
+ elements: elements,
600
+ branch_colors: BRANCH_COLORS,
601
+ metadata: {
602
+ tier: tier,
603
+ branch_counts: branch_counts,
604
+ total_nodes: typeof raw.total_nodes === 'number' ? raw.total_nodes : 0,
605
+ total_edges: typeof raw.total_edges === 'number' ? raw.total_edges : 0,
606
+ schema_version: SCHEMA_VERSION,
607
+ },
608
+ };
609
+
610
+ const html_wrapper = buildHtmlWrapper(result);
611
+
612
+ // Canon Part 8 defense-in-depth: audit the FINAL HTML wrapper before
613
+ // return. Throws ExternalEgressViolation on any FORBIDDEN_PATTERNS hit
614
+ // with meta.surface = 'rs-mind-map-html'. Result is NEVER returned on
615
+ // audit failure; the caller learns precisely which surface tripped
616
+ // the guard via meta.matched_pattern.
617
+ auditQueryObject({ html: html_wrapper }, SURFACE);
618
+
619
+ result.html_wrapper = html_wrapper;
620
+ return result;
621
+ }
622
+
623
+ // ---------- Edge type registry consumption ----------
624
+ //
625
+ // Defensive guard: warn (not throw) if EDGE_TYPES is missing the 5 RS
626
+ // edge types Plan 89.3-01 added. This module is read-only against the
627
+ // schema, so the warning surfaces upstream issues without blocking
628
+ // the renderer for users whose graph already has the edges.
629
+
630
+ const REQUIRED_EDGE_TYPES = ['DISCOVERED', 'DERIVED_FROM', 'ENABLES', 'AUTHORED_BY', 'AFFILIATED_WITH'];
631
+ for (const t of REQUIRED_EDGE_TYPES) {
632
+ if (!lazygraph.EDGE_TYPES.includes(t)) {
633
+ process.stderr.write('rs-mind-map: WARNING -- EDGE_TYPES missing required type: ' + t + '\n');
634
+ }
635
+ }
636
+
637
+ // ---------- Exports ----------
638
+
639
+ module.exports = {
640
+ renderMindMap,
641
+ BRANCHES,
642
+ BRANCH_COLORS,
643
+ SCHEMA_VERSION,
644
+ CYTOSCAPE_CDN_URL,
645
+ _test: {
646
+ detectTier,
647
+ readSqliteBranches,
648
+ readAuraBranches,
649
+ buildHtmlWrapper,
650
+ dedupeAndCombine,
651
+ safeJsonParse,
652
+ buildLabel,
653
+ shouldEmitBranch,
654
+ escapeHtml,
655
+ },
656
+ };