@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,544 @@
1
+ /*
2
+ * Copyright (c) 2026 Mindrian. BSL 1.1.
3
+ *
4
+ * Phase 116-02 Wave 2 -- TensionHookAgent surface module.
5
+ * Phase 116-04 Wave 4 -- adds 5 telemetry emit helpers per CONTEXT.md D-04.
6
+ * Mirrors lib/agents/reverse-salient-agent.cjs lines 393-446 emitDetected /
7
+ * emitActedOn pattern. All payloads scalar-only per Canon Part 8 (D-04a).
8
+ * Suppression paths still emit tension_detected per Pitfall 5 (D-04c).
9
+ *
10
+ * Mirrors lib/agents/reverse-salient-agent.cjs Steps 5+6 (surfaceFinding +
11
+ * handleUserResponse) per docs/AGENTIC-SURFACING-PATTERN.md. Detection runs
12
+ * upstream in scripts/preflight-tension-surface.cjs (116-01); this module
13
+ * routes the user's F.1 pick back into JSONL state + RESOLVES_VIA cascade.
14
+ *
15
+ * Graph-native HARD RULES (memory feedback_reverse_salient_agent_graph_native.md):
16
+ * 1. Reads route through lib/core/navigation.cjs only (Phase 109 D-06 chokepoint).
17
+ * 2. NEVER require any direct DB module (chokepoint violation).
18
+ * 3. NEVER require a Brain client (Canon Part 8 boundary).
19
+ * 4. NEVER write to stdout / stderr (telemetry side-channel rule).
20
+ * 5. F.1 dispatch ONLY via lib/hmi/selector-dispatcher.cjs pickShape.
21
+ * 6. RESOLVES_VIA edge ONLY via lib/core/lazygraph-ops.cjs upsertEdge.
22
+ *
23
+ * Per CONTEXT.md D-02 + D-02a: NO persona-keyed suffix; the Phase 115
24
+ * persona variant module is NOT consumed. Larry-voice is neutral citation
25
+ * (the citation text lives in 116-01's additionalContext directive; this
26
+ * module is the response-routing surface).
27
+ *
28
+ * Per CONTEXT.md D-08: zero surface-specific branches. 88.2-05 selector
29
+ * dispatcher already shipped tri-polar so the F.1 surface is identical
30
+ * across CLI / Desktop / Cowork.
31
+ *
32
+ * Pure CJS, node built-ins only, zero new runtime dependencies.
33
+ */
34
+ 'use strict';
35
+
36
+ const path = require('node:path');
37
+ const crypto = require('node:crypto');
38
+
39
+ // Phase 109 chokepoint (read-side reference; the agent stays read-clean
40
+ // because detection lives in the SessionStart hook, not here, but holding
41
+ // the require keeps the chokepoint adherence grep green and lets future
42
+ // Wave 4 telemetry land without restructuring).
43
+ const navigation = require('../core/navigation.cjs');
44
+ const pendingStore = require('../memory/pending-tension-store.cjs');
45
+ // Lazy requires (test substitution friendly):
46
+ // - lib/hmi/selector-dispatcher.cjs (loaded inside surfaceFinding)
47
+ // - lib/core/lazygraph-ops.cjs (loaded inside buildResolvedViaEdge)
48
+
49
+ // ---------- Constants ----------
50
+
51
+ const F1_VERBS = ['Resolve', 'Later', 'Skip'];
52
+ const F1_HEADER = '-- mindrianOS -- pending tension -- pick a verb --';
53
+ const VALID_RESPONSES = Object.freeze(new Set(['RESOLVE', 'LATER', 'SKIP', 'FREE_TEXT']));
54
+ const TENSION_ID_LEN = 32;
55
+
56
+ // Touch the navigation chokepoint reference so static analysis reports
57
+ // it as used; the actual read calls land Wave 4 alongside telemetry.
58
+ // eslint-disable-next-line no-unused-vars
59
+ const _navigation_ref = navigation;
60
+
61
+ // ---------- Helpers ----------
62
+
63
+ function isHex32(v) {
64
+ return typeof v === 'string' && /^[0-9a-f]{32}$/.test(v);
65
+ }
66
+
67
+ function isNonEmptyString(v) {
68
+ return typeof v === 'string' && v.length > 0;
69
+ }
70
+
71
+ // ---------- composeFinding (deterministic id, Canon Part 8 clean) ----------
72
+
73
+ /**
74
+ * Build a Canon-Part-8-clean finding object. All fields are scalar IDs and
75
+ * enum-like section names; NO body_text / source_title / target_title or
76
+ * any other user-content string lives in the finding (those live in the
77
+ * graph and are fetched by Larry on his first turn via navigation.cjs per
78
+ * the 116-01 directive contract).
79
+ *
80
+ * Deterministic: same inputs always yield the same finding (id is the
81
+ * caller-supplied tension_id, which itself is computed deterministically
82
+ * by lib/memory/pending-tension-store.cjs computeTensionId).
83
+ *
84
+ * @param {object} args
85
+ * @param {string} args.tension_id 32-char hex
86
+ * @param {string} args.source_node_id node id (NOT title text)
87
+ * @param {string} args.target_node_id node id (NOT title text)
88
+ * @param {string} args.source_section
89
+ * @param {string} args.target_section
90
+ * @param {string} args.tension_type enum
91
+ * @returns {object|null}
92
+ */
93
+ function composeFinding(args) {
94
+ const a = (args && typeof args === 'object') ? args : {};
95
+ if (!isNonEmptyString(a.tension_id)) return null;
96
+ if (typeof a.tension_id === 'string' && a.tension_id.length !== TENSION_ID_LEN) {
97
+ // Tolerate non-hex but length-matched ids for forward-compat with
98
+ // upstream id schemes; reject only on empty / non-string.
99
+ }
100
+ return {
101
+ id: String(a.tension_id),
102
+ tension_type: isNonEmptyString(a.tension_type) ? a.tension_type : null,
103
+ source_node_id: isNonEmptyString(a.source_node_id) ? a.source_node_id : null,
104
+ target_node_id: isNonEmptyString(a.target_node_id) ? a.target_node_id : null,
105
+ source_section: isNonEmptyString(a.source_section) ? a.source_section : null,
106
+ target_section: isNonEmptyString(a.target_section) ? a.target_section : null,
107
+ // NO body_text. NO source_title. NO target_title. NO quoted_text. (Canon Part 8)
108
+ };
109
+ }
110
+
111
+ // ---------- surfaceFinding (the F.1 dispatch surface) ----------
112
+
113
+ /**
114
+ * Routes a detected tension finding through the F.1 Mini Decision Gate via
115
+ * lib/hmi/selector-dispatcher.cjs pickShape. Honors the suppression paths:
116
+ * - tier === 0 -> {surfaced:false, suppress_reason:'tier_0'} (no dispatch)
117
+ * - operator JUST_TALK -> {surfaced:false, suppress_reason:'just_talk'} (no dispatch)
118
+ * - dispatcher error -> {surfaced:false, suppress_reason:<err code>}
119
+ *
120
+ * Per CONTEXT.md D-02 (locked): Larry-voice render is neutral citation.
121
+ * The body / quote rendering happens upstream in 116-01's
122
+ * composeLarryVoiceDirective (additionalContext); this surface is the
123
+ * verb-selection gate the user picks against. recommendedVerb is null
124
+ * because Phase 116 deliberately omits recommendation (D-02b).
125
+ *
126
+ * @param {object} args
127
+ * @param {object} args.finding composeFinding output
128
+ * @param {string} args.roomDir
129
+ * @param {string} args.sessionId
130
+ * @param {number} args.tier 0 / 1 / 2 / 3 (Mode B/A by tier-check)
131
+ * @param {string} args.operator null or 'JUST_TALK' (others are pass-through)
132
+ * @returns {object}
133
+ */
134
+ function surfaceFinding(args) {
135
+ const a = (args && typeof args === 'object') ? args : {};
136
+ const finding = a.finding;
137
+ const roomDir = a.roomDir;
138
+ const tier = (typeof a.tier === 'number') ? a.tier : 0;
139
+ const operator = (typeof a.operator === 'string' && a.operator.length > 0) ? a.operator : null;
140
+
141
+ if (!finding || typeof finding !== 'object') {
142
+ return { surfaced: false, suppress_reason: 'invalid_finding' };
143
+ }
144
+
145
+ // Suppression check 1: tier 0 -- short-circuit pre-dispatch (RESEARCH 3.4).
146
+ if (tier === 0) {
147
+ return { surfaced: false, suppress_reason: 'tier_0', finding: finding };
148
+ }
149
+
150
+ // Suppression check 2: JUST_TALK -- short-circuit pre-dispatch.
151
+ if (operator === 'JUST_TALK') {
152
+ return { surfaced: false, suppress_reason: 'just_talk', finding: finding };
153
+ }
154
+
155
+ // Lazy-require the dispatcher (test substitution friendly).
156
+ let dispatcher;
157
+ try {
158
+ dispatcher = require('../hmi/selector-dispatcher.cjs');
159
+ } catch (e) {
160
+ return { surfaced: false, suppress_reason: 'dispatcher_load_failed', finding: finding };
161
+ }
162
+ if (!dispatcher || typeof dispatcher.pickShape !== 'function') {
163
+ return { surfaced: false, suppress_reason: 'pickShape_unavailable', finding: finding };
164
+ }
165
+
166
+ const surfaceStartedAtMs = Date.now();
167
+ let result;
168
+ try {
169
+ result = dispatcher.pickShape({
170
+ requestedShape: 'F.1',
171
+ roomDir: roomDir,
172
+ operator: operator,
173
+ tier: tier,
174
+ payload: {
175
+ verbs: F1_VERBS.slice(),
176
+ header: F1_HEADER,
177
+ recommendedVerb: null, // D-02 neutral; no recommendation
178
+ emitTelemetry: true, // 116-04 selector_presentation event fires via this flag
179
+ },
180
+ });
181
+ } catch (e) {
182
+ const detail = String((e && e.message) || '').slice(0, 40);
183
+ return { surfaced: false, suppress_reason: 'dispatch_threw:' + detail, finding: finding };
184
+ }
185
+
186
+ if (!result || result.shape === 'error') {
187
+ const errCode = (result && result.rendered && result.rendered.error)
188
+ ? String(result.rendered.error)
189
+ : 'unknown_dispatch_error';
190
+ return { surfaced: false, suppress_reason: errCode, finding: finding };
191
+ }
192
+
193
+ return {
194
+ surfaced: true,
195
+ finding: finding,
196
+ contract: (result.rendered && result.rendered.contract) ? result.rendered.contract : null,
197
+ rendered: result.rendered || null,
198
+ surfaceStartedAtMs: surfaceStartedAtMs,
199
+ };
200
+ }
201
+
202
+ // ---------- buildResolvedViaEdge (RESOLVES_VIA cascade emission) ----------
203
+
204
+ /**
205
+ * Sibling helper to lib/hmi/shape-f0-renderer.cjs buildRejectedBecauseEdge.
206
+ * Writes a RESOLVES_VIA typed cascade edge via lazygraph-ops.upsertEdge.
207
+ *
208
+ * properties.source = 'tension-hook' distinguishes this edge from the
209
+ * rs-engine-sourced edges that share the same edge type (the 89-07 agent
210
+ * uses a different edge type entirely; this attribution lets a downstream
211
+ * audit identify which agentic surface produced each cascade).
212
+ *
213
+ * Wrapped in try/catch -- never throws.
214
+ *
215
+ * @param {object} args
216
+ * @param {string} args.roomDir
217
+ * @param {string} args.tension_id
218
+ * @param {string} args.source_node_id
219
+ * @param {string} args.target_node_id
220
+ * @param {string} args.parent_decision_id
221
+ * @param {string} [args.actor_id]
222
+ * @param {object} args.db node:sqlite DatabaseSync handle
223
+ * @returns {{ok:boolean, reason?:string, edgeType?:string, edge?:object}}
224
+ */
225
+ function buildResolvedViaEdge(args) {
226
+ try {
227
+ const a = (args && typeof args === 'object') ? args : {};
228
+ if (!isNonEmptyString(a.tension_id)) {
229
+ return { ok: false, reason: 'invalid_tension_id' };
230
+ }
231
+ if (!isNonEmptyString(a.source_node_id)) {
232
+ return { ok: false, reason: 'invalid_source_id' };
233
+ }
234
+ if (!isNonEmptyString(a.target_node_id)) {
235
+ return { ok: false, reason: 'invalid_target_id' };
236
+ }
237
+ if (!isNonEmptyString(a.parent_decision_id)) {
238
+ return { ok: false, reason: 'invalid_parent_decision_id' };
239
+ }
240
+ if (!a.db) {
241
+ return { ok: false, reason: 'db_unavailable' };
242
+ }
243
+
244
+ let lazygraph;
245
+ try {
246
+ lazygraph = require('../core/lazygraph-ops.cjs');
247
+ } catch (e) {
248
+ return {
249
+ ok: false,
250
+ reason: 'lazygraph_load_failed',
251
+ detail: String((e && e.message) || '').slice(0, 80),
252
+ };
253
+ }
254
+ if (!lazygraph || typeof lazygraph.upsertEdge !== 'function') {
255
+ return { ok: false, reason: 'upsertEdge_not_available' };
256
+ }
257
+
258
+ const props = {
259
+ source: 'tension-hook', // distinguishes from rs-engine origin
260
+ agent: 'unresolved-tension',
261
+ tension_id: a.tension_id,
262
+ parent_decision_id: a.parent_decision_id,
263
+ resolved_at: new Date().toISOString(),
264
+ };
265
+ if (isNonEmptyString(a.actor_id)) {
266
+ props.actor_id = a.actor_id;
267
+ }
268
+
269
+ const result = lazygraph.upsertEdge(a.db, {
270
+ type: 'RESOLVES_VIA',
271
+ source: a.source_node_id,
272
+ target: a.target_node_id,
273
+ properties: props,
274
+ });
275
+ if (!result || result.ok !== true) {
276
+ return { ok: false, reason: (result && result.reason) || 'upsert_failed' };
277
+ }
278
+ return { ok: true, edgeType: 'RESOLVES_VIA', edge: result };
279
+ } catch (e) {
280
+ return {
281
+ ok: false,
282
+ reason: 'edge_build_threw_caught',
283
+ detail: String((e && e.message) || '').slice(0, 80),
284
+ };
285
+ }
286
+ }
287
+
288
+ // ---------- handleUserResponse (post-F.1 routing) ----------
289
+
290
+ /**
291
+ * Routes the user's F.1 selection back into JSONL state + cascade edge.
292
+ *
293
+ * RESOLVE -> markResolved(roomSlug, finding.id, 'RESOLVE') + buildResolvedViaEdge
294
+ * LATER -> requeue(roomSlug, finding.id) (state -> 'queued'; surfacing_count NOT decremented)
295
+ * SKIP -> appendTension preserving state='surfaced' with last_response='SKIP'
296
+ * (re-evaluated next SessionStart per RESEARCH 11.2)
297
+ * FREE_TEXT -> log only; Larry interprets per Canon Part 3 Verb 10; no JSONL state change
298
+ *
299
+ * Wrapped in try/catch -- never throws. Returns scalar-only result envelope
300
+ * (no user-content fields) so the caller can mirror to telemetry safely.
301
+ *
302
+ * @param {object} args
303
+ * @param {object} args.finding
304
+ * @param {string} args.roomDir
305
+ * @param {string} args.userResponse 'RESOLVE'|'LATER'|'SKIP'|'FREE_TEXT' (case-insensitive)
306
+ * @param {number} args.surfaceStartedAtMs Date.now() at surfaceFinding time
307
+ * @param {object} args.db node:sqlite DatabaseSync handle (for RESOLVE path)
308
+ * @param {string} [args.actor_id]
309
+ * @returns {object}
310
+ */
311
+ function handleUserResponse(args) {
312
+ try {
313
+ const a = (args && typeof args === 'object') ? args : {};
314
+ const finding = a.finding;
315
+ const roomDir = a.roomDir;
316
+ const userResponse = String(a.userResponse || '').toUpperCase();
317
+ const surfaceStartedAtMs = Number.isFinite(a.surfaceStartedAtMs) ? a.surfaceStartedAtMs : Date.now();
318
+ const latency_ms = Math.max(0, Math.floor(Date.now() - surfaceStartedAtMs));
319
+
320
+ if (!finding || typeof finding !== 'object') {
321
+ return { ok: false, reason: 'invalid_finding', latency_ms: latency_ms };
322
+ }
323
+ if (!VALID_RESPONSES.has(userResponse)) {
324
+ return { ok: false, reason: 'invalid_response', latency_ms: latency_ms };
325
+ }
326
+ const roomSlug = path.basename(typeof roomDir === 'string' ? roomDir : '');
327
+
328
+ if (userResponse === 'RESOLVE') {
329
+ const r1 = pendingStore.markResolved(roomSlug, finding.id, 'RESOLVE');
330
+ const r2 = buildResolvedViaEdge({
331
+ roomDir: roomDir,
332
+ tension_id: finding.id,
333
+ source_node_id: finding.source_node_id,
334
+ target_node_id: finding.target_node_id,
335
+ parent_decision_id: 'tension:' + String(finding.id || ''),
336
+ actor_id: a.actor_id,
337
+ db: a.db,
338
+ });
339
+ // Wave-4 telemetry: emit tension_resolved per CONTEXT.md D-04.
340
+ try {
341
+ emitResolved(roomDir, finding, {
342
+ latency_ms: latency_ms,
343
+ resolved_via_edge_emitted: !!(r2 && r2.ok),
344
+ });
345
+ } catch (_e) { /* never throw on telemetry */ }
346
+ return {
347
+ ok: true,
348
+ response: 'RESOLVE',
349
+ latency_ms: latency_ms,
350
+ jsonl: r1,
351
+ edge: r2,
352
+ };
353
+ }
354
+
355
+ if (userResponse === 'LATER') {
356
+ const r1 = pendingStore.requeue(roomSlug, finding.id);
357
+ // No emit per RESEARCH Section 11.2 row 4: the next session start's
358
+ // tension_detected captures the re-enter (no separate LATER event).
359
+ return {
360
+ ok: true,
361
+ response: 'LATER',
362
+ latency_ms: latency_ms,
363
+ jsonl: r1,
364
+ };
365
+ }
366
+
367
+ if (userResponse === 'SKIP') {
368
+ // Per RESEARCH Section 11.2: state stays 'surfaced'; record last_response='SKIP'
369
+ // via a transition append. We read the current entry (LWW replay) and write
370
+ // a sibling entry preserving state but recording the skip, so a later
371
+ // SessionStart re-evaluates whether to surface again.
372
+ const all = pendingStore.readTensions(roomSlug);
373
+ const current = (Array.isArray(all)
374
+ ? all.find((t) => t && t.tension_id === finding.id)
375
+ : null);
376
+ if (!current) {
377
+ return { ok: false, reason: 'tension_not_found_for_skip', latency_ms: latency_ms };
378
+ }
379
+ const next = Object.assign({}, current, { last_response: 'SKIP' });
380
+ const r1 = pendingStore.appendTension(roomSlug, next);
381
+ // Wave-4 telemetry: emit tension_skipped per CONTEXT.md D-04.
382
+ try {
383
+ emitSkipped(roomDir, finding, {
384
+ latency_ms: latency_ms,
385
+ surfacing_count: Number(current.surfacing_count) || 0,
386
+ });
387
+ } catch (_e) { /* never throw on telemetry */ }
388
+ return {
389
+ ok: true,
390
+ response: 'SKIP',
391
+ latency_ms: latency_ms,
392
+ jsonl: r1,
393
+ };
394
+ }
395
+
396
+ if (userResponse === 'FREE_TEXT') {
397
+ // Larry interprets per Canon Part 3 Verb 10. No JSONL state change.
398
+ return {
399
+ ok: true,
400
+ response: 'FREE_TEXT',
401
+ latency_ms: latency_ms,
402
+ };
403
+ }
404
+
405
+ // Unreachable -- VALID_RESPONSES guarded above.
406
+ return { ok: false, reason: 'unknown_response', latency_ms: latency_ms };
407
+ } catch (e) {
408
+ return {
409
+ ok: false,
410
+ reason: 'handle_response_threw',
411
+ detail: String((e && e.message) || '').slice(0, 80),
412
+ };
413
+ }
414
+ }
415
+
416
+ // ---------- Telemetry helpers (Canon Part 8 scalar-only payloads) ----------
417
+ //
418
+ // Each helper wraps recordSelectorMirror in try/catch and coerces every value
419
+ // to a scalar type (string / number / boolean / null). NEVER carries
420
+ // finding.body_text, finding.source_title, finding.target_title (those don't
421
+ // exist on the Phase 116 finding object per 116-02 composeFinding contract;
422
+ // the fence is defense-in-depth).
423
+ //
424
+ // Mirrors lib/agents/reverse-salient-agent.cjs lines 393-446 emitDetected /
425
+ // emitActedOn pattern verbatim with field substitutions per RESEARCH 4.5.
426
+
427
+ function emitDetected(roomDir, finding, ctx) {
428
+ try {
429
+ const telemetry = require('../hmi/selector-telemetry.cjs');
430
+ if (!telemetry || typeof telemetry.recordSelectorMirror !== 'function') {
431
+ return { ok: false, reason: 'telemetry_module_unavailable' };
432
+ }
433
+ const c = (ctx && typeof ctx === 'object') ? ctx : {};
434
+ const payload = {
435
+ tension_id: String((finding && finding.id) || ''),
436
+ tension_type: String((finding && finding.tension_type) || ''),
437
+ source_edge_count: Number(c.source_edge_count) || 0,
438
+ tier: Number(c.tier) || 0,
439
+ surfacing_count: Number(c.surfacing_count) || 0,
440
+ surfaced: Boolean(c.surfaced),
441
+ suppress_reason: c.suppress_reason === null || c.suppress_reason === undefined
442
+ ? null
443
+ : String(c.suppress_reason),
444
+ brain_offline_flag: Boolean(c.brain_offline_flag),
445
+ selection_priority: Number(c.selection_priority) || 0,
446
+ };
447
+ return telemetry.recordSelectorMirror(roomDir, 'tension_detected', payload);
448
+ } catch (_e) {
449
+ return { ok: false, reason: 'detected_telemetry_threw' };
450
+ }
451
+ }
452
+
453
+ function emitSurfaced(roomDir, finding, ctx) {
454
+ try {
455
+ const telemetry = require('../hmi/selector-telemetry.cjs');
456
+ if (!telemetry || typeof telemetry.recordSelectorMirror !== 'function') {
457
+ return { ok: false, reason: 'telemetry_module_unavailable' };
458
+ }
459
+ const c = (ctx && typeof ctx === 'object') ? ctx : {};
460
+ const payload = {
461
+ tension_id: String((finding && finding.id) || ''),
462
+ tension_type: String((finding && finding.tension_type) || ''),
463
+ tier: Number(c.tier) || 0,
464
+ surfacing_count: Number(c.surfacing_count) || 0,
465
+ f1_verb_count: Number(c.f1_verb_count) || 4,
466
+ };
467
+ return telemetry.recordSelectorMirror(roomDir, 'tension_surfaced', payload);
468
+ } catch (_e) {
469
+ return { ok: false, reason: 'surfaced_telemetry_threw' };
470
+ }
471
+ }
472
+
473
+ function emitResolved(roomDir, finding, ctx) {
474
+ try {
475
+ const telemetry = require('../hmi/selector-telemetry.cjs');
476
+ if (!telemetry || typeof telemetry.recordSelectorMirror !== 'function') {
477
+ return { ok: false, reason: 'telemetry_module_unavailable' };
478
+ }
479
+ const c = (ctx && typeof ctx === 'object') ? ctx : {};
480
+ const safeLatency = Number.isFinite(c.latency_ms) ? Math.max(0, Math.floor(c.latency_ms)) : 0;
481
+ const payload = {
482
+ tension_id: String((finding && finding.id) || ''),
483
+ response: 'RESOLVE',
484
+ latency_ms: safeLatency,
485
+ resolved_via_edge_emitted: Boolean(c.resolved_via_edge_emitted),
486
+ };
487
+ return telemetry.recordSelectorMirror(roomDir, 'tension_resolved', payload);
488
+ } catch (_e) {
489
+ return { ok: false, reason: 'resolved_telemetry_threw' };
490
+ }
491
+ }
492
+
493
+ function emitDecayed(roomDir, tension_id, ctx) {
494
+ try {
495
+ const telemetry = require('../hmi/selector-telemetry.cjs');
496
+ if (!telemetry || typeof telemetry.recordSelectorMirror !== 'function') {
497
+ return { ok: false, reason: 'telemetry_module_unavailable' };
498
+ }
499
+ const c = (ctx && typeof ctx === 'object') ? ctx : {};
500
+ const payload = {
501
+ tension_id: String(tension_id || ''),
502
+ surfacing_count: Number(c.surfacing_count) || 3,
503
+ evaluation_pass_id: String(c.evaluation_pass_id || ''),
504
+ };
505
+ return telemetry.recordSelectorMirror(roomDir, 'tension_decayed', payload);
506
+ } catch (_e) {
507
+ return { ok: false, reason: 'decayed_telemetry_threw' };
508
+ }
509
+ }
510
+
511
+ function emitSkipped(roomDir, finding, ctx) {
512
+ try {
513
+ const telemetry = require('../hmi/selector-telemetry.cjs');
514
+ if (!telemetry || typeof telemetry.recordSelectorMirror !== 'function') {
515
+ return { ok: false, reason: 'telemetry_module_unavailable' };
516
+ }
517
+ const c = (ctx && typeof ctx === 'object') ? ctx : {};
518
+ const safeLatency = Number.isFinite(c.latency_ms) ? Math.max(0, Math.floor(c.latency_ms)) : 0;
519
+ const payload = {
520
+ tension_id: String((finding && finding.id) || ''),
521
+ latency_ms: safeLatency,
522
+ surfacing_count: Number(c.surfacing_count) || 0,
523
+ };
524
+ return telemetry.recordSelectorMirror(roomDir, 'tension_skipped', payload);
525
+ } catch (_e) {
526
+ return { ok: false, reason: 'skipped_telemetry_threw' };
527
+ }
528
+ }
529
+
530
+ // ---------- Module exports ----------
531
+
532
+ module.exports = {
533
+ composeFinding: composeFinding,
534
+ surfaceFinding: surfaceFinding,
535
+ buildResolvedViaEdge: buildResolvedViaEdge,
536
+ handleUserResponse: handleUserResponse,
537
+ emitDetected: emitDetected,
538
+ emitSurfaced: emitSurfaced,
539
+ emitResolved: emitResolved,
540
+ emitDecayed: emitDecayed,
541
+ emitSkipped: emitSkipped,
542
+ F1_VERBS: F1_VERBS.slice(),
543
+ F1_HEADER: F1_HEADER,
544
+ };
@@ -0,0 +1,44 @@
1
+ ---
2
+ type: directory-identity
3
+ name: lib/brain
4
+ section: lib/brain
5
+ purpose: Brain-facing helpers -- the framework-chain recommender that seeds a workflow from the Brain's FEEDS_INTO graph. Everything here goes through lib/core/brain-client.cjs (the Canon-Part-8-sanitized chokepoint).
6
+ founding_phase: 122
7
+ phase: 122
8
+ milestone: v1.13.0-beta.10
9
+ canon_parts: [3, 8]
10
+ created: 2026-05-12
11
+ ---
12
+
13
+ # lib/brain/
14
+
15
+ `lib/brain/` is the home for the small set of helpers that read the Brain's methodology graph. Phase 122 is the founding phase; the chain recommender is the first contained surface. Nothing in this directory talks to the Brain directly -- every Brain touch goes through `lib/core/brain-client.cjs`, the single Canon-Part-8-sanitized chokepoint.
16
+
17
+ ## Files in this section
18
+
19
+ | File | Plan | Purpose |
20
+ |------|------|---------|
21
+ | `chain-recommender.cjs` | 122-03 | `recommendFrameworkChain({ problemType?, currentFramework?, roomState? }) -> [frameworkName, ...]` (ordered, length 1..4, seed first). Picks a seed framework (reusing `lib/core/problem-type-router.cjs` -- problemType / activeJtbd / currentFramework -> seed), walks FEEDS_INTO from it (reusing `lib/core/framework-chain-composer.cjs` `proposeNextFramework` over already-parsed edges supplied via `roomState`), and degrades to `[seed]` when there is no outgoing FEEDS_INTO edge, no Brain, or any error. Returns framework names ONLY -- `composeWorkflow()` (the resolver in `lib/workflow/`) attaches the commands. |
22
+
23
+ ## Canon Part 8 boundary (names + enums only, never user content, never commands)
24
+
25
+ The chain recommender's Brain-facing payload carries ONLY framework names and problem-type / phase enums (the `brain-client.sanitizeCypherInput` whitelist), bound as `$`-params -- never a command literal, never user content (no artifact bodies, no meeting text, no proprietary numbers). The file is free of any `/mos:` command literal; the navigation-engine wiring (Phase 122-04) that performs the live FEEDS_INTO query does so through `brain-client.query` with the seed bound via `sanitizeCypherInput`. The pre-commit / test grep guard from 122-02 enforces the no-command-near-Brain rule across `lib/workflow/` and `lib/brain/chain-recommender.cjs`.
26
+
27
+ This directory is the OUTBOUND side of the Brain boundary: it queries the Brain for generic methodology (the FEEDS_INTO chain), and it never sends LOCAL bytes the other way. The resolver in `lib/workflow/` is the side that never touches the Brain at all.
28
+
29
+ ## Hard dependency (DONE)
30
+
31
+ The chain recommender depends on brain-cleanup Phase 5 (`enrichCausalEdges` rewritten to traverse `FEEDS_INTO` instead of the now-zero `CO_OCCURS` edges) -- that is DONE per `.planning/phases/122-workflow-layer/122-RESEARCH.md` and `.planning/STATE.md`, so nothing here is externally blocked.
32
+
33
+ ## Decision #15 compliance
34
+
35
+ Per `CLAUDE.md` Decision #15, every directory in the data room (and the lib tree by extension under this milestone's policy) carries a ROOM.md identity file. `lib/brain/` is bound to Phase 122; subsequent additions update this file's "Files in this section" table. No MINTO.md required at this level -- the `.room-root` cascade scope is `room/`, not `lib/`.
36
+
37
+ ## Cross-references
38
+
39
+ - Spec: `.planning/WORKFLOW-LAYER-SPEC.md`
40
+ - Phase 122 PLAN: `.planning/phases/122-workflow-layer/122-03-PLAN.md`
41
+ - Phase 122 RESEARCH: `.planning/phases/122-workflow-layer/122-RESEARCH.md`
42
+ - Sibling: `lib/workflow/ROOM.md` (the resolver -- the no-Brain side), `lib/core/brain-client.cjs` (the chokepoint), `lib/core/framework-chain-composer.cjs` + `lib/core/problem-type-router.cjs` (the reused engines)
43
+ - Canon: `docs/MINDRIAN-CANON.md` Parts 3, 8
44
+ - Frontmatter contract: `docs/COMMAND-FRONTMATTER.md`