@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,600 @@
1
+ /**
2
+ * MindrianOS Plugin -- Memory Layer Operations
3
+ * Persistent memory tables on the same room/.mindrian/room.db as lazygraph-ops.cjs.
4
+ * Covers L0 Identity, L1 Facts, and schema for L2 Sessions, L3 Fragments, Assumptions.
5
+ *
6
+ * Exports: initMemorySchema, getIdentity, setIdentity, addFact, getValidFacts, invalidateFact,
7
+ * startSession, endSession, addFragment, getSessionHistory,
8
+ * createAssumption, updateAssumptionValidity, getAssumptions
9
+ *
10
+ * All functions use prepared statements with ? parameters (no string interpolation).
11
+ * Async wrappers for backward compatibility with callers that use await.
12
+ */
13
+
14
+ 'use strict';
15
+
16
+ // --- Schema ---
17
+
18
+ /**
19
+ * Create all 5 memory tables and 5 indexes. Idempotent (CREATE IF NOT EXISTS).
20
+ * Call after openGraph() on the same db instance.
21
+ * @param {import('node:sqlite').DatabaseSync} db - node:sqlite DatabaseSync instance
22
+ */
23
+ function initMemorySchema(db) {
24
+ db.exec(`
25
+ CREATE TABLE IF NOT EXISTS identity (
26
+ key TEXT PRIMARY KEY,
27
+ value TEXT NOT NULL,
28
+ updated_at TEXT NOT NULL
29
+ );
30
+
31
+ CREATE TABLE IF NOT EXISTS facts (
32
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
33
+ subject TEXT NOT NULL,
34
+ predicate TEXT NOT NULL,
35
+ object TEXT NOT NULL,
36
+ confidence REAL DEFAULT 1.0,
37
+ source_artifact TEXT,
38
+ source_meeting TEXT,
39
+ valid_from TEXT NOT NULL,
40
+ invalidated_at TEXT,
41
+ invalidated_by TEXT
42
+ );
43
+
44
+ CREATE TABLE IF NOT EXISTS sessions (
45
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
46
+ started_at TEXT NOT NULL,
47
+ ended_at TEXT,
48
+ summary TEXT,
49
+ key_decisions TEXT DEFAULT '[]',
50
+ open_questions TEXT DEFAULT '[]',
51
+ methodology_used TEXT,
52
+ artifacts_filed TEXT DEFAULT '[]'
53
+ );
54
+
55
+ CREATE TABLE IF NOT EXISTS fragments (
56
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
57
+ session_id INTEGER NOT NULL REFERENCES sessions(id),
58
+ role TEXT NOT NULL,
59
+ content TEXT NOT NULL,
60
+ timestamp TEXT NOT NULL,
61
+ section_context TEXT
62
+ );
63
+
64
+ CREATE TABLE IF NOT EXISTS assumptions (
65
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
66
+ claim TEXT NOT NULL,
67
+ section TEXT,
68
+ validity TEXT NOT NULL DEFAULT 'untested' CHECK(validity IN ('untested','supported','contradicted','stale')),
69
+ evidence_for TEXT DEFAULT '[]',
70
+ evidence_against TEXT DEFAULT '[]',
71
+ created_at TEXT NOT NULL,
72
+ last_tested TEXT,
73
+ invalidated_at TEXT
74
+ );
75
+
76
+ CREATE INDEX IF NOT EXISTS idx_facts_subject ON facts(subject);
77
+ CREATE INDEX IF NOT EXISTS idx_facts_invalidated_at ON facts(invalidated_at);
78
+ CREATE INDEX IF NOT EXISTS idx_fragments_session_id ON fragments(session_id);
79
+ CREATE INDEX IF NOT EXISTS idx_assumptions_section ON assumptions(section);
80
+ CREATE INDEX IF NOT EXISTS idx_assumptions_validity ON assumptions(validity);
81
+
82
+ CREATE TABLE IF NOT EXISTS scaffold_log (
83
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
84
+ timestamp TEXT NOT NULL,
85
+ action TEXT NOT NULL,
86
+ section TEXT NOT NULL,
87
+ collection TEXT,
88
+ user_reason TEXT,
89
+ surface TEXT NOT NULL
90
+ );
91
+
92
+ CREATE TABLE IF NOT EXISTS voice_log (
93
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
94
+ timestamp TEXT NOT NULL,
95
+ command TEXT NOT NULL,
96
+ question TEXT,
97
+ answer_summary TEXT,
98
+ artifacts_cited TEXT,
99
+ confidence INTEGER,
100
+ contradictions_flagged TEXT
101
+ );
102
+
103
+ CREATE TABLE IF NOT EXISTS held_contradictions (
104
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
105
+ created_at TEXT NOT NULL,
106
+ source_artifact TEXT,
107
+ target_artifact TEXT,
108
+ tension_summary TEXT,
109
+ status TEXT NOT NULL DEFAULT 'open',
110
+ resolved_at TEXT
111
+ );
112
+
113
+ CREATE TABLE IF NOT EXISTS decisions_index (
114
+ id TEXT PRIMARY KEY,
115
+ decision TEXT NOT NULL,
116
+ rationale TEXT,
117
+ reversibility TEXT,
118
+ witnesses TEXT,
119
+ date TEXT,
120
+ pressure_context TEXT,
121
+ status TEXT,
122
+ artifact_path TEXT
123
+ );
124
+
125
+ CREATE INDEX IF NOT EXISTS idx_scaffold_log_section ON scaffold_log(section);
126
+ CREATE INDEX IF NOT EXISTS idx_voice_log_timestamp ON voice_log(timestamp);
127
+ CREATE INDEX IF NOT EXISTS idx_held_contradictions_status ON held_contradictions(status);
128
+ CREATE INDEX IF NOT EXISTS idx_decisions_index_status ON decisions_index(status);
129
+ `);
130
+ }
131
+
132
+ // --- L0 Identity ---
133
+
134
+ /**
135
+ * Set (upsert) an identity key-value pair.
136
+ * @param {import('node:sqlite').DatabaseSync} db - node:sqlite DatabaseSync instance
137
+ * @param {string} key - Identity key (e.g. 'venture_name', 'founder', 'stage')
138
+ * @param {string} value - Identity value
139
+ * @returns {Promise<void>}
140
+ */
141
+ async function setIdentity(db, key, value) {
142
+ const updatedAt = new Date().toISOString();
143
+ db.prepare(
144
+ 'INSERT INTO identity (key, value, updated_at) VALUES (?, ?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value, updated_at = excluded.updated_at'
145
+ ).run(key, value, updatedAt);
146
+ return Promise.resolve();
147
+ }
148
+
149
+ /**
150
+ * Get all identity key-value pairs as a plain object.
151
+ * @param {import('node:sqlite').DatabaseSync} db - node:sqlite DatabaseSync instance
152
+ * @returns {Promise<object>} e.g. { venture_name: 'Acme', founder: 'Jane' }
153
+ */
154
+ async function getIdentity(db) {
155
+ const rows = db.prepare('SELECT key, value FROM identity').all();
156
+ const identity = {};
157
+ for (const row of rows) {
158
+ identity[row.key] = row.value;
159
+ }
160
+ return Promise.resolve(identity);
161
+ }
162
+
163
+ // --- L1 Facts ---
164
+
165
+ /**
166
+ * Add a new fact with auto-generated valid_from timestamp.
167
+ * @param {import('node:sqlite').DatabaseSync} db - node:sqlite DatabaseSync instance
168
+ * @param {object} fact - Fact to add
169
+ * @param {string} fact.subject - Fact subject (e.g. 'market', 'team')
170
+ * @param {string} fact.predicate - Fact predicate (e.g. 'size', 'count')
171
+ * @param {string} fact.object - Fact object value (e.g. '$1B', '5')
172
+ * @param {number} [fact.confidence=1.0] - Confidence score (0-1)
173
+ * @param {string} [fact.source_artifact] - Source artifact ID
174
+ * @param {string} [fact.source_meeting] - Source meeting ID
175
+ * @returns {Promise<{id: number, subject: string, predicate: string, object: string, confidence: number, valid_from: string}>}
176
+ */
177
+ async function addFact(db, fact) {
178
+ const validFrom = new Date().toISOString();
179
+ const confidence = typeof fact.confidence === 'number' ? fact.confidence : 1.0;
180
+ const sourceArtifact = fact.source_artifact || null;
181
+ const sourceMeeting = fact.source_meeting || null;
182
+
183
+ const info = db.prepare(
184
+ 'INSERT INTO facts (subject, predicate, object, confidence, source_artifact, source_meeting, valid_from) VALUES (?, ?, ?, ?, ?, ?, ?)'
185
+ ).run(fact.subject, fact.predicate, fact.object, confidence, sourceArtifact, sourceMeeting, validFrom);
186
+
187
+ return Promise.resolve({
188
+ id: Number(info.lastInsertRowid),
189
+ subject: fact.subject,
190
+ predicate: fact.predicate,
191
+ object: fact.object,
192
+ confidence,
193
+ valid_from: validFrom,
194
+ });
195
+ }
196
+
197
+ /**
198
+ * Get all valid (non-invalidated) facts, optionally filtered by subject.
199
+ * @param {import('node:sqlite').DatabaseSync} db - node:sqlite DatabaseSync instance
200
+ * @param {string} [subject] - Optional subject filter
201
+ * @returns {Promise<Array<object>>}
202
+ */
203
+ async function getValidFacts(db, subject) {
204
+ let rows;
205
+ if (subject) {
206
+ rows = db.prepare('SELECT * FROM facts WHERE invalidated_at IS NULL AND subject = ?').all(subject);
207
+ } else {
208
+ rows = db.prepare('SELECT * FROM facts WHERE invalidated_at IS NULL').all();
209
+ }
210
+ return Promise.resolve(rows);
211
+ }
212
+
213
+ /**
214
+ * Invalidate a fact by setting invalidated_at and invalidated_by.
215
+ * @param {import('node:sqlite').DatabaseSync} db - node:sqlite DatabaseSync instance
216
+ * @param {number} factId - Fact ID to invalidate
217
+ * @param {string} invalidatedBy - Reason/source for invalidation
218
+ * @returns {Promise<{success: boolean, id: number}>}
219
+ */
220
+ async function invalidateFact(db, factId, invalidatedBy) {
221
+ const invalidatedAt = new Date().toISOString();
222
+ db.prepare(
223
+ 'UPDATE facts SET invalidated_at = ?, invalidated_by = ? WHERE id = ?'
224
+ ).run(invalidatedAt, invalidatedBy, factId);
225
+ return Promise.resolve({ success: true, id: factId });
226
+ }
227
+
228
+ // --- L2 Sessions ---
229
+
230
+ /**
231
+ * Start a new session. Creates a row with started_at = now.
232
+ * @param {import('node:sqlite').DatabaseSync} db - node:sqlite DatabaseSync instance
233
+ * @returns {Promise<{id: number, started_at: string}>}
234
+ */
235
+ async function startSession(db) {
236
+ const startedAt = new Date().toISOString();
237
+ const info = db.prepare(
238
+ 'INSERT INTO sessions (started_at) VALUES (?)'
239
+ ).run(startedAt);
240
+ return Promise.resolve({
241
+ id: Number(info.lastInsertRowid),
242
+ started_at: startedAt,
243
+ });
244
+ }
245
+
246
+ /**
247
+ * End a session by setting ended_at and optional metadata fields.
248
+ * @param {import('node:sqlite').DatabaseSync} db - node:sqlite DatabaseSync instance
249
+ * @param {number} sessionId - Session ID to end
250
+ * @param {object} [opts={}] - Optional fields
251
+ * @param {string} [opts.summary] - Session summary
252
+ * @param {Array|string} [opts.key_decisions] - Key decisions (array or JSON string)
253
+ * @param {Array|string} [opts.open_questions] - Open questions (array or JSON string)
254
+ * @param {string} [opts.methodology_used] - Methodology used
255
+ * @param {Array|string} [opts.artifacts_filed] - Artifacts filed (array or JSON string)
256
+ * @returns {Promise<{success: boolean, id: number, ended_at: string}>}
257
+ */
258
+ async function endSession(db, sessionId, opts = {}) {
259
+ const endedAt = new Date().toISOString();
260
+ const summary = opts.summary || null;
261
+ const methodologyUsed = opts.methodology_used || null;
262
+
263
+ // JSON fields: if array, stringify; if string, use as-is; if undefined, use default '[]'
264
+ const keyDecisions = Array.isArray(opts.key_decisions)
265
+ ? JSON.stringify(opts.key_decisions)
266
+ : (typeof opts.key_decisions === 'string' ? opts.key_decisions : '[]');
267
+ const openQuestions = Array.isArray(opts.open_questions)
268
+ ? JSON.stringify(opts.open_questions)
269
+ : (typeof opts.open_questions === 'string' ? opts.open_questions : '[]');
270
+ const artifactsFiled = Array.isArray(opts.artifacts_filed)
271
+ ? JSON.stringify(opts.artifacts_filed)
272
+ : (typeof opts.artifacts_filed === 'string' ? opts.artifacts_filed : '[]');
273
+
274
+ db.prepare(
275
+ 'UPDATE sessions SET ended_at = ?, summary = ?, key_decisions = ?, open_questions = ?, methodology_used = ?, artifacts_filed = ? WHERE id = ?'
276
+ ).run(endedAt, summary, keyDecisions, openQuestions, methodologyUsed, artifactsFiled, sessionId);
277
+
278
+ return Promise.resolve({ success: true, id: sessionId, ended_at: endedAt });
279
+ }
280
+
281
+ // --- L3 Fragments ---
282
+
283
+ /**
284
+ * Add a conversation fragment linked to a session.
285
+ * @param {import('node:sqlite').DatabaseSync} db - node:sqlite DatabaseSync instance
286
+ * @param {object} fragment - Fragment data
287
+ * @param {number} fragment.session_id - Parent session ID (FK)
288
+ * @param {string} fragment.role - Speaker role (e.g. 'user', 'assistant')
289
+ * @param {string} fragment.content - Message content
290
+ * @param {string} [fragment.section_context] - Room section context
291
+ * @returns {Promise<{id: number, session_id: number, timestamp: string}>}
292
+ */
293
+ async function addFragment(db, fragment) {
294
+ const timestamp = new Date().toISOString();
295
+ const sectionContext = fragment.section_context || null;
296
+
297
+ const info = db.prepare(
298
+ 'INSERT INTO fragments (session_id, role, content, timestamp, section_context) VALUES (?, ?, ?, ?, ?)'
299
+ ).run(fragment.session_id, fragment.role, fragment.content, timestamp, sectionContext);
300
+
301
+ return Promise.resolve({
302
+ id: Number(info.lastInsertRowid),
303
+ session_id: fragment.session_id,
304
+ timestamp,
305
+ });
306
+ }
307
+
308
+ /**
309
+ * Get session history with nested fragments, ordered by started_at DESC.
310
+ * @param {import('node:sqlite').DatabaseSync} db - node:sqlite DatabaseSync instance
311
+ * @param {number} [limit=10] - Maximum number of sessions to return
312
+ * @returns {Promise<Array<object>>} Sessions with fragments array property
313
+ */
314
+ async function getSessionHistory(db, limit) {
315
+ const effectiveLimit = typeof limit === 'number' ? limit : 10;
316
+
317
+ const sessions = db.prepare(
318
+ 'SELECT * FROM sessions ORDER BY started_at DESC LIMIT ?'
319
+ ).all(effectiveLimit);
320
+
321
+ const fragStmt = db.prepare(
322
+ 'SELECT * FROM fragments WHERE session_id = ? ORDER BY timestamp ASC'
323
+ );
324
+
325
+ for (const session of sessions) {
326
+ session.fragments = fragStmt.all(session.id);
327
+ // Parse JSON fields
328
+ try { session.key_decisions = JSON.parse(session.key_decisions); } catch { session.key_decisions = []; }
329
+ try { session.open_questions = JSON.parse(session.open_questions); } catch { session.open_questions = []; }
330
+ try { session.artifacts_filed = JSON.parse(session.artifacts_filed); } catch { session.artifacts_filed = []; }
331
+ }
332
+
333
+ return Promise.resolve(sessions);
334
+ }
335
+
336
+ // --- Assumptions ---
337
+
338
+ /**
339
+ * Create an assumption with validity = 'untested'.
340
+ * @param {import('node:sqlite').DatabaseSync} db - node:sqlite DatabaseSync instance
341
+ * @param {object} opts - Assumption data
342
+ * @param {string} opts.claim - The assumption claim text
343
+ * @param {string} [opts.section] - Room section this assumption belongs to
344
+ * @returns {Promise<{id: number, claim: string, section: string|null, validity: string, created_at: string}>}
345
+ */
346
+ async function createAssumption(db, opts) {
347
+ const createdAt = new Date().toISOString();
348
+ const section = opts.section || null;
349
+
350
+ const info = db.prepare(
351
+ 'INSERT INTO assumptions (claim, section, created_at) VALUES (?, ?, ?)'
352
+ ).run(opts.claim, section, createdAt);
353
+
354
+ return Promise.resolve({
355
+ id: Number(info.lastInsertRowid),
356
+ claim: opts.claim,
357
+ section,
358
+ validity: 'untested',
359
+ created_at: createdAt,
360
+ });
361
+ }
362
+
363
+ /**
364
+ * Update an assumption's validity status and evidence arrays.
365
+ * @param {import('node:sqlite').DatabaseSync} db - node:sqlite DatabaseSync instance
366
+ * @param {number} assumptionId - Assumption ID to update
367
+ * @param {string} newValidity - New validity ('supported', 'contradicted', 'stale')
368
+ * @param {object} [opts={}] - Options
369
+ * @param {string} [opts.evidence] - Evidence artifact/source that changed validity
370
+ * @returns {Promise<{success: boolean, id: number, validity: string}>}
371
+ */
372
+ async function updateAssumptionValidity(db, assumptionId, newValidity, opts = {}) {
373
+ const lastTested = new Date().toISOString();
374
+
375
+ // Read current assumption
376
+ const current = db.prepare('SELECT * FROM assumptions WHERE id = ?').get(assumptionId);
377
+ if (!current) {
378
+ throw new Error(`Assumption ${assumptionId} not found`);
379
+ }
380
+
381
+ // Parse existing evidence arrays
382
+ let evidenceFor;
383
+ let evidenceAgainst;
384
+ try { evidenceFor = JSON.parse(current.evidence_for); } catch { evidenceFor = []; }
385
+ try { evidenceAgainst = JSON.parse(current.evidence_against); } catch { evidenceAgainst = []; }
386
+
387
+ // Append evidence based on validity direction
388
+ if (newValidity === 'supported' && opts.evidence) {
389
+ evidenceFor.push(opts.evidence);
390
+ } else if (newValidity === 'contradicted' && opts.evidence) {
391
+ evidenceAgainst.push(opts.evidence);
392
+ }
393
+
394
+ // Set invalidated_at for stale
395
+ const invalidatedAt = newValidity === 'stale' ? lastTested : current.invalidated_at;
396
+
397
+ db.prepare(
398
+ 'UPDATE assumptions SET validity = ?, evidence_for = ?, evidence_against = ?, last_tested = ?, invalidated_at = ? WHERE id = ?'
399
+ ).run(newValidity, JSON.stringify(evidenceFor), JSON.stringify(evidenceAgainst), lastTested, invalidatedAt, assumptionId);
400
+
401
+ return Promise.resolve({ success: true, id: assumptionId, validity: newValidity });
402
+ }
403
+
404
+ /**
405
+ * Get assumptions, optionally filtered by section and/or validity.
406
+ * @param {import('node:sqlite').DatabaseSync} db - node:sqlite DatabaseSync instance
407
+ * @param {object} [filters={}] - Optional filters
408
+ * @param {string} [filters.section] - Filter by room section
409
+ * @param {string} [filters.validity] - Filter by validity status
410
+ * @returns {Promise<Array<object>>}
411
+ */
412
+ async function getAssumptions(db, filters = {}) {
413
+ let query = 'SELECT * FROM assumptions';
414
+ const conditions = [];
415
+ const params = [];
416
+
417
+ if (filters.section) {
418
+ conditions.push('section = ?');
419
+ params.push(filters.section);
420
+ }
421
+ if (filters.validity) {
422
+ conditions.push('validity = ?');
423
+ params.push(filters.validity);
424
+ }
425
+
426
+ if (conditions.length > 0) {
427
+ query += ' WHERE ' + conditions.join(' AND ');
428
+ }
429
+
430
+ const rows = db.prepare(query).all(...params);
431
+
432
+ // Parse JSON evidence fields
433
+ for (const row of rows) {
434
+ try { row.evidence_for = JSON.parse(row.evidence_for); } catch { row.evidence_for = []; }
435
+ try { row.evidence_against = JSON.parse(row.evidence_against); } catch { row.evidence_against = []; }
436
+ }
437
+
438
+ return Promise.resolve(rows);
439
+ }
440
+
441
+ // --- Scaffold + Voice Log Helpers (Phase 84) ---
442
+
443
+ /**
444
+ * Insert a row into scaffold_log. Records a materialization audit event.
445
+ * @param {import('node:sqlite').DatabaseSync} db - node:sqlite DatabaseSync instance
446
+ * @param {object} opts
447
+ * @param {string} opts.action - e.g. 'materialize', 'dematerialize'
448
+ * @param {string} opts.section - Room section name
449
+ * @param {string} [opts.collection] - Optional collection identifier
450
+ * @param {string} [opts.user_reason] - Optional user-provided reason
451
+ * @param {string} opts.surface - 'cli' | 'desktop' | 'cowork'
452
+ * @returns {Promise<{id: number, timestamp: string}>}
453
+ */
454
+ async function logScaffoldAction(db, opts) {
455
+ const timestamp = new Date().toISOString();
456
+ const collection = opts.collection || null;
457
+ const userReason = opts.user_reason || null;
458
+
459
+ const info = db.prepare(
460
+ 'INSERT INTO scaffold_log (timestamp, action, section, collection, user_reason, surface) VALUES (?, ?, ?, ?, ?, ?)'
461
+ ).run(timestamp, opts.action, opts.section, collection, userReason, opts.surface);
462
+
463
+ return Promise.resolve({
464
+ id: Number(info.lastInsertRowid),
465
+ timestamp,
466
+ });
467
+ }
468
+
469
+ /**
470
+ * Insert a structured row into voice_log built from a closing session's
471
+ * fragments. Phase 84-07 writer half: replaces the stub call in
472
+ * memory-lifecycle.cjs stop with a row that captures the session's question,
473
+ * answer summary, cited artifacts, and any contradictions flagged by the
474
+ * proactive-intelligence layer. Additive alongside writeVoiceLogStub, which
475
+ * remains the fallback for sessions with zero captured fragments.
476
+ *
477
+ * Truncation is codepoint-safe (Array.from -> slice -> join) so multi-byte
478
+ * characters are not cut mid-sequence. JSON arrays are stringified before
479
+ * insert. confidence stays null in v1.10.8; a future analysis pass will
480
+ * populate it.
481
+ *
482
+ * @param {import('node:sqlite').DatabaseSync} db - node:sqlite DatabaseSync instance
483
+ * @param {object} opts
484
+ * @param {string} opts.command - Command/context the session was for
485
+ * @param {string} [opts.question] - First user fragment content
486
+ * @param {string} [opts.answer_summary] - Last assistant fragment or summary
487
+ * @param {Array<string>} [opts.artifacts_cited] - Artifact IDs referenced
488
+ * @param {number|null} [opts.confidence] - 1-5 integer or null
489
+ * @param {Array<string>} [opts.contradictions_flagged] - Contradiction IDs
490
+ * @returns {Promise<{id: number, timestamp: string}>}
491
+ */
492
+ async function writeVoiceLogRow(db, opts) {
493
+ const TRUNCATE = 200;
494
+ function truncCodepoints(s, n) {
495
+ if (typeof s !== 'string' || s.length === 0) return null;
496
+ const arr = Array.from(s);
497
+ if (arr.length <= n) return s;
498
+ return arr.slice(0, n).join('');
499
+ }
500
+
501
+ try {
502
+ const timestamp = new Date().toISOString();
503
+ const command = (opts && typeof opts.command === 'string' && opts.command) || 'session-summary';
504
+ const question = truncCodepoints(opts && opts.question, TRUNCATE);
505
+ const answerSummary = truncCodepoints(opts && opts.answer_summary, TRUNCATE);
506
+ const artifactsCited = JSON.stringify(
507
+ Array.isArray(opts && opts.artifacts_cited) ? opts.artifacts_cited : []
508
+ );
509
+ const confidence = (opts && typeof opts.confidence === 'number') ? opts.confidence : null;
510
+ const contradictionsFlagged = JSON.stringify(
511
+ Array.isArray(opts && opts.contradictions_flagged) ? opts.contradictions_flagged : []
512
+ );
513
+
514
+ const info = db.prepare(
515
+ 'INSERT INTO voice_log (timestamp, command, question, answer_summary, artifacts_cited, confidence, contradictions_flagged) VALUES (?, ?, ?, ?, ?, ?, ?)'
516
+ ).run(timestamp, command, question, answerSummary, artifactsCited, confidence, contradictionsFlagged);
517
+
518
+ return Promise.resolve({
519
+ id: Number(info.lastInsertRowid),
520
+ timestamp,
521
+ });
522
+ } catch (_) {
523
+ return Promise.resolve({ id: 0, timestamp: new Date().toISOString() });
524
+ }
525
+ }
526
+
527
+ /**
528
+ * Read the latest voice_log row for a given session. Phase 84-07 reader half.
529
+ * Returns null when no row exists. Errors are swallowed (advisory contract:
530
+ * the on-stop hook must never crash because voice-log read failed).
531
+ *
532
+ * The voice_log table has no session_id column in v1.10.8 (the schema in
533
+ * 84-01 keys voice rows by timestamp). This helper returns the most recent
534
+ * row globally for the active room db, which in the on-stop flow is the row
535
+ * just written by writeVoiceLogRow for the closing session. Future schema
536
+ * iterations may add a session_id FK; until then "latest row" is the
537
+ * advisory contract.
538
+ *
539
+ * @param {import('node:sqlite').DatabaseSync} db
540
+ * @returns {Promise<object|null>}
541
+ */
542
+ async function readVoiceLogTail(db) {
543
+ try {
544
+ const row = db.prepare(
545
+ 'SELECT id, timestamp, command, question, answer_summary, artifacts_cited, confidence, contradictions_flagged FROM voice_log ORDER BY id DESC LIMIT 1'
546
+ ).get();
547
+ if (!row) return Promise.resolve(null);
548
+ try { row.artifacts_cited = JSON.parse(row.artifacts_cited); } catch { row.artifacts_cited = []; }
549
+ try { row.contradictions_flagged = JSON.parse(row.contradictions_flagged); } catch { row.contradictions_flagged = []; }
550
+ return Promise.resolve(row);
551
+ } catch (_) {
552
+ return Promise.resolve(null);
553
+ }
554
+ }
555
+
556
+ /**
557
+ * Insert a stub row into voice_log. Used by PostCompact/Stop hooks in v1.10.8
558
+ * to reserve schema space for the synthesis voice. question/confidence are null,
559
+ * artifacts_cited and contradictions_flagged default to '[]'.
560
+ * @param {import('node:sqlite').DatabaseSync} db - node:sqlite DatabaseSync instance
561
+ * @param {object} opts
562
+ * @param {string} opts.command - Command that triggered the stub write
563
+ * @param {string} [opts.answer_summary] - Optional summary text
564
+ * @returns {Promise<{id: number, timestamp: string}>}
565
+ */
566
+ async function writeVoiceLogStub(db, opts) {
567
+ const timestamp = new Date().toISOString();
568
+ const answerSummary = opts.answer_summary || null;
569
+
570
+ const info = db.prepare(
571
+ 'INSERT INTO voice_log (timestamp, command, question, answer_summary, artifacts_cited, confidence, contradictions_flagged) VALUES (?, ?, ?, ?, ?, ?, ?)'
572
+ ).run(timestamp, opts.command, null, answerSummary, '[]', null, '[]');
573
+
574
+ return Promise.resolve({
575
+ id: Number(info.lastInsertRowid),
576
+ timestamp,
577
+ });
578
+ }
579
+
580
+ // --- Exports ---
581
+
582
+ module.exports = {
583
+ initMemorySchema,
584
+ setIdentity,
585
+ getIdentity,
586
+ addFact,
587
+ getValidFacts,
588
+ invalidateFact,
589
+ startSession,
590
+ endSession,
591
+ addFragment,
592
+ getSessionHistory,
593
+ createAssumption,
594
+ updateAssumptionValidity,
595
+ getAssumptions,
596
+ logScaffoldAction,
597
+ writeVoiceLogStub,
598
+ writeVoiceLogRow,
599
+ readVoiceLogTail,
600
+ };
@@ -0,0 +1,33 @@
1
+ # lib/core/migrations/
2
+
3
+ ICM Layer 0 identity for the Phase 109 migrations directory.
4
+
5
+ Phase-scoped idempotent SQLite migrations for room.db. Each migration is a CJS
6
+ module exporting runMigration(db) that:
7
+
8
+ 1. Checks an identity table sentinel row (key = 'phase_NNN_migration_vN').
9
+ 2. If present, returns { applied: false } without touching the schema.
10
+ 3. If absent, runs the migration in a single BEGIN/COMMIT transaction and
11
+ inserts the sentinel row at the end.
12
+
13
+ Migrations are CALLED from lib/core/room-db.cjs openRoomDb composition entry
14
+ point. Every caller of openRoomDb sees migrated schema. Cold and warm calls
15
+ return identical handles.
16
+
17
+ ## Current migrations
18
+
19
+ - phase-109-nodes-provenance.cjs: 9-column provenance addition to nodes table
20
+ per PROVENANCE.md (Plan 108-02); status_aliases backfill of assumptions to
21
+ graph nodes per TRUTH-STATES.md (Plan 108-03); 6 new indices; closed-enum
22
+ CHECK constraints on created_by and review_status.
23
+
24
+ ## Invariants (Canon Part 8)
25
+
26
+ - Migrations write only to room.db.
27
+ - Zero Brain queries.
28
+ - Zero remote egress.
29
+ - Sentinel row in identity table is local-only.
30
+
31
+ ## Owner
32
+
33
+ Phase 109 SQL Context-Memory Navigation Spine.