@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,182 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Unit tests for lib/vault/wikilink-builder.cjs
4
+ *
5
+ * Zero-dependency test runner using Node's built-in `assert`.
6
+ * Run: node lib/vault/wikilink-builder.test.cjs
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const assert = require('assert');
12
+ const wb = require('./wikilink-builder.cjs');
13
+
14
+ let passed = 0;
15
+ let failed = 0;
16
+
17
+ function test(name, fn) {
18
+ try {
19
+ fn();
20
+ passed += 1;
21
+ process.stdout.write(` ok ${name}\n`);
22
+ } catch (err) {
23
+ failed += 1;
24
+ process.stdout.write(` FAIL ${name}\n ${err.message}\n`);
25
+ }
26
+ }
27
+
28
+ const profiles = [
29
+ {
30
+ name: 'avital-leibovich',
31
+ displayName: 'Avital Leibovich',
32
+ path: '/room/team/advisors/avital-leibovich/PROFILE.md',
33
+ category: 'advisors',
34
+ },
35
+ {
36
+ name: 'avital-only',
37
+ displayName: 'Avital',
38
+ path: '/room/team/advisors/avital-only/PROFILE.md',
39
+ category: 'advisors',
40
+ },
41
+ {
42
+ name: 'lawrence-aronhime',
43
+ displayName: 'Lawrence Aronhime',
44
+ path: '/room/team/mentors/lawrence-aronhime/PROFILE.md',
45
+ category: 'mentors',
46
+ },
47
+ ];
48
+
49
+ // Test 1: first occurrence only
50
+ test('buildTeamLinks replaces first occurrence only', () => {
51
+ const input = 'Lawrence Aronhime said X. Later Lawrence Aronhime said Y.';
52
+ const out = wb.buildTeamLinks(input, profiles, {});
53
+ const link = '[[team/mentors/lawrence-aronhime/PROFILE.md|Lawrence Aronhime]]';
54
+ assert.ok(out.includes(link), 'expected link inserted');
55
+ // Only one link
56
+ const count = out.split(link).length - 1;
57
+ assert.strictEqual(count, 1, `expected exactly 1 link, got ${count}`);
58
+ // Second occurrence is untouched plain text
59
+ assert.ok(out.endsWith('Later Lawrence Aronhime said Y.'), 'second occurrence preserved');
60
+ });
61
+
62
+ // Test 2: longest-name preference
63
+ test('buildTeamLinks prefers longer name over prefix (Avital Leibovich > Avital)', () => {
64
+ const input = 'Meeting with Avital Leibovich today.';
65
+ const out = wb.buildTeamLinks(input, profiles, {});
66
+ assert.ok(
67
+ out.includes('[[team/advisors/avital-leibovich/PROFILE.md|Avital Leibovich]]'),
68
+ 'longer name should win'
69
+ );
70
+ assert.ok(
71
+ !out.includes('[[team/advisors/avital-only/PROFILE.md|Avital]]'),
72
+ 'shorter prefix should not link'
73
+ );
74
+ });
75
+
76
+ // Test 3: self-link skipped
77
+ test('buildTeamLinks skips self-link when ownProfilePath matches', () => {
78
+ const input = '# Lawrence Aronhime\n\nLawrence Aronhime is a mentor.';
79
+ const out = wb.buildTeamLinks(input, profiles, {
80
+ ownProfilePath: '/room/team/mentors/lawrence-aronhime/PROFILE.md',
81
+ });
82
+ assert.strictEqual(out, input, 'content should be unchanged when processing own profile');
83
+ });
84
+
85
+ // Test 4: frontmatter skipped
86
+ test('buildTeamLinks skips frontmatter region', () => {
87
+ const input =
88
+ '---\nauthor: Lawrence Aronhime\n---\nBody text by Lawrence Aronhime here.';
89
+ const out = wb.buildTeamLinks(input, profiles, {});
90
+ // Frontmatter author line unchanged
91
+ assert.ok(out.includes('author: Lawrence Aronhime'), 'frontmatter untouched');
92
+ // Body got linked
93
+ assert.ok(
94
+ out.includes('Body text by [[team/mentors/lawrence-aronhime/PROFILE.md|Lawrence Aronhime]] here.'),
95
+ 'body should be linked'
96
+ );
97
+ });
98
+
99
+ // Test 5: idempotence
100
+ test('buildTeamLinks is idempotent (running twice = same output)', () => {
101
+ const input = 'Lawrence Aronhime opened the meeting.';
102
+ const once = wb.buildTeamLinks(input, profiles, {});
103
+ const twice = wb.buildTeamLinks(once, profiles, {});
104
+ assert.strictEqual(once, twice, 'second pass should not change output');
105
+ });
106
+
107
+ // Test 6: buildSectionLink
108
+ test('buildSectionLink returns exact format and honors display override', () => {
109
+ assert.strictEqual(
110
+ wb.buildSectionLink('business-model'),
111
+ '[[business-model/ROOM.md|business-model]]'
112
+ );
113
+ assert.strictEqual(
114
+ wb.buildSectionLink('business-model', { display: 'Business Model' }),
115
+ '[[business-model/ROOM.md|Business Model]]'
116
+ );
117
+ });
118
+
119
+ // Test 7: buildMeetingLink
120
+ test('buildMeetingLink strips date prefix and title-cases', () => {
121
+ const out = wb.buildMeetingLink('2026-04-09-align-strategy-session');
122
+ assert.strictEqual(
123
+ out,
124
+ '[[meetings/2026-04-09-align-strategy-session/summary.md|Align Strategy Session]]'
125
+ );
126
+ });
127
+
128
+ // Test 8: buildFiledToFooter
129
+ test('buildFiledToFooter returns both lines / one line appropriately', () => {
130
+ const both = wb.buildFiledToFooter({
131
+ targetPath: 'market-analysis/2026-04-09-tam.md',
132
+ meetingSlug: '2026-04-09-align-strategy-session',
133
+ });
134
+ assert.ok(both.includes('-> Full artifact: [[market-analysis/2026-04-09-tam.md]]'));
135
+ assert.ok(
136
+ both.includes('<- Source meeting: [[meetings/2026-04-09-align-strategy-session/summary.md|Align Strategy Session]]')
137
+ );
138
+ assert.strictEqual(both.split('\n').length, 2, 'should be 2 lines');
139
+
140
+ const one = wb.buildFiledToFooter({
141
+ targetPath: null,
142
+ meetingSlug: '2026-04-09-align-strategy-session',
143
+ });
144
+ assert.strictEqual(one.split('\n').length, 1, 'should be 1 line');
145
+ assert.ok(one.startsWith('<- Source meeting:'));
146
+ });
147
+
148
+ // Test 9: injectFiledToFooter idempotent + placement
149
+ test('injectFiledToFooter inserts after frontmatter and is idempotent', () => {
150
+ const input = '---\nmeeting_id: 2026-04-09-align-strategy-session\n---\nBody.';
151
+ const once = wb.injectFiledToFooter(input, {
152
+ targetPath: 'market-analysis/2026-04-09-tam.md',
153
+ meetingSlug: '2026-04-09-align-strategy-session',
154
+ });
155
+ assert.ok(once.includes('-> Full artifact: [[market-analysis/2026-04-09-tam.md]]'));
156
+ assert.ok(once.includes('<- Source meeting: [[meetings/2026-04-09-align-strategy-session/summary.md|Align Strategy Session]]'));
157
+ // Lines sit after frontmatter close
158
+ const fmIdx = once.indexOf('\n---');
159
+ const arrowIdx = once.indexOf('-> Full artifact');
160
+ assert.ok(arrowIdx > fmIdx, 'footer should be after frontmatter close');
161
+
162
+ const twice = wb.injectFiledToFooter(once, {
163
+ targetPath: 'market-analysis/2026-04-09-tam.md',
164
+ meetingSlug: '2026-04-09-align-strategy-session',
165
+ });
166
+ assert.strictEqual(once, twice, 'second injection should be a no-op');
167
+ });
168
+
169
+ // Test 10: graceful zero-profile behavior
170
+ test('buildTeamLinks with zero team profiles returns content unchanged', () => {
171
+ const input = 'Some body text mentioning Lawrence Aronhime.';
172
+ assert.strictEqual(wb.buildTeamLinks(input, [], {}), input);
173
+ assert.strictEqual(wb.buildTeamLinks(input, null, {}), input);
174
+ });
175
+
176
+ // ---------- Summary ----------
177
+ process.stdout.write(`\n${passed} passed, ${failed} failed\n`);
178
+ if (failed > 0) {
179
+ process.exit(1);
180
+ }
181
+ process.stdout.write('PASS\n');
182
+ process.exit(0);
@@ -0,0 +1,281 @@
1
+ 'use strict';
2
+ /**
3
+ * graph-links.cjs -- SQLite integration for the wiki
4
+ *
5
+ * Queries LazyGraph edges (SQLite via lazygraph-ops.cjs) and converts
6
+ * them into navigational hyperlinks, backlinks, "See also" sections,
7
+ * and full graph data for Cytoscape.js visualization.
8
+ *
9
+ * Exports: getPageLinks, getBacklinks, getSeeAlso, getGraphData
10
+ */
11
+
12
+ const path = require('path');
13
+ const fs = require('fs');
14
+
15
+ // Edge type display configuration
16
+ // BELONGS_TO and REASONING_INFORMS are structural -- skip for navigation
17
+ const EDGE_DISPLAY = {
18
+ INFORMS: { symbol: '\u2192', color: '#1E3A6E', cssClass: 'link-informs', label: 'Informs' },
19
+ CONTRADICTS: { symbol: '\u2297', color: '#A63D2F', cssClass: 'link-contradicts', label: 'Contradicts' },
20
+ CONVERGES: { symbol: '\u2295', color: '#C8A43C', cssClass: 'link-converges', label: 'Converges' },
21
+ ENABLES: { symbol: '\u25B6', color: '#2D6B4A', cssClass: 'link-enables', label: 'Enables' },
22
+ INVALIDATES: { symbol: '\u2298', color: '#B5602A', cssClass: 'link-invalidates', label: 'Invalidates' }
23
+ };
24
+
25
+ const NAV_EDGE_TYPES = Object.keys(EDGE_DISPLAY);
26
+
27
+ /**
28
+ * Safely require lazygraph-ops. Returns null if not available.
29
+ */
30
+ function getLazyGraphOps() {
31
+ try {
32
+ return require('../core/lazygraph-ops.cjs');
33
+ } catch (e) {
34
+ return null;
35
+ }
36
+ }
37
+
38
+ /**
39
+ * Check if a LazyGraph SQLite database exists for the room.
40
+ * @param {string} roomDir
41
+ * @returns {boolean}
42
+ */
43
+ function hasLazyGraph(roomDir) {
44
+ const dbPath = path.join(path.resolve(roomDir), '.mindrian', 'room.db');
45
+ return fs.existsSync(dbPath);
46
+ }
47
+
48
+ /**
49
+ * Get all outgoing navigational edges from an artifact.
50
+ *
51
+ * @param {string} roomDir - Path to room/ directory
52
+ * @param {string} artifactId - e.g. "problem-definition/market-trends"
53
+ * @returns {Promise<Array<{type, targetId, targetTitle, symbol, color, cssClass, label}>>}
54
+ */
55
+ async function getPageLinks(roomDir, artifactId) {
56
+ if (!hasLazyGraph(roomDir)) return [];
57
+
58
+ const ops = getLazyGraphOps();
59
+ if (!ops) return [];
60
+
61
+ let db, conn;
62
+ try {
63
+ ({ db, conn } = await ops.openGraph(roomDir));
64
+
65
+ // SQLite query: outgoing edges from this artifact to other artifacts
66
+ const rows = await ops.queryGraph(conn,
67
+ `SELECT e.type AS rel, e.target AS target, json_extract(n.properties, '$.title') AS title
68
+ FROM edges e
69
+ JOIN nodes n ON n.id = e.target AND n.type = 'Artifact'
70
+ WHERE e.source = '${esc(artifactId)}'`
71
+ );
72
+
73
+ const links = [];
74
+ for (const row of rows) {
75
+ const edgeType = row.rel;
76
+ const display = EDGE_DISPLAY[edgeType];
77
+ if (!display) continue; // Skip BELONGS_TO, REASONING_INFORMS, etc.
78
+
79
+ links.push({
80
+ type: edgeType,
81
+ targetId: row.target,
82
+ targetTitle: row.title || row.target,
83
+ symbol: display.symbol,
84
+ color: display.color,
85
+ cssClass: display.cssClass,
86
+ label: display.label
87
+ });
88
+ }
89
+
90
+ return links;
91
+ } catch (e) {
92
+ process.stderr.write(`[wiki] graph-links getPageLinks error: ${e.message}\n`);
93
+ return [];
94
+ } finally {
95
+ if (db) try { await ops.closeGraph(db); } catch (_) { /* ignore */ }
96
+ }
97
+ }
98
+
99
+ /**
100
+ * Get all incoming edges TO an artifact (backlinks -- "What links here").
101
+ *
102
+ * @param {string} roomDir - Path to room/ directory
103
+ * @param {string} artifactId - e.g. "problem-definition/market-trends"
104
+ * @returns {Promise<Array<{type, sourceId, sourceTitle, symbol, color}>>}
105
+ */
106
+ async function getBacklinks(roomDir, artifactId) {
107
+ if (!hasLazyGraph(roomDir)) return [];
108
+
109
+ const ops = getLazyGraphOps();
110
+ if (!ops) return [];
111
+
112
+ let db, conn;
113
+ try {
114
+ ({ db, conn } = await ops.openGraph(roomDir));
115
+
116
+ // SQLite query: incoming edges to this artifact from other artifacts
117
+ const rows = await ops.queryGraph(conn,
118
+ `SELECT e.type AS rel, e.source AS source, json_extract(n.properties, '$.title') AS title
119
+ FROM edges e
120
+ JOIN nodes n ON n.id = e.source AND n.type = 'Artifact'
121
+ WHERE e.target = '${esc(artifactId)}'`
122
+ );
123
+
124
+ const backlinks = [];
125
+ for (const row of rows) {
126
+ const edgeType = row.rel;
127
+ const display = EDGE_DISPLAY[edgeType];
128
+ if (!display) continue;
129
+
130
+ backlinks.push({
131
+ type: edgeType,
132
+ sourceId: row.source,
133
+ sourceTitle: row.title || row.source,
134
+ symbol: display.symbol,
135
+ color: display.color
136
+ });
137
+ }
138
+
139
+ return backlinks;
140
+ } catch (e) {
141
+ process.stderr.write(`[wiki] graph-links getBacklinks error: ${e.message}\n`);
142
+ return [];
143
+ } finally {
144
+ if (db) try { await ops.closeGraph(db); } catch (_) { /* ignore */ }
145
+ }
146
+ }
147
+
148
+ /**
149
+ * Get "See also" links -- CONVERGES and ENABLES edges grouped by theme.
150
+ *
151
+ * @param {string} roomDir - Path to room/ directory
152
+ * @param {string} artifactId - e.g. "problem-definition/market-trends"
153
+ * @returns {Promise<Array<{targetId, targetTitle, reason}>>}
154
+ */
155
+ async function getSeeAlso(roomDir, artifactId) {
156
+ if (!hasLazyGraph(roomDir)) return [];
157
+
158
+ const ops = getLazyGraphOps();
159
+ if (!ops) return [];
160
+
161
+ let db, conn;
162
+ try {
163
+ ({ db, conn } = await ops.openGraph(roomDir));
164
+
165
+ // CONVERGES edges (with optional theme from properties.term)
166
+ const convergesRows = await ops.queryGraph(conn,
167
+ `SELECT e.target AS target, json_extract(n.properties, '$.title') AS title, json_extract(e.properties, '$.term') AS theme
168
+ FROM edges e
169
+ JOIN nodes n ON n.id = e.target AND n.type = 'Artifact'
170
+ WHERE e.source = '${esc(artifactId)}' AND e.type = 'CONVERGES'`
171
+ );
172
+
173
+ // ENABLES edges
174
+ const enablesRows = await ops.queryGraph(conn,
175
+ `SELECT e.target AS target, json_extract(n.properties, '$.title') AS title
176
+ FROM edges e
177
+ JOIN nodes n ON n.id = e.target AND n.type = 'Artifact'
178
+ WHERE e.source = '${esc(artifactId)}' AND e.type = 'ENABLES'`
179
+ );
180
+
181
+ const seeAlso = [];
182
+ const seen = new Set();
183
+
184
+ for (const row of convergesRows) {
185
+ if (seen.has(row.target)) continue;
186
+ seen.add(row.target);
187
+ seeAlso.push({
188
+ targetId: row.target,
189
+ targetTitle: row.title || row.target,
190
+ reason: row.theme ? `Converges on: ${row.theme}` : 'Converging topic'
191
+ });
192
+ }
193
+
194
+ for (const row of enablesRows) {
195
+ if (seen.has(row.target)) continue;
196
+ seen.add(row.target);
197
+ seeAlso.push({
198
+ targetId: row.target,
199
+ targetTitle: row.title || row.target,
200
+ reason: 'Enables'
201
+ });
202
+ }
203
+
204
+ return seeAlso;
205
+ } catch (e) {
206
+ process.stderr.write(`[wiki] graph-links getSeeAlso error: ${e.message}\n`);
207
+ return [];
208
+ } finally {
209
+ if (db) try { await ops.closeGraph(db); } catch (_) { /* ignore */ }
210
+ }
211
+ }
212
+
213
+ /**
214
+ * Get all artifacts and edges for Cytoscape.js graph visualization.
215
+ *
216
+ * @param {string} roomDir - Path to room/ directory
217
+ * @returns {Promise<{nodes: Array<{id, title, section}>, edges: Array<{source, target, type}>}>}
218
+ */
219
+ async function getGraphData(roomDir) {
220
+ if (!hasLazyGraph(roomDir)) return { nodes: [], edges: [] };
221
+
222
+ const ops = getLazyGraphOps();
223
+ if (!ops) return { nodes: [], edges: [] };
224
+
225
+ let db, conn;
226
+ try {
227
+ ({ db, conn } = await ops.openGraph(roomDir));
228
+
229
+ // All artifact nodes
230
+ const nodeRows = await ops.queryGraph(conn,
231
+ `SELECT id, json_extract(properties, '$.title') AS title, json_extract(properties, '$.section') AS section
232
+ FROM nodes WHERE type = 'Artifact'`
233
+ );
234
+
235
+ const nodes = nodeRows.map(row => ({
236
+ id: row.id,
237
+ title: row.title || row.id,
238
+ section: row.section || ''
239
+ }));
240
+
241
+ // All navigational edges between artifacts (skip BELONGS_TO, REASONING_INFORMS)
242
+ const typePlaceholders = NAV_EDGE_TYPES.map(t => `'${t}'`).join(',');
243
+ const edgeRows = await ops.queryGraph(conn,
244
+ `SELECT e.source AS source, e.target AS target, e.type AS type
245
+ FROM edges e
246
+ JOIN nodes n1 ON n1.id = e.source AND n1.type = 'Artifact'
247
+ JOIN nodes n2 ON n2.id = e.target AND n2.type = 'Artifact'
248
+ WHERE e.type IN (${typePlaceholders})`
249
+ );
250
+
251
+ const edges = edgeRows.map(row => ({
252
+ source: row.source,
253
+ target: row.target,
254
+ type: row.type
255
+ }));
256
+
257
+ return { nodes, edges };
258
+ } catch (e) {
259
+ process.stderr.write(`[wiki] graph-links getGraphData error: ${e.message}\n`);
260
+ return { nodes: [], edges: [] };
261
+ } finally {
262
+ if (db) try { await ops.closeGraph(db); } catch (_) { /* ignore */ }
263
+ }
264
+ }
265
+
266
+ /**
267
+ * Escape single quotes for SQL string literals.
268
+ */
269
+ function esc(str) {
270
+ if (!str) return '';
271
+ return str.replace(/'/g, "''");
272
+ }
273
+
274
+ module.exports = {
275
+ getPageLinks,
276
+ getBacklinks,
277
+ getSeeAlso,
278
+ getGraphData,
279
+ EDGE_DISPLAY,
280
+ NAV_EDGE_TYPES
281
+ };
@@ -0,0 +1,229 @@
1
+ 'use strict';
2
+ /**
3
+ * page-renderer.cjs — Markdown rendering pipeline for the wiki
4
+ *
5
+ * Scans room/ directory for .md files, parses frontmatter,
6
+ * renders markdown with wikilinks, and generates TOC.
7
+ */
8
+
9
+ const fs = require('fs');
10
+ const path = require('path');
11
+ const markdownIt = require('markdown-it');
12
+ const matter = require('gray-matter');
13
+
14
+ // Directories to skip when scanning room/
15
+ const SKIP_DIRS = new Set(['.lazygraph', '.reasoning', 'meetings', 'node_modules', '.git']);
16
+ const SKIP_FILES = new Set(['STATE.md']);
17
+
18
+ // Section color mapping (matches build-graph)
19
+ const SECTION_COLORS = {
20
+ 'problem-definition': '#A63D2F',
21
+ 'market-analysis': '#C8A43C',
22
+ 'solution-design': '#5C5A56',
23
+ 'business-model': '#2D6B4A',
24
+ 'competitive-analysis': '#B5602A',
25
+ 'team-execution': '#1E3A6E',
26
+ 'team': '#1E3A6E',
27
+ 'legal-ip': '#6B4E8B',
28
+ 'financial-model': '#2A6B5E',
29
+ 'opportunity-bank': '#C8A43C',
30
+ 'funding': '#2D6B4A',
31
+ 'personas': '#6B4E8B'
32
+ };
33
+
34
+ /**
35
+ * Scan room/ directory recursively for .md files.
36
+ * Returns { pages: Map, sections: Map }
37
+ */
38
+ function scanRoom(roomDir) {
39
+ const absRoom = path.resolve(roomDir);
40
+ const pages = new Map(); // id -> { path, section, title, frontmatter, content }
41
+ const sections = new Map(); // section-name -> { label, color, pages: [] }
42
+
43
+ if (!fs.existsSync(absRoom)) {
44
+ return { pages, sections };
45
+ }
46
+
47
+ const entries = fs.readdirSync(absRoom, { withFileTypes: true });
48
+
49
+ for (const entry of entries) {
50
+ if (!entry.isDirectory()) {
51
+ // Top-level .md files (e.g., README.md at room root)
52
+ if (entry.name.endsWith('.md') && !SKIP_FILES.has(entry.name)) {
53
+ const filePath = path.join(absRoom, entry.name);
54
+ const page = parsePage(filePath, '_root', absRoom);
55
+ pages.set(page.id, page);
56
+ }
57
+ continue;
58
+ }
59
+
60
+ const sectionName = entry.name;
61
+ if (SKIP_DIRS.has(sectionName)) continue;
62
+
63
+ const sectionDir = path.join(absRoom, sectionName);
64
+ const label = sectionName
65
+ .split('-')
66
+ .map(w => w.charAt(0).toUpperCase() + w.slice(1))
67
+ .join(' ');
68
+ const color = SECTION_COLORS[sectionName] || '#5C5A56';
69
+
70
+ const sectionPages = [];
71
+
72
+ // Read .md files in section directory (one level deep)
73
+ const sectionEntries = fs.readdirSync(sectionDir, { withFileTypes: true });
74
+ for (const se of sectionEntries) {
75
+ if (!se.isFile() || !se.name.endsWith('.md')) continue;
76
+ if (SKIP_FILES.has(se.name)) continue;
77
+
78
+ const filePath = path.join(sectionDir, se.name);
79
+ const page = parsePage(filePath, sectionName, absRoom);
80
+ pages.set(page.id, page);
81
+ sectionPages.push(page.id);
82
+ }
83
+
84
+ sections.set(sectionName, { label, color, pages: sectionPages });
85
+ }
86
+
87
+ return { pages, sections };
88
+ }
89
+
90
+ /**
91
+ * Parse a single .md file into a page object.
92
+ */
93
+ function parsePage(filePath, section, roomDir) {
94
+ const raw = fs.readFileSync(filePath, 'utf8');
95
+ const { data: frontmatter, content } = matter(raw);
96
+ const basename = path.basename(filePath, '.md');
97
+ const id = section === '_root' ? basename : `${section}/${basename}`;
98
+ const title = frontmatter.title || basename
99
+ .split('-')
100
+ .map(w => w.charAt(0).toUpperCase() + w.slice(1))
101
+ .join(' ');
102
+
103
+ return { id, path: filePath, section, title, frontmatter, content };
104
+ }
105
+
106
+ /**
107
+ * Build lookup index for wikilink resolution.
108
+ * Maps lowercase title / id variants to wiki URLs.
109
+ */
110
+ function buildPageIndex(pages) {
111
+ const index = new Map();
112
+ for (const [id, page] of pages) {
113
+ const url = `/wiki/${id}`;
114
+ index.set(id.toLowerCase(), url);
115
+ index.set(page.title.toLowerCase(), url);
116
+ // Also map just the basename
117
+ const base = id.includes('/') ? id.split('/').pop() : id;
118
+ if (!index.has(base.toLowerCase())) {
119
+ index.set(base.toLowerCase(), url);
120
+ }
121
+ }
122
+ return index;
123
+ }
124
+
125
+ /**
126
+ * Create configured markdown-it instance with wikilinks.
127
+ */
128
+ function createMarkdownRenderer(pageIndex) {
129
+ const md = markdownIt({
130
+ html: true,
131
+ linkify: true,
132
+ typographer: true
133
+ });
134
+
135
+ // Wikilinks plugin — resolve [[page-name]] to wiki URLs
136
+ try {
137
+ const wikilinks = require('@ig3/markdown-it-wikilinks');
138
+ md.use(wikilinks({
139
+ baseURL: '/wiki/',
140
+ uriSuffix: '',
141
+ makeAllLinksAbsolute: true,
142
+ postProcessPageName: (pageName) => {
143
+ // Try exact lookup first
144
+ const lower = pageName.toLowerCase().replace(/\s+/g, '-');
145
+ if (pageIndex && pageIndex.has(lower)) {
146
+ // Return just the path part after /wiki/
147
+ return pageIndex.get(lower).replace('/wiki/', '');
148
+ }
149
+ return lower;
150
+ }
151
+ }));
152
+ } catch (e) {
153
+ // Wikilinks plugin not installed — render as plain text
154
+ // This is non-fatal; links just won't resolve
155
+ }
156
+
157
+ return md;
158
+ }
159
+
160
+ /**
161
+ * Render a page object to HTML with TOC and wikilink extraction.
162
+ * @param {object} pageData - Page object from scanRoom
163
+ * @param {Map} pageIndex - Wikilink resolution index
164
+ * @param {Set} [contradictsTargets] - Set of artifact IDs that have CONTRADICTS relationship from this page
165
+ * @returns {{html, toc, frontmatter, wikilinks}}
166
+ */
167
+ function renderPage(pageData, pageIndex, contradictsTargets) {
168
+ const md = createMarkdownRenderer(pageIndex);
169
+ let html = md.render(pageData.content);
170
+
171
+ // Post-process: mark CONTRADICTS wikilinks with special class
172
+ if (contradictsTargets && contradictsTargets.size > 0) {
173
+ // Match rendered wikilinks (from markdown-it-wikilinks) and add contradicts class
174
+ html = html.replace(/<a href="\/wiki\/([^"]+)"([^>]*)class="wikilink"([^>]*)>/g, (match, href, before, after) => {
175
+ const normalizedHref = href.toLowerCase();
176
+ for (const target of contradictsTargets) {
177
+ // Check if the link resolves to a contradicts target (by section or full id)
178
+ if (normalizedHref === target.toLowerCase() ||
179
+ normalizedHref.startsWith(target.toLowerCase().split('/')[0])) {
180
+ return `<a href="/wiki/${href}"${before}class="wikilink wikilink-contradicts"${after}>`;
181
+ }
182
+ }
183
+ return match;
184
+ });
185
+ }
186
+
187
+ // Extract TOC from rendered HTML (h2/h3)
188
+ const toc = extractTOC(html);
189
+
190
+ // Extract wikilinks from source content
191
+ const wikilinks = [];
192
+ const wlRegex = /\[\[([^\]]+)\]\]/g;
193
+ let match;
194
+ while ((match = wlRegex.exec(pageData.content)) !== null) {
195
+ wikilinks.push(match[1]);
196
+ }
197
+
198
+ return {
199
+ html,
200
+ toc,
201
+ frontmatter: pageData.frontmatter,
202
+ wikilinks
203
+ };
204
+ }
205
+
206
+ /**
207
+ * Extract TOC entries from rendered HTML.
208
+ * Returns array of { level, text, id }.
209
+ */
210
+ function extractTOC(html) {
211
+ const toc = [];
212
+ const headingRegex = /<h([23])[^>]*(?:id="([^"]*)")?[^>]*>(.*?)<\/h[23]>/gi;
213
+ let match;
214
+ while ((match = headingRegex.exec(html)) !== null) {
215
+ const level = parseInt(match[1], 10);
216
+ const text = match[3].replace(/<[^>]+>/g, '').trim();
217
+ const id = match[2] || text.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, '');
218
+ toc.push({ level, text, id });
219
+ }
220
+ return toc;
221
+ }
222
+
223
+ module.exports = {
224
+ scanRoom,
225
+ renderPage,
226
+ buildPageIndex,
227
+ extractTOC,
228
+ SECTION_COLORS
229
+ };