@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,82 @@
1
+ 'use strict';
2
+ // Phase 109-08 Brain Result Ingestion. Per CONTEXT D-07 + RESEARCH section 8.
3
+ // Canon Part 9 LOAD-BEARING: Brain CAN'T write trusted memory.
4
+ // Every brain_insight row: created_by='brain', review_status='proposed', confirmed_by NULL.
5
+ //
6
+ // Per RESEARCH section 8.1: BEGIN/COMMIT/ROLLBACK transaction; partial failures roll back.
7
+ // Per RESEARCH section 8.3: ONE brain_suggestion_received memory_event per ingestion call,
8
+ // not one per insight. The event's review_status='confirmed' because it records a fact
9
+ // about what happened; created_by='system' because the ingestion code wrote it (not Brain).
10
+ // Per Phase 108 PROVENANCE.md L79-89: post-ingestion the canonical invariant SQL query
11
+ // SELECT id, type, source_path, created_by, confirmed_by FROM nodes
12
+ // WHERE review_status = 'confirmed' AND (confirmed_by IS NULL OR confirmed_by != 'user')
13
+ // MUST NOT return any brain_insight rows. brain_insight nodes are 'proposed', so they
14
+ // trivially satisfy the invariant.
15
+
16
+ const { logEvent } = require('./memory-events.cjs');
17
+
18
+ function isPlainObject(v) {
19
+ return typeof v === 'object' && v !== null && !Array.isArray(v);
20
+ }
21
+
22
+ function storeBrainSuggestions(db, packetResult, sessionId) {
23
+ if (!isPlainObject(packetResult) || !Array.isArray(packetResult.suggestions) || packetResult.suggestions.length === 0) {
24
+ return { ok: false, reason: 'no_suggestions' };
25
+ }
26
+ const jobId = packetResult.job_id || 'unknown_job';
27
+ const insightIds = [];
28
+ db.exec('BEGIN');
29
+ try {
30
+ for (const sug of packetResult.suggestions) {
31
+ const suggestionJobId = sug.job_id || jobId;
32
+ const suggestionIndex = (sug.suggestion_index !== undefined && sug.suggestion_index !== null) ? sug.suggestion_index : insightIds.length;
33
+ const insightId = 'brain_insight:' + suggestionJobId + ':' + suggestionIndex;
34
+ const propsJson = JSON.stringify({
35
+ summary: typeof sug.summary === 'string' ? sug.summary : '',
36
+ methodology: typeof sug.methodology === 'string' ? sug.methodology : null,
37
+ body: typeof sug.body === 'string' ? sug.body : '',
38
+ });
39
+ const sourcePath = 'brain:job:' + suggestionJobId;
40
+ const confidence = typeof sug.confidence === 'number' ? sug.confidence : 0.5;
41
+ const nowMs = Date.now();
42
+ db.prepare(
43
+ "INSERT INTO nodes (id, type, properties, source_path, created_by, confidence, review_status, created_at, last_seen_at) " +
44
+ "VALUES (?, 'brain_insight', ?, ?, 'brain', ?, 'proposed', ?, ?)"
45
+ ).run(insightId, propsJson, sourcePath, confidence, nowMs, nowMs);
46
+ insightIds.push(insightId);
47
+
48
+ if (Array.isArray(sug.graph_updates_proposed)) {
49
+ for (const ep of sug.graph_updates_proposed) {
50
+ if (!ep || typeof ep.source !== 'string' || typeof ep.target !== 'string' || typeof ep.type !== 'string') continue;
51
+ const edgeProps = JSON.stringify({
52
+ confidence: typeof ep.confidence === 'number' ? ep.confidence : 0.5,
53
+ review_status: 'proposed',
54
+ created_by: 'brain',
55
+ });
56
+ db.prepare("INSERT OR IGNORE INTO edges (source, target, type, properties) VALUES (?, ?, ?, ?)").run(ep.source, ep.target, ep.type, edgeProps);
57
+ }
58
+ }
59
+ }
60
+
61
+ // ONE memory_event per ingestion call (NOT one per insight; per RESEARCH section 8.3).
62
+ const evRes = logEvent(db, 'brain_suggestion_received', {
63
+ session_id: sessionId,
64
+ insight_ids: insightIds,
65
+ job_id: jobId,
66
+ source_path: 'session:' + sessionId,
67
+ created_by: 'system',
68
+ });
69
+ if (!evRes.ok) {
70
+ db.exec('ROLLBACK');
71
+ return { ok: false, reason: 'event_log_failed:' + evRes.reason };
72
+ }
73
+
74
+ db.exec('COMMIT');
75
+ return { ok: true, insightIds, eventId: evRes.eventId };
76
+ } catch (err) {
77
+ try { db.exec('ROLLBACK'); } catch (_rb) { /* ignore */ }
78
+ return { ok: false, reason: err.message };
79
+ }
80
+ }
81
+
82
+ module.exports = { storeBrainSuggestions };
@@ -0,0 +1,350 @@
1
+ 'use strict';
2
+ // Phase 109-05 insight query primitives. 6 of the 7; findRecentChanges lives in memory-events.cjs.
3
+ //
4
+ // Per RESEARCH section 2.5: each query is a single SELECT (with one CTE for findBlockingAssumptions)
5
+ // plus templated explanation rendering. ZERO LLM in the loop. Pure SQL on the local room.db.
6
+ //
7
+ // Per RESEARCH section 11.1 SUPPORTS vs ENABLES: shipped as SEPARATE edge types. findUnsupportedClaims
8
+ // uses a single edge-type filter (NOT EXISTS edge of type 'SUPPORTS'); ENABLES does not satisfy it.
9
+ // Per RESEARCH section 11.2 CausalClaim subsumption: findUnsupportedClaims accepts BOTH type='claim'
10
+ // AND type='CausalClaim' rows via UNION across types (forward-compat with future single-type fold).
11
+ //
12
+ // Canon Part 5: findUnsupportedClaims surfaces missing SUPPORTS edges; findStaleDecisions surfaces
13
+ // decisions older than 30 days; the queries make the evidence bar legible.
14
+ // Canon Part 7: lives under lib/core/navigation/ subdirectory; the chokepoint module navigation.cjs
15
+ // re-exports.
16
+ // Canon Part 8: zero Brain queries; pure SQL on the local room.db.
17
+ // Canon Part 9: SELECT supersedes folder scanning; templated explanation renders the typed edge
18
+ // labels as the explanation substrate.
19
+
20
+ const path = require('node:path');
21
+ const { getNeighborhood } = require('./neighborhood.cjs');
22
+ const { renderExplanation } = require('./explanation.cjs');
23
+
24
+ function loadJtbd(roomDir, mocks) {
25
+ if (mocks && mocks.jtbd) return mocks.jtbd;
26
+ try {
27
+ return require(path.resolve(__dirname, '..', '..', 'hmi', 'jtbd-state.cjs'));
28
+ } catch (_) {
29
+ return null;
30
+ }
31
+ }
32
+
33
+ function jaccard(a, b) {
34
+ const setA = new Set(Array.isArray(a) ? a : []);
35
+ const setB = new Set(Array.isArray(b) ? b : []);
36
+ if (setA.size === 0 && setB.size === 0) return 0;
37
+ let inter = 0;
38
+ for (const x of setA) if (setB.has(x)) inter++;
39
+ const union = setA.size + setB.size - inter;
40
+ return union === 0 ? 0 : inter / union;
41
+ }
42
+
43
+ function findContradictions(db, focusNodeId) {
44
+ const exists = db.prepare('SELECT 1 AS x FROM nodes WHERE id = ?').get(focusNodeId);
45
+ if (!exists) return [];
46
+ // Walk the neighborhood; collect node ids reachable from focus.
47
+ const neighbors = getNeighborhood(db, focusNodeId, { maxDepth: 2, topK: 200 });
48
+ const reachable = new Set([focusNodeId]);
49
+ for (const n of neighbors) reachable.add(n.id);
50
+ // Find edges of type CONTRADICTS where both endpoints are in the reachable set.
51
+ const ids = Array.from(reachable);
52
+ const placeholders = ids.map(() => '?').join(',');
53
+ const rows = db.prepare(
54
+ "SELECT e.source AS s, e.target AS t, n_a.type AS s_type, n_b.type AS t_type "
55
+ + "FROM edges e "
56
+ + "JOIN nodes n_a ON n_a.id = e.source "
57
+ + "JOIN nodes n_b ON n_b.id = e.target "
58
+ + "WHERE e.type = 'CONTRADICTS' AND e.source IN (" + placeholders + ") AND e.target IN (" + placeholders + ")"
59
+ ).all(...ids, ...ids);
60
+ return rows.map((row) => ({
61
+ claimA: { id: row.s, type: row.s_type },
62
+ claimB: { id: row.t, type: row.t_type },
63
+ edgePath: [row.s, row.t],
64
+ explanation: renderExplanation('contradiction', { claimA: row.s, claimB: row.t, depth: 1 }),
65
+ }));
66
+ }
67
+
68
+ function findUnsupportedClaims(db, roomId) {
69
+ // Per RESEARCH section 11.2 CausalClaim subsumption: UNION across both types.
70
+ // Per RESEARCH section 11.1 SUPPORTS-only filter: NOT EXISTS edge of type SUPPORTS.
71
+ const rows = db.prepare(
72
+ "SELECT n.id, n.type, n.source_path, n.review_status, n.last_seen_at "
73
+ + "FROM nodes n "
74
+ + "WHERE n.type IN ('claim','CausalClaim') "
75
+ + "AND n.review_status IN ('confirmed','needs_evidence') "
76
+ + "AND NOT EXISTS (SELECT 1 FROM edges e WHERE e.target = n.id AND e.type = 'SUPPORTS')"
77
+ ).all();
78
+ return rows.map((r) => ({
79
+ claim: { id: r.id, type: r.type, sourcePath: r.source_path, reviewStatus: r.review_status, lastSeenAt: r.last_seen_at },
80
+ missingEvidenceFor: r.id,
81
+ explanation: renderExplanation('unsupported', { claim: r.id, reviewStatus: r.review_status, lastSeenAt: r.last_seen_at }),
82
+ }));
83
+ }
84
+
85
+ function findBlockingAssumptions(db, goalNodeId) {
86
+ const exists = db.prepare('SELECT 1 AS x FROM nodes WHERE id = ?').get(goalNodeId);
87
+ if (!exists) return [];
88
+ // Recursive cascade: walk DEPENDS_ON + ASSUMES edges from goal upstream.
89
+ // Cascade direction: goal node has outgoing DEPENDS_ON / ASSUMES edges to assumptions.
90
+ // Walk source -> target where current cascade member is the source.
91
+ const rows = db.prepare(
92
+ "WITH RECURSIVE cascade(id, depth) AS ( "
93
+ + "SELECT ? AS id, 0 AS depth "
94
+ + "UNION ALL "
95
+ + "SELECT e.target, c.depth + 1 FROM edges e JOIN cascade c ON e.source = c.id "
96
+ + "WHERE e.type IN ('DEPENDS_ON', 'ASSUMES') AND c.depth < 5 "
97
+ + ") "
98
+ + "SELECT DISTINCT n.id, n.type, n.source_path, n.confidence, n.review_status, c.depth "
99
+ + "FROM nodes n JOIN cascade c ON c.id = n.id "
100
+ + "WHERE n.type = 'assumption' AND n.review_status IN ('proposed', 'needs_evidence')"
101
+ ).all(goalNodeId);
102
+ return rows.map((r) => ({
103
+ assumption: { id: r.id, type: r.type, sourcePath: r.source_path, confidence: r.confidence, reviewStatus: r.review_status },
104
+ blocksGoal: { id: goalNodeId },
105
+ cascadePath: [r.id, goalNodeId],
106
+ explanation: renderExplanation('blocking', { assumption: r.id, goal: goalNodeId, cascadePath: [r.id, goalNodeId] }),
107
+ }));
108
+ }
109
+
110
+ function findStaleDecisions(db, roomId, opts) {
111
+ // Per RESEARCH section 2.5 simplification: 30 days old AND review_status='confirmed'.
112
+ // The opts.staleAfterSessions parameter is preserved for API compatibility but is
113
+ // interpreted as the 30-day threshold (RESEARCH lines 540 simplification).
114
+ const thresholdMs = Date.now() - 30 * 24 * 60 * 60 * 1000;
115
+ const rows = db.prepare(
116
+ "SELECT n.id, n.type, n.source_path, n.last_seen_at, n.review_status "
117
+ + "FROM nodes n "
118
+ + "WHERE n.type = 'decision' AND n.review_status = 'confirmed' AND n.last_seen_at < ?"
119
+ ).all(thresholdMs);
120
+ return rows.map((r) => ({
121
+ decision: { id: r.id, type: r.type, sourcePath: r.source_path, reviewStatus: r.review_status },
122
+ lastSeenAt: r.last_seen_at,
123
+ explanation: renderExplanation('stale', { decision: r.id, lastSeenAt: r.last_seen_at }),
124
+ }));
125
+ }
126
+
127
+ function findOpenQuestions(db, roomId) {
128
+ const rows = db.prepare(
129
+ "SELECT n.id, n.source_path, n.created_at "
130
+ + "FROM nodes n "
131
+ + "WHERE n.type = 'open_question' "
132
+ + "AND n.review_status IN ('proposed', 'confirmed') "
133
+ + "AND NOT EXISTS (SELECT 1 FROM edges e WHERE e.target = n.id AND e.type IN ('SUPPORTS', 'EVIDENCES'))"
134
+ ).all();
135
+ return rows.map((r) => ({
136
+ question: { id: r.id, sourcePath: r.source_path, createdAt: r.created_at },
137
+ createdAt: r.created_at,
138
+ explanation: renderExplanation('open', { question: r.id, createdAt: r.created_at }),
139
+ }));
140
+ }
141
+
142
+ function hsiBand(score) {
143
+ const s = Number(score) || 0;
144
+ if (s >= 70) return 'high';
145
+ if (s >= 40) return 'medium';
146
+ return 'low';
147
+ }
148
+
149
+ function findRelevantOpportunities(db, focusNodeId, opts) {
150
+ const options = opts || {};
151
+ const topK = Number.isInteger(options.topK) && options.topK > 0 ? options.topK : 5;
152
+ const wHsi = typeof options.weightHsi === 'number' ? options.weightHsi : 0.5;
153
+ const wDist = typeof options.weightDistance === 'number' ? options.weightDistance : 0.3;
154
+ const wJtbd = typeof options.weightJtbd === 'number' ? options.weightJtbd : 0.2;
155
+ const exists = db.prepare('SELECT 1 AS x FROM nodes WHERE id = ?').get(focusNodeId);
156
+ if (!exists) return [];
157
+
158
+ const neighbors = getNeighborhood(db, focusNodeId, { maxDepth: 3, topK: 200 });
159
+ const distMap = new Map();
160
+ for (const n of neighbors) {
161
+ if (n.type === 'opportunity') distMap.set(n.id, n.depth);
162
+ }
163
+
164
+ // Also include any opportunity nodes room-wide; the Opportunity Bank is "always ambient"
165
+ // per Canon Part 2 so we score every opportunity, not just neighborhood-reachable ones.
166
+ // Distance falls back to a high depth penalty when the opportunity is not in the neighborhood.
167
+ const allOpps = db.prepare(
168
+ "SELECT id, "
169
+ + "json_extract(properties, '$.hsi_score') AS hsi_score, "
170
+ + "json_extract(properties, '$.tags') AS tags_json, "
171
+ + "source_path, review_status "
172
+ + "FROM nodes WHERE type = 'opportunity' AND review_status IN ('proposed','confirmed','validated')"
173
+ ).all();
174
+
175
+ // Per Plan 109-02 focus.cjs precedent: jtbd is read via getCurrent and the test mock returns
176
+ // { current: { id, tags } }. The real jtbd-state.cjs requires a roomDir; when no _mocks seam
177
+ // is provided AND no roomDir is configured (the common navigation API call shape), we treat
178
+ // active JTBD as absent (jtbdScore = 0 across the board) rather than crash on path.join(null).
179
+ const roomDir = typeof options.roomDir === 'string' ? options.roomDir : null;
180
+ const jtbdMod = loadJtbd(roomDir, options._mocks);
181
+ let jtbd = null;
182
+ if (jtbdMod && (options._mocks && options._mocks.jtbd || roomDir)) {
183
+ try {
184
+ jtbd = jtbdMod.getCurrent(roomDir);
185
+ } catch (_) {
186
+ jtbd = null;
187
+ }
188
+ }
189
+ const activeTags = jtbd && jtbd.current && Array.isArray(jtbd.current.tags) ? jtbd.current.tags : [];
190
+
191
+ const ranked = allOpps.map((row) => {
192
+ const tags = row.tags_json ? JSON.parse(row.tags_json) : [];
193
+ const hsi = (Number(row.hsi_score) || 0) / 100;
194
+ const depth = distMap.has(row.id) ? distMap.get(row.id) : 99;
195
+ const distScore = 1.0 / (1 + depth);
196
+ const jtbdScore = activeTags.length > 0 ? jaccard(activeTags, tags) : 0;
197
+ const composite = wHsi * hsi + wDist * distScore + wJtbd * jtbdScore;
198
+ return {
199
+ opportunityId: row.id,
200
+ hsiScore: Number(row.hsi_score) || 0,
201
+ graphDistance: depth,
202
+ jtbdMatch: jtbdScore,
203
+ compositeScore: Math.round(composite * 1000) / 1000,
204
+ tags,
205
+ sourcePath: row.source_path,
206
+ explanation: renderExplanation('opportunity', { opportunityId: row.id, hsiBand: hsiBand(row.hsi_score), jtbdMatch: jtbdScore, depth }),
207
+ };
208
+ });
209
+ ranked.sort((a, b) => b.compositeScore - a.compositeScore);
210
+ return ranked.slice(0, topK);
211
+ }
212
+
213
+ /**
214
+ * Phase 116-01 Wave 1 -- room-wide tension candidate query joining JSONL decay state.
215
+ *
216
+ * Returns deterministic-id candidates derived from CONTRADICTS edges (priority 1)
217
+ * with fallback to CONVERGES edges (priority 2) per CONTEXT D-03b. Filters out
218
+ * tension_ids whose JSONL state shows surfacing_count >= 3 OR state IN
219
+ * ('resolved','dropped') so a resolved or decayed tension never re-surfaces.
220
+ *
221
+ * Sync. Defensive. Returns [] on empty / missing graph or missing roomSlug.
222
+ * Reads JSONL state via lib/memory/pending-tension-store.cjs (lazy require so a
223
+ * test substituting that module in require.cache wins).
224
+ *
225
+ * Per RESEARCH OQ-1: this function lives ON the closed navigation surface
226
+ * (re-exported by lib/core/navigation.cjs) so the SessionStart hook reads
227
+ * tensions through the Phase 109 D-06 chokepoint, NOT around it.
228
+ *
229
+ * @param {import('node:sqlite').DatabaseSync} db
230
+ * @param {string} roomId preserved for API symmetry; unused in v1
231
+ * @param {object} opts
232
+ * @param {string} opts.roomSlug required for JSONL state filter
233
+ * @param {number} [opts.limit=10] max candidates returned
234
+ * @param {boolean} [opts.includeConvergence] default true (D-03b priority 2)
235
+ * @returns {Array<object>}
236
+ */
237
+ function findSurfaceableTensions(db, roomId, opts) {
238
+ const options = (opts && typeof opts === 'object') ? opts : {};
239
+ const roomSlug = (typeof options.roomSlug === 'string' && options.roomSlug.length > 0)
240
+ ? options.roomSlug
241
+ : null;
242
+ const limit = (Number.isInteger(options.limit) && options.limit > 0) ? options.limit : 10;
243
+ const includeConvergence = (options.includeConvergence !== false); // default true
244
+
245
+ if (!db || !roomSlug) return [];
246
+
247
+ // Lazy require so tests can mock pending-tension-store via require.cache.
248
+ let pendingStore = null;
249
+ try {
250
+ pendingStore = require('../../memory/pending-tension-store.cjs');
251
+ } catch (_e) {
252
+ pendingStore = null;
253
+ }
254
+
255
+ // Build excluded-id Set from JSONL state (D-03b filter).
256
+ const excluded = new Set();
257
+ if (pendingStore && typeof pendingStore.readTensions === 'function') {
258
+ try {
259
+ const entries = pendingStore.readTensions(roomSlug);
260
+ for (const e of entries) {
261
+ if (!e || typeof e.tension_id !== 'string') continue;
262
+ if (e.surfacing_count >= 3 || e.state === 'resolved' || e.state === 'dropped') {
263
+ excluded.add(e.tension_id);
264
+ }
265
+ }
266
+ } catch (_e) {
267
+ // graceful: empty exclusion set on JSONL read failure
268
+ }
269
+ }
270
+
271
+ // Deterministic id helper (re-uses pending-tension-store.computeTensionId
272
+ // when available; falls back to inline sha256 if module load failed).
273
+ const computeId = (pendingStore && typeof pendingStore.computeTensionId === 'function')
274
+ ? pendingStore.computeTensionId
275
+ : function (s, t, ty) {
276
+ return require('node:crypto')
277
+ .createHash('sha256')
278
+ .update(String(s) + '|' + String(t) + '|' + String(ty))
279
+ .digest('hex')
280
+ .slice(0, 32);
281
+ };
282
+
283
+ // SELECT helper: returns rows for a given edge type, sorted by created_at DESC.
284
+ // edges.created_at lives inside properties JSON (lazygraph schema convention);
285
+ // we use json_extract for the ORDER BY and a LEFT JOIN on nodes to fetch
286
+ // section names (source_section / source_path) for the candidate context.
287
+ function selectEdges(edgeType) {
288
+ try {
289
+ return db.prepare(
290
+ "SELECT e.rowid AS edge_id, e.source AS source_node_id, e.target AS target_node_id, " +
291
+ "e.type AS edge_type, " +
292
+ "COALESCE(json_extract(e.properties, '$.created_at'), 0) AS created_at, " +
293
+ "ns.source_path AS source_section, " +
294
+ "nt.source_path AS target_section " +
295
+ "FROM edges e " +
296
+ "LEFT JOIN nodes ns ON ns.id = e.source " +
297
+ "LEFT JOIN nodes nt ON nt.id = e.target " +
298
+ "WHERE e.type = ? " +
299
+ "ORDER BY COALESCE(json_extract(e.properties, '$.created_at'), 0) DESC " +
300
+ "LIMIT ?"
301
+ ).all(edgeType, limit * 3); // overfetch then filter
302
+ } catch (_e) {
303
+ return [];
304
+ }
305
+ }
306
+
307
+ function pushCandidates(rows, tensionType, candidates, seen) {
308
+ for (const r of rows) {
309
+ const tid = computeId(r.source_node_id, r.target_node_id, tensionType);
310
+ if (excluded.has(tid) || seen.has(tid)) continue;
311
+ seen.add(tid);
312
+ candidates.push({
313
+ tension_id: tid,
314
+ tension_type: tensionType,
315
+ source_node_id: r.source_node_id,
316
+ target_node_id: r.target_node_id,
317
+ source_section: r.source_section || '',
318
+ target_section: r.target_section || '',
319
+ edge_id: r.edge_id,
320
+ created_at: r.created_at,
321
+ });
322
+ if (candidates.length >= limit) return true;
323
+ }
324
+ return false;
325
+ }
326
+
327
+ const candidates = [];
328
+ const seen = new Set();
329
+
330
+ // Priority 1: CONTRADICTS edges DESC.
331
+ pushCandidates(selectEdges('CONTRADICTS'), 'contradiction', candidates, seen);
332
+
333
+ // Priority 2: CONVERGES edges DESC (only when CONTRADICTS yielded nothing AND
334
+ // includeConvergence is true). Per D-03b, the fallback fires only on empty.
335
+ if (candidates.length === 0 && includeConvergence) {
336
+ pushCandidates(selectEdges('CONVERGES'), 'convergence', candidates, seen);
337
+ }
338
+
339
+ return candidates;
340
+ }
341
+
342
+ module.exports = {
343
+ findContradictions,
344
+ findUnsupportedClaims,
345
+ findBlockingAssumptions,
346
+ findStaleDecisions,
347
+ findOpenQuestions,
348
+ findRelevantOpportunities,
349
+ findSurfaceableTensions,
350
+ };
@@ -0,0 +1,118 @@
1
+ 'use strict';
2
+ // Phase 109-03 memory event log primitives. Internal to lib/core/navigation/.
3
+ // Re-exported by lib/core/navigation.cjs (Plan 109-04) as findRecentChanges (closed surface).
4
+ // logEvent is internal (not in the closed 13-function surface); other navigation/* helpers
5
+ // call it directly. Plan 109-02 setFocus writes focus_changed events inline (predates this
6
+ // plan); Plan 109-08 storeBrainSuggestions uses logEvent for brain_suggestion_received.
7
+
8
+ const crypto = require('node:crypto');
9
+
10
+ const EVENT_TYPES = Object.freeze(new Set([
11
+ 'node_created',
12
+ 'status_promoted',
13
+ 'status_rejected',
14
+ 'status_stale',
15
+ 'status_superseded',
16
+ 'focus_changed',
17
+ 'brain_query_sent',
18
+ 'brain_suggestion_received',
19
+ 'edge_added',
20
+ 'edge_removed',
21
+ 'opportunity_added',
22
+ 'opportunity_reacted',
23
+ 'opportunity_reflected',
24
+ 'opportunity_answered',
25
+ 'state_alias_migration',
26
+ // Phase 88.2-00 Wave 0 extension (D-AMEND-02 telemetry mirror, R1-safe, INTERNAL Set)
27
+ 'selector_presentation',
28
+ 'selector_response',
29
+ 'selector_rejection_captured',
30
+ 'f6_round_completed',
31
+ // Phase 89-07 Wave 0 extension (graph-native HARD RULE; ReverseSalientAgent dual-surface
32
+ // telemetry mirror per memory feedback_reverse_salient_agent_graph_native.md rule 3).
33
+ 'reverse_salient_detected',
34
+ 'reverse_salient_acted_on',
35
+ // Phase 116-00 Wave 0 extension (graph-native HARD RULE; unresolved-tension-hook
36
+ // dual-surface telemetry mirror per memory feedback_reverse_salient_agent_graph_native.md
37
+ // rule 3, mirroring the 89-07 ReverseSalientAgent pattern).
38
+ 'tension_detected',
39
+ 'tension_surfaced',
40
+ 'tension_resolved',
41
+ 'tension_decayed',
42
+ 'tension_skipped',
43
+ // Phase 117-00 Wave 0 extension (graph-native HARD RULE; auto-explore-domains
44
+ // dual-surface telemetry mirror per memory feedback_reverse_salient_agent_graph_native.md
45
+ // rule 3, mirroring the 116-00 + 89-07-00 ReverseSalientAgent extension pattern).
46
+ // Per RESEARCH §4.7 + §8.6: 4 auto_explore lifecycle events + 1 Brain-canon-drift event:
47
+ // fired (fingerprint detection -> spawn) -> finding_surfaced (drain -> F.1)
48
+ // -> user_response (Explore/Skip/Later/Free-text) OR skipped (suppression).
49
+ // brain_canon_drift_observed (FourLenses Brain vs FiveLenses Canon; emitted once per
50
+ // session by 117-05 emitBrainCanonDrift via this EVENT_TYPES string; size 31 invariant).
51
+ 'auto_explore_fired',
52
+ 'auto_explore_finding_surfaced',
53
+ 'auto_explore_user_response',
54
+ 'auto_explore_skipped',
55
+ 'auto_explore_sanitizer_hit',
56
+ 'brain_canon_drift_observed',
57
+ ]));
58
+
59
+ function isPlainObject(v) {
60
+ return typeof v === 'object' && v !== null && !Array.isArray(v);
61
+ }
62
+
63
+ function logEvent(db, eventType, payload) {
64
+ if (!EVENT_TYPES.has(eventType)) {
65
+ return { ok: false, reason: 'invalid_event_type' };
66
+ }
67
+ if (!isPlainObject(payload)) {
68
+ return { ok: false, reason: 'invalid_payload' };
69
+ }
70
+ const nowMs = Date.now();
71
+ const eventId = 'memory_event:' + eventType + ':' + nowMs + ':' + crypto.randomBytes(4).toString('hex');
72
+ // Merge event_type as top-level key (overrides any caller-supplied event_type to prevent drift).
73
+ const merged = Object.assign({}, payload, { event_type: eventType });
74
+ const propsJson = JSON.stringify(merged);
75
+ const sourcePath = typeof payload.source_path === 'string' ? payload.source_path : 'system:default';
76
+ const createdBy = typeof payload.created_by === 'string' ? payload.created_by : 'system';
77
+ try {
78
+ db.prepare(
79
+ "INSERT INTO nodes (id, type, properties, source_path, created_by, confidence, review_status, created_at, last_seen_at) " +
80
+ "VALUES (?, 'memory_event', ?, ?, ?, NULL, 'confirmed', ?, ?)"
81
+ ).run(eventId, propsJson, sourcePath, createdBy, nowMs, nowMs);
82
+ } catch (err) {
83
+ return { ok: false, reason: err.message };
84
+ }
85
+ return { ok: true, eventId };
86
+ }
87
+
88
+ function findRecentChanges(db, sinceEpochMs, opts) {
89
+ const options = opts || {};
90
+ const limit = Number.isInteger(options.limit) && options.limit > 0 ? options.limit : 100;
91
+ const eventTypeFilter = typeof options.eventType === 'string' && EVENT_TYPES.has(options.eventType) ? options.eventType : null;
92
+
93
+ let sql =
94
+ "SELECT n.id, json_extract(n.properties, '$.event_type') AS event_type, " +
95
+ "json_extract(n.properties, '$.target_node_id') AS target_node_id, " +
96
+ "n.created_at, n.source_path, n.properties " +
97
+ "FROM nodes n " +
98
+ "WHERE n.type = 'memory_event' AND n.created_at > ? ";
99
+ const params = [sinceEpochMs];
100
+ if (eventTypeFilter) {
101
+ sql += "AND json_extract(n.properties, '$.event_type') = ? ";
102
+ params.push(eventTypeFilter);
103
+ }
104
+ sql += "ORDER BY n.created_at DESC LIMIT ?";
105
+ params.push(limit);
106
+
107
+ const rows = db.prepare(sql).all(...params);
108
+ return rows.map((r) => ({
109
+ id: r.id,
110
+ eventType: r.event_type,
111
+ targetNodeId: r.target_node_id,
112
+ createdAt: r.created_at,
113
+ sourcePath: r.source_path,
114
+ properties: JSON.parse(r.properties),
115
+ }));
116
+ }
117
+
118
+ module.exports = { EVENT_TYPES, logEvent, findRecentChanges };
@@ -0,0 +1,78 @@
1
+ 'use strict';
2
+ // Phase 109-04 neighborhood retrieval. The recursive CTE per RESEARCH section 2.1.
3
+ // Frozen edge weights per CONTEXT D-02 lines 113-118.
4
+ //
5
+ // Canon Part 1: getNeighborhood IS the answer to "what is near my focus?"; the
6
+ // navigator never folder-scans again.
7
+ // Canon Part 4: typed edges drive ranking; the edge_path field carries the
8
+ // graph paths that later plans render as explanation strings.
9
+ // Canon Part 7: lives under lib/core/navigation/ subdirectory established by
10
+ // Plan 109-02; the chokepoint module navigation.cjs re-exports.
11
+ // Canon Part 9: SELECT supersedes folder scanning; this is the load-bearing
12
+ // query for the acceptance test.
13
+
14
+ const NEIGHBORHOOD_SQL = "WITH RECURSIVE neighborhood(id, type, edge_path, depth, edge_type_in, last_seen_at, confidence, source_section, review_status, created_by, source_path) AS ( "
15
+ + "SELECT n.id, n.type, json_array(n.id) AS edge_path, 0 AS depth, NULL AS edge_type_in, "
16
+ + "n.last_seen_at, n.confidence, n.source_section, n.review_status, n.created_by, n.source_path "
17
+ + "FROM nodes n WHERE n.id = :focus_node_id "
18
+ + "UNION ALL "
19
+ + "SELECT next_n.id, next_n.type, json_insert(nh.edge_path, '$[#]', next_n.id) AS edge_path, "
20
+ + "nh.depth + 1 AS depth, e.type AS edge_type_in, "
21
+ + "next_n.last_seen_at, next_n.confidence, next_n.source_section, next_n.review_status, next_n.created_by, next_n.source_path "
22
+ + "FROM neighborhood nh JOIN edges e ON e.source = nh.id JOIN nodes next_n ON next_n.id = e.target "
23
+ + "WHERE nh.depth < :max_depth "
24
+ + "AND json_array_length(nh.edge_path) < (:max_depth + 1) "
25
+ + "AND nh.id != next_n.id "
26
+ + ") "
27
+ + "SELECT id, type, edge_path, depth, edge_type_in, source_path, review_status, created_by, confidence, last_seen_at, "
28
+ + "( "
29
+ + "CASE edge_type_in "
30
+ + "WHEN 'CONTRADICTS' THEN 1.0 "
31
+ + "WHEN 'INVALIDATES' THEN 1.0 "
32
+ + "WHEN 'DEPENDS_ON' THEN 0.9 "
33
+ + "WHEN 'ASSUMES' THEN 0.9 "
34
+ + "WHEN 'SUPPORTS' THEN 0.8 "
35
+ + "WHEN 'EVIDENCES' THEN 0.8 "
36
+ + "WHEN 'INFORMS' THEN 0.6 "
37
+ + "WHEN 'ENABLES' THEN 0.6 "
38
+ + "WHEN 'CONVERGES' THEN 0.4 "
39
+ + "WHEN 'MENTIONS_ENTITY' THEN 0.4 "
40
+ + "ELSE 0.3 "
41
+ + "END * 0.4 "
42
+ + "+ MAX(0.0, MIN(1.0, 1.0 - (CAST(strftime('%s','now') AS REAL) * 1000 - last_seen_at) / (1000.0 * 60 * 60 * 24 * 90))) * 0.2 "
43
+ + "+ COALESCE(confidence, 0.5) * 0.2 "
44
+ + "+ CASE WHEN source_section = (SELECT source_section FROM nodes WHERE id = :focus_node_id) THEN 1.0 ELSE 0.0 END * 0.2 "
45
+ + ") AS score "
46
+ + "FROM neighborhood WHERE depth > 0 ORDER BY score DESC LIMIT :top_k";
47
+
48
+ function getNeighborhood(db, focusNodeId, opts) {
49
+ const options = opts || {};
50
+ const maxDepth = Number.isInteger(options.maxDepth) && options.maxDepth >= 1 ? options.maxDepth : 2;
51
+ const topK = Number.isInteger(options.topK) && options.topK > 0 ? options.topK : 20;
52
+
53
+ // Politely return [] if focus does not exist (avoids letting the CTE return base-case row with no recursion).
54
+ const exists = db.prepare("SELECT 1 AS x FROM nodes WHERE id = ?").get(focusNodeId);
55
+ if (!exists) return [];
56
+
57
+ const rows = db.prepare(NEIGHBORHOOD_SQL).all({
58
+ focus_node_id: focusNodeId,
59
+ max_depth: maxDepth,
60
+ top_k: topK,
61
+ });
62
+
63
+ return rows.map((r) => ({
64
+ id: r.id,
65
+ type: r.type,
66
+ edgePath: typeof r.edge_path === 'string' ? JSON.parse(r.edge_path) : r.edge_path,
67
+ depth: r.depth,
68
+ edgeTypeIn: r.edge_type_in,
69
+ score: r.score,
70
+ sourcePath: r.source_path,
71
+ reviewStatus: r.review_status,
72
+ createdBy: r.created_by,
73
+ confidence: r.confidence,
74
+ lastSeenAt: r.last_seen_at,
75
+ }));
76
+ }
77
+
78
+ module.exports = { getNeighborhood, NEIGHBORHOOD_SQL };