@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,548 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /*
5
+ * Copyright (c) 2026 Mindrian. BSL 1.1.
6
+ *
7
+ * Phase 90-04 -- readQuadruple fixture tests (17 cases)
8
+ * =====================================================
9
+ * Extends Phase 88-01 readTriple to readQuadruple additively. Five
10
+ * parser-isolation tests (Task 1) + twelve integration tests (Task 2).
11
+ *
12
+ * Test map (17 cases, one-to-one with the PLAN <behavior> blocks):
13
+ *
14
+ * Task 1 (parser-level, folder-memory-shared.cjs):
15
+ * 1. parseBrainMd on valid fixture -> full struct, parse_failed:false, 9 sections mapped
16
+ * 2. parseBrainMd on absent path -> null (literal)
17
+ * 3. parseBrainMd on malformed frontmatter -> emptyBrain with parse_failed:true
18
+ * 4. parseBrainMd with 3/9 sections populated -> sections[present]:{body,tokens_estimate}, sections[absent]:null
19
+ * 5. parseBrainMd with unknown heading '## Secret Analysis' -> ignored (future-compat)
20
+ * (Bonus): OPTIONAL_SECTION_HEADINGS byte-identical parity with brain-md-schema
21
+ *
22
+ * Task 2 (integration, folder-memory.cjs + folder-memory-async.cjs):
23
+ * 6. readQuadruple sync on section with triple + valid BRAIN.md -> {room,state,reasoning,brain:{exists:true,...}}
24
+ * 7. readQuadruple sync on section with triple + BRAIN.md absent -> {..., brain:null}
25
+ * 8. readQuadruple sync on section with triple + malformed BRAIN.md -> {..., brain:{exists:true, parse_failed:true, ...}}
26
+ * 9. readQuadruple sync on nonexistent sectionPath -> does NOT throw; returns all-empty shells + brain:null
27
+ * 10. readQuadruple async AsyncFunction constructor.name === 'AsyncFunction'
28
+ * 11. sync + async return identical shapes on same fixture (deep equality)
29
+ * 12. key-set parity: Object.keys(sync).filter(fn).sort() === Object.keys(async).filter(fn).sort()
30
+ * 13. isQuadrupleFresh: reasoning.is_stale:false + brain:null -> true
31
+ * 14. isQuadrupleFresh: reasoning.is_stale:false + brain.staleness:'fresh' -> true
32
+ * 15. isQuadrupleFresh: reasoning.is_stale:true -> false (regardless of brain)
33
+ * 16. isQuadrupleFresh: reasoning.is_stale:false + brain.stale_reason:'brain_offline' -> true
34
+ * 17. isQuadrupleFresh: reasoning.is_stale:false + brain.staleness:'stale' + stale_reason:'governing_thought_changed' -> false
35
+ *
36
+ * Registered in lib/memory/run-feynman-tests.cjs.
37
+ */
38
+
39
+ const assert = require('node:assert/strict');
40
+ const fs = require('node:fs');
41
+ const os = require('node:os');
42
+ const path = require('node:path');
43
+
44
+ const REPO = path.resolve(__dirname, '..', '..');
45
+ const SHARED_PATH = path.join(REPO, 'lib/core/folder-memory-shared.cjs');
46
+ const SYNC_PATH = path.join(REPO, 'lib/core/folder-memory.cjs');
47
+ const ASYNC_PATH = path.join(REPO, 'lib/core/folder-memory-async.cjs');
48
+ const SCHEMA_PATH = path.join(REPO, 'lib/core/brain-md-schema.cjs');
49
+
50
+ // ---------- Tmp workspace helpers ----------
51
+
52
+ const TMP_ROOTS = [];
53
+ function mkTmp(prefix) {
54
+ const d = fs.mkdtempSync(path.join(os.tmpdir(), prefix));
55
+ TMP_ROOTS.push(d);
56
+ return d;
57
+ }
58
+ process.on('exit', () => {
59
+ for (const d of TMP_ROOTS) {
60
+ try {
61
+ fs.rmSync(d, { recursive: true, force: true });
62
+ } catch (_e) { /* best effort */ }
63
+ }
64
+ });
65
+
66
+ function isoFromMs(ms) {
67
+ return new Date(ms).toISOString().replace(/\.\d+Z$/, 'Z');
68
+ }
69
+
70
+ // ---------- Fixture writers ----------
71
+
72
+ function writeRoomMd(dir, identity, refs) {
73
+ const payload =
74
+ identity +
75
+ '\n\n<!-- BEGIN REFERENCES -->\n' +
76
+ (refs || '') +
77
+ '\n<!-- END REFERENCES -->\n';
78
+ fs.writeFileSync(path.join(dir, 'ROOM.md'), payload, 'utf8');
79
+ }
80
+
81
+ function writeStateMd(dir, opts) {
82
+ const o = opts || {};
83
+ const lines = [
84
+ '# Section State',
85
+ '',
86
+ 'artifact_count: ' + (o.artifact_count != null ? o.artifact_count : 2),
87
+ 'gap_status: ' + (o.gap_status || 'active'),
88
+ 'completeness_score: ' + (o.completeness_score != null ? o.completeness_score : 0.6),
89
+ '',
90
+ 'Last activity: ' + (o.last_activity || '2026-04-19'),
91
+ '',
92
+ ];
93
+ fs.writeFileSync(path.join(dir, 'STATE.md'), lines.join('\n'), 'utf8');
94
+ }
95
+
96
+ function writeMintoMd(dir, fm, body) {
97
+ const lines = ['---'];
98
+ for (const k of Object.keys(fm)) {
99
+ const v = fm[k];
100
+ if (Array.isArray(v)) {
101
+ if (v.length === 0) {
102
+ lines.push(k + ': []');
103
+ } else {
104
+ lines.push(k + ':');
105
+ for (const s of v) lines.push(' - ' + JSON.stringify(s));
106
+ }
107
+ } else if (v === null) {
108
+ lines.push(k + ': null');
109
+ } else if (typeof v === 'string') {
110
+ lines.push(k + ': "' + v.replace(/"/g, '\\"') + '"');
111
+ } else {
112
+ lines.push(k + ': ' + v);
113
+ }
114
+ }
115
+ lines.push('---');
116
+ lines.push('');
117
+ lines.push(body || '# MINTO body');
118
+ fs.writeFileSync(path.join(dir, 'MINTO.md'), lines.join('\n'), 'utf8');
119
+ }
120
+
121
+ // Build a BRAIN.md fixture with given frontmatter + section bodies map.
122
+ // sections is { '## Pattern Matches': 'body text', ... } -- only present
123
+ // headings become sections; absent headings stay absent on parse.
124
+ function writeBrainMd(dir, fm, sections) {
125
+ fs.mkdirSync(dir, { recursive: true });
126
+ const lines = ['---'];
127
+ for (const k of Object.keys(fm)) {
128
+ const v = fm[k];
129
+ if (v === null) {
130
+ lines.push(k + ': null');
131
+ } else if (typeof v === 'string') {
132
+ lines.push(k + ': "' + v.replace(/"/g, '\\"') + '"');
133
+ } else {
134
+ lines.push(k + ': ' + v);
135
+ }
136
+ }
137
+ lines.push('---');
138
+ lines.push('');
139
+ lines.push('# Brain Derivation -- ' + (fm.section || 'unknown'));
140
+ lines.push('');
141
+ if (sections && typeof sections === 'object') {
142
+ for (const h of Object.keys(sections)) {
143
+ lines.push(h);
144
+ lines.push('');
145
+ lines.push(sections[h]);
146
+ lines.push('');
147
+ }
148
+ }
149
+ fs.writeFileSync(path.join(dir, 'BRAIN.md'), lines.join('\n'), 'utf8');
150
+ }
151
+
152
+ function defaultBrainFm(section) {
153
+ return {
154
+ section: section || 'market-analysis',
155
+ brain_generated_at: isoFromMs(Date.now()),
156
+ brain_graph_version: 1,
157
+ governing_thought_hash: 'sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855',
158
+ staleness: 'fresh',
159
+ stale_reason: null,
160
+ author: 'brain',
161
+ confidence_baseline: 0.7,
162
+ };
163
+ }
164
+
165
+ // Seed a full section directory with ROOM/STATE/MINTO + optional BRAIN.
166
+ function seedSection(dir, opts) {
167
+ const o = opts || {};
168
+ writeRoomMd(dir, o.identity || '# test-section\n\nIdentity prose.', o.refs || '');
169
+ writeStateMd(dir, o.state || {});
170
+ writeMintoMd(
171
+ dir,
172
+ {
173
+ schema_version: 'v88',
174
+ governing_thought: o.governing_thought || 'Test governing thought.',
175
+ last_generated_at: isoFromMs(Date.now()),
176
+ decision_log: [],
177
+ },
178
+ o.body || 'body content'
179
+ );
180
+ }
181
+
182
+ // ---------- Task 1: Parser-level tests ----------
183
+
184
+ function test_1_parseBrainMd_valid(shared) {
185
+ const dir = mkTmp('quad-t1-');
186
+ const fm = defaultBrainFm('market-analysis');
187
+ const sections = {
188
+ '## Pattern Matches': 'Framework match: SWOT + Porter Five.',
189
+ '## Cross-Domain Analogies': 'Analogous to 1995 ISP market.',
190
+ '## Wicked Indicators': 'High uncertainty + stakeholder divergence.',
191
+ '## Unfilled Opportunity Matches': 'Gap in mid-market enterprise.',
192
+ '## Framework Chain Predictions': 'SWOT -> Porter -> JTBD.',
193
+ '## Assessment Thinking Chain Position': 'RigorLevel 3.',
194
+ '## ProblemType Classification': 'UDP-Complex, confidence 0.8.',
195
+ '## Flagged Contradictions (cross-room)': '(no signal)',
196
+ '## HSI Signals': 'Disruption index high.',
197
+ };
198
+ writeBrainMd(dir, fm, sections);
199
+
200
+ const brain = shared.parseBrainMd(path.join(dir, 'BRAIN.md'));
201
+ assert.notStrictEqual(brain, null, 't1: brain non-null');
202
+ assert.strictEqual(brain.exists, true, 't1: exists true');
203
+ assert.strictEqual(brain.parse_failed, false, 't1: parse_failed false');
204
+ assert.strictEqual(brain.section, 'market-analysis', 't1: section scalar');
205
+ assert.strictEqual(brain.brain_graph_version, 1, 't1: brain_graph_version cast');
206
+ assert.strictEqual(brain.staleness, 'fresh', 't1: staleness scalar');
207
+ assert.strictEqual(brain.stale_reason, null, 't1: stale_reason null');
208
+ assert.strictEqual(brain.author, 'brain', 't1: author');
209
+ assert.strictEqual(brain.confidence_baseline, 0.7, 't1: confidence_baseline float');
210
+ assert.ok(brain.sections && typeof brain.sections === 'object', 't1: sections present');
211
+ const expectedKeys = [
212
+ 'pattern_matches',
213
+ 'cross_domain_analogies',
214
+ 'wicked_indicators',
215
+ 'unfilled_opportunity_matches',
216
+ 'framework_chain_predictions',
217
+ 'assessment_thinking_chain_position',
218
+ 'problemtype_classification',
219
+ 'flagged_contradictions_xroom',
220
+ 'hsi_signals',
221
+ ];
222
+ for (const k of expectedKeys) {
223
+ assert.ok(k in brain.sections, 't1: key ' + k + ' present');
224
+ assert.ok(brain.sections[k] !== null, 't1: section ' + k + ' populated');
225
+ assert.ok(typeof brain.sections[k].body === 'string', 't1: ' + k + ' body string');
226
+ assert.ok(brain.sections[k].body.length > 0, 't1: ' + k + ' body non-empty');
227
+ assert.ok(typeof brain.sections[k].tokens_estimate === 'number', 't1: ' + k + ' tokens_estimate number');
228
+ assert.ok(brain.sections[k].tokens_estimate > 0, 't1: ' + k + ' tokens_estimate positive');
229
+ }
230
+ assert.ok(Array.isArray(brain.flagged_weaknesses), 't1: flagged_weaknesses array');
231
+ }
232
+
233
+ function test_2_parseBrainMd_absent(shared) {
234
+ const dir = mkTmp('quad-t2-');
235
+ const result = shared.parseBrainMd(path.join(dir, 'BRAIN.md'));
236
+ assert.strictEqual(result, null, 't2: absent -> null literal');
237
+ }
238
+
239
+ function test_3_parseBrainMd_malformed(shared) {
240
+ const dir = mkTmp('quad-t3-');
241
+ fs.mkdirSync(dir, { recursive: true });
242
+ // No frontmatter delimiters at all.
243
+ fs.writeFileSync(
244
+ path.join(dir, 'BRAIN.md'),
245
+ 'This is not a BRAIN.md. No frontmatter. No sections.\n',
246
+ 'utf8'
247
+ );
248
+ const brain = shared.parseBrainMd(path.join(dir, 'BRAIN.md'));
249
+ assert.notStrictEqual(brain, null, 't3: malformed still returns emptyBrain struct');
250
+ assert.strictEqual(brain.exists, true, 't3: exists:true for present-but-malformed');
251
+ assert.strictEqual(brain.parse_failed, true, 't3: parse_failed:true');
252
+ assert.strictEqual(brain.staleness, 'stale', 't3: staleness:stale on parse fail');
253
+ assert.ok(brain.sections && typeof brain.sections === 'object', 't3: sections shell');
254
+ for (const k of Object.keys(brain.sections)) {
255
+ assert.strictEqual(brain.sections[k], null, 't3: ' + k + ' null on parse fail');
256
+ }
257
+ }
258
+
259
+ function test_4_parseBrainMd_partialSections(shared) {
260
+ const dir = mkTmp('quad-t4-');
261
+ const fm = defaultBrainFm('problem-definition');
262
+ const sections = {
263
+ '## Pattern Matches': 'Only three present.',
264
+ '## Wicked Indicators': 'Second of three.',
265
+ '## HSI Signals': 'Third of three.',
266
+ };
267
+ writeBrainMd(dir, fm, sections);
268
+ const brain = shared.parseBrainMd(path.join(dir, 'BRAIN.md'));
269
+ assert.strictEqual(brain.parse_failed, false, 't4: parse ok');
270
+ assert.ok(brain.sections.pattern_matches != null, 't4: pattern_matches present');
271
+ assert.ok(brain.sections.wicked_indicators != null, 't4: wicked_indicators present');
272
+ assert.ok(brain.sections.hsi_signals != null, 't4: hsi_signals present');
273
+ // Six absent sections stay null.
274
+ const absentKeys = [
275
+ 'cross_domain_analogies',
276
+ 'unfilled_opportunity_matches',
277
+ 'framework_chain_predictions',
278
+ 'assessment_thinking_chain_position',
279
+ 'problemtype_classification',
280
+ 'flagged_contradictions_xroom',
281
+ ];
282
+ for (const k of absentKeys) {
283
+ assert.strictEqual(brain.sections[k], null, 't4: absent ' + k + ' is null');
284
+ }
285
+ }
286
+
287
+ function test_5_parseBrainMd_unknownHeading(shared) {
288
+ const dir = mkTmp('quad-t5-');
289
+ const fm = defaultBrainFm('solution-design');
290
+ const sections = {
291
+ '## Pattern Matches': 'Known heading.',
292
+ '## Secret Analysis': 'Unknown heading; must be ignored.',
293
+ };
294
+ writeBrainMd(dir, fm, sections);
295
+ const brain = shared.parseBrainMd(path.join(dir, 'BRAIN.md'));
296
+ assert.strictEqual(brain.parse_failed, false, 't5: still parses fine');
297
+ assert.ok(brain.sections.pattern_matches != null, 't5: known heading captured');
298
+ // The unknown heading must not appear as a key anywhere.
299
+ for (const k of Object.keys(brain.sections)) {
300
+ assert.ok(
301
+ k.indexOf('secret') === -1,
302
+ 't5: no secret_* key leaked into sections'
303
+ );
304
+ }
305
+ }
306
+
307
+ function test_bonus_optionalHeadingsParity(shared) {
308
+ // Parity with brain-md-schema OPTIONAL_SECTION_HEADINGS array.
309
+ const schema = require(SCHEMA_PATH);
310
+ assert.ok(Array.isArray(schema.OPTIONAL_SECTION_HEADINGS), 'bonus: schema array present');
311
+ assert.ok(Array.isArray(shared.OPTIONAL_SECTION_HEADINGS), 'bonus: shared array present');
312
+ assert.strictEqual(
313
+ shared.OPTIONAL_SECTION_HEADINGS.length,
314
+ schema.OPTIONAL_SECTION_HEADINGS.length,
315
+ 'bonus: same length'
316
+ );
317
+ for (let i = 0; i < schema.OPTIONAL_SECTION_HEADINGS.length; i++) {
318
+ assert.strictEqual(
319
+ shared.OPTIONAL_SECTION_HEADINGS[i],
320
+ schema.OPTIONAL_SECTION_HEADINGS[i],
321
+ 'bonus: entry ' + i + ' byte-identical'
322
+ );
323
+ }
324
+ }
325
+
326
+ // ---------- Task 2: Integration tests ----------
327
+
328
+ function test_6_readQuadruple_valid(sync) {
329
+ const dir = mkTmp('quad-t6-');
330
+ seedSection(dir, {});
331
+ writeBrainMd(dir, defaultBrainFm(path.basename(dir)), {
332
+ '## Pattern Matches': 'Framework match body.',
333
+ '## HSI Signals': 'HSI signal body.',
334
+ });
335
+ const q = sync.readQuadruple(dir);
336
+ assert.ok(q, 't6: returns object');
337
+ assert.ok(q.room && q.room.exists === true, 't6: room.exists');
338
+ assert.ok(q.state && q.state.exists === true, 't6: state.exists');
339
+ assert.ok(q.reasoning && q.reasoning.exists === true, 't6: reasoning.exists');
340
+ assert.ok(q.brain != null, 't6: brain non-null');
341
+ assert.strictEqual(q.brain.exists, true, 't6: brain.exists');
342
+ assert.strictEqual(q.brain.parse_failed, false, 't6: brain parsed ok');
343
+ assert.strictEqual(q.brain.author, 'brain', 't6: brain.author');
344
+ }
345
+
346
+ function test_7_readQuadruple_brainAbsent(sync) {
347
+ const dir = mkTmp('quad-t7-');
348
+ seedSection(dir, {});
349
+ // No BRAIN.md.
350
+ const q = sync.readQuadruple(dir);
351
+ assert.ok(q.room.exists === true, 't7: room still present');
352
+ assert.strictEqual(q.brain, null, 't7: brain null when absent');
353
+ }
354
+
355
+ function test_8_readQuadruple_malformedBrain(sync) {
356
+ const dir = mkTmp('quad-t8-');
357
+ seedSection(dir, {});
358
+ fs.writeFileSync(path.join(dir, 'BRAIN.md'), 'garbage no frontmatter\n', 'utf8');
359
+ const q = sync.readQuadruple(dir);
360
+ assert.ok(q.brain != null, 't8: brain non-null (file exists)');
361
+ assert.strictEqual(q.brain.exists, true, 't8: exists:true when file present');
362
+ assert.strictEqual(q.brain.parse_failed, true, 't8: parse_failed:true');
363
+ assert.strictEqual(q.brain.staleness, 'stale', 't8: staleness:stale on malformed');
364
+ }
365
+
366
+ function test_9_readQuadruple_nonexistentPath(sync) {
367
+ const dir = path.join(os.tmpdir(), 'quad-t9-nonexistent-' + Date.now() + '-' + Math.random());
368
+ let q;
369
+ assert.doesNotThrow(() => {
370
+ q = sync.readQuadruple(dir);
371
+ }, 't9: no throws on nonexistent path');
372
+ assert.strictEqual(q.room.exists, false, 't9: room shell');
373
+ assert.strictEqual(q.state.exists, false, 't9: state shell');
374
+ assert.strictEqual(q.reasoning.exists, false, 't9: reasoning shell');
375
+ assert.strictEqual(q.brain, null, 't9: brain null on absent path');
376
+ }
377
+
378
+ function test_10_asyncReadQuadruple_isAsyncFunction(asyncMod) {
379
+ assert.strictEqual(
380
+ typeof asyncMod.readQuadruple,
381
+ 'function',
382
+ 't10: readQuadruple defined on async module'
383
+ );
384
+ assert.strictEqual(
385
+ asyncMod.readQuadruple.constructor.name,
386
+ 'AsyncFunction',
387
+ 't10: async readQuadruple is AsyncFunction (got ' + asyncMod.readQuadruple.constructor.name + ')'
388
+ );
389
+ assert.strictEqual(
390
+ asyncMod.isQuadrupleFresh.constructor.name,
391
+ 'AsyncFunction',
392
+ 't10: async isQuadrupleFresh is AsyncFunction'
393
+ );
394
+ }
395
+
396
+ async function test_11_syncAsyncDeepEquality(sync, asyncMod) {
397
+ const dir = mkTmp('quad-t11-');
398
+ seedSection(dir, { governing_thought: 'Parity GT' });
399
+ writeBrainMd(dir, defaultBrainFm(path.basename(dir)), {
400
+ '## Pattern Matches': 'same body both paths',
401
+ });
402
+
403
+ const syncResult = sync.readQuadruple(dir);
404
+ const asyncResult = await asyncMod.readQuadruple(dir);
405
+
406
+ assert.deepStrictEqual(
407
+ Object.keys(syncResult).sort(),
408
+ Object.keys(asyncResult).sort(),
409
+ 't11: top-level keys match'
410
+ );
411
+ assert.deepStrictEqual(
412
+ syncResult.brain,
413
+ asyncResult.brain,
414
+ 't11: brain field deep equal'
415
+ );
416
+ assert.strictEqual(
417
+ syncResult.reasoning.governing_thought,
418
+ asyncResult.reasoning.governing_thought,
419
+ 't11: reasoning gt match'
420
+ );
421
+ }
422
+
423
+ function test_12_keySetParity(sync, asyncMod) {
424
+ const syncKeys = Object.keys(sync).filter((k) => typeof sync[k] === 'function').sort();
425
+ const asyncKeys = Object.keys(asyncMod).filter((k) => typeof asyncMod[k] === 'function').sort();
426
+ assert.deepStrictEqual(syncKeys, asyncKeys, 't12: key-set parity');
427
+ // Sanity: both include readQuadruple and isQuadrupleFresh.
428
+ assert.ok(syncKeys.indexOf('readQuadruple') !== -1, 't12: sync.readQuadruple present');
429
+ assert.ok(syncKeys.indexOf('isQuadrupleFresh') !== -1, 't12: sync.isQuadrupleFresh present');
430
+ assert.ok(asyncKeys.indexOf('readQuadruple') !== -1, 't12: async.readQuadruple present');
431
+ assert.ok(asyncKeys.indexOf('isQuadrupleFresh') !== -1, 't12: async.isQuadrupleFresh present');
432
+ // Phase 88-01 back-compat: readTriple still exported on both.
433
+ assert.ok(syncKeys.indexOf('readTriple') !== -1, 't12: sync.readTriple back-compat');
434
+ assert.ok(asyncKeys.indexOf('readTriple') !== -1, 't12: async.readTriple back-compat');
435
+ // Every async export is AsyncFunction.
436
+ for (const k of asyncKeys) {
437
+ assert.strictEqual(
438
+ asyncMod[k].constructor.name,
439
+ 'AsyncFunction',
440
+ 't12: async.' + k + ' must be AsyncFunction'
441
+ );
442
+ }
443
+ }
444
+
445
+ function test_13_isQuadrupleFresh_brainNull(sync) {
446
+ const q = {
447
+ room: { exists: true },
448
+ state: { exists: true },
449
+ reasoning: { exists: true, is_stale: false, stale_reason: null },
450
+ brain: null,
451
+ };
452
+ assert.strictEqual(sync.isQuadrupleFresh(q), true, 't13: fresh triple + brain null -> true');
453
+ }
454
+
455
+ function test_14_isQuadrupleFresh_brainFresh(sync) {
456
+ const q = {
457
+ room: { exists: true },
458
+ state: { exists: true },
459
+ reasoning: { exists: true, is_stale: false },
460
+ brain: { exists: true, staleness: 'fresh', stale_reason: null },
461
+ };
462
+ assert.strictEqual(sync.isQuadrupleFresh(q), true, 't14: fresh triple + fresh brain -> true');
463
+ }
464
+
465
+ function test_15_isQuadrupleFresh_tripleStale(sync) {
466
+ const q = {
467
+ room: { exists: true },
468
+ state: { exists: true },
469
+ reasoning: { exists: true, is_stale: true, stale_reason: 'artifacts_newer_than_minto' },
470
+ brain: { exists: true, staleness: 'fresh' },
471
+ };
472
+ assert.strictEqual(sync.isQuadrupleFresh(q), false, 't15: stale triple -> false');
473
+ // And even with brain null.
474
+ const q2 = Object.assign({}, q, { brain: null });
475
+ assert.strictEqual(sync.isQuadrupleFresh(q2), false, 't15b: stale triple + brain null -> false');
476
+ }
477
+
478
+ function test_16_isQuadrupleFresh_brainOffline(sync) {
479
+ const q = {
480
+ room: { exists: true },
481
+ state: { exists: true },
482
+ reasoning: { exists: true, is_stale: false },
483
+ brain: { exists: true, staleness: 'stale', stale_reason: 'brain_offline' },
484
+ };
485
+ assert.strictEqual(
486
+ sync.isQuadrupleFresh(q),
487
+ true,
488
+ 't16: brain-offline not counted as derivation-stale'
489
+ );
490
+ }
491
+
492
+ function test_17_isQuadrupleFresh_brainStale(sync) {
493
+ const q = {
494
+ room: { exists: true },
495
+ state: { exists: true },
496
+ reasoning: { exists: true, is_stale: false },
497
+ brain: { exists: true, staleness: 'stale', stale_reason: 'governing_thought_changed' },
498
+ };
499
+ assert.strictEqual(
500
+ sync.isQuadrupleFresh(q),
501
+ false,
502
+ 't17: derivation-stale -> false'
503
+ );
504
+ }
505
+
506
+ // ---------- Runner ----------
507
+
508
+ async function run() {
509
+ // Module-file existence checks.
510
+ assert.ok(fs.existsSync(SHARED_PATH), 'precondition: shared module exists');
511
+ assert.ok(fs.existsSync(SYNC_PATH), 'precondition: sync module exists');
512
+ assert.ok(fs.existsSync(ASYNC_PATH), 'precondition: async module exists');
513
+
514
+ const shared = require(SHARED_PATH);
515
+ const sync = require(SYNC_PATH);
516
+ const asyncMod = require(ASYNC_PATH);
517
+
518
+ // Task 1 -- parser-level.
519
+ test_1_parseBrainMd_valid(shared);
520
+ test_2_parseBrainMd_absent(shared);
521
+ test_3_parseBrainMd_malformed(shared);
522
+ test_4_parseBrainMd_partialSections(shared);
523
+ test_5_parseBrainMd_unknownHeading(shared);
524
+ test_bonus_optionalHeadingsParity(shared);
525
+
526
+ // Task 2 -- integration.
527
+ test_6_readQuadruple_valid(sync);
528
+ test_7_readQuadruple_brainAbsent(sync);
529
+ test_8_readQuadruple_malformedBrain(sync);
530
+ test_9_readQuadruple_nonexistentPath(sync);
531
+ test_10_asyncReadQuadruple_isAsyncFunction(asyncMod);
532
+ await test_11_syncAsyncDeepEquality(sync, asyncMod);
533
+ test_12_keySetParity(sync, asyncMod);
534
+ test_13_isQuadrupleFresh_brainNull(sync);
535
+ test_14_isQuadrupleFresh_brainFresh(sync);
536
+ test_15_isQuadrupleFresh_tripleStale(sync);
537
+ test_16_isQuadrupleFresh_brainOffline(sync);
538
+ test_17_isQuadrupleFresh_brainStale(sync);
539
+
540
+ process.stdout.write('folder-memory-quadruple: 17/17 tests passed (5 parser + 12 integration + 1 parity bonus)\n');
541
+ process.exit(0);
542
+ }
543
+
544
+ run().catch((e) => {
545
+ process.stderr.write((e && e.stack) || String(e));
546
+ process.stderr.write('\n');
547
+ process.exit(1);
548
+ });