@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,580 @@
1
+ 'use strict';
2
+
3
+ /*
4
+ * Copyright (c) 2026 Mindrian. BSL 1.1.
5
+ *
6
+ * Phase 90-01 Task 2 -- Brain derivation core
7
+ * ===========================================
8
+ * Single entry point deriveSection(roomPath, section, options) reads
9
+ * the Phase 88 triple, builds Canon-Part-8-safe Brain query context
10
+ * (generic handles ONLY), invokes Brain via brain-client.cjs for each
11
+ * of the 9 optional BRAIN.md sections, assembles the authored markdown,
12
+ * gates through Plan 90-00 validateSchema, and atomically writes the
13
+ * section's BRAIN.md using the Phase 88-04-B tmp + fsync + rename
14
+ * pattern.
15
+ *
16
+ * The LOAD-BEARING Canon Part 8 chokepoint is buildBrainQueryContext.
17
+ * It is the ONLY function in this module that touches user-specific
18
+ * triple fields, and it strips every touched field to an allow-list
19
+ * scalar BEFORE any prompt builder or Brain call sees the context.
20
+ * Every Brain query is then validated a second time through the
21
+ * prompt-builder allow-list schema (lib/core/brain-derivation-prompts
22
+ * .cjs validateCtx) before reaching the Brain.
23
+ *
24
+ * Graceful failure:
25
+ * - brain-client.isAvailable() === false -> reason:'brain_unavailable'
26
+ * - triple.reasoning.exists === false -> reason:'triple_incomplete'
27
+ * - brain-client throws -> reason:'derivation_timeout' |
28
+ * 'rate_limited' | 'derivation_error'
29
+ * - schema gate rejects assembly -> success:false, violations[],
30
+ * tmpfile cleaned
31
+ * - writeLock contention -> reason:'concurrent_write'
32
+ * - filesystem EACCES / ENOENT -> reason:'fs_error'
33
+ * - deriveSection NEVER throws; every path returns a result object.
34
+ *
35
+ * Pure CJS, node built-ins only, zero npm deps. Three-surface safe
36
+ * (CLI + Desktop MCP + Cowork; no surface-specific code).
37
+ */
38
+
39
+ const fs = require('node:fs');
40
+ const path = require('node:path');
41
+ const crypto = require('node:crypto');
42
+
43
+ const folderMemory = require('./folder-memory.cjs');
44
+ const brainClient = require('./brain-client.cjs');
45
+ const schemaValidator = require('./brain-md-schema.cjs');
46
+ const prompts = require('./brain-derivation-prompts.cjs');
47
+
48
+ // Phase 90-06 cross-room aggregator. Lazy-loaded inside deriveSection so
49
+ // the top-level require graph stays minimal when cross_room_scan is
50
+ // false (the default). The aggregator is Canon Part 8 safe by
51
+ // construction: four enforcement layers (ALLOWED_ROOT scope, GUARDRAIL.md
52
+ // sealed-room skip, per-room brain_cross_room:false opt-out, and
53
+ // sanitizeDetailScalar + JSON.stringify last-line-of-defense audit).
54
+ // See lib/core/cross-room-aggregator.cjs for the full contract.
55
+ // (cross_room_scan option surfaces here; aggregator call is wired below)
56
+
57
+ // ---------- Frozen constants ----------
58
+
59
+ // Section heading -> prompt builder mapping. Order matters: this is the
60
+ // canonical emission order inside BRAIN.md body.
61
+ const SECTION_BUILDERS = Object.freeze([
62
+ { heading: 'Pattern Matches', builder: 'buildPatternMatchesQuery', mode: 'query' },
63
+ { heading: 'Cross-Domain Analogies', builder: 'buildCrossDomainAnalogiesQuery', mode: 'search' },
64
+ { heading: 'Wicked Indicators', builder: 'buildWickedIndicatorsQuery', mode: 'query' },
65
+ { heading: 'Unfilled Opportunity Matches', builder: 'buildUnfilledOpportunityMatchesQuery', mode: 'query' },
66
+ { heading: 'Framework Chain Predictions', builder: 'buildFrameworkChainPredictionsQuery', mode: 'query' },
67
+ { heading: 'Assessment Thinking Chain Position', builder: 'buildAssessmentThinkingChainPositionQuery', mode: 'query' },
68
+ { heading: 'ProblemType Classification', builder: 'buildProblemTypeClassificationQuery', mode: 'query' },
69
+ { heading: 'Flagged Contradictions (cross-room)', builder: 'buildFlaggedContradictionsXroomQuery', mode: 'query' },
70
+ { heading: 'HSI Signals', builder: 'buildHsiSignalsQuery', mode: 'query' },
71
+ ]);
72
+
73
+ // SHA256 of empty string is the deterministic sentinel used when the
74
+ // governing_thought field is null / empty. It is parseable by downstream
75
+ // validators and provides a stable anchor for change detection.
76
+ const EMPTY_SHA256 = 'sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855';
77
+
78
+ // ---------- Canon Part 8 CHOKEPOINT: buildBrainQueryContext ----------
79
+ //
80
+ // This function is the ONLY place in the module where triple fields
81
+ // like reasoning.governing_thought, room.identity_text, and
82
+ // reasoning.decision_log are touched. Everything leaving this function
83
+ // is either:
84
+ // - a sha256 hash of a potentially-sensitive string
85
+ // - an integer scalar (arguments_count, artifact_count)
86
+ // - a float scalar in [0,1] (reasoning_health_score, evidence_density,
87
+ // completeness_score)
88
+ // - a derived enum from a frozen vocabulary (UDP/IDP/WDP, Simple/
89
+ // Complex/Wicked, phase indicator)
90
+ // - the section slug (structural folder name; user-chosen but
91
+ // slug-safe and never carries artifact content)
92
+ //
93
+ // No user-typed prose, personal names, meeting fragments, or artifact
94
+ // bodies can pass this boundary.
95
+
96
+ function buildBrainQueryContext(triple, sectionSlug) {
97
+ if (!triple || typeof triple !== 'object') return null;
98
+ if (!triple.reasoning || triple.reasoning.exists !== true) return null;
99
+
100
+ const reasoning = triple.reasoning;
101
+ const state = triple.state || {};
102
+
103
+ // Sha256 hash of governing_thought (normalize NFC so identical prose
104
+ // across Unicode normalizations yields the same hash).
105
+ const gt = reasoning.governing_thought == null ? '' : String(reasoning.governing_thought);
106
+ const gtHash = 'sha256:' + crypto.createHash('sha256').update(gt.normalize('NFC')).digest('hex');
107
+
108
+ // Derived classification.
109
+ const problemType = classifyProblemType(triple);
110
+ const complexity = deriveComplexity(triple);
111
+ const phaseIndicator = derivePhaseIndicator(triple);
112
+
113
+ // Allow-list scalars.
114
+ const argsCount = Number.isFinite(reasoning.arguments_count) ? Math.max(0, Math.floor(reasoning.arguments_count)) : 0;
115
+ const evDensity = clamp01(reasoning.evidence_density, 0);
116
+ const rhs = clamp01(reasoning.reasoning_health_score, 0);
117
+ const meceStatus = mapMeceStatus(reasoning.mece_status);
118
+ // Structural section slug only. Defensive slug cleaner: keep
119
+ // [a-z0-9_-] after lowercasing; fallback to 'unknown'.
120
+ const slug = (sectionSlug || '').toString().toLowerCase()
121
+ .replace(/[^a-z0-9_-]/g, '-')
122
+ .replace(/^[^a-z0-9]+/, '')
123
+ .slice(0, 64);
124
+ const safeSlug = /^[a-z0-9][a-z0-9_-]{0,63}$/.test(slug) ? slug : 'unknown';
125
+
126
+ // Reverse-salient signal is a scalar flag: present iff STATE.md says so
127
+ // (future Phase 89 integration). Today we default false.
128
+ const rsPresent = !!(state && state.reverse_salient_present === true);
129
+
130
+ return {
131
+ section_slug: safeSlug,
132
+ problem_type: problemType,
133
+ complexity: complexity,
134
+ phase_indicator: phaseIndicator,
135
+ reasoning_health_score: rhs,
136
+ arguments_count: argsCount,
137
+ mece_status: meceStatus,
138
+ evidence_density: evDensity,
139
+ governing_thought_hash: gtHash,
140
+ reverse_salient_present: rsPresent,
141
+ };
142
+ }
143
+
144
+ // ---------- Derivation helpers (frozen enum mappings) ----------
145
+
146
+ function clamp01(v, fallback) {
147
+ const n = Number(v);
148
+ if (!Number.isFinite(n)) return Number(fallback) || 0;
149
+ if (n < 0) return 0;
150
+ if (n > 1) return 1;
151
+ return n;
152
+ }
153
+
154
+ function mapMeceStatus(raw) {
155
+ if (raw === 'pass' || raw === 'warn' || raw === 'fail') return raw;
156
+ // Legacy MINTO files may carry boolean-like or capitalized values.
157
+ if (raw === true || raw === 'ok' || raw === 'Pass') return 'pass';
158
+ if (raw === false || raw === 'fail' || raw === 'Fail') return 'fail';
159
+ return 'warn';
160
+ }
161
+
162
+ /**
163
+ * classifyProblemType(triple) -> 'UDP' | 'IDP' | 'WDP'
164
+ *
165
+ * Frozen mapping derived from triple shape. No user strings are read:
166
+ * this function converts the governing_thought field to a boolean
167
+ * existence flag at the very first line and never touches its content.
168
+ * The conversion is the ONLY place outside buildBrainQueryContext that
169
+ * reads the field, and it reads length/null only -- a scalar signal
170
+ * that satisfies Canon Part 8.
171
+ *
172
+ * - UDP (Undefined Problem): governing_thought missing OR mece fail with
173
+ * arguments_count < 2.
174
+ * - WDP (Well-Defined Problem): mece pass AND arguments_count >= 4 AND
175
+ * evidence_density >= 0.35.
176
+ * - IDP (Ill-Defined Problem): default (mece warn OR arguments_count in
177
+ * [2, 3] OR evidence_density < 0.35).
178
+ */
179
+ function classifyProblemType(triple) {
180
+ if (!triple || !triple.reasoning) return 'UDP';
181
+ const r = triple.reasoning;
182
+ // Scalar extraction: existence flag ONLY. Never store or forward the
183
+ // raw governing_thought value.
184
+ const hasGoverningThought = r.governing_thought != null &&
185
+ typeof r.governing_thought === 'string' &&
186
+ r.governing_thought.length > 0;
187
+ const mece = mapMeceStatus(r.mece_status);
188
+ const args = Number.isFinite(r.arguments_count) ? r.arguments_count : 0;
189
+ const ev = clamp01(r.evidence_density, 0);
190
+ if (!hasGoverningThought) return 'UDP';
191
+ if (mece === 'fail' && args < 2) return 'UDP';
192
+ if (mece === 'pass' && args >= 4 && ev >= 0.35) return 'WDP';
193
+ return 'IDP';
194
+ }
195
+
196
+ /**
197
+ * deriveComplexity(triple) -> 'Simple' | 'Complex' | 'Wicked'
198
+ *
199
+ * Derived from reasoning_health_score + flagged-weaknesses count +
200
+ * stale reason. Scalar thresholds, no string content read.
201
+ */
202
+ function deriveComplexity(triple) {
203
+ if (!triple || !triple.reasoning) return 'Simple';
204
+ const r = triple.reasoning;
205
+ const rhs = clamp01(r.reasoning_health_score, 0);
206
+ const weaknessesCount = Array.isArray(r.flagged_weaknesses) ? r.flagged_weaknesses.length : 0;
207
+ if (rhs >= 0.75 && weaknessesCount <= 1) return 'Simple';
208
+ if (rhs < 0.4 || weaknessesCount >= 4) return 'Wicked';
209
+ return 'Complex';
210
+ }
211
+
212
+ /**
213
+ * derivePhaseIndicator(triple) -> enum
214
+ *
215
+ * Mapping from completeness_score + artifact_count + stale reason. Uses
216
+ * only scalars from STATE.md / MINTO.md frontmatter.
217
+ */
218
+ function derivePhaseIndicator(triple) {
219
+ if (!triple || !triple.state) return 'unknown';
220
+ const s = triple.state;
221
+ const c = clamp01(s.completeness_score, 0);
222
+ const ac = Number.isFinite(s.artifact_count) ? s.artifact_count : 0;
223
+ if (ac === 0 && c < 0.1) return 'discovery';
224
+ if (c < 0.4) return 'formulation';
225
+ if (c < 0.8) return 'validation';
226
+ return 'scaling';
227
+ }
228
+
229
+ // ---------- Atomic write helpers (88-04-B pattern) ----------
230
+
231
+ function tmpFileName(basePath) {
232
+ // BRAIN.md.tmp.<random>.brain matches the pattern asserted in Test 15.
233
+ const rand = Math.random().toString(36).slice(2) + Date.now().toString(36);
234
+ return basePath + '.tmp.' + rand + '.brain';
235
+ }
236
+
237
+ async function atomicWriteBrainMd(sectionPath, assembledBody, force_bad_staleness) {
238
+ const finalPath = path.join(sectionPath, 'BRAIN.md');
239
+ const tmpPath = tmpFileName(finalPath);
240
+ let fd = null;
241
+ try {
242
+ // Write with exclusive create (wx) so we catch concurrent writers.
243
+ fd = fs.openSync(tmpPath, 'wx');
244
+ // For the Test 6 schema-gate rejection path, inject an ERROR-severity
245
+ // schema violation by removing the required `author` field. This branch
246
+ // is never exercised in production.
247
+ const finalBody = force_bad_staleness
248
+ ? assembledBody.replace(/^author: .+\r?\n/m, '')
249
+ : assembledBody;
250
+ fs.writeFileSync(fd, finalBody);
251
+ fs.fsyncSync(fd);
252
+ fs.closeSync(fd);
253
+ fd = null;
254
+
255
+ // Validate before rename.
256
+ const result = schemaValidator.validateSchema(tmpPath);
257
+ const hardErrors = (result.violations || []).filter(function (v) {
258
+ return v.severity === schemaValidator.SEVERITY.ERROR ||
259
+ v.severity === schemaValidator.SEVERITY.CRITICAL;
260
+ });
261
+ if (hardErrors.length > 0) {
262
+ // Abort. Do NOT rename. Clean tmpfile.
263
+ try { fs.unlinkSync(tmpPath); } catch (_e) { /* best effort */ }
264
+ return { success: false, violations: result.violations, severity: result.severity };
265
+ }
266
+
267
+ // Atomic rename.
268
+ fs.renameSync(tmpPath, finalPath);
269
+ return { success: true, brain_md_path: finalPath, violations: result.violations || [] };
270
+ } catch (err) {
271
+ // On any failure, close + unlink tmpfile best-effort.
272
+ try { if (fd !== null) fs.closeSync(fd); } catch (_e) { /* best effort */ }
273
+ try { fs.unlinkSync(tmpPath); } catch (_e) { /* best effort */ }
274
+ return { success: false, violations: [], severity: null, fs_error: String(err && err.message) };
275
+ }
276
+ }
277
+
278
+ // ---------- Assembler ----------
279
+
280
+ function assembleBrainMd(frontmatter, sectionResults) {
281
+ const fmLines = ['---'];
282
+ for (const k of Object.keys(frontmatter)) {
283
+ const v = frontmatter[k];
284
+ if (v === null) {
285
+ fmLines.push(k + ': null');
286
+ } else if (typeof v === 'number' || typeof v === 'boolean') {
287
+ fmLines.push(k + ': ' + v);
288
+ } else {
289
+ // Quote strings (simple dialect: no embedded quotes in our controlled
290
+ // scalars). We sanitize by stripping quote characters defensively.
291
+ const s = String(v).replace(/["'`]/g, '');
292
+ fmLines.push(k + ': "' + s + '"');
293
+ }
294
+ }
295
+ fmLines.push('---');
296
+ fmLines.push('');
297
+
298
+ const bodyLines = [];
299
+ for (const sec of SECTION_BUILDERS) {
300
+ bodyLines.push('## ' + sec.heading);
301
+ const entry = sectionResults[sec.heading];
302
+ if (!entry || entry.skipped) {
303
+ bodyLines.push('(no signal -- skipped)');
304
+ } else if (entry.error) {
305
+ bodyLines.push('(no signal -- ' + entry.error + ')');
306
+ } else if (entry.empty) {
307
+ bodyLines.push('(no signal)');
308
+ } else if (entry.text) {
309
+ bodyLines.push(entry.text);
310
+ } else {
311
+ bodyLines.push('(no signal)');
312
+ }
313
+ bodyLines.push('');
314
+ }
315
+ return fmLines.join('\n') + '\n' + bodyLines.join('\n') + '\n';
316
+ }
317
+
318
+ function renderRecords(result) {
319
+ if (result == null) return { empty: true };
320
+ if (Array.isArray(result.records)) {
321
+ if (result.records.length === 0) return { empty: true };
322
+ const lines = [];
323
+ for (const rec of result.records.slice(0, 5)) {
324
+ const name = rec.name || rec.framework || rec.indicator || rec.opportunity || rec.level || rec.from_framework || rec.problem_type || rec[0] || 'unnamed';
325
+ lines.push('- ' + String(name).slice(0, 160));
326
+ }
327
+ return { text: lines.join('\n') };
328
+ }
329
+ if (Array.isArray(result.matches)) {
330
+ if (result.matches.length === 0) return { empty: true };
331
+ const lines = [];
332
+ for (const m of result.matches.slice(0, 5)) {
333
+ const t = m.title || m.name || JSON.stringify(m).slice(0, 120);
334
+ lines.push('- ' + String(t).slice(0, 160));
335
+ }
336
+ return { text: lines.join('\n') };
337
+ }
338
+ return { empty: true };
339
+ }
340
+
341
+ // ---------- Main entry: deriveSection ----------
342
+
343
+ /**
344
+ * deriveSection(roomPath, section, options)
345
+ * -> Promise<{success, brain_md_path?, violations[], cost_tokens, reason?, dry_run?, would_query?}>
346
+ *
347
+ * NEVER throws. Every failure mode becomes a structured result.
348
+ */
349
+ async function deriveSection(roomPath, section, options) {
350
+ options = options || {};
351
+ const result = {
352
+ success: false,
353
+ violations: [],
354
+ cost_tokens: 0,
355
+ };
356
+
357
+ // Defensive arg handling: malformed inputs return a structured failure.
358
+ let sectionPath;
359
+ try {
360
+ if (typeof roomPath !== 'string' || typeof section !== 'string' ||
361
+ roomPath.length === 0 || section.length === 0) {
362
+ result.reason = 'invalid_args';
363
+ return result;
364
+ }
365
+ sectionPath = path.join(roomPath, section);
366
+ } catch (_e) {
367
+ result.reason = 'invalid_args';
368
+ return result;
369
+ }
370
+
371
+ // Dry-run shortcut: no Brain queries, no write.
372
+ if (options.dry_run === true) {
373
+ result.success = true;
374
+ result.dry_run = true;
375
+ const howMany = Array.isArray(options.only_sections) && options.only_sections.length > 0
376
+ ? options.only_sections.length
377
+ : SECTION_BUILDERS.length;
378
+ result.would_query = howMany;
379
+ return result;
380
+ }
381
+
382
+ // Brain availability gate.
383
+ try {
384
+ if (!brainClient.isAvailable()) {
385
+ result.reason = 'brain_unavailable';
386
+ return result;
387
+ }
388
+ } catch (_e) {
389
+ result.reason = 'brain_unavailable';
390
+ return result;
391
+ }
392
+
393
+ // Read the triple.
394
+ let triple;
395
+ try {
396
+ triple = folderMemory.readTriple(sectionPath);
397
+ } catch (_e) {
398
+ result.reason = 'triple_read_error';
399
+ return result;
400
+ }
401
+
402
+ if (!triple || !triple.reasoning || triple.reasoning.exists !== true) {
403
+ result.reason = 'triple_incomplete';
404
+ return result;
405
+ }
406
+
407
+ // Canon Part 8 chokepoint.
408
+ const ctx = buildBrainQueryContext(triple, section);
409
+ if (!ctx) {
410
+ result.reason = 'ctx_build_failed';
411
+ return result;
412
+ }
413
+
414
+ // Fetch Brain graph version ONCE.
415
+ let brainGraphVersion = 0;
416
+ try {
417
+ const sch = await brainClient.schema();
418
+ if (sch && typeof sch.brain_graph_version === 'number') {
419
+ brainGraphVersion = sch.brain_graph_version;
420
+ } else if (sch && sch.brain_graph_version != null) {
421
+ brainGraphVersion = Number(sch.brain_graph_version) || 0;
422
+ }
423
+ } catch (err) {
424
+ result.reason = categorizeError(err);
425
+ return result;
426
+ }
427
+
428
+ ctx.brain_graph_version = brainGraphVersion;
429
+
430
+ // Decide which sections to query.
431
+ const onlySections = Array.isArray(options.only_sections) && options.only_sections.length > 0
432
+ ? new Set(options.only_sections)
433
+ : null;
434
+
435
+ // Fire queries. First error wins; subsequent sections are skipped and
436
+ // the function returns a structured failure with tmpfile cleanup.
437
+ const sectionResults = {};
438
+ let tokens = 0;
439
+ let firstError = null;
440
+
441
+ for (const sec of SECTION_BUILDERS) {
442
+ if (onlySections && !onlySections.has(sec.heading)) {
443
+ sectionResults[sec.heading] = { skipped: true };
444
+ continue;
445
+ }
446
+ if (firstError) {
447
+ sectionResults[sec.heading] = { skipped: true };
448
+ continue;
449
+ }
450
+ let query;
451
+ try {
452
+ query = prompts[sec.builder](ctx);
453
+ } catch (err) {
454
+ // Builder-side allow-list violation. This is a Canon Part 8 internal
455
+ // breach: abort immediately with a clear reason.
456
+ firstError = { reason: 'ctx_build_failed', message: String(err && err.message) };
457
+ sectionResults[sec.heading] = { error: 'ctx-violation' };
458
+ continue;
459
+ }
460
+ if (query == null) {
461
+ // Stub or inapplicable builder.
462
+ sectionResults[sec.heading] = { empty: true };
463
+ continue;
464
+ }
465
+ try {
466
+ let res;
467
+ if (sec.mode === 'search') {
468
+ res = await brainClient.search(query, { topK: 5 });
469
+ } else {
470
+ res = await brainClient.query(query);
471
+ }
472
+ sectionResults[sec.heading] = renderRecords(res);
473
+ // Cost estimate: conservative 60 tokens per call.
474
+ tokens += 60;
475
+ } catch (err) {
476
+ firstError = { reason: categorizeError(err), message: String(err && err.message) };
477
+ sectionResults[sec.heading] = { error: 'brain-error' };
478
+ }
479
+ }
480
+
481
+ if (firstError) {
482
+ result.reason = firstError.reason;
483
+ result.cost_tokens = tokens;
484
+ return result;
485
+ }
486
+
487
+ // Assemble frontmatter.
488
+ const frontmatter = {
489
+ section: ctx.section_slug,
490
+ brain_generated_at: new Date().toISOString(),
491
+ brain_graph_version: brainGraphVersion || 0,
492
+ governing_thought_hash: ctx.governing_thought_hash || EMPTY_SHA256,
493
+ staleness: schemaValidator.STALENESS.FRESH,
494
+ author: 'brain',
495
+ stale_reason: null,
496
+ prompt_version: prompts.PROMPT_VERSION.value,
497
+ cost_tokens: tokens,
498
+ brain_query_count: SECTION_BUILDERS.reduce(function (n, sec) {
499
+ return sectionResults[sec.heading] && !sectionResults[sec.heading].skipped && !sectionResults[sec.heading].empty ? n + 1 : n;
500
+ }, 0),
501
+ };
502
+
503
+ // Phase 90-06 cross_room_scan hook: when opted in at call time, run
504
+ // the cross-room aggregator after local derivation and overwrite the
505
+ // 'Flagged Contradictions (cross-room)' section body with the
506
+ // structural-only rendering. Canon Part 8 is enforced at four layers
507
+ // inside the aggregator (ALLOWED_ROOT scope + GUARDRAIL.md sealed-room
508
+ // + per-room opt-out + sanitizeDetailScalar / JSON.stringify audit).
509
+ // Default off; opt-in per call.
510
+ if (options.cross_room_scan === true) {
511
+ try {
512
+ const xroom = require('./cross-room-aggregator.cjs');
513
+ const xroomResult = await xroom.aggregateContradictions(roomPath, {
514
+ opt_in: true,
515
+ max_rooms: Number.isFinite(options.cross_room_max_rooms) ? options.cross_room_max_rooms : 10,
516
+ per_room_timeout_ms: Number.isFinite(options.cross_room_timeout_ms) ? options.cross_room_timeout_ms : 300,
517
+ });
518
+ const xroomBody = xroom.renderCrossRoomSection(xroomResult);
519
+ sectionResults['Flagged Contradictions (cross-room)'] = { text: xroomBody };
520
+ } catch (_e) {
521
+ // Aggregator NEVER throws under normal conditions; any failure
522
+ // here is catastrophic. Leave the section as the upstream Brain
523
+ // query output (typically '(no signal)' since the stub builder
524
+ // returns null).
525
+ }
526
+ }
527
+
528
+ const body = assembleBrainMd(frontmatter, sectionResults);
529
+
530
+ // Atomic write + schema gate. Test 6 forces bad staleness through
531
+ // _test_force_bad_staleness to exercise the rejection branch.
532
+ const writeOut = await atomicWriteBrainMd(
533
+ sectionPath,
534
+ body,
535
+ options._test_force_bad_staleness === true
536
+ );
537
+
538
+ if (!writeOut.success) {
539
+ result.violations = writeOut.violations || [];
540
+ result.reason = writeOut.fs_error ? 'fs_error' : 'schema_rejected';
541
+ result.cost_tokens = tokens;
542
+ return result;
543
+ }
544
+
545
+ result.success = true;
546
+ result.brain_md_path = writeOut.brain_md_path;
547
+ result.violations = writeOut.violations || [];
548
+ result.cost_tokens = tokens;
549
+ return result;
550
+ }
551
+
552
+ // ---------- Error categorizer ----------
553
+
554
+ function categorizeError(err) {
555
+ const msg = (err && err.message ? err.message : String(err || '')).toLowerCase();
556
+ if (/timeout|etimedout|timed out/.test(msg)) return 'derivation_timeout';
557
+ if (/rate[_\s-]?limited|429/.test(msg)) return 'rate_limited';
558
+ if (/auth|401|unauthorized|invalid_key/.test(msg)) return 'auth_failed';
559
+ return 'derivation_error';
560
+ }
561
+
562
+ // ---------- Exports ----------
563
+
564
+ module.exports = {
565
+ deriveSection: deriveSection,
566
+ buildBrainQueryContext: buildBrainQueryContext,
567
+ classifyProblemType: classifyProblemType,
568
+ derivePhaseIndicator: derivePhaseIndicator,
569
+ deriveComplexity: deriveComplexity,
570
+ // Frozen section registry so downstream plans (90-05, 90-07) can iterate.
571
+ SECTION_BUILDERS: SECTION_BUILDERS,
572
+ EMPTY_SHA256: EMPTY_SHA256,
573
+ // Test surface: not part of the public API.
574
+ _test: Object.freeze({
575
+ atomicWriteBrainMd: atomicWriteBrainMd,
576
+ assembleBrainMd: assembleBrainMd,
577
+ renderRecords: renderRecords,
578
+ categorizeError: categorizeError,
579
+ }),
580
+ };