@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,388 @@
1
+ /*
2
+ * Copyright (c) 2026 Mindrian. BSL 1.1.
3
+ * Phase 89.3 Plan 01 -- Aura Cypher writer for canonical RS schema.
4
+ *
5
+ * writeDiscovery(pair, opts) is the Tier 1 (Aura-connected) writer in the
6
+ * dual-tier output layer. Takes a scored+classified+thesis-bearing pair
7
+ * (from Plan 89.2-07 generateThesis output) and persists it into the user's
8
+ * own LazyGraph Aura via idempotent MERGE Cypher.
9
+ *
10
+ * Schema (per kickoff section 5):
11
+ * Nodes: RSDiscovery + ReverseSalient + Innovation + Paper + Author + Institution
12
+ * Edges: DISCOVERED + DERIVED_FROM + ENABLES + AUTHORED_BY + AFFILIATED_WITH
13
+ *
14
+ * REAL idempotency in Aura (not mock-state tracking): the 3 core node ids
15
+ * (discovery_id, rs_id, innovation_id) are deterministically derived via
16
+ * sha256 over {query_concept, doc_concept, classification}, so the same
17
+ * pair always produces the same ids and Cypher MERGE matches existing
18
+ * nodes by id PRIMARY KEY. The aura_op_id is random per-op telemetry,
19
+ * NOT a node identifier.
20
+ *
21
+ * The buildDeterministicIds helper mirrors Plan 89.3-02 (rs-sqlite-mirror)
22
+ * byte-for-byte so the dual-tier dedup contract is consistent across
23
+ * writers. Both backends produce the same ids for the same pair.
24
+ *
25
+ * Canon Part 7 (Reuse Before Build): consumes EDGE_TYPES from
26
+ * lazygraph-ops.cjs (extended in this plan, not forked); shares
27
+ * ExternalEgressViolation + auditQueryObject with 89.2 fetchers.
28
+ *
29
+ * Canon Part 8 (Graph Boundary -- defense-in-depth): even though writes
30
+ * go to the user's OWN graph (not Brain), auditQueryObject runs over the
31
+ * full Cypher params object BEFORE every session.run call. Catches
32
+ * forbidden patterns smuggled through node properties OR UNWIND input
33
+ * collections (papers / experts / paper_author_pairs). Throws
34
+ * ExternalEgressViolation on hit.
35
+ *
36
+ * Tier dispatch is NOT this module's responsibility. The writer assumes
37
+ * Aura is reachable. If the backend returns a connection error, throws
38
+ * AuraUnreachableError (a SEPARATE class, NOT ExternalEgressViolation).
39
+ * Caller (Plan 89.3-05 dispatch) reads this error to fall back to
40
+ * rs-sqlite-mirror.
41
+ *
42
+ * Mockable backend: opts.driver is the injection point. Tests pass a mock
43
+ * driver; production callers (Plan 89.3-05) pass the live Aura driver.
44
+ *
45
+ * Pure CJS, zero npm deps, node built-ins only (crypto).
46
+ */
47
+ 'use strict';
48
+
49
+ const crypto = require('crypto');
50
+ const { ExternalEgressViolation } = require('./rs-egress-violations.cjs');
51
+ const { auditQueryObject } = require('./rs-egress-prompts.cjs');
52
+ const { EDGE_TYPES } = require('./lazygraph-ops.cjs');
53
+
54
+ const SURFACE = 'rs-neo4j-writer';
55
+ const SCHEMA_VERSION = '1.0';
56
+ const REQUIRED_FIELDS = Object.freeze(['query_concept', 'doc_concept', 'classification', 'thesis']);
57
+
58
+ // ---------- AuraUnreachableError ----------
59
+ //
60
+ // Tier-dispatch signal (NOT a security violation). Caller catches this and
61
+ // falls back to rs-sqlite-mirror (Tier 0). Distinct from ExternalEgressViolation
62
+ // so the two error classes never get conflated in stack traces or audit logs.
63
+
64
+ class AuraUnreachableError extends Error {
65
+ constructor(message, meta) {
66
+ super(message);
67
+ this.name = 'AuraUnreachableError';
68
+ this.meta = meta || {};
69
+ }
70
+ }
71
+
72
+ // ---------- buildDeterministicIds ----------
73
+ //
74
+ // The dedup contract shared with Plan 89.3-02 (rs-sqlite-mirror). The
75
+ // implementation MUST be byte-identical across both writers so the same
76
+ // pair produces the same 3 core ids regardless of which tier is active.
77
+ //
78
+ // stableKey is JSON.stringify of {q, d, c} (in fixed key order so the
79
+ // resulting bytes are stable across Node versions). sha256 then hex-slice
80
+ // the first 16 chars gives a 64-bit collision space (sufficient for
81
+ // per-room discovery counts; collision probability negligible).
82
+
83
+ function buildDeterministicIds(pair) {
84
+ const stableKey = JSON.stringify({
85
+ q: pair.query_concept,
86
+ d: pair.doc_concept,
87
+ c: pair.classification,
88
+ });
89
+ const hash = crypto.createHash('sha256').update(stableKey).digest('hex').slice(0, 16);
90
+ return {
91
+ discovery_id: 'rsd-' + hash,
92
+ rs_id: 'rs-' + hash,
93
+ innovation_id: 'inn-' + hash,
94
+ };
95
+ }
96
+
97
+ // ---------- generateOpId ----------
98
+ //
99
+ // Random per-op telemetry id (NOT a node id). Caller may journal this for
100
+ // rollback bookkeeping. The id is intentionally non-deterministic so two
101
+ // re-runs of the same pair produce DIFFERENT op ids (proving the call
102
+ // happened twice even though the underlying nodes were MERGE-matched).
103
+
104
+ function generateOpId() {
105
+ return 'op-' + new Date().toISOString().slice(0, 10) + '-' + crypto.randomUUID();
106
+ }
107
+
108
+ // ---------- validateRequiredFields ----------
109
+ //
110
+ // Shape gate. Runs BEFORE audit + driver call. Throws TypeError naming the
111
+ // missing field so callers can surface a precise error to the user.
112
+
113
+ function validateRequiredFields(pair) {
114
+ if (!pair || typeof pair !== 'object') {
115
+ throw new TypeError(SURFACE + ': pair must be an object');
116
+ }
117
+ for (const f of REQUIRED_FIELDS) {
118
+ if (typeof pair[f] !== 'string' || pair[f].length === 0) {
119
+ throw new TypeError(SURFACE + ': missing required field: ' + f);
120
+ }
121
+ }
122
+ }
123
+
124
+ // ---------- buildCypherParams ----------
125
+ //
126
+ // Assemble the params object passed to session.run. Includes all node
127
+ // properties (RSDiscovery + ReverseSalient + Innovation core; Paper +
128
+ // Author + Institution conditional on opts.context).
129
+ //
130
+ // CRITICAL: paper_author_pairs is constructed from
131
+ // ctx.papers.flatMap(p => (p.authors || []).map(a => ({
132
+ // paper_id: p.id,
133
+ // author_key: a.name + '|' + (a.orcid || '__no_orcid__')
134
+ // })))
135
+ // so the AUTHORED_BY UNWIND has ready-to-MATCH tuples. The author_key
136
+ // shape mirrors the Author MERGE key (name + '|' + orcid-or-sentinel)
137
+ // so MATCH succeeds without a JOIN.
138
+ //
139
+ // paper_author_pairs is ALWAYS present (possibly []) so the Cypher does
140
+ // not need an IF guard around the UNWIND.
141
+
142
+ function buildCypherParams(pair, ctx, ids) {
143
+ const breakthrough = pair.breakthrough || {};
144
+ const breakdown = breakthrough.breakdown || {};
145
+ const created_at = new Date().toISOString();
146
+
147
+ const papers = Array.isArray(ctx.papers) ? ctx.papers : [];
148
+ const experts = Array.isArray(ctx.experts) ? ctx.experts : [];
149
+
150
+ const paper_author_pairs = papers.reduce(function (acc, p) {
151
+ const authors = Array.isArray(p.authors) ? p.authors : [];
152
+ for (const a of authors) {
153
+ acc.push({
154
+ paper_id: p.id,
155
+ author_key: (a.name || '') + '|' + (a.orcid || '__no_orcid__'),
156
+ });
157
+ }
158
+ return acc;
159
+ }, []);
160
+
161
+ return {
162
+ // Core RS node ids (deterministic).
163
+ discovery_id: ids.discovery_id,
164
+ rs_id: ids.rs_id,
165
+ innovation_id: ids.innovation_id,
166
+ // RSDiscovery properties.
167
+ classification: pair.classification,
168
+ breakthrough_score: typeof breakthrough.score === 'number' ? breakthrough.score : 0,
169
+ dominant_dimension: typeof breakthrough.dominant_dimension === 'string' ? breakthrough.dominant_dimension : '',
170
+ thesis: pair.thesis,
171
+ bridge_concept: typeof pair.bridge_concept === 'string' ? pair.bridge_concept : '',
172
+ diff: typeof pair.diff === 'number' ? pair.diff : 0,
173
+ lsa: typeof pair.lsa === 'number' ? pair.lsa : 0,
174
+ bert: typeof pair.bert === 'number' ? pair.bert : 0,
175
+ feasibility: typeof breakdown.feasibility === 'number' ? breakdown.feasibility : 0,
176
+ market: typeof breakdown.market === 'number' ? breakdown.market : 0,
177
+ magnitude: typeof breakdown.magnitude === 'number' ? breakdown.magnitude : 0,
178
+ advantage: typeof breakdown.advantage === 'number' ? breakdown.advantage : 0,
179
+ impact: typeof breakdown.impact === 'number' ? breakdown.impact : 0,
180
+ created_at: created_at,
181
+ // ReverseSalient properties.
182
+ query_concept: pair.query_concept,
183
+ doc_concept: pair.doc_concept,
184
+ // Context UNWIND inputs (always present; may be empty arrays).
185
+ papers: papers,
186
+ experts: experts,
187
+ paper_author_pairs: paper_author_pairs,
188
+ // Optional context metadata.
189
+ room_id: typeof ctx.room_id === 'string' ? ctx.room_id : '',
190
+ domain: typeof ctx.domain === 'string' ? ctx.domain : '',
191
+ };
192
+ }
193
+
194
+ // ---------- buildMergeCypher ----------
195
+ //
196
+ // Returns one of two pre-built Cypher strings: core-only when no context,
197
+ // core+context when papers/experts present. Both use MERGE for
198
+ // idempotency. The core+context version includes the AUTHORED_BY UNWIND
199
+ // over $paper_author_pairs.
200
+ //
201
+ // Cypher style: MERGE primary keys explicitly per node so re-runs match
202
+ // existing nodes by PRIMARY KEY (discovery_id, rs_id, innovation_id are
203
+ // deterministic; paper.id is from external source; author name_orcid_key
204
+ // composite handles the missing-orcid case via __no_orcid__ sentinel;
205
+ // institution.name is the natural key).
206
+
207
+ const CORE_CYPHER = [
208
+ 'MERGE (d:RSDiscovery {id: $discovery_id})',
209
+ ' SET d.classification = $classification,',
210
+ ' d.breakthrough_score = $breakthrough_score,',
211
+ ' d.dominant_dimension = $dominant_dimension,',
212
+ ' d.thesis = $thesis,',
213
+ ' d.bridge_concept = $bridge_concept,',
214
+ ' d.diff = $diff,',
215
+ ' d.lsa = $lsa,',
216
+ ' d.bert = $bert,',
217
+ ' d.feasibility = $feasibility,',
218
+ ' d.market = $market,',
219
+ ' d.magnitude = $magnitude,',
220
+ ' d.advantage = $advantage,',
221
+ ' d.impact = $impact,',
222
+ ' d.created_at = $created_at',
223
+ 'MERGE (rs:ReverseSalient {id: $rs_id})',
224
+ ' SET rs.query_concept = $query_concept,',
225
+ ' rs.doc_concept = $doc_concept,',
226
+ ' rs.classification = $classification',
227
+ 'MERGE (i:Innovation {id: $innovation_id})',
228
+ ' SET i.thesis = $thesis,',
229
+ ' i.breakthrough_score = $breakthrough_score',
230
+ 'MERGE (d)-[:DISCOVERED]->(rs)',
231
+ 'MERGE (rs)-[:DERIVED_FROM]->(i)',
232
+ 'MERGE (d)-[:ENABLES]->(i)',
233
+ ].join('\n');
234
+
235
+ const CONTEXT_CYPHER = [
236
+ CORE_CYPHER,
237
+ '',
238
+ '// Paper nodes (UNWIND $papers)',
239
+ 'WITH d',
240
+ 'UNWIND $papers AS p',
241
+ ' MERGE (paper:Paper {id: p.id})',
242
+ ' SET paper.title = p.title,',
243
+ ' paper.doi = p.doi,',
244
+ ' paper.source = p.source',
245
+ ' MERGE (d)-[:DERIVED_FROM]->(paper)',
246
+ '',
247
+ '// Author + Institution nodes (UNWIND $experts)',
248
+ 'WITH d',
249
+ 'UNWIND $experts AS e',
250
+ ' MERGE (a:Author {name_orcid_key: e.name + \'|\' + coalesce(e.orcid, \'__no_orcid__\')})',
251
+ ' SET a.name = e.name,',
252
+ ' a.orcid = e.orcid,',
253
+ ' a.h_index_estimate = e.h_index_estimate',
254
+ ' WITH a, e',
255
+ ' WHERE e.institution IS NOT NULL',
256
+ ' MERGE (inst:Institution {name: e.institution})',
257
+ ' MERGE (a)-[:AFFILIATED_WITH]->(inst)',
258
+ '',
259
+ '// AUTHORED_BY edges (UNWIND $paper_author_pairs)',
260
+ 'WITH 1 AS _step',
261
+ 'UNWIND $paper_author_pairs AS pa',
262
+ ' MATCH (paper:Paper {id: pa.paper_id})',
263
+ ' MATCH (author:Author {name_orcid_key: pa.author_key})',
264
+ ' MERGE (paper)-[:AUTHORED_BY]->(author)',
265
+ ].join('\n');
266
+
267
+ function buildMergeCypher(hasContext) {
268
+ return hasContext ? CONTEXT_CYPHER : CORE_CYPHER;
269
+ }
270
+
271
+ // ---------- buildRollbackCypher ----------
272
+ //
273
+ // Inverse DELETE for the 3 core nodes only. Shared Paper/Author/Institution
274
+ // nodes are NOT torn down by rollback because they may be referenced by
275
+ // other RSDiscoveries; only the RS-specific nodes are removed. DETACH
276
+ // ensures all incident edges are removed atomically with each node.
277
+ //
278
+ // Returned as a multi-statement string (caller can split on ';' or pass
279
+ // to driver.session().run as separate statements). Format mirrors the
280
+ // schema exactly so callers can journal verbatim for manual rollback.
281
+
282
+ function buildRollbackCypher(ids) {
283
+ return [
284
+ 'DETACH DELETE (d:RSDiscovery {id: "' + ids.discovery_id + '"});',
285
+ 'DETACH DELETE (rs:ReverseSalient {id: "' + ids.rs_id + '"});',
286
+ 'DETACH DELETE (i:Innovation {id: "' + ids.innovation_id + '"});',
287
+ ].join('\n');
288
+ }
289
+
290
+ // ---------- writeDiscovery ----------
291
+ //
292
+ // The public entry point. Orchestration:
293
+ // 1. Validate pair shape (throws TypeError on missing required field)
294
+ // 2. Validate opts.driver presence (throws TypeError if absent)
295
+ // 3. Build deterministic ids (sha256-derived)
296
+ // 4. Build Cypher params (includes paper_author_pairs always)
297
+ // 5. Run auditQueryObject pre-write (Canon Part 8 defense-in-depth;
298
+ // throws ExternalEgressViolation on FORBIDDEN_PATTERNS hit; covers
299
+ // UNWIND inputs via JSON.stringify walk)
300
+ // 6. Build Cypher (core OR core+context)
301
+ // 7. session.run(cypher, params); catch ConnectionError; throw
302
+ // AuraUnreachableError on backend failure (clean tier-dispatch signal)
303
+ // 8. Return {wrote_node_count, wrote_edge_count, rollback_cypher,
304
+ // aura_op_id, schema_version}
305
+
306
+ async function writeDiscovery(pair, opts) {
307
+ opts = opts || {};
308
+ validateRequiredFields(pair);
309
+
310
+ if (!opts.driver || typeof opts.driver.session !== 'function') {
311
+ throw new TypeError(SURFACE + ': opts.driver required (call rs-output-dispatch from Plan 89.3-05 if you need tier auto-resolution)');
312
+ }
313
+
314
+ const ids = buildDeterministicIds(pair);
315
+ const ctx = (opts.context && typeof opts.context === 'object') ? opts.context : {};
316
+ const params = buildCypherParams(pair, ctx, ids);
317
+
318
+ // Canon Part 8 defense-in-depth: audit BEFORE Cypher execution. Covers
319
+ // UNWIND inputs ($experts, $papers, $paper_author_pairs) via the
320
+ // JSON.stringify walk in auditQueryObject.
321
+ auditQueryObject(params, SURFACE);
322
+
323
+ const hasContext = (Array.isArray(ctx.papers) && ctx.papers.length > 0) ||
324
+ (Array.isArray(ctx.experts) && ctx.experts.length > 0);
325
+ const cypher = buildMergeCypher(hasContext);
326
+
327
+ const session = opts.driver.session();
328
+ let result;
329
+ try {
330
+ result = await session.run(cypher, params);
331
+ } catch (err) {
332
+ if (err instanceof ExternalEgressViolation) {
333
+ // Bubble up unchanged.
334
+ throw err;
335
+ }
336
+ throw new AuraUnreachableError(
337
+ 'Aura backend unreachable: ' + (err && err.message ? err.message : String(err)),
338
+ { original: err && err.message ? err.message : String(err) }
339
+ );
340
+ } finally {
341
+ if (session && typeof session.close === 'function') {
342
+ try {
343
+ await session.close();
344
+ } catch (_e) { /* best effort */ }
345
+ }
346
+ }
347
+
348
+ const counters = (result && result.summary && result.summary.counters) || {};
349
+ return {
350
+ wrote_node_count: typeof counters.nodesCreated === 'number' ? counters.nodesCreated : 0,
351
+ wrote_edge_count: typeof counters.relationshipsCreated === 'number' ? counters.relationshipsCreated : 0,
352
+ rollback_cypher: buildRollbackCypher(ids),
353
+ aura_op_id: generateOpId(),
354
+ schema_version: SCHEMA_VERSION,
355
+ };
356
+ }
357
+
358
+ // ---------- Edge type registry consumption ----------
359
+ //
360
+ // Defensive guard: refuse to load if the EDGE_TYPES extension Plan 89.3-01
361
+ // Task 1 shipped is missing. This guarantees the writer cannot ship
362
+ // against a stale lazygraph-ops.cjs. Non-throwing in production (warn on
363
+ // stderr) so the writer remains usable while the upstream is fixed; in
364
+ // tests this can be tightened to throw if desired.
365
+
366
+ const REQUIRED_EDGE_TYPES = ['DISCOVERED', 'DERIVED_FROM', 'ENABLES', 'AUTHORED_BY', 'AFFILIATED_WITH'];
367
+ for (const t of REQUIRED_EDGE_TYPES) {
368
+ if (!EDGE_TYPES.includes(t)) {
369
+ process.stderr.write(SURFACE + ': WARNING -- EDGE_TYPES missing required type: ' + t + '\n');
370
+ }
371
+ }
372
+
373
+ // ---------- Exports ----------
374
+
375
+ module.exports = {
376
+ writeDiscovery,
377
+ AuraUnreachableError,
378
+ SCHEMA_VERSION,
379
+ REQUIRED_FIELDS,
380
+ _test: {
381
+ buildDeterministicIds,
382
+ generateOpId,
383
+ buildCypherParams,
384
+ buildMergeCypher,
385
+ buildRollbackCypher,
386
+ validateRequiredFields,
387
+ },
388
+ };