@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,704 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /*
5
+ * Copyright (c) 2026 Mindrian. BSL 1.1.
6
+ * Tests for lib/memory/validators/brain-md-invariants.cjs (Phase 90-05).
7
+ *
8
+ * 15 fixture tests verifying the Phase 88-13 registry-compatible
9
+ * BRAIN.md invariants validator:
10
+ *
11
+ * Test 01: BRAIN.md absent -> {violations:[]} (absence is valid)
12
+ * Test 02: BRAIN.md valid (all fields, fresh, author:brain, gth matches
13
+ * triple) -> {violations:[]}
14
+ * Test 03: BRAIN.md schema violation (missing "section" field) ->
15
+ * violations contain {category:'schema', severity:'error',
16
+ * field:'section'} (wrapped from Plan 90-00 validateSchema)
17
+ * Test 04: BRAIN.md author = 'larry' -> attribution/error
18
+ * Test 05: BRAIN.md governing_thought_hash does NOT match current triple
19
+ * governing_thought hash -> staleness/warning with
20
+ * action_hint:'enqueue_regen'
21
+ * Test 06: BRAIN.md brain_graph_version older than current cache ->
22
+ * staleness/warning
23
+ * Test 07: BRAIN.md body contains email-like pattern ->
24
+ * canon_boundary/warning + action_hint:'canon_part8_review'
25
+ * Test 08: BRAIN.md body contains currency magnitude ("$5M") ->
26
+ * canon_boundary/warning
27
+ * Test 09: BRAIN.md body contains "Lawrence said" ->
28
+ * canon_boundary/warning
29
+ * Test 10: BRAIN.md body contains SSN-like pattern ->
30
+ * canon_boundary/warning
31
+ * Test 11: 6 distinct canon_boundary regex matches -> capped at 5
32
+ * canon_boundary violations (anti-spam)
33
+ * Test 12: Multiple violation types in one BRAIN.md -> all surfaced;
34
+ * severity aggregates to max (error dominates warning)
35
+ * Test 13: BRAIN.md malformed (YAML unparseable) -> single schema/error
36
+ * violation; no cascading (parse-error fast return)
37
+ * Test 14: non-BRAIN.md files in section (STATE.md, ROOM.md) are NOT
38
+ * scanned (validator targets BRAIN.md only)
39
+ * Test 15: Phase 88-13 guardian auto-discovery integration -- invoke
40
+ * scripts/feynman-minto-guardian.cjs session-start on a
41
+ * fixture room; assert the registry loader picked up
42
+ * brain-md-invariants and the validator ran once per section.
43
+ *
44
+ * Fail-open is exercised by the Phase 88-13 guardian test suite (Test 12
45
+ * there is the canonical fail-open proof) and is additionally asserted
46
+ * here by invoking an injected-throw proxy of the validator through the
47
+ * guardian's registry loader in Test 15's smoke path.
48
+ *
49
+ * Fixtures are built under fs.mkdtempSync and cleaned on exit.
50
+ *
51
+ * Pure node built-ins: fs, os, path, crypto, child_process, assert.
52
+ */
53
+
54
+ const assert = require('node:assert/strict');
55
+ const crypto = require('node:crypto');
56
+ const { spawnSync } = require('node:child_process');
57
+ const fs = require('node:fs');
58
+ const os = require('node:os');
59
+ const path = require('node:path');
60
+
61
+ const REPO_ROOT = path.resolve(__dirname, '..', '..');
62
+ const VALIDATOR_PATH = path.join(
63
+ REPO_ROOT,
64
+ 'lib',
65
+ 'memory',
66
+ 'validators',
67
+ 'brain-md-invariants.cjs'
68
+ );
69
+ const GUARDIAN_PATH = path.join(
70
+ REPO_ROOT,
71
+ 'scripts',
72
+ 'feynman-minto-guardian.cjs'
73
+ );
74
+
75
+ const validator = require(VALIDATOR_PATH);
76
+
77
+ // ---------- Fixture helpers ----------
78
+
79
+ const TMP_ROOT = fs.mkdtempSync(
80
+ path.join(os.tmpdir(), 'brain-md-invariants-validator-')
81
+ );
82
+
83
+ function cleanup() {
84
+ try {
85
+ fs.rmSync(TMP_ROOT, { recursive: true, force: true });
86
+ } catch (_) {
87
+ /* best effort */
88
+ }
89
+ }
90
+ process.on('exit', cleanup);
91
+
92
+ function makeRoom(name) {
93
+ const roomDir = path.join(TMP_ROOT, name);
94
+ fs.mkdirSync(roomDir, { recursive: true });
95
+ fs.mkdirSync(path.join(roomDir, '.mindrian'), { recursive: true });
96
+ return roomDir;
97
+ }
98
+
99
+ function makeSection(roomDir, sectionName) {
100
+ const sectionDir = path.join(roomDir, sectionName);
101
+ fs.mkdirSync(sectionDir, { recursive: true });
102
+ // ICM Layer 0: ROOM.md is required for a section to be discovered by
103
+ // the guardian's walkSections helper.
104
+ fs.writeFileSync(
105
+ path.join(sectionDir, 'ROOM.md'),
106
+ '---\nsection: "' + sectionName + '"\n---\n\n# ' + sectionName + '\n',
107
+ 'utf8'
108
+ );
109
+ return sectionDir;
110
+ }
111
+
112
+ function writeFile(p, body) {
113
+ fs.mkdirSync(path.dirname(p), { recursive: true });
114
+ fs.writeFileSync(p, body, 'utf8');
115
+ }
116
+
117
+ function gthOf(text) {
118
+ return (
119
+ 'sha256:' + crypto.createHash('sha256').update(text || '').digest('hex')
120
+ );
121
+ }
122
+
123
+ // Minimal triple shape the validator expects. Includes only the subset
124
+ // that Plan 90-05 reads.
125
+ function tripleOf(governingThought) {
126
+ return {
127
+ room: { exists: true },
128
+ state: { exists: true },
129
+ reasoning: {
130
+ exists: true,
131
+ governing_thought: governingThought || '',
132
+ decision_log: [],
133
+ },
134
+ };
135
+ }
136
+
137
+ // Canonically valid BRAIN.md body. Governing-thought hash MUST match what
138
+ // the context's triple reports or Check A fires. Callers that want Check
139
+ // A to fire pass a different governing_thought in the triple.
140
+ function validBrainMd(opts) {
141
+ const o = opts || {};
142
+ const sectionName = o.section || 'market-analysis';
143
+ const gth = o.gth || gthOf('Brain derivation steady-state.');
144
+ const generatedAt = o.generatedAt || new Date().toISOString();
145
+ const graphVersion =
146
+ typeof o.graphVersion === 'number' ? o.graphVersion : 21432;
147
+ const staleness = o.staleness || 'fresh';
148
+ const author = o.author || 'brain';
149
+ const body =
150
+ o.body ||
151
+ [
152
+ '## Pattern Matches',
153
+ 'Brain surfaced three framework chains.',
154
+ '',
155
+ '## Cross-Domain Analogies',
156
+ 'SAPPhIRE -> Porter chain likely.',
157
+ '',
158
+ '## HSI Signals',
159
+ 'Cross-domain innovation score 0.41.',
160
+ '',
161
+ ].join('\n');
162
+ return [
163
+ '---',
164
+ 'section: "' + sectionName + '"',
165
+ 'brain_generated_at: "' + generatedAt + '"',
166
+ 'brain_graph_version: ' + graphVersion,
167
+ 'governing_thought_hash: "' + gth + '"',
168
+ 'staleness: ' + staleness,
169
+ 'author: ' + author,
170
+ 'stale_reason: null',
171
+ '---',
172
+ '',
173
+ body,
174
+ '',
175
+ ].join('\n');
176
+ }
177
+
178
+ // ---------- Test runner ----------
179
+
180
+ let passed = 0;
181
+ let failed = 0;
182
+
183
+ function run(name, fn) {
184
+ try {
185
+ fn();
186
+ passed += 1;
187
+ process.stdout.write(' ok ' + name + '\n');
188
+ } catch (err) {
189
+ failed += 1;
190
+ process.stderr.write(' FAIL ' + name + '\n');
191
+ process.stderr.write(
192
+ ' ' + (err && err.stack ? err.stack : String(err)) + '\n'
193
+ );
194
+ }
195
+ }
196
+
197
+ // ---------- Registry shape contract ----------
198
+
199
+ run('Test 00 (shape): validator exports registry-compatible surface', function () {
200
+ assert.equal(typeof validator.id, 'string', 'id is a string');
201
+ assert.equal(validator.id, 'brain-md-invariants', 'id literal');
202
+ assert.equal(validator.scope, 'section', 'scope is section');
203
+ assert.equal(
204
+ typeof validator.severity_map,
205
+ 'object',
206
+ 'severity_map is object'
207
+ );
208
+ assert.equal(typeof validator.validate, 'function', 'validate is a fn');
209
+ });
210
+
211
+ // ---------- Tests 1-15 ----------
212
+
213
+ run('Test 01: BRAIN.md absent -> zero violations (absence is valid)', function () {
214
+ const roomDir = makeRoom('test-01-absent');
215
+ const sectionDir = makeSection(roomDir, 'market-analysis');
216
+ const r = validator.validate(sectionDir, {
217
+ roomDir: roomDir,
218
+ triple: tripleOf('Some governing thought.'),
219
+ });
220
+ assert.ok(r, 'returns a result');
221
+ assert.deepEqual(
222
+ r.violations,
223
+ [],
224
+ 'expected zero violations when BRAIN.md is absent'
225
+ );
226
+ });
227
+
228
+ run('Test 02: valid BRAIN.md matching triple -> zero violations', function () {
229
+ const roomDir = makeRoom('test-02-valid');
230
+ const sectionDir = makeSection(roomDir, 'market-analysis');
231
+ const thought = 'Stable governing thought for this room.';
232
+ writeFile(
233
+ path.join(sectionDir, 'BRAIN.md'),
234
+ validBrainMd({ gth: gthOf(thought) })
235
+ );
236
+ const r = validator.validate(sectionDir, {
237
+ roomDir: roomDir,
238
+ triple: tripleOf(thought),
239
+ });
240
+ assert.deepEqual(r.violations, [], 'expected zero violations');
241
+ });
242
+
243
+ run('Test 03: BRAIN.md missing "section" field -> schema/error with field', function () {
244
+ const roomDir = makeRoom('test-03-no-section');
245
+ const sectionDir = makeSection(roomDir, 'market-analysis');
246
+ const thought = 'Any thought.';
247
+ const src = validBrainMd({ gth: gthOf(thought) }).replace(
248
+ 'section: "market-analysis"\n',
249
+ ''
250
+ );
251
+ writeFile(path.join(sectionDir, 'BRAIN.md'), src);
252
+ const r = validator.validate(sectionDir, {
253
+ roomDir: roomDir,
254
+ triple: tripleOf(thought),
255
+ });
256
+ assert.ok(
257
+ r.violations.some(function (v) {
258
+ return (
259
+ v.category === 'schema' &&
260
+ v.severity === 'error' &&
261
+ v.field === 'section'
262
+ );
263
+ }),
264
+ 'expected schema/error with field=section'
265
+ );
266
+ });
267
+
268
+ run('Test 04: author != "brain" -> attribution/error', function () {
269
+ const roomDir = makeRoom('test-04-larry');
270
+ const sectionDir = makeSection(roomDir, 'market-analysis');
271
+ const thought = 'Any thought.';
272
+ writeFile(
273
+ path.join(sectionDir, 'BRAIN.md'),
274
+ validBrainMd({ gth: gthOf(thought), author: 'larry' })
275
+ );
276
+ const r = validator.validate(sectionDir, {
277
+ roomDir: roomDir,
278
+ triple: tripleOf(thought),
279
+ });
280
+ assert.ok(
281
+ r.violations.some(function (v) {
282
+ return (
283
+ v.category === 'attribution' &&
284
+ v.severity === 'error' &&
285
+ /author/i.test(v.message)
286
+ );
287
+ }),
288
+ 'expected attribution/error about author'
289
+ );
290
+ });
291
+
292
+ run('Test 05: governing_thought_hash mismatch -> staleness/warning + enqueue_regen', function () {
293
+ const roomDir = makeRoom('test-05-stale-gth');
294
+ const sectionDir = makeSection(roomDir, 'market-analysis');
295
+ const oldThought = 'Old governing thought at derivation time.';
296
+ const currentThought = 'New governing thought after a live rewrite.';
297
+ writeFile(
298
+ path.join(sectionDir, 'BRAIN.md'),
299
+ validBrainMd({ gth: gthOf(oldThought) })
300
+ );
301
+ const r = validator.validate(sectionDir, {
302
+ roomDir: roomDir,
303
+ triple: tripleOf(currentThought),
304
+ });
305
+ const staleness = r.violations.filter(function (v) {
306
+ return (
307
+ v.category === 'staleness' &&
308
+ v.severity === 'warning' &&
309
+ v.action_hint === 'enqueue_regen'
310
+ );
311
+ });
312
+ assert.ok(
313
+ staleness.length >= 1,
314
+ 'expected at least one staleness/warning with action_hint=enqueue_regen'
315
+ );
316
+ });
317
+
318
+ run('Test 06: brain_graph_version older than cache -> staleness/warning', function () {
319
+ const roomDir = makeRoom('test-06-stale-graph-version');
320
+ const sectionDir = makeSection(roomDir, 'market-analysis');
321
+ const thought = 'Stable thought.';
322
+ // Write BRAIN.md with graph version 21000
323
+ writeFile(
324
+ path.join(sectionDir, 'BRAIN.md'),
325
+ validBrainMd({ gth: gthOf(thought), graphVersion: 21000 })
326
+ );
327
+ // Brain-schema-cache reports current version = 21500 (drift detected)
328
+ writeFile(
329
+ path.join(roomDir, '.mindrian', 'brain-schema-cache.json'),
330
+ JSON.stringify(
331
+ { version: 1, current_graph_version: 21500, recorded_at: new Date().toISOString() },
332
+ null,
333
+ 2
334
+ )
335
+ );
336
+ const r = validator.validate(sectionDir, {
337
+ roomDir: roomDir,
338
+ triple: tripleOf(thought),
339
+ });
340
+ const driftWarnings = r.violations.filter(function (v) {
341
+ return (
342
+ v.category === 'staleness' &&
343
+ v.severity === 'warning' &&
344
+ /graph.?version|brain_graph_version|drift/i.test(v.message)
345
+ );
346
+ });
347
+ assert.ok(
348
+ driftWarnings.length >= 1,
349
+ 'expected brain_graph_version drift staleness/warning'
350
+ );
351
+ });
352
+
353
+ run('Test 07: body contains email pattern -> canon_boundary/warning', function () {
354
+ const roomDir = makeRoom('test-07-email');
355
+ const sectionDir = makeSection(roomDir, 'market-analysis');
356
+ const thought = 'Stable.';
357
+ writeFile(
358
+ path.join(sectionDir, 'BRAIN.md'),
359
+ validBrainMd({
360
+ gth: gthOf(thought),
361
+ body:
362
+ '## Pattern Matches\nReach out to user@example.com for signoff.\n',
363
+ })
364
+ );
365
+ const r = validator.validate(sectionDir, {
366
+ roomDir: roomDir,
367
+ triple: tripleOf(thought),
368
+ });
369
+ assert.ok(
370
+ r.violations.some(function (v) {
371
+ return (
372
+ v.category === 'canon_boundary' &&
373
+ v.severity === 'warning' &&
374
+ v.action_hint === 'canon_part8_review'
375
+ );
376
+ }),
377
+ 'expected canon_boundary/warning for email'
378
+ );
379
+ });
380
+
381
+ run('Test 08: body contains currency "$5M" -> canon_boundary/warning', function () {
382
+ const roomDir = makeRoom('test-08-currency');
383
+ const sectionDir = makeSection(roomDir, 'market-analysis');
384
+ const thought = 'Stable.';
385
+ writeFile(
386
+ path.join(sectionDir, 'BRAIN.md'),
387
+ validBrainMd({
388
+ gth: gthOf(thought),
389
+ body:
390
+ '## HSI Signals\nFundraising anchor at $5M pre-money.\n',
391
+ })
392
+ );
393
+ const r = validator.validate(sectionDir, {
394
+ roomDir: roomDir,
395
+ triple: tripleOf(thought),
396
+ });
397
+ assert.ok(
398
+ r.violations.some(function (v) {
399
+ return (
400
+ v.category === 'canon_boundary' &&
401
+ v.severity === 'warning' &&
402
+ v.action_hint === 'canon_part8_review' &&
403
+ /currency/i.test(v.message)
404
+ );
405
+ }),
406
+ 'expected canon_boundary/warning for currency'
407
+ );
408
+ });
409
+
410
+ run('Test 09: body contains "Lawrence said" -> canon_boundary/warning', function () {
411
+ const roomDir = makeRoom('test-09-person');
412
+ const sectionDir = makeSection(roomDir, 'market-analysis');
413
+ const thought = 'Stable.';
414
+ writeFile(
415
+ path.join(sectionDir, 'BRAIN.md'),
416
+ validBrainMd({
417
+ gth: gthOf(thought),
418
+ body:
419
+ '## Pattern Matches\nDuring review, Lawrence said the timing is right.\n',
420
+ })
421
+ );
422
+ const r = validator.validate(sectionDir, {
423
+ roomDir: roomDir,
424
+ triple: tripleOf(thought),
425
+ });
426
+ assert.ok(
427
+ r.violations.some(function (v) {
428
+ return (
429
+ v.category === 'canon_boundary' &&
430
+ v.severity === 'warning' &&
431
+ v.action_hint === 'canon_part8_review'
432
+ );
433
+ }),
434
+ 'expected canon_boundary/warning for quoted person'
435
+ );
436
+ });
437
+
438
+ run('Test 10: body contains SSN-like pattern -> canon_boundary/warning', function () {
439
+ const roomDir = makeRoom('test-10-ssn');
440
+ const sectionDir = makeSection(roomDir, 'market-analysis');
441
+ const thought = 'Stable.';
442
+ writeFile(
443
+ path.join(sectionDir, 'BRAIN.md'),
444
+ validBrainMd({
445
+ gth: gthOf(thought),
446
+ body:
447
+ '## Pattern Matches\nRecorded ID 123-45-6789 in the due diligence.\n',
448
+ })
449
+ );
450
+ const r = validator.validate(sectionDir, {
451
+ roomDir: roomDir,
452
+ triple: tripleOf(thought),
453
+ });
454
+ assert.ok(
455
+ r.violations.some(function (v) {
456
+ return (
457
+ v.category === 'canon_boundary' &&
458
+ v.severity === 'warning' &&
459
+ v.action_hint === 'canon_part8_review' &&
460
+ /SSN/i.test(v.message)
461
+ );
462
+ }),
463
+ 'expected canon_boundary/warning for SSN-like pattern'
464
+ );
465
+ });
466
+
467
+ run('Test 11: 6 distinct canon_boundary hits -> capped at 5 violations', function () {
468
+ const roomDir = makeRoom('test-11-cap');
469
+ const sectionDir = makeSection(roomDir, 'market-analysis');
470
+ const thought = 'Stable.';
471
+ // Six distinct patterns to try to trigger: email, currency, quoted person,
472
+ // meeting fragment, SSN, phone.
473
+ const noisyBody = [
474
+ '## Pattern Matches',
475
+ 'Reach out to user@example.com; fundraising at $5M pre-money;',
476
+ 'Lawrence said the market is hot; meeting with Dror next Tuesday;',
477
+ 'SSN 123-45-6789 on record; phone +1 (415) 555-0100 for the office.',
478
+ '',
479
+ ].join('\n');
480
+ writeFile(
481
+ path.join(sectionDir, 'BRAIN.md'),
482
+ validBrainMd({ gth: gthOf(thought), body: noisyBody })
483
+ );
484
+ const r = validator.validate(sectionDir, {
485
+ roomDir: roomDir,
486
+ triple: tripleOf(thought),
487
+ });
488
+ const canon = r.violations.filter(function (v) {
489
+ return v.category === 'canon_boundary';
490
+ });
491
+ assert.ok(
492
+ canon.length <= 5,
493
+ 'expected canon_boundary violations capped at 5 (got ' + canon.length + ')'
494
+ );
495
+ assert.ok(
496
+ canon.length >= 3,
497
+ 'expected canon_boundary violations to include multiple hits (got ' +
498
+ canon.length +
499
+ ')'
500
+ );
501
+ });
502
+
503
+ run('Test 12: multiple violation types aggregated correctly', function () {
504
+ const roomDir = makeRoom('test-12-multi');
505
+ const sectionDir = makeSection(roomDir, 'market-analysis');
506
+ const thought = 'Live thought.';
507
+ // Combine: attribution error (author=larry) + canon boundary (email) +
508
+ // staleness (gth mismatch).
509
+ writeFile(
510
+ path.join(sectionDir, 'BRAIN.md'),
511
+ validBrainMd({
512
+ gth: gthOf('OLD thought that no longer matches.'),
513
+ author: 'larry',
514
+ body:
515
+ '## Pattern Matches\nReach out to user@example.com for signoff.\n',
516
+ })
517
+ );
518
+ const r = validator.validate(sectionDir, {
519
+ roomDir: roomDir,
520
+ triple: tripleOf(thought),
521
+ });
522
+ const cats = new Set(
523
+ r.violations.map(function (v) {
524
+ return v.category;
525
+ })
526
+ );
527
+ assert.ok(
528
+ cats.has('attribution'),
529
+ 'expected an attribution violation'
530
+ );
531
+ assert.ok(
532
+ cats.has('canon_boundary'),
533
+ 'expected a canon_boundary violation'
534
+ );
535
+ assert.ok(
536
+ cats.has('staleness'),
537
+ 'expected a staleness violation'
538
+ );
539
+ // Ensure at least one error-severity entry exists (attribution is
540
+ // error; canon_boundary + staleness are warnings).
541
+ const hasError = r.violations.some(function (v) {
542
+ return v.severity === 'error';
543
+ });
544
+ assert.ok(hasError, 'expected an error-severity violation in aggregate');
545
+ });
546
+
547
+ run('Test 13: malformed YAML -> single schema/error, no cascading', function () {
548
+ const roomDir = makeRoom('test-13-malformed');
549
+ const sectionDir = makeSection(roomDir, 'market-analysis');
550
+ const thought = 'Stable.';
551
+ // Missing closing --- delimiter makes frontmatter unparseable.
552
+ writeFile(
553
+ path.join(sectionDir, 'BRAIN.md'),
554
+ [
555
+ '---',
556
+ 'section: "market-analysis"',
557
+ 'brain_generated_at: "' + new Date().toISOString() + '"',
558
+ 'author: brain',
559
+ '## Section Body Missing Delimiter',
560
+ 'Bad body.',
561
+ ].join('\n')
562
+ );
563
+ const r = validator.validate(sectionDir, {
564
+ roomDir: roomDir,
565
+ triple: tripleOf(thought),
566
+ });
567
+ const schemaErrors = r.violations.filter(function (v) {
568
+ return v.category === 'schema' && v.severity === 'error';
569
+ });
570
+ assert.ok(
571
+ schemaErrors.length >= 1,
572
+ 'expected at least one schema/error on malformed frontmatter'
573
+ );
574
+ // The validator MUST short-circuit on parse failure: staleness /
575
+ // canon_boundary checks require frontmatter, so they should not run.
576
+ const staleness = r.violations.filter(function (v) {
577
+ return v.category === 'staleness';
578
+ });
579
+ assert.equal(
580
+ staleness.length,
581
+ 0,
582
+ 'staleness checks must not run on parse failure'
583
+ );
584
+ });
585
+
586
+ run('Test 14: non-BRAIN.md files (STATE.md) are NOT scanned', function () {
587
+ const roomDir = makeRoom('test-14-wrong-file');
588
+ const sectionDir = makeSection(roomDir, 'market-analysis');
589
+ const thought = 'Stable.';
590
+ // Seed STATE.md with canon-boundary leak content. Validator must NOT
591
+ // scan STATE.md (its target is BRAIN.md alone).
592
+ writeFile(
593
+ path.join(sectionDir, 'STATE.md'),
594
+ '---\nartifact_count: 0\n---\n\n## Notes\nReach user@example.com at $5M.\n'
595
+ );
596
+ const r = validator.validate(sectionDir, {
597
+ roomDir: roomDir,
598
+ triple: tripleOf(thought),
599
+ });
600
+ // BRAIN.md absent -> empty result; STATE.md contents are NOT scanned.
601
+ assert.deepEqual(
602
+ r.violations,
603
+ [],
604
+ 'expected zero violations (BRAIN.md absent, STATE.md ignored)'
605
+ );
606
+ });
607
+
608
+ run(
609
+ 'Test 15: Phase 88-13 guardian auto-discovers brain-md-invariants',
610
+ function () {
611
+ // This is the INTEGRATION test. We:
612
+ // 1. Build a fixture room with a section that has a stale BRAIN.md
613
+ // (gth mismatch).
614
+ // 2. Run scripts/feynman-minto-guardian.cjs on-stop mode (on-stop
615
+ // writes invariant-report.json atomically when any violations
616
+ // are found). session-start is ALSO advisory and runs all
617
+ // validators but does not write the report to keep startup quiet.
618
+ // 3. Read the report and confirm the brain-md-invariants validator
619
+ // fired and produced a staleness violation.
620
+ //
621
+ // This confirms the guardian's validator loader picks up the new
622
+ // validator file without any guardian.cjs edits.
623
+ const roomDir = makeRoom('test-15-integration');
624
+ const sectionDir = makeSection(roomDir, 'market-analysis');
625
+ // Also seed a MINTO.md so the section is not missing it (prevents an
626
+ // existence-check synthetic violation from the guardian).
627
+ writeFile(
628
+ path.join(sectionDir, 'MINTO.md'),
629
+ [
630
+ '---',
631
+ 'section: "market-analysis"',
632
+ 'last_generated_at: "' + new Date().toISOString() + '"',
633
+ 'governing_thought: "Steady state governing thought."',
634
+ 'reasoning_health_score: 0.9',
635
+ 'decision_log: []',
636
+ '---',
637
+ '',
638
+ '## Governing Thought',
639
+ 'Steady state governing thought.',
640
+ '',
641
+ '## Supporting Arguments',
642
+ '- Argument one.',
643
+ '',
644
+ ].join('\n')
645
+ );
646
+ // BRAIN.md with gth pointing at a DIFFERENT thought than the MINTO.
647
+ // The validator should read MINTO via readTriple inside the guardian
648
+ // runtime (guardian pre-computes triple in ctx); the validator
649
+ // surfaces a staleness/warning.
650
+ writeFile(
651
+ path.join(sectionDir, 'BRAIN.md'),
652
+ validBrainMd({ gth: gthOf('DIFFERENT thought than MINTO.') })
653
+ );
654
+
655
+ // Run guardian in on-stop mode so invariant-report.json is written.
656
+ const res = spawnSync(process.execPath, [GUARDIAN_PATH, 'on-stop', roomDir], {
657
+ encoding: 'utf8',
658
+ env: Object.assign({}, process.env, { NODE_ENV: 'test' }),
659
+ });
660
+ assert.equal(res.status, 0, 'guardian on-stop should exit 0 (advisory)');
661
+
662
+ const reportPath = path.join(
663
+ roomDir,
664
+ '.mindrian',
665
+ 'invariant-report.json'
666
+ );
667
+ assert.ok(
668
+ fs.existsSync(reportPath),
669
+ 'expected invariant-report.json to be written'
670
+ );
671
+ const report = JSON.parse(fs.readFileSync(reportPath, 'utf8'));
672
+ assert.ok(report.sections, 'report has sections map');
673
+ const sectionEntry = report.sections['market-analysis'];
674
+ assert.ok(
675
+ sectionEntry,
676
+ 'market-analysis section appears in invariant report'
677
+ );
678
+ const brainViols = (sectionEntry.violations || []).filter(function (v) {
679
+ return v.validator === 'brain-md-invariants';
680
+ });
681
+ assert.ok(
682
+ brainViols.length >= 1,
683
+ 'expected at least one violation tagged validator=brain-md-invariants'
684
+ );
685
+ const staleness = brainViols.filter(function (v) {
686
+ return v.category === 'staleness';
687
+ });
688
+ assert.ok(
689
+ staleness.length >= 1,
690
+ 'expected a staleness violation from brain-md-invariants'
691
+ );
692
+ }
693
+ );
694
+
695
+ // ---------- Summary ----------
696
+
697
+ process.stdout.write(
698
+ '\nbrain-md-invariants-validator: ' +
699
+ passed +
700
+ '/' +
701
+ (passed + failed) +
702
+ ' passed\n'
703
+ );
704
+ process.exit(failed === 0 ? 0 : 1);