@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,404 @@
1
+ #!/usr/bin/env node
2
+ /*
3
+ * Copyright (c) 2026 Mindrian. BSL 1.1.
4
+ *
5
+ * Phase 88-06 -- on-stop close-out snapshot tests
6
+ * ================================================
7
+ * Wires the session-close triple snapshot. On every Stop hook fire, the
8
+ * extended on-stop script must:
9
+ *
10
+ * 1. Preserve the Phase 84 STATE.md write contract byte-for-byte.
11
+ * 2. Drain the minto-debouncer queue with a bounded wall-clock budget
12
+ * (plan default 1500ms so the 3000ms hook timeout absorbs slack).
13
+ * 3. Recompile ROOM.md references for every active section.
14
+ * 4. Walk sections via folder-memory.readTriple() and assemble
15
+ * .mindrian/session-snapshot.json for session-start (88-07) to read.
16
+ * 5. Write .mindrian/minto-stale.json for any section whose reasoning
17
+ * is stale after the drain.
18
+ * 6. Atomic writes (tmp + rename) so a mid-write crash leaves the
19
+ * previous snapshot intact.
20
+ * 7. Exit 0 on every error path (soft-fail contract).
21
+ *
22
+ * Test map (8 tests, one per PLAN <behavior> case):
23
+ *
24
+ * Test 1: 3-section room -> session-snapshot.json has 3 section entries.
25
+ * Test 2: Each snapshot entry has the readTriple() shape (room, state,
26
+ * reasoning keys present).
27
+ * Test 3: Queue drain: a fixture queue with pending entries that were
28
+ * enqueued long ago (synthesized) drains out; remainder (if any)
29
+ * surfaces in minto-stale.json.
30
+ * Test 4: Stale reasoning: a section with a sentinel 1970-01-01
31
+ * last_generated_at appears in minto-stale.json with a reason.
32
+ * Test 5: Rapid exit: on-stop for a single-section room with no pending
33
+ * queue finishes under the 3000ms hook budget.
34
+ * Test 6: STATE.md contract preserved -- on-stop still writes STATE.md
35
+ * for the active room.
36
+ * Test 7: Atomic writes -- session-snapshot.json and minto-stale.json
37
+ * do not leave a .tmp. suffix in .mindrian/ after success.
38
+ * Test 8: Soft-fail contract -- on-stop exits 0 even when the cascade
39
+ * dependencies are degraded.
40
+ *
41
+ * Test harness: spawnSync bash on scripts/on-stop with a minimal working
42
+ * directory that is itself the active room. Each test owns its tmpdir and
43
+ * passes it via PWD so resolve-room picks it up (the resolve-room script
44
+ * walks up from PWD looking for the .room-root sentinel).
45
+ *
46
+ * BSL 1.1. Zero npm deps. Node built-ins only. Three-surface by construction.
47
+ */
48
+
49
+ 'use strict';
50
+
51
+ const assert = require('node:assert/strict');
52
+ const fs = require('node:fs');
53
+ const os = require('node:os');
54
+ const path = require('node:path');
55
+ const { spawnSync } = require('node:child_process');
56
+
57
+ const REPO_ROOT = path.resolve(__dirname, '..', '..');
58
+ const ON_STOP = path.join(REPO_ROOT, 'scripts', 'on-stop');
59
+ const DEBOUNCER = path.join(REPO_ROOT, 'scripts', 'minto-debouncer.cjs');
60
+
61
+ const TMPDIRS = [];
62
+ function mkTmp(prefix) {
63
+ const d = fs.mkdtempSync(path.join(os.tmpdir(), prefix));
64
+ TMPDIRS.push(d);
65
+ return d;
66
+ }
67
+
68
+ process.on('exit', () => {
69
+ for (const d of TMPDIRS) {
70
+ try { fs.rmSync(d, { recursive: true, force: true }); } catch (_) {}
71
+ }
72
+ });
73
+
74
+ /**
75
+ * Seed a room fixture that resolve-room can find via Strategy 0b
76
+ * (MINDRIAN_ROOMS_HOME directory scan). Layout:
77
+ * <tmp>/rooms-home/ <- set as MINDRIAN_ROOMS_HOME
78
+ * <tmp>/rooms-home/<basename>/ <- the room dir (basename matches WS_BASENAME)
79
+ * <tmp>/rooms-home/<basename>/.room-root
80
+ * <tmp>/rooms-home/<basename>/.mindrian/
81
+ * <tmp>/rooms-home/<basename>/<section>/ROOM.md + artifact-01.md
82
+ *
83
+ * Returns { roomDir, roomsHome, workDir } where workDir's basename
84
+ * matches the room's basename so resolve-room finds it. The test
85
+ * invokes on-stop from workDir (PWD) with MINDRIAN_ROOMS_HOME pointing
86
+ * at roomsHome.
87
+ */
88
+ function seedRoom(tmp, sections) {
89
+ const roomsHome = path.join(tmp, 'rooms-home');
90
+ const roomBase = 'venture';
91
+ const roomDir = path.join(roomsHome, roomBase);
92
+ fs.mkdirSync(roomDir, { recursive: true });
93
+ fs.writeFileSync(path.join(roomDir, '.room-root'), '');
94
+ fs.mkdirSync(path.join(roomDir, '.mindrian'), { recursive: true });
95
+
96
+ // workDir mirrors roomBase so resolve-room Strategy 0b picks it up
97
+ // (basename(WORK_DIR) === ROOM_BASENAME under ROOMS_HOME).
98
+ const workDir = path.join(tmp, 'work', roomBase);
99
+ fs.mkdirSync(workDir, { recursive: true });
100
+
101
+ for (const s of sections) {
102
+ const dir = path.join(roomDir, s);
103
+ fs.mkdirSync(dir, { recursive: true });
104
+ fs.writeFileSync(
105
+ path.join(dir, 'ROOM.md'),
106
+ '# ' + s + '\n\nIdentity text for ' + s + '.\n'
107
+ );
108
+ // one placeholder artifact so the cross-refs compiler has something
109
+ fs.writeFileSync(
110
+ path.join(dir, 'artifact-01.md'),
111
+ '# ' + s + ' artifact 01\n\nBody.\n'
112
+ );
113
+ }
114
+ return { roomDir, roomsHome, workDir };
115
+ }
116
+
117
+ /**
118
+ * Seed a MINTO.md for a section so readTriple returns reasoning.exists=true.
119
+ * The frontmatter is the narrow v88 dialect that folder-memory-shared parses.
120
+ * When stale=true, last_generated_at is the 1970 sentinel so staleness trips.
121
+ */
122
+ function writeMinto(sectionDir, opts) {
123
+ const last = opts && opts.stale
124
+ ? '1970-01-01T00:00:00Z'
125
+ : new Date().toISOString();
126
+ const gt = (opts && opts.governing_thought) || 'Governing thought placeholder.';
127
+ const frontmatter = [
128
+ '---',
129
+ 'schema_version: 88',
130
+ 'governing_thought: "' + gt + '"',
131
+ 'last_generated_at: "' + last + '"',
132
+ 'last_artifact_write_seen_at: "' + last + '"',
133
+ 'reasoning_health_score: 0.75',
134
+ 'flagged_weaknesses: []',
135
+ 'decision_log: []',
136
+ '---',
137
+ '',
138
+ '# Governing Thought',
139
+ '',
140
+ gt,
141
+ '',
142
+ '# Claim 1',
143
+ '',
144
+ 'Supporting claim.',
145
+ '',
146
+ ].join('\n');
147
+ fs.writeFileSync(path.join(sectionDir, 'MINTO.md'), frontmatter);
148
+ }
149
+
150
+ /**
151
+ * Invoke scripts/on-stop in the fixture. Returns the spawnSync result.
152
+ *
153
+ * @param {object} fixture shape from seedRoom: { roomDir, roomsHome, workDir }
154
+ * @param {object} [extraEnv]
155
+ */
156
+ function invokeOnStop(fixture, extraEnv) {
157
+ const env = Object.assign({}, process.env, {
158
+ PWD: fixture.workDir,
159
+ MINDRIAN_ROOMS_HOME: fixture.roomsHome,
160
+ CLAUDE_PLUGIN_ROOT: REPO_ROOT,
161
+ }, extraEnv || {});
162
+ return spawnSync('bash', [ON_STOP], {
163
+ cwd: fixture.workDir,
164
+ env,
165
+ stdio: ['ignore', 'pipe', 'pipe'],
166
+ timeout: 10000,
167
+ });
168
+ }
169
+
170
+ // ---------------------------------------------------------------------------
171
+ // Runner
172
+ // ---------------------------------------------------------------------------
173
+
174
+ const tests = [];
175
+ function test(name, fn) { tests.push({ name, fn }); }
176
+
177
+ // ---------------------------------------------------------------------------
178
+ // Test 1: 3-section room -> snapshot has 3 entries
179
+ // ---------------------------------------------------------------------------
180
+ test('3-section room -> session-snapshot.json has 3 section entries', () => {
181
+ const tmp = mkTmp('on-stop-t1-');
182
+ const fx = seedRoom(tmp, ['market-analysis', 'problem-definition', 'solution-design']);
183
+ // Give each section a healthy MINTO so readTriple returns exists:true
184
+ writeMinto(path.join(fx.roomDir, 'market-analysis'), { governing_thought: 'TAM bottom-up.' });
185
+ writeMinto(path.join(fx.roomDir, 'problem-definition'), { governing_thought: 'Problem bounded.' });
186
+ writeMinto(path.join(fx.roomDir, 'solution-design'), { governing_thought: 'Solution viable.' });
187
+
188
+ const res = invokeOnStop(fx);
189
+ assert.equal(res.status, 0, 'on-stop should exit 0: stderr=' + (res.stderr || ''));
190
+
191
+ const snapPath = path.join(fx.roomDir, '.mindrian', 'session-snapshot.json');
192
+ assert.ok(fs.existsSync(snapPath), 'session-snapshot.json should exist at ' + snapPath);
193
+
194
+ const snap = JSON.parse(fs.readFileSync(snapPath, 'utf8'));
195
+ assert.equal(snap.version, 1, 'snapshot.version === 1');
196
+ assert.ok(typeof snap.snapshot_at === 'string', 'snapshot.snapshot_at is string');
197
+ assert.ok(typeof snap.active_room === 'string', 'snapshot.active_room is string');
198
+ assert.ok(snap.sections && typeof snap.sections === 'object', 'snapshot.sections is object');
199
+
200
+ const keys = Object.keys(snap.sections).sort();
201
+ assert.deepEqual(
202
+ keys,
203
+ ['market-analysis', 'problem-definition', 'solution-design'],
204
+ 'snapshot has exactly the 3 seeded sections'
205
+ );
206
+ });
207
+
208
+ // ---------------------------------------------------------------------------
209
+ // Test 2: snapshot sections match readTriple() shape
210
+ // ---------------------------------------------------------------------------
211
+ test('snapshot section shape matches readTriple() (room, state, reasoning)', () => {
212
+ const tmp = mkTmp('on-stop-t2-');
213
+ const fx = seedRoom(tmp, ['market-analysis']);
214
+ writeMinto(path.join(fx.roomDir, 'market-analysis'), { governing_thought: 'Market exists.' });
215
+
216
+ const res = invokeOnStop(fx);
217
+ assert.equal(res.status, 0, 'on-stop exits 0: ' + (res.stderr || ''));
218
+
219
+ const snap = JSON.parse(
220
+ fs.readFileSync(path.join(fx.roomDir, '.mindrian', 'session-snapshot.json'), 'utf8')
221
+ );
222
+ const entry = snap.sections['market-analysis'];
223
+ assert.ok(entry, 'market-analysis entry exists');
224
+
225
+ // The readTriple return shape carries room, state, reasoning top-level keys.
226
+ assert.ok(entry.room && typeof entry.room === 'object', 'entry.room is object');
227
+ assert.ok(entry.state && typeof entry.state === 'object', 'entry.state is object');
228
+ assert.ok(entry.reasoning && typeof entry.reasoning === 'object', 'entry.reasoning is object');
229
+
230
+ // reasoning carries the governing thought we seeded
231
+ assert.ok(
232
+ typeof entry.reasoning.governing_thought === 'string' &&
233
+ entry.reasoning.governing_thought.length > 0,
234
+ 'reasoning.governing_thought surfaces from MINTO.md'
235
+ );
236
+ // reasoning_health_score is a number in [0,1]
237
+ assert.ok(
238
+ typeof entry.reasoning.reasoning_health_score === 'number' &&
239
+ entry.reasoning.reasoning_health_score >= 0 &&
240
+ entry.reasoning.reasoning_health_score <= 1,
241
+ 'reasoning_health_score in [0,1]'
242
+ );
243
+ });
244
+
245
+ // ---------------------------------------------------------------------------
246
+ // Test 3: Queue drain under budget -- on-stop drains pre-queued items
247
+ // ---------------------------------------------------------------------------
248
+ test('pending queue drains during on-stop; remainder surfaces in stale if any', () => {
249
+ const tmp = mkTmp('on-stop-t3-');
250
+ const fx = seedRoom(tmp, ['market-analysis', 'problem-definition']);
251
+ writeMinto(path.join(fx.roomDir, 'market-analysis'), { governing_thought: 'M.' });
252
+ writeMinto(path.join(fx.roomDir, 'problem-definition'), { governing_thought: 'P.' });
253
+
254
+ // Pre-populate the queue with 2 entries (one per section) so the drain
255
+ // path in on-stop has work to do.
256
+ const dbnc = require(DEBOUNCER);
257
+ dbnc.enqueue(fx.roomDir, 'market-analysis', 'pre-existing');
258
+ dbnc.enqueue(fx.roomDir, 'problem-definition', 'pre-existing');
259
+ const preDrain = dbnc.peek(fx.roomDir);
260
+ assert.equal(preDrain.entries.length, 2, 'queue seeded with 2 entries');
261
+
262
+ const res = invokeOnStop(fx);
263
+ assert.equal(res.status, 0, 'on-stop exits 0: ' + (res.stderr || ''));
264
+
265
+ // Snapshot written regardless
266
+ const snapPath = path.join(fx.roomDir, '.mindrian', 'session-snapshot.json');
267
+ assert.ok(fs.existsSync(snapPath), 'session-snapshot.json exists');
268
+
269
+ // The queue may have been fully drained (olderThanMs=0). The snapshot
270
+ // or the stale file absorbs the state -- either way, on-stop completed
271
+ // cleanly and no .tmp. artifacts leak.
272
+ const mindrianEntries = fs.readdirSync(path.join(fx.roomDir, '.mindrian'));
273
+ const tmpLeaks = mindrianEntries.filter((n) => n.indexOf('.tmp.') !== -1);
274
+ assert.deepEqual(tmpLeaks, [], 'no .tmp. suffix files leak in .mindrian/');
275
+ });
276
+
277
+ // ---------------------------------------------------------------------------
278
+ // Test 4: Stale reasoning surfaces in minto-stale.json
279
+ // ---------------------------------------------------------------------------
280
+ test('sentinel last_generated_at (1970) -> minto-stale.json lists that section', () => {
281
+ const tmp = mkTmp('on-stop-t4-');
282
+ const fx = seedRoom(tmp, ['competitive-analysis', 'market-analysis']);
283
+ // competitive-analysis is stale (sentinel); market-analysis is fresh.
284
+ writeMinto(path.join(fx.roomDir, 'competitive-analysis'), { stale: true, governing_thought: 'C.' });
285
+ writeMinto(path.join(fx.roomDir, 'market-analysis'), { governing_thought: 'M.' });
286
+
287
+ const res = invokeOnStop(fx);
288
+ assert.equal(res.status, 0, 'on-stop exits 0: ' + (res.stderr || ''));
289
+
290
+ const stalePath = path.join(fx.roomDir, '.mindrian', 'minto-stale.json');
291
+ assert.ok(fs.existsSync(stalePath), 'minto-stale.json should exist when stale section is present');
292
+
293
+ const stale = JSON.parse(fs.readFileSync(stalePath, 'utf8'));
294
+ assert.equal(stale.version, 1, 'stale.version === 1');
295
+ assert.ok(Array.isArray(stale.sections), 'stale.sections is an array');
296
+ const staleNames = stale.sections.map((e) => e.section).sort();
297
+ assert.ok(
298
+ staleNames.indexOf('competitive-analysis') !== -1,
299
+ 'competitive-analysis present in stale list (sentinel timestamp trips never_generated)'
300
+ );
301
+ // Each entry must carry a reason string.
302
+ for (const e of stale.sections) {
303
+ assert.ok(typeof e.reason === 'string' && e.reason.length > 0, 'stale entry has reason');
304
+ }
305
+ });
306
+
307
+ // ---------------------------------------------------------------------------
308
+ // Test 5: Rapid exit under 3000ms hook budget
309
+ // ---------------------------------------------------------------------------
310
+ test('single-section room with empty queue completes under the 3000ms budget', () => {
311
+ const tmp = mkTmp('on-stop-t5-');
312
+ const fx = seedRoom(tmp, ['market-analysis']);
313
+ writeMinto(path.join(fx.roomDir, 'market-analysis'), { governing_thought: 'M.' });
314
+
315
+ const t0 = Date.now();
316
+ const res = invokeOnStop(fx);
317
+ const elapsed = Date.now() - t0;
318
+
319
+ assert.equal(res.status, 0, 'on-stop exits 0: ' + (res.stderr || ''));
320
+ assert.ok(
321
+ elapsed < 3000,
322
+ 'on-stop completes under 3000ms hook budget; elapsed=' + elapsed + 'ms'
323
+ );
324
+ });
325
+
326
+ // ---------------------------------------------------------------------------
327
+ // Test 6: STATE.md write preserved (Phase 84 contract)
328
+ // ---------------------------------------------------------------------------
329
+ test('STATE.md write path still fires (Phase 84 on-stop contract preserved)', () => {
330
+ const tmp = mkTmp('on-stop-t6-');
331
+ const fx = seedRoom(tmp, ['market-analysis']);
332
+ writeMinto(path.join(fx.roomDir, 'market-analysis'), { governing_thought: 'M.' });
333
+
334
+ const res = invokeOnStop(fx);
335
+ assert.equal(res.status, 0, 'on-stop exits 0: ' + (res.stderr || ''));
336
+
337
+ const statePath = path.join(fx.roomDir, 'STATE.md');
338
+ assert.ok(fs.existsSync(statePath), 'STATE.md created by on-stop (Phase 84 contract)');
339
+ const stateContent = fs.readFileSync(statePath, 'utf8');
340
+ assert.ok(
341
+ stateContent.length > 0,
342
+ 'STATE.md is non-empty'
343
+ );
344
+ });
345
+
346
+ // ---------------------------------------------------------------------------
347
+ // Test 7: Atomic writes -- no leftover .tmp. files
348
+ // ---------------------------------------------------------------------------
349
+ test('session-snapshot.json and minto-stale.json written atomically (no tmp leakage)', () => {
350
+ const tmp = mkTmp('on-stop-t7-');
351
+ const fx = seedRoom(tmp, ['a', 'b', 'c']);
352
+ writeMinto(path.join(fx.roomDir, 'a'), { governing_thought: 'A.' });
353
+ writeMinto(path.join(fx.roomDir, 'b'), { stale: true, governing_thought: 'B.' });
354
+ writeMinto(path.join(fx.roomDir, 'c'), { governing_thought: 'C.' });
355
+
356
+ const res = invokeOnStop(fx);
357
+ assert.equal(res.status, 0, 'on-stop exits 0: ' + (res.stderr || ''));
358
+
359
+ // After a successful run, every write should be via tmp+rename. No
360
+ // residual .tmp. files should remain in .mindrian/.
361
+ const mindrianDir = path.join(fx.roomDir, '.mindrian');
362
+ const entries = fs.readdirSync(mindrianDir);
363
+ const tmpLeaks = entries.filter((n) => n.indexOf('.tmp.') !== -1);
364
+ assert.deepEqual(tmpLeaks, [], '.mindrian/ has no .tmp. leftovers: ' + JSON.stringify(tmpLeaks));
365
+ });
366
+
367
+ // ---------------------------------------------------------------------------
368
+ // Test 8: Soft-fail -- on-stop exits 0 even when no MINTO files exist
369
+ // ---------------------------------------------------------------------------
370
+ test('on-stop exits 0 even on fully degraded fixture (no MINTO files)', () => {
371
+ const tmp = mkTmp('on-stop-t8-');
372
+ // Seed only ROOM.md per section -- no MINTO.md, no artifact bodies wired.
373
+ // readTriple degrades gracefully; on-stop must not propagate a failure.
374
+ const fx = seedRoom(tmp, ['x']);
375
+
376
+ const res = invokeOnStop(fx);
377
+ assert.equal(res.status, 0, 'on-stop exits 0 under degraded conditions: ' + (res.stderr || ''));
378
+
379
+ // Snapshot is still written (empty section entry is acceptable).
380
+ const snapPath = path.join(fx.roomDir, '.mindrian', 'session-snapshot.json');
381
+ assert.ok(fs.existsSync(snapPath), 'snapshot still written under degraded conditions');
382
+ });
383
+
384
+ // ---------------------------------------------------------------------------
385
+ // Epilogue
386
+ // ---------------------------------------------------------------------------
387
+
388
+ (async () => {
389
+ let passed = 0;
390
+ let failed = 0;
391
+ for (const t of tests) {
392
+ try {
393
+ const r = t.fn();
394
+ if (r && typeof r.then === 'function') await r;
395
+ process.stdout.write('PASS ' + t.name + '\n');
396
+ passed += 1;
397
+ } catch (e) {
398
+ process.stderr.write('FAIL ' + t.name + '\n' + (e && e.stack ? e.stack : e) + '\n');
399
+ failed += 1;
400
+ }
401
+ }
402
+ process.stdout.write('\non-stop-snapshot.test.cjs: ' + passed + '/' + tests.length + ' passed\n');
403
+ process.exit(failed === 0 ? 0 : 1);
404
+ })();