@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,661 @@
1
+ /**
2
+ * MindrianOS Plugin -- Intelligence Cascade (Shared Module)
3
+ * Shared cascade body (steps 1-11) called by both the CLI PostToolUse hook
4
+ * (via mindrian-tools.cjs cascade) and MCP tool handlers after write ops.
5
+ *
6
+ * Steps: (1) classify-insight, (2) graph-index, (3) compute-hsi.py,
7
+ * (4) detect-reverse-salients.py, (5) hsi-to-graph.cjs, (6) generate-presentation,
8
+ * (7) inject artifact ID + (7b) git commit, (8) compute-state, (9) build-graph,
9
+ * (10) analyze-room + persistIntelligence, (11) extractOpportunities + bank.
10
+ *
11
+ * Optimization layers (Phase 54): HSI Debounce 30s (HOOK-01), Analyze-Room
12
+ * Cache 5min TTL (HOOK-02), Write Batching 500ms window (HOOK-03). Binary
13
+ * files route to file-asset. Every step wrapped in try/catch; failures never
14
+ * break the cascade.
15
+ *
16
+ * Phase 87-03: cascade body lives once in private `_runCascadeSteps`; both
17
+ * `runCascade` (single artifact, flat return) and `queueCascade` (batch,
18
+ * batch return) delegate to it after their own guards + debounce checks.
19
+ *
20
+ * @module intelligence-cascade
21
+ */
22
+
23
+ 'use strict';
24
+
25
+ const fs = require('fs');
26
+ const path = require('path');
27
+ const { execFile, execSync } = require('child_process');
28
+
29
+ const PLUGIN_ROOT = path.resolve(__dirname, '../..');
30
+ const SCRIPTS_DIR = path.join(PLUGIN_ROOT, 'scripts');
31
+ const gitOps = require('./git-ops.cjs');
32
+ const { extractTitle } = require('./artifact-id.cjs');
33
+ const { extractOpportunities } = require('./opportunity-extractor.cjs');
34
+ const { bankOpportunity } = require('./opportunity-ops.cjs');
35
+ // Phase 87-07 (CASCADE-06): bounded LRU drop-in for the three long-running
36
+ // in-memory caches below. Map had no eviction -- distinct-room growth in a
37
+ // long-lived MCP server leaked unbounded. LRU exposes Map-parity iteration
38
+ // (entries/keys/values/forEach/clear/[Symbol.iterator]) so existing call
39
+ // sites (e.g. .get/.set/.has/.delete/.entries/.forEach) keep working with
40
+ // zero refactoring. Cap 100 -- generous for single-user sessions, bounded
41
+ // for team MCP servers.
42
+ const { LRU } = require('./lru-cache.cjs');
43
+
44
+ // HSI Debounce (HOOK-01): roomDir -> last HSI computation timestamp.
45
+ /** @type {LRU} */
46
+ const lastHsiByRoom = new LRU(100);
47
+ const HSI_DEBOUNCE_MS = 30000; // 30 seconds
48
+
49
+ // SEC-03 (Phase 87-01): HSI compute timeouts bumped from 5000ms to 30000ms.
50
+ // Real rooms with 50+ artifacts exceed 5s on compute-hsi.py and abort mid-run.
51
+ // HSI_TIMEOUT_MS is the single source of truth for HSI-path spawn ceilings.
52
+ // After Phase 87-03 cascade deduplication, HSI_TIMEOUT_MS is applied at 6
53
+ // unique spawn sites inside `_runCascadeSteps` (classify, check-deps,
54
+ // compute-hsi, reverse-salients, hsi-bridge, compute-state) rather than 12
55
+ // duplicated sites across runCascade + queueCascade. Every HSI-path spawn
56
+ // reads HSI_TIMEOUT_MS; future bumps remain a one-line change.
57
+ // The 1 intentional 15000ms site (generate-presentation.cjs) stays untouched.
58
+ const HSI_TIMEOUT_MS = 30000;
59
+
60
+ // Write Batch Queue (HOOK-03): roomDir -> { files, timeout, waiters, options }.
61
+ const BATCH_WINDOW_MS = 500;
62
+ /** @type {LRU} */
63
+ const batchQueues = new LRU(100);
64
+
65
+ // Analyze-Room Cache (HOOK-02): STATE.md hash -> cached analyze-room result.
66
+ /** @type {LRU} */
67
+ const analyzeRoomCache = new LRU(100);
68
+ const ANALYZE_CACHE_TTL = 300000; // 5 minutes
69
+
70
+ /** djb2 hash for cache keys (non-crypto, sufficient for content comparison). */
71
+ function djb2Hash(str) {
72
+ let hash = 5381;
73
+ for (let i = 0; i < str.length; i++) {
74
+ hash = ((hash << 5) + hash + str.charCodeAt(i)) | 0;
75
+ }
76
+ return hash.toString(36);
77
+ }
78
+
79
+ /** Get cached analyze-room result if STATE.md unchanged within TTL. */
80
+ function getCachedAnalysis(roomDir) {
81
+ const statePath = path.join(roomDir, 'STATE.md');
82
+ let stateContent = '';
83
+ try {
84
+ stateContent = fs.readFileSync(statePath, 'utf8');
85
+ } catch (_e) {
86
+ // No STATE.md -- nothing to cache
87
+ return { cached: false, result: null };
88
+ }
89
+
90
+ const hash = djb2Hash(stateContent);
91
+ const entry = analyzeRoomCache.get(roomDir);
92
+
93
+ if (entry && entry.hash === hash && (Date.now() - entry.timestamp) < ANALYZE_CACHE_TTL) {
94
+ return { cached: true, result: entry.result };
95
+ }
96
+
97
+ return { cached: false, result: null };
98
+ }
99
+
100
+ /** Store an analyze-room result in the cache. */
101
+ function setAnalysisCache(roomDir, result) {
102
+ const statePath = path.join(roomDir, 'STATE.md');
103
+ let stateContent = '';
104
+ try {
105
+ stateContent = fs.readFileSync(statePath, 'utf8');
106
+ } catch (_e) {
107
+ return;
108
+ }
109
+ analyzeRoomCache.set(roomDir, {
110
+ hash: djb2Hash(stateContent),
111
+ result,
112
+ timestamp: Date.now()
113
+ });
114
+ }
115
+
116
+ /** Invalidate the analyze-room cache for a specific room. */
117
+ function invalidateAnalysisCache(roomDir) {
118
+ analyzeRoomCache.delete(roomDir);
119
+ }
120
+
121
+ /**
122
+ * Inject a classification field into the YAML frontmatter of a markdown file.
123
+ * Idempotent: skips if classification: already exists or no frontmatter found.
124
+ */
125
+ function injectClassification(filePath, classification) {
126
+ if (!classification) return false;
127
+
128
+ let content;
129
+ try {
130
+ content = fs.readFileSync(filePath, 'utf8');
131
+ } catch (_e) {
132
+ return false;
133
+ }
134
+
135
+ // Must have frontmatter
136
+ if (!content.startsWith('---\n')) return false;
137
+
138
+ // Find closing ---
139
+ const fmEnd = content.indexOf('\n---', 4);
140
+ if (fmEnd === -1) return false;
141
+
142
+ // Check if classification: already exists (idempotent)
143
+ const frontmatter = content.slice(4, fmEnd);
144
+ if (frontmatter.includes('classification:')) return false;
145
+
146
+ // Insert classification line before the closing ---
147
+ const before = content.slice(0, fmEnd);
148
+ const after = content.slice(fmEnd);
149
+ const updated = before + '\nclassification: ' + classification + after;
150
+
151
+ fs.writeFileSync(filePath, updated, 'utf8');
152
+ return true;
153
+ }
154
+
155
+ // Binary file extensions that route to file-asset instead of markdown cascade.
156
+ const BINARY_EXTENSIONS = new Set([
157
+ 'pdf', 'png', 'jpg', 'jpeg', 'gif', 'svg', 'webp',
158
+ 'mp4', 'mov', 'avi', 'mkv', 'webm',
159
+ 'mp3', 'wav', 'm4a', 'ogg', 'flac', 'aac',
160
+ 'pptx', 'xlsx', 'docx', 'csv', 'zip', 'tar', 'gz'
161
+ ]);
162
+
163
+ // Known room sections for binary asset filing
164
+ const KNOWN_SECTIONS = [
165
+ 'problem-definition', 'market-analysis', 'solution-design',
166
+ 'business-model', 'competitive-analysis', 'team-execution',
167
+ 'legal-ip', 'financial-model'
168
+ ];
169
+
170
+ /** True if filePath is inside a room directory (contains /room/ or /rooms/). */
171
+ function isRoomFile(filePath) {
172
+ return filePath.includes('/room/') || filePath.includes('/rooms/');
173
+ }
174
+
175
+ /** Walk up from filePath looking for STATE.md; returns roomDir or null. */
176
+ function findRoomDir(filePath) {
177
+ let checkDir = path.dirname(filePath);
178
+ while (checkDir !== '/' && checkDir !== '.') {
179
+ if (fs.existsSync(path.join(checkDir, 'STATE.md'))) return checkDir;
180
+ checkDir = path.dirname(checkDir);
181
+ }
182
+ return null;
183
+ }
184
+
185
+ /** Determine the section name for a binary asset. Mirrors scripts/post-write. */
186
+ function detectBinarySection(roomDir, filePath) {
187
+ const relPath = path.relative(roomDir, filePath);
188
+
189
+ // Check known sections
190
+ for (const section of KNOWN_SECTIONS) {
191
+ if (relPath.startsWith(section + '/') || relPath.startsWith('assets/' + section + '/')) {
192
+ return section;
193
+ }
194
+ }
195
+
196
+ // Check meetings
197
+ if (relPath.startsWith('meetings/')) {
198
+ return 'meetings';
199
+ }
200
+
201
+ // Fallback: parent directory name
202
+ return path.basename(path.dirname(filePath)) || 'unknown';
203
+ }
204
+
205
+ /**
206
+ * Phase 87-03: shared cascade body (steps 1-11). Private helper; runCascade
207
+ * and queueCascade both delegate. Caller pre-resolves roomDir, filters
208
+ * binary files, computes options.debounced. See 87-03 CONTEXT.md.
209
+ *
210
+ * Return shape: { perFile[], hsi, reverseSalients, hsiBridge, presentation,
211
+ * computeState, buildGraph, proactiveIntelligence, opportunityExtraction,
212
+ * hsiRanAt }. Caller updates lastHsiByRoom using hsiRanAt; helper never
213
+ * mutates the module-level debounce Map.
214
+ *
215
+ * @param {string} roomDir
216
+ * @param {Array<{filePath: string, section?: string}>} artifacts
217
+ * @param {{trigger: string, debounced: boolean, frameworkHint?: string}} options
218
+ */
219
+ async function _runCascadeSteps(roomDir, artifacts, options) {
220
+ const { debounced = false, frameworkHint } = options || {};
221
+
222
+ const stepsResult = {
223
+ perFile: [],
224
+ hsi: null,
225
+ reverseSalients: null,
226
+ hsiBridge: null,
227
+ presentation: null,
228
+ computeState: null,
229
+ buildGraph: null,
230
+ proactiveIntelligence: null,
231
+ opportunityExtraction: null,
232
+ hsiRanAt: null
233
+ };
234
+
235
+ // Per-artifact steps (1, 2, 7, 7b) -- classify, graph-index, artifact-id, git commit.
236
+ for (const art of artifacts) {
237
+ const fp = art.filePath;
238
+ const isMd = path.extname(fp).slice(1).toLowerCase() === 'md';
239
+
240
+ const entry = {
241
+ filePath: fp,
242
+ classification: null,
243
+ graphIndex: null,
244
+ artifactId: null,
245
+ gitCommit: null
246
+ };
247
+
248
+ if (isMd) {
249
+ // Step 1: classify-insight + inject into frontmatter.
250
+ try {
251
+ const classifyScript = path.join(SCRIPTS_DIR, 'classify-insight');
252
+ const classifyOutput = execSync(`bash "${classifyScript}" "${fp}"`, {
253
+ timeout: HSI_TIMEOUT_MS,
254
+ encoding: 'utf8',
255
+ stdio: ['ignore', 'pipe', 'pipe']
256
+ }).trim();
257
+ entry.classification = classifyOutput || 'UNCERTAIN';
258
+ injectClassification(fp, entry.classification);
259
+ } catch (e) {
260
+ entry.classification = { status: 'error', message: e.message };
261
+ }
262
+
263
+ // Step 2: graph-index (SQLite artifact indexing).
264
+ try {
265
+ const graphOps = require('./graph-ops.cjs');
266
+ const indexResult = await graphOps.indexArtifact(roomDir, fp);
267
+ entry.graphIndex = { status: 'ok', ...indexResult };
268
+ } catch (e) {
269
+ entry.graphIndex = { status: 'error', message: e.message };
270
+ }
271
+
272
+ // Step 7: inject deterministic artifact ID.
273
+ try {
274
+ const artifactId = require('./artifact-id.cjs');
275
+ const injected = artifactId.injectArtifactId(roomDir, fp);
276
+ entry.artifactId = { status: injected ? 'injected' : 'skipped' };
277
+ } catch (e) {
278
+ entry.artifactId = { status: 'error', message: e.message };
279
+ }
280
+
281
+ // Step 7b: git commit the filed artifact.
282
+ try {
283
+ const fileContent = fs.readFileSync(fp, 'utf8');
284
+ const title = extractTitle(fileContent, fp);
285
+ const sectionName = path.basename(path.dirname(fp));
286
+ const commitMsg = `file(${sectionName}): ${title}`;
287
+ const commitResult = gitOps.commitArtifact(roomDir, fp, commitMsg);
288
+ entry.gitCommit = { status: commitResult.committed ? 'ok' : 'skipped', message: commitMsg };
289
+ } catch (e) {
290
+ entry.gitCommit = { status: 'error', message: e.message };
291
+ }
292
+ }
293
+
294
+ stepsResult.perFile.push(entry);
295
+ }
296
+
297
+ // Shared steps (3-6, 8-11) -- run once per roomDir for the whole batch.
298
+
299
+ // Steps 3-5: HSI compute + reverse salients + bridge. Skip when debounced
300
+ // or when room.db has not been created yet.
301
+ const anyMd = artifacts.some(a => path.extname(a.filePath).slice(1).toLowerCase() === 'md');
302
+ const roomDbPath = path.join(roomDir, '.mindrian', 'room.db');
303
+ if (anyMd && fs.existsSync(roomDbPath)) {
304
+ if (debounced) {
305
+ const lastHsi = lastHsiByRoom.get(roomDir) || 0;
306
+ stepsResult.hsi = { status: 'debounced', lastRun: new Date(lastHsi).toISOString() };
307
+ } else {
308
+ let hsiSuccess = false;
309
+ try {
310
+ execSync(`bash "${path.join(SCRIPTS_DIR, 'check-hsi-deps')}"`, {
311
+ timeout: HSI_TIMEOUT_MS,
312
+ stdio: ['ignore', 'pipe', 'pipe']
313
+ });
314
+ try {
315
+ execSync(`python3 "${path.join(SCRIPTS_DIR, 'compute-hsi.py')}" "${roomDir}"`, {
316
+ timeout: HSI_TIMEOUT_MS,
317
+ stdio: ['ignore', 'pipe', 'pipe']
318
+ });
319
+ stepsResult.hsi = { status: 'ok' };
320
+ hsiSuccess = true;
321
+ stepsResult.hsiRanAt = Date.now(); // caller updates lastHsiByRoom
322
+ } catch (e) {
323
+ stepsResult.hsi = { status: 'error', message: e.message };
324
+ }
325
+ } catch (e) {
326
+ stepsResult.hsi = { status: 'skipped', reason: 'HSI deps not available' };
327
+ }
328
+
329
+ if (hsiSuccess) {
330
+ try {
331
+ execSync(`python3 "${path.join(SCRIPTS_DIR, 'detect-reverse-salients.py')}" "${roomDir}"`, {
332
+ timeout: HSI_TIMEOUT_MS,
333
+ stdio: ['ignore', 'pipe', 'pipe']
334
+ });
335
+ stepsResult.reverseSalients = { status: 'ok' };
336
+ } catch (e) {
337
+ stepsResult.reverseSalients = { status: 'error', message: e.message };
338
+ }
339
+ }
340
+
341
+ if (fs.existsSync(path.join(roomDir, '.hsi-results.json'))) {
342
+ try {
343
+ execSync(`node "${path.join(SCRIPTS_DIR, 'hsi-to-graph.cjs')}" "${roomDir}"`, {
344
+ timeout: HSI_TIMEOUT_MS,
345
+ stdio: ['ignore', 'pipe', 'pipe']
346
+ });
347
+ stepsResult.hsiBridge = { status: 'ok' };
348
+ } catch (e) {
349
+ stepsResult.hsiBridge = { status: 'error', message: e.message };
350
+ }
351
+ }
352
+ }
353
+ }
354
+
355
+ // Step 6: presentation regeneration.
356
+ const presentationDir = path.join(roomDir, 'exports', 'presentation');
357
+ if (fs.existsSync(presentationDir)) {
358
+ try {
359
+ execSync(`node "${path.join(SCRIPTS_DIR, 'generate-presentation.cjs')}" "${roomDir}" --output "${presentationDir}"`, {
360
+ timeout: 15000,
361
+ stdio: ['ignore', 'pipe', 'pipe']
362
+ });
363
+ stepsResult.presentation = { status: 'ok' };
364
+ } catch (e) {
365
+ stepsResult.presentation = { status: 'error', message: e.message };
366
+ }
367
+ }
368
+
369
+ // Step 8: compute-state (recompute STATE.md).
370
+ try {
371
+ execSync(`bash "${path.join(SCRIPTS_DIR, 'compute-state')}" "${roomDir}"`, {
372
+ timeout: HSI_TIMEOUT_MS,
373
+ stdio: ['ignore', 'pipe', 'pipe']
374
+ });
375
+ stepsResult.computeState = { status: 'ok' };
376
+ } catch (e) {
377
+ stepsResult.computeState = { status: 'error', message: e.message };
378
+ }
379
+
380
+ // Step 9: build-graph (rebuild dashboard graph.json).
381
+ try {
382
+ execSync(`bash "${path.join(SCRIPTS_DIR, 'build-graph')}" "${roomDir}"`, {
383
+ timeout: 10000,
384
+ stdio: ['ignore', 'pipe', 'pipe']
385
+ });
386
+ stepsResult.buildGraph = { status: 'ok' };
387
+ } catch (e) {
388
+ stepsResult.buildGraph = { status: 'error', message: e.message };
389
+ }
390
+
391
+ // Step 10: analyze-room + persistIntelligence. Phase 84-05 also reads
392
+ // graph findings via readGraphFindings().
393
+ let analyzeOutput = '';
394
+ try {
395
+ analyzeOutput = execSync(`bash "${path.join(SCRIPTS_DIR, 'analyze-room')}" "${roomDir}"`, {
396
+ timeout: 10000,
397
+ encoding: 'utf8',
398
+ stdio: ['ignore', 'pipe', 'pipe']
399
+ });
400
+ const proactiveIntel = require('./proactive-intelligence.cjs');
401
+ const intelResult = proactiveIntel.persistIntelligence(roomDir, analyzeOutput);
402
+ const parsed = proactiveIntel.parseAnalyzeOutput(analyzeOutput);
403
+ const newFindings = proactiveIntel.getNewFindings(roomDir, parsed);
404
+ stepsResult.proactiveIntelligence = { status: 'ok', ...intelResult, newFindings };
405
+ } catch (e) {
406
+ stepsResult.proactiveIntelligence = { status: 'error', message: e.message };
407
+ }
408
+
409
+ // Step 11: extractOpportunities + bankOpportunity. Framework-name precedence:
410
+ // frameworkHint from caller > parsed "CLASSIFIED:<fw>:<conf>" > 'cascade'.
411
+ if (stepsResult.proactiveIntelligence && stepsResult.proactiveIntelligence.status === 'ok') {
412
+ try {
413
+ const proactiveIntel = require('./proactive-intelligence.cjs');
414
+ const parsed = proactiveIntel.parseAnalyzeOutput(analyzeOutput);
415
+ let frameworkName = frameworkHint || 'cascade';
416
+ if (!frameworkHint && stepsResult.perFile.length > 0) {
417
+ const firstCls = stepsResult.perFile[0].classification;
418
+ if (typeof firstCls === 'string' && firstCls.startsWith('CLASSIFIED:')) {
419
+ const parts = firstCls.split(':');
420
+ if (parts[1]) frameworkName = parts[1];
421
+ }
422
+ }
423
+ const opportunities = extractOpportunities(parsed, frameworkName, roomDir);
424
+ const banked = [];
425
+ for (const opp of opportunities) {
426
+ const result = bankOpportunity(roomDir, opp);
427
+ if (result.banked || result.updated) banked.push(result);
428
+ }
429
+ stepsResult.opportunityExtraction = {
430
+ status: 'ok',
431
+ extracted: opportunities.length,
432
+ banked: banked.filter(b => b.banked).length,
433
+ updated: banked.filter(b => b.updated).length
434
+ };
435
+ } catch (e) {
436
+ stepsResult.opportunityExtraction = { status: 'error', message: e.message };
437
+ }
438
+ }
439
+
440
+ invalidateAnalysisCache(roomDir);
441
+ return stepsResult;
442
+ }
443
+
444
+ /**
445
+ * Run the cascade for a single filed artifact. Thin wrapper around
446
+ * `_runCascadeSteps`: validates inputs, handles binary early-return, computes
447
+ * HSI debounce, delegates, then flattens the internal shape to the flat
448
+ * public shape (classification/graphIndex/artifactId/gitCommit at top level).
449
+ */
450
+ async function runCascade(roomDir, { trigger, filePath, section } = {}) {
451
+ const results = {
452
+ trigger,
453
+ roomDir,
454
+ filePath: filePath || null,
455
+ skipped: false,
456
+ classification: null,
457
+ graphIndex: null,
458
+ hsi: null,
459
+ reverseSalients: null,
460
+ hsiBridge: null,
461
+ presentation: null,
462
+ binaryAsset: null,
463
+ gitCommit: null
464
+ };
465
+
466
+ // Guard: no file path means nothing to process
467
+ if (!filePath) {
468
+ results.skipped = true;
469
+ results.skipReason = 'no filePath provided';
470
+ return results;
471
+ }
472
+
473
+ // Guard: file must be inside a room
474
+ if (!isRoomFile(filePath)) {
475
+ results.skipped = true;
476
+ results.skipReason = 'filePath not inside a room directory';
477
+ return results;
478
+ }
479
+
480
+ // Resolve roomDir if not provided or verify it exists
481
+ const resolvedRoomDir = roomDir || findRoomDir(filePath);
482
+ if (!resolvedRoomDir || !fs.existsSync(resolvedRoomDir)) {
483
+ results.skipped = true;
484
+ results.skipReason = 'roomDir not found or does not exist';
485
+ return results;
486
+ }
487
+ results.roomDir = resolvedRoomDir;
488
+
489
+ // Skip STATE.md and ROOM.md (not artifacts)
490
+ const basename = path.basename(filePath);
491
+ if (basename === 'STATE.md' || basename === 'ROOM.md') {
492
+ results.skipped = true;
493
+ results.skipReason = `${basename} is not an artifact`;
494
+ return results;
495
+ }
496
+
497
+ // Detect file extension
498
+ const ext = path.extname(filePath).slice(1).toLowerCase();
499
+
500
+ // -- Binary file handling (NOT part of _runCascadeSteps) --
501
+ if (BINARY_EXTENSIONS.has(ext)) {
502
+ try {
503
+ const assetSection = section || detectBinarySection(resolvedRoomDir, filePath);
504
+ const fileAssetScript = path.join(SCRIPTS_DIR, 'file-asset');
505
+ execFile('bash', [fileAssetScript, resolvedRoomDir, filePath, assetSection], {
506
+ timeout: 10000,
507
+ stdio: ['ignore', 'pipe', 'pipe']
508
+ }, () => {}); // fire-and-forget
509
+ results.binaryAsset = { section: assetSection, status: 'dispatched' };
510
+ } catch (e) {
511
+ results.binaryAsset = { status: 'error', message: e.message };
512
+ }
513
+ return results;
514
+ }
515
+
516
+ // HSI Debounce (HOOK-01): compute flag BEFORE helper entry so the
517
+ // lastHsiByRoom Map stays owned by public entry points.
518
+ const lastHsi = lastHsiByRoom.get(resolvedRoomDir) || 0;
519
+ const debounced = (Date.now() - lastHsi) < HSI_DEBOUNCE_MS;
520
+
521
+ const stepsResult = await _runCascadeSteps(
522
+ resolvedRoomDir,
523
+ [{ filePath, section }],
524
+ { trigger, debounced }
525
+ );
526
+
527
+ if (stepsResult.hsiRanAt !== null) {
528
+ lastHsiByRoom.set(resolvedRoomDir, stepsResult.hsiRanAt);
529
+ }
530
+
531
+ // Adapt internal shape -> flat public shape. Spread perFile[0] onto results.
532
+ const first = stepsResult.perFile[0] || {};
533
+ results.classification = first.classification !== undefined ? first.classification : null;
534
+ results.graphIndex = first.graphIndex !== undefined ? first.graphIndex : null;
535
+ if (first.artifactId !== undefined) results.artifactId = first.artifactId;
536
+ if (first.gitCommit !== undefined) results.gitCommit = first.gitCommit;
537
+
538
+ results.hsi = stepsResult.hsi;
539
+ results.reverseSalients = stepsResult.reverseSalients;
540
+ results.hsiBridge = stepsResult.hsiBridge;
541
+ results.presentation = stepsResult.presentation;
542
+ if (stepsResult.computeState !== null) results.computeState = stepsResult.computeState;
543
+ if (stepsResult.buildGraph !== null) results.buildGraph = stepsResult.buildGraph;
544
+ if (stepsResult.proactiveIntelligence !== null) results.proactiveIntelligence = stepsResult.proactiveIntelligence;
545
+ if (stepsResult.opportunityExtraction !== null) results.opportunityExtraction = stepsResult.opportunityExtraction;
546
+
547
+ return results;
548
+ }
549
+
550
+ /**
551
+ * Queue a cascade request for batched execution. Collects multiple writes
552
+ * within a 500ms window; steps 1-2 run per-file, steps 3-11 run once per
553
+ * batch (inside the shared `_runCascadeSteps` helper).
554
+ */
555
+ function queueCascade(roomDir, { trigger, filePath, section } = {}) {
556
+ if (!filePath) {
557
+ return Promise.resolve({
558
+ trigger,
559
+ roomDir,
560
+ skipped: true,
561
+ skipReason: 'no filePath provided'
562
+ });
563
+ }
564
+
565
+ return new Promise((resolve, reject) => {
566
+ let batch = batchQueues.get(roomDir);
567
+
568
+ if (!batch) {
569
+ batch = {
570
+ files: [],
571
+ timeout: null,
572
+ waiters: [],
573
+ options: { trigger, section }
574
+ };
575
+ batchQueues.set(roomDir, batch);
576
+ }
577
+
578
+ batch.files.push(filePath);
579
+ batch.waiters.push({ resolve, reject });
580
+
581
+ // Reset the debounce timer
582
+ if (batch.timeout) {
583
+ clearTimeout(batch.timeout);
584
+ }
585
+
586
+ batch.timeout = setTimeout(async () => {
587
+ const currentBatch = batchQueues.get(roomDir);
588
+ batchQueues.delete(roomDir);
589
+
590
+ if (!currentBatch) return;
591
+
592
+ try {
593
+ const batchResults = {
594
+ trigger: currentBatch.options.trigger,
595
+ roomDir,
596
+ batchSize: currentBatch.files.length,
597
+ files: currentBatch.files,
598
+ perFile: [],
599
+ hsi: null,
600
+ reverseSalients: null,
601
+ hsiBridge: null,
602
+ presentation: null
603
+ };
604
+
605
+ const resolvedRoomDir = roomDir || findRoomDir(currentBatch.files[0]);
606
+ if (!resolvedRoomDir || !fs.existsSync(resolvedRoomDir)) {
607
+ batchResults.skipped = true;
608
+ batchResults.skipReason = 'roomDir not found or does not exist';
609
+ for (const w of currentBatch.waiters) w.resolve(batchResults);
610
+ return;
611
+ }
612
+
613
+ const artifacts = currentBatch.files.map(fp => ({
614
+ filePath: fp,
615
+ section: currentBatch.options.section
616
+ }));
617
+
618
+ const lastHsi = lastHsiByRoom.get(resolvedRoomDir) || 0;
619
+ const debounced = (Date.now() - lastHsi) < HSI_DEBOUNCE_MS;
620
+
621
+ // frameworkHint 'cascade-batch' preserves legacy queueCascade step 11
622
+ // provenance (existing opportunity-bank consumers expect this string).
623
+ const stepsResult = await _runCascadeSteps(resolvedRoomDir, artifacts, {
624
+ trigger: currentBatch.options.trigger,
625
+ debounced,
626
+ frameworkHint: 'cascade-batch'
627
+ });
628
+
629
+ if (stepsResult.hsiRanAt !== null) {
630
+ lastHsiByRoom.set(resolvedRoomDir, stepsResult.hsiRanAt);
631
+ }
632
+
633
+ batchResults.perFile = stepsResult.perFile;
634
+ batchResults.hsi = stepsResult.hsi;
635
+ batchResults.reverseSalients = stepsResult.reverseSalients;
636
+ batchResults.hsiBridge = stepsResult.hsiBridge;
637
+ batchResults.presentation = stepsResult.presentation;
638
+ if (stepsResult.computeState !== null) batchResults.computeState = stepsResult.computeState;
639
+ if (stepsResult.buildGraph !== null) batchResults.buildGraph = stepsResult.buildGraph;
640
+ if (stepsResult.proactiveIntelligence !== null) batchResults.proactiveIntelligence = stepsResult.proactiveIntelligence;
641
+ if (stepsResult.opportunityExtraction !== null) batchResults.opportunityExtraction = stepsResult.opportunityExtraction;
642
+
643
+ for (const waiter of currentBatch.waiters) {
644
+ waiter.resolve(batchResults);
645
+ }
646
+ } catch (err) {
647
+ for (const waiter of currentBatch.waiters) {
648
+ waiter.reject(err);
649
+ }
650
+ }
651
+ }, BATCH_WINDOW_MS);
652
+ });
653
+ }
654
+
655
+ module.exports = {
656
+ runCascade,
657
+ queueCascade,
658
+ getCachedAnalysis,
659
+ setAnalysisCache,
660
+ invalidateAnalysisCache
661
+ };