@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,528 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /*
5
+ * Copyright (c) 2026 Mindrian. BSL 1.1.
6
+ * BRAIN.md schema validator -- Phase 90-00.
7
+ *
8
+ * Single source of truth for the shape of the Brain-authored derivation
9
+ * layer (fourth memory file in the per-folder quadruple: ROOM.md +
10
+ * STATE.md + Feynman-MINTO.md + BRAIN.md). Consumed by every downstream
11
+ * Phase 90-* plan:
12
+ * 90-01 derivation core writes BRAIN.md that passes validateSchema
13
+ * 90-04 readQuadruple extends the read contract
14
+ * 90-05 registry-discoverable invariants validator wraps this entry point
15
+ * 90-09 Phase 91 Navigation Engine interface spec cites this schema
16
+ *
17
+ * Pure CJS, zero npm dependencies, node built-ins only (fs + path). No
18
+ * js-yaml: the frontmatter is a narrow subset (scalars, ISO timestamps,
19
+ * small integers, null) that a hand-written parser handles deterministically
20
+ * and audit-friendly. The parser is scoped to BRAIN.md fields only (zero
21
+ * cross-import from feynman-minto-invariants.cjs; keeps lib/core
22
+ * dependency graph flat per 88-01 pattern).
23
+ *
24
+ * API: validateSchema(filePath) -> { valid, violations[], severity }
25
+ * violations[i] = { category, severity, message, field?, action_hint? }
26
+ * severity = max severity across violations (null if none)
27
+ *
28
+ * Also exports frozen enums so downstream modules do not stringify
29
+ * values:
30
+ * SCHEMA_VERSION, SEVERITY, CATEGORIES, STALENESS, STALE_REASON,
31
+ * REQUIRED_FRONTMATTER_FIELDS, OPTIONAL_SECTION_HEADINGS.
32
+ *
33
+ * Canon Part 8 boundary is baked in at the schema layer. The validator
34
+ * scans every frontmatter scalar value against a conservative regex set
35
+ * (email-like, currency magnitudes, quoted persons, meeting fragments,
36
+ * SSN-like patterns). Matches emit canon_boundary/warning with
37
+ * action_hint "canon_part8_review". Heuristics are deliberately
38
+ * over-inclusive: this is a manual review flag, never a hard block.
39
+ */
40
+
41
+ const fs = require('node:fs');
42
+
43
+ // ---------- Enums (frozen exports) ----------
44
+
45
+ const SCHEMA_VERSION = 1;
46
+
47
+ const SEVERITY = Object.freeze({
48
+ CRITICAL: 'critical',
49
+ ERROR: 'error',
50
+ WARNING: 'warning',
51
+ INFO: 'info',
52
+ });
53
+
54
+ const CATEGORIES = Object.freeze({
55
+ EXISTENCE: 'existence',
56
+ SCHEMA: 'schema',
57
+ STALENESS: 'staleness',
58
+ ATTRIBUTION: 'attribution',
59
+ CANON_BOUNDARY: 'canon_boundary',
60
+ });
61
+
62
+ const STALENESS = Object.freeze({
63
+ FRESH: 'fresh',
64
+ STALE: 'stale',
65
+ UNAVAILABLE: 'unavailable',
66
+ });
67
+
68
+ const STALE_REASON = Object.freeze({
69
+ NONE: null,
70
+ GOVERNING_THOUGHT_CHANGED: 'governing_thought_changed',
71
+ BRAIN_OFFLINE: 'brain_offline',
72
+ DERIVATION_TIMEOUT: 'derivation_timeout',
73
+ BRAIN_GRAPH_VERSION_MISMATCH: 'brain_graph_version_mismatch',
74
+ });
75
+
76
+ const REQUIRED_FRONTMATTER_FIELDS = Object.freeze([
77
+ 'section',
78
+ 'brain_generated_at',
79
+ 'brain_graph_version',
80
+ 'governing_thought_hash',
81
+ 'staleness',
82
+ 'author',
83
+ ]);
84
+
85
+ const OPTIONAL_SECTION_HEADINGS = Object.freeze([
86
+ '## Pattern Matches',
87
+ '## Cross-Domain Analogies',
88
+ '## Wicked Indicators',
89
+ '## Unfilled Opportunity Matches',
90
+ '## Framework Chain Predictions',
91
+ '## Assessment Thinking Chain Position',
92
+ '## ProblemType Classification',
93
+ '## Flagged Contradictions (cross-room)',
94
+ '## HSI Signals',
95
+ ]);
96
+
97
+ // Severity ordering (lowest -> highest) for aggregate max calculation.
98
+ const SEVERITY_ORDER = [
99
+ SEVERITY.INFO,
100
+ SEVERITY.WARNING,
101
+ SEVERITY.ERROR,
102
+ SEVERITY.CRITICAL,
103
+ ];
104
+
105
+ // Attribution invariant: author frozen to "brain" (BRAIN.md is
106
+ // self-attributed; writing any other value is a constitutional breach).
107
+ const AUTHOR_FROZEN_VALUE = 'brain';
108
+
109
+ // Valid enum sets for frontmatter values.
110
+ const STALENESS_VALUES = Object.freeze([
111
+ STALENESS.FRESH,
112
+ STALENESS.STALE,
113
+ STALENESS.UNAVAILABLE,
114
+ ]);
115
+
116
+ const STALE_REASON_VALUES = Object.freeze([
117
+ null,
118
+ STALE_REASON.GOVERNING_THOUGHT_CHANGED,
119
+ STALE_REASON.BRAIN_OFFLINE,
120
+ STALE_REASON.DERIVATION_TIMEOUT,
121
+ STALE_REASON.BRAIN_GRAPH_VERSION_MISMATCH,
122
+ ]);
123
+
124
+ // ---------- Canon Part 8 leak heuristics (frozen regex set) ----------
125
+ //
126
+ // These patterns are conservative and deliberately over-flag. Any match
127
+ // in a frontmatter scalar value emits canon_boundary/warning with
128
+ // action_hint "canon_part8_review". The schema layer is the first line
129
+ // of defense against user-content seepage into Brain-queryable handles.
130
+ // Hard blocks live at the runtime layer (Plan 90-01 derivation writer
131
+ // enforces emission-time sanitization; this validator is the read-time
132
+ // and ship-time audit).
133
+
134
+ const CANON_LEAK_PATTERNS = Object.freeze([
135
+ { re: /@[a-zA-Z0-9._-]+\.[a-zA-Z]{2,}/, hint: 'email-like pattern' },
136
+ { re: /\$[0-9][\d,.]*[KMB]?\b/, hint: 'currency magnitude' },
137
+ {
138
+ re: /\b(Lawrence|Jonathan|Nimrod|Oren|Dror)\s+said\b/i,
139
+ hint: 'quoted-person attribution',
140
+ },
141
+ { re: /\bmeeting with\b/i, hint: 'meeting fragment' },
142
+ { re: /\b\d{3}-\d{2}-\d{4}\b/, hint: 'SSN-like pattern' },
143
+ ]);
144
+
145
+ // ---------- Helpers ----------
146
+
147
+ function addViolation(list, category, severity, message, field, actionHint) {
148
+ const v = { category: category, severity: severity, message: message };
149
+ if (field) v.field = field;
150
+ if (actionHint) v.action_hint = actionHint;
151
+ list.push(v);
152
+ }
153
+
154
+ function aggregateSeverity(violations) {
155
+ let max = -1;
156
+ for (const v of violations) {
157
+ const idx = SEVERITY_ORDER.indexOf(v.severity);
158
+ if (idx > max) max = idx;
159
+ }
160
+ return max === -1 ? null : SEVERITY_ORDER[max];
161
+ }
162
+
163
+ function unquote(raw) {
164
+ const s = raw.trim();
165
+ if (s.length === 0) return '';
166
+ if (s[0] === '"') {
167
+ if (s.length < 2 || s[s.length - 1] !== '"') return null;
168
+ return s.slice(1, -1);
169
+ }
170
+ if (s[0] === "'") {
171
+ if (s.length < 2 || s[s.length - 1] !== "'") return null;
172
+ return s.slice(1, -1);
173
+ }
174
+ return s;
175
+ }
176
+
177
+ // ---------- Hand-written YAML parser (narrow dialect only) ----------
178
+ //
179
+ // Accepts only:
180
+ // key: scalar
181
+ // key: "quoted scalar"
182
+ // key: 'quoted scalar'
183
+ // key: 123 (integer)
184
+ // key: 0.75 (float)
185
+ // key: null
186
+ // key: true | false
187
+ //
188
+ // Arrays and nested objects are explicitly NOT supported: BRAIN.md
189
+ // frontmatter by contract is flat scalars only. If a user tries an
190
+ // array-value, the parser returns { ok: false } and the caller emits
191
+ // a schema/error violation.
192
+ //
193
+ // Returns { ok: true, data } or { ok: false, error }.
194
+
195
+ function parseYaml(src) {
196
+ const lines = src.split(/\r?\n/);
197
+ const root = {};
198
+ for (let i = 0; i < lines.length; i++) {
199
+ const raw = lines[i];
200
+ if (raw.length === 0 || /^\s*$/.test(raw) || /^\s*#/.test(raw)) continue;
201
+ // BRAIN.md frontmatter lines MUST be top-level key: value. Indented
202
+ // lines, array entries, or nested blocks are not part of the
203
+ // contract.
204
+ const m = raw.match(/^([A-Za-z_][A-Za-z0-9_-]*):(.*)$/);
205
+ if (!m) {
206
+ return {
207
+ ok: false,
208
+ error: 'unrecognized line at frontmatter line ' + (i + 1),
209
+ };
210
+ }
211
+ const key = m[1];
212
+ const rest = m[2];
213
+ if (rest.trim().length === 0) {
214
+ // key: with empty value is allowed (treated as empty string).
215
+ // But BRAIN.md contract is flat scalars only; if next line is
216
+ // indented, reject (array or block marker).
217
+ if (i + 1 < lines.length && /^\s+[^\s]/.test(lines[i + 1])) {
218
+ return {
219
+ ok: false,
220
+ error:
221
+ 'unexpected indented block for key "' +
222
+ key +
223
+ '" (BRAIN.md frontmatter is flat scalars only)',
224
+ };
225
+ }
226
+ root[key] = '';
227
+ continue;
228
+ }
229
+ const vStr = unquote(rest);
230
+ if (vStr === null) {
231
+ return {
232
+ ok: false,
233
+ error: 'unterminated quoted scalar for key "' + key + '"',
234
+ };
235
+ }
236
+ // Cast known scalar shapes: null / boolean / integer / float stay
237
+ // as native JS values; everything else is a string.
238
+ root[key] = castScalar(vStr);
239
+ }
240
+ return { ok: true, data: root };
241
+ }
242
+
243
+ function castScalar(s) {
244
+ if (s === 'null' || s === '~') return null;
245
+ if (s === 'true') return true;
246
+ if (s === 'false') return false;
247
+ // Integer (no decimal point)
248
+ if (/^-?\d+$/.test(s)) {
249
+ const n = parseInt(s, 10);
250
+ if (Number.isSafeInteger(n)) return n;
251
+ }
252
+ // Float (has decimal point)
253
+ if (/^-?\d+\.\d+$/.test(s)) {
254
+ const f = parseFloat(s);
255
+ if (Number.isFinite(f)) return f;
256
+ }
257
+ return s;
258
+ }
259
+
260
+ // ---------- Canon Part 8 leak scanner ----------
261
+ //
262
+ // Walks every string-valued frontmatter field and tests against the
263
+ // frozen regex set. Non-string values are skipped (booleans, ints, null
264
+ // cannot carry user content). Matches produce canon_boundary/warning.
265
+ // One violation per (field, pattern) to avoid pathological noise.
266
+
267
+ function scanCanonLeaks(fm, violations) {
268
+ for (const key of Object.keys(fm)) {
269
+ const value = fm[key];
270
+ if (typeof value !== 'string' || value.length === 0) continue;
271
+ for (const p of CANON_LEAK_PATTERNS) {
272
+ if (p.re.test(value)) {
273
+ addViolation(
274
+ violations,
275
+ CATEGORIES.CANON_BOUNDARY,
276
+ SEVERITY.WARNING,
277
+ 'Possible Canon Part 8 leak in "' +
278
+ key +
279
+ '": ' +
280
+ p.hint +
281
+ ' matched. Review for user-content seepage into Brain-queryable handle.',
282
+ key,
283
+ 'canon_part8_review'
284
+ );
285
+ }
286
+ }
287
+ }
288
+ }
289
+
290
+ // ---------- Main validator ----------
291
+
292
+ /**
293
+ * validateSchema(filePath) -> { valid, violations[], severity }
294
+ *
295
+ * Does not throw. Every failure mode is expressed as a violation so the
296
+ * caller can decide policy (warn vs block vs repair).
297
+ */
298
+ function validateSchema(filePath) {
299
+ const violations = [];
300
+
301
+ // --- Existence check ---
302
+ let stat;
303
+ try {
304
+ stat = fs.statSync(filePath);
305
+ } catch (_err) {
306
+ addViolation(
307
+ violations,
308
+ CATEGORIES.EXISTENCE,
309
+ SEVERITY.CRITICAL,
310
+ 'BRAIN.md not found: ' + filePath
311
+ );
312
+ return {
313
+ valid: false,
314
+ violations: violations,
315
+ severity: aggregateSeverity(violations),
316
+ };
317
+ }
318
+
319
+ if (!stat.isFile()) {
320
+ addViolation(
321
+ violations,
322
+ CATEGORIES.EXISTENCE,
323
+ SEVERITY.CRITICAL,
324
+ 'Path is not a regular file: ' + filePath
325
+ );
326
+ return {
327
+ valid: false,
328
+ violations: violations,
329
+ severity: aggregateSeverity(violations),
330
+ };
331
+ }
332
+
333
+ if (stat.size === 0) {
334
+ addViolation(
335
+ violations,
336
+ CATEGORIES.EXISTENCE,
337
+ SEVERITY.CRITICAL,
338
+ 'BRAIN.md is empty (zero bytes): ' + filePath
339
+ );
340
+ return {
341
+ valid: false,
342
+ violations: violations,
343
+ severity: aggregateSeverity(violations),
344
+ };
345
+ }
346
+
347
+ const raw = fs.readFileSync(filePath, 'utf8');
348
+
349
+ // --- Frontmatter delimiter check ---
350
+ //
351
+ // Parse-error fast return: if delimiters are missing or YAML is
352
+ // unparseable, emit ONE schema/error and stop. Do not run
353
+ // required-field checks against an undefined frontmatter object.
354
+ const fmRe = /^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/;
355
+ const fmMatch = raw.match(fmRe);
356
+ if (!fmMatch) {
357
+ addViolation(
358
+ violations,
359
+ CATEGORIES.SCHEMA,
360
+ SEVERITY.ERROR,
361
+ 'Missing or malformed frontmatter delimiters (--- ... ---)'
362
+ );
363
+ return {
364
+ valid: false,
365
+ violations: violations,
366
+ severity: aggregateSeverity(violations),
367
+ };
368
+ }
369
+
370
+ const fmText = fmMatch[1];
371
+ const body = fmMatch[2];
372
+
373
+ // --- YAML parse ---
374
+ const parsed = parseYaml(fmText);
375
+ if (!parsed.ok) {
376
+ addViolation(
377
+ violations,
378
+ CATEGORIES.SCHEMA,
379
+ SEVERITY.ERROR,
380
+ 'Frontmatter parse failure: ' + parsed.error
381
+ );
382
+ return {
383
+ valid: false,
384
+ violations: violations,
385
+ severity: aggregateSeverity(violations),
386
+ };
387
+ }
388
+ const fm = parsed.data;
389
+
390
+ // --- Required fields ---
391
+ //
392
+ // Each missing required field is a schema/error -- except "author",
393
+ // whose absence or mismatch is an ATTRIBUTION error (BRAIN.md MUST be
394
+ // self-attributed to the Brain; a wrong author is a constitutional
395
+ // breach, not a shape miss).
396
+ for (const field of REQUIRED_FRONTMATTER_FIELDS) {
397
+ if (!(field in fm) || fm[field] === '' || fm[field] === undefined) {
398
+ if (field === 'author') {
399
+ addViolation(
400
+ violations,
401
+ CATEGORIES.ATTRIBUTION,
402
+ SEVERITY.ERROR,
403
+ 'Missing required frontmatter field: author (must be "brain")',
404
+ field
405
+ );
406
+ } else {
407
+ addViolation(
408
+ violations,
409
+ CATEGORIES.SCHEMA,
410
+ SEVERITY.ERROR,
411
+ 'Missing required frontmatter field: ' + field,
412
+ field
413
+ );
414
+ }
415
+ }
416
+ }
417
+
418
+ // --- Author must equal "brain" ---
419
+ if ('author' in fm && fm.author !== '' && fm.author !== AUTHOR_FROZEN_VALUE) {
420
+ addViolation(
421
+ violations,
422
+ CATEGORIES.ATTRIBUTION,
423
+ SEVERITY.ERROR,
424
+ 'author field is "' +
425
+ String(fm.author) +
426
+ '", must be "' +
427
+ AUTHOR_FROZEN_VALUE +
428
+ '" (BRAIN.md is self-attributed; other values are a Canon Part 2 breach)',
429
+ 'author'
430
+ );
431
+ }
432
+
433
+ // --- Staleness enum ---
434
+ if (
435
+ 'staleness' in fm &&
436
+ fm.staleness !== '' &&
437
+ STALENESS_VALUES.indexOf(fm.staleness) === -1
438
+ ) {
439
+ addViolation(
440
+ violations,
441
+ CATEGORIES.STALENESS,
442
+ SEVERITY.WARNING,
443
+ 'staleness value "' +
444
+ String(fm.staleness) +
445
+ '" not in enum [fresh, stale, unavailable]',
446
+ 'staleness'
447
+ );
448
+ }
449
+
450
+ // --- stale_reason enum + cross-field rule ---
451
+ //
452
+ // If staleness=stale, stale_reason MUST be set to one of the non-null
453
+ // values (otherwise we cannot explain why the derivation is stale).
454
+ // If stale_reason is present, it must match the frozen enum.
455
+ if ('stale_reason' in fm) {
456
+ // Accept both null (parsed from "null" scalar) and undefined.
457
+ const sr = fm.stale_reason;
458
+ if (sr !== null && STALE_REASON_VALUES.indexOf(sr) === -1) {
459
+ addViolation(
460
+ violations,
461
+ CATEGORIES.STALENESS,
462
+ SEVERITY.WARNING,
463
+ 'stale_reason value "' +
464
+ String(sr) +
465
+ '" not in enum [null, governing_thought_changed, brain_offline, derivation_timeout, brain_graph_version_mismatch]',
466
+ 'stale_reason'
467
+ );
468
+ }
469
+ }
470
+
471
+ if (fm.staleness === STALENESS.STALE) {
472
+ const sr = 'stale_reason' in fm ? fm.stale_reason : undefined;
473
+ if (sr === null || sr === undefined || sr === '') {
474
+ addViolation(
475
+ violations,
476
+ CATEGORIES.STALENESS,
477
+ SEVERITY.WARNING,
478
+ 'staleness=stale requires a non-null stale_reason (why is the derivation stale?)',
479
+ 'stale_reason'
480
+ );
481
+ }
482
+ }
483
+
484
+ // --- Section headings scan (body) ---
485
+ //
486
+ // Walk the body for any "## " lines. Headings not in
487
+ // OPTIONAL_SECTION_HEADINGS are downgraded to schema/info (users may
488
+ // extend the schema locally; we note but do not fail).
489
+ const headingRe = /^##\s+.+$/gm;
490
+ const matches = body.match(headingRe) || [];
491
+ const knownSet = new Set(OPTIONAL_SECTION_HEADINGS);
492
+ for (const h of matches) {
493
+ if (!knownSet.has(h)) {
494
+ addViolation(
495
+ violations,
496
+ CATEGORIES.SCHEMA,
497
+ SEVERITY.INFO,
498
+ 'Unknown section heading "' +
499
+ h +
500
+ '" (not in OPTIONAL_SECTION_HEADINGS; user-extended sections are permitted but noted)',
501
+ 'body'
502
+ );
503
+ }
504
+ }
505
+
506
+ // --- Canon Part 8 leak scan ---
507
+ scanCanonLeaks(fm, violations);
508
+
509
+ // --- Aggregate ---
510
+ const severity = aggregateSeverity(violations);
511
+ const valid = violations.length === 0;
512
+ return {
513
+ valid: valid,
514
+ violations: violations,
515
+ severity: severity,
516
+ };
517
+ }
518
+
519
+ module.exports = {
520
+ validateSchema: validateSchema,
521
+ SCHEMA_VERSION: SCHEMA_VERSION,
522
+ SEVERITY: SEVERITY,
523
+ CATEGORIES: CATEGORIES,
524
+ STALENESS: STALENESS,
525
+ STALE_REASON: STALE_REASON,
526
+ REQUIRED_FRONTMATTER_FIELDS: REQUIRED_FRONTMATTER_FIELDS,
527
+ OPTIONAL_SECTION_HEADINGS: OPTIONAL_SECTION_HEADINGS,
528
+ };