@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,160 @@
1
+ /**
2
+ * MindrianOS Plugin -- Mullins Scaffold Loader (Phase 84-04)
3
+ *
4
+ * Loads the canonical Mullins 7-domain venture assessment scaffold from
5
+ * skills/mullins-scaffold/scaffold.json and exposes a small read-only API for
6
+ * callers that want to enumerate sections, fetch a single section, or test for
7
+ * existence. The scaffold is a TEMPLATE, not a mandatory skeleton: rooms that
8
+ * reference it gain structure, rooms that ignore it are structurally
9
+ * unaffected. Materialization (writing sections into a room) is deferred to
10
+ * v1.10.9; this module never touches disk and never mutates STATE.md.
11
+ *
12
+ * The scaffold JSON is loaded lazily and cached in module scope. Internal
13
+ * failures (missing file, malformed JSON) degrade to safe fallbacks ([], null,
14
+ * false) so early-hook callers cannot crash the plugin if the file is absent.
15
+ *
16
+ * Closes SCOPE-NB-01 and SCOPE-NB-02.
17
+ *
18
+ * Exports: loadScaffold, listSections, getSection, sectionExists,
19
+ * getDomainsForSection
20
+ */
21
+
22
+ 'use strict';
23
+
24
+ const fs = require('fs');
25
+ const path = require('path');
26
+
27
+ const SCAFFOLD_PATH = path.join(
28
+ __dirname,
29
+ '..',
30
+ '..',
31
+ 'skills',
32
+ 'mullins-scaffold',
33
+ 'scaffold.json'
34
+ );
35
+
36
+ let cache = null;
37
+ let loadAttempted = false;
38
+
39
+ /**
40
+ * Read and parse skills/mullins-scaffold/scaffold.json once and cache the
41
+ * result in module scope. Subsequent calls return the cached value. On any
42
+ * filesystem or JSON parse error, the cache is set to a safe empty document
43
+ * and a debug line is written to stderr; callers always receive a usable
44
+ * object shape.
45
+ *
46
+ * @returns {{version: number, generated_from: string, sections: Array<object>}}
47
+ * The parsed scaffold document, or an empty fallback document on error.
48
+ */
49
+ function loadScaffold() {
50
+ if (cache !== null) return cache;
51
+ if (loadAttempted) return cache || { version: 0, generated_from: '', sections: [] };
52
+ loadAttempted = true;
53
+ try {
54
+ const raw = fs.readFileSync(SCAFFOLD_PATH, 'utf8');
55
+ const parsed = JSON.parse(raw);
56
+ if (!parsed || !Array.isArray(parsed.sections)) {
57
+ throw new Error('scaffold.json missing sections array');
58
+ }
59
+ cache = parsed;
60
+ return cache;
61
+ } catch (err) {
62
+ if (process.env.MOS_DEBUG) {
63
+ process.stderr.write(
64
+ '[mullins-scaffold] loadScaffold failed: ' + (err && err.message) + '\n'
65
+ );
66
+ }
67
+ cache = { version: 0, generated_from: '', sections: [] };
68
+ return cache;
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Return all scaffold sections as a shallow-cloned array. Callers may mutate
74
+ * the returned array without affecting the module cache. Returns an empty
75
+ * array if the scaffold could not be loaded.
76
+ *
77
+ * @returns {Array<{id: string, domain: string, title: string, prompt: string, required: boolean}>}
78
+ */
79
+ function listSections() {
80
+ try {
81
+ const doc = loadScaffold();
82
+ if (!doc || !Array.isArray(doc.sections)) return [];
83
+ return doc.sections.map(function (s) {
84
+ return Object.assign({}, s);
85
+ });
86
+ } catch (err) {
87
+ if (process.env.MOS_DEBUG) {
88
+ process.stderr.write(
89
+ '[mullins-scaffold] listSections failed: ' + (err && err.message) + '\n'
90
+ );
91
+ }
92
+ return [];
93
+ }
94
+ }
95
+
96
+ /**
97
+ * Return a single section by its kebab-case id, or null if no such section
98
+ * exists. The returned object is a shallow clone so callers cannot mutate the
99
+ * module cache.
100
+ *
101
+ * @param {string} id - The section id (e.g. 'market-size-now').
102
+ * @returns {{id: string, domain: string, title: string, prompt: string, required: boolean}|null}
103
+ */
104
+ function getSection(id) {
105
+ try {
106
+ if (typeof id !== 'string' || id.length === 0) return null;
107
+ const doc = loadScaffold();
108
+ if (!doc || !Array.isArray(doc.sections)) return null;
109
+ const found = doc.sections.find(function (s) {
110
+ return s && s.id === id;
111
+ });
112
+ return found ? Object.assign({}, found) : null;
113
+ } catch (err) {
114
+ if (process.env.MOS_DEBUG) {
115
+ process.stderr.write(
116
+ '[mullins-scaffold] getSection failed: ' + (err && err.message) + '\n'
117
+ );
118
+ }
119
+ return null;
120
+ }
121
+ }
122
+
123
+ /**
124
+ * Test whether a section id exists in the scaffold.
125
+ *
126
+ * @param {string} id - The section id to test.
127
+ * @returns {boolean} True if a section with this id exists, false otherwise.
128
+ */
129
+ function sectionExists(id) {
130
+ try {
131
+ return getSection(id) !== null;
132
+ } catch (err) {
133
+ return false;
134
+ }
135
+ }
136
+
137
+ /**
138
+ * Return the Mullins domain string for a given section id, or null if the
139
+ * section is unknown. Useful for routing logic that wants to group artifacts
140
+ * by domain without re-parsing the scaffold.
141
+ *
142
+ * @param {string} id - The section id.
143
+ * @returns {string|null} The domain slug (e.g. 'market-attractiveness') or null.
144
+ */
145
+ function getDomainsForSection(id) {
146
+ try {
147
+ const section = getSection(id);
148
+ return section && section.domain ? section.domain : null;
149
+ } catch (err) {
150
+ return null;
151
+ }
152
+ }
153
+
154
+ module.exports = {
155
+ loadScaffold: loadScaffold,
156
+ listSections: listSections,
157
+ getSection: getSection,
158
+ sectionExists: sectionExists,
159
+ getDomainsForSection: getDomainsForSection,
160
+ };
@@ -0,0 +1,316 @@
1
+ /*
2
+ * Copyright (c) 2026 Mindrian. BSL 1.1.
3
+ *
4
+ * Phase 91-06 -- Larry dial: pure resolver + formatter for the statusline
5
+ * navigation indicator
6
+ * =======================================================================
7
+ * Pure-function module. Zero I/O. Caller (scripts/context-monitor) reads
8
+ * the latest decision-trace entry from .mindrian/decision-traces/<session>
9
+ * .json and passes it in as a plain object. This module returns the dial
10
+ * position and a formatted segment string for the statusline.
11
+ *
12
+ * Three positions: Investigate | Blend | Insight. The active position
13
+ * carries a glyph (check / warn / low / --) drawn from the Canon Part 2
14
+ * UI vocabulary, byte-identical with Plan 88.1-04 statusline-cache
15
+ * classifyHealth (mirrored here, not require'd, to keep lib/core/ self-
16
+ * contained and lib/memory/ <-> lib/core/ decoupled).
17
+ *
18
+ * Position mapping (engine-state-derived):
19
+ * - tier_0 -> Investigate / -- / null
20
+ * - mode_b OR weight < 0.3 -> Investigate / warn / active
21
+ * - mode_a + weight 0.3..0.7 -> Blend / warn / active
22
+ * - mode_a + weight 0.7..0.9 -> Blend / check / active
23
+ * - mode_a + weight >= 0.9 + insight rationale -> Insight / check / active
24
+ * - mode_a + weight >= 0.9 + non-insight -> Blend / check / active
25
+ * - null trace OR malformed -> Investigate / -- / null
26
+ *
27
+ * Insight markers: 'synthesize' | 'insight' | 'converge' (case-insensitive)
28
+ * appearing anywhere in chosen_rationale promote weight >= 0.9 from Blend
29
+ * to Insight. The keyword set is canonical to Phase 91 and matches the
30
+ * Canon Part 3 verb 'Synthesize' (collapse branches back to insight).
31
+ *
32
+ * Canon references:
33
+ * Part 2 UI glyph vocabulary -- check / warn / low / --, byte-identical
34
+ * to lib/core/statusline-cache.cjs classifyHealth (see line 94 of that
35
+ * file). Mirrored here as a 4-line function to keep this module
36
+ * dependency-free.
37
+ * Part 3 Tri-Context Decision Gate -- dial position reflects the
38
+ * triangulated tier_mode + weight_applied result; never an arbitrary
39
+ * scrollwheel state. Updates per turn as new traces land.
40
+ * Part 8 Graph Boundary -- this module performs ZERO I/O. Caller does
41
+ * all reads from .mindrian/decision-traces/<session>.json (LOCAL only).
42
+ * No fetch, no Brain client, no shell-out, no network surface.
43
+ *
44
+ * Tyler meeting quote (Canon Appendix D / Phase 91-CONTEXT R4):
45
+ * "my students almost unanimously said, 'We love the slider.'"
46
+ * The dial is pedagogically meaningful (tied to engine state), not a
47
+ * gimmick. The reason field is the audit trail; /mos:explain-decision
48
+ * surfaces the same chosen_rationale that drove the dial.
49
+ *
50
+ * API:
51
+ * resolveDialPosition(trace) -> {label, glyph, highlight, reason}
52
+ * - trace: a decision-trace entry (the last element of traces[] in
53
+ * a .mindrian/decision-traces/<session>.json file). null is allowed.
54
+ * - label: 'Investigate' | 'Blend' | 'Insight'
55
+ * - glyph: 'check' | 'warn' | 'low' | '--'
56
+ * - highlight: 'active' | null
57
+ * - reason: human-readable string explaining why this position
58
+ *
59
+ * formatDialSegment(position) -> string
60
+ * - position: object returned by resolveDialPosition
61
+ * - returns: 'Larry: Investigate | Blend | Insight' with the active
62
+ * position visually emphasized via De Stijl ANSI color codes
63
+ * (mirrors visual-ops.cjs ANSI palette without requiring it)
64
+ * - byte-budget: visible chars (ANSI-stripped) <= 60
65
+ *
66
+ * classifyHealth(score) -> 'check' | 'warn' | 'low' | '--'
67
+ * - mirror of lib/core/statusline-cache.cjs classifyHealth
68
+ * - 0.7 -> check; 0.4 -> warn; 0.0 -> low; null/NaN/string -> '--'
69
+ *
70
+ * Three-surface compatible: pure CJS, node built-ins not even used (the
71
+ * module imports nothing). Works the same on CLI + Desktop MCP + Cowork.
72
+ */
73
+
74
+ 'use strict';
75
+
76
+ // ---------- Frozen constants ----------
77
+
78
+ // Insight markers in chosen_rationale (case-insensitive).
79
+ // Synthesize: Canon Part 3 verb 7 (collapse branches back to insight).
80
+ // Converge: Canon Part 4 cross-relationship signal (3+ sections agree).
81
+ // Insight: plain English; the engine signals when it has reached one.
82
+ const INSIGHT_MARKERS = ['synthesize', 'insight', 'converge'];
83
+
84
+ // Canon Part 2 thresholds. Byte-identical to Plan 88.1-04
85
+ // statusline-cache.cjs classifyHealth (lines 94-99 of that file).
86
+ const HEALTH_CHECK_THRESHOLD = 0.7;
87
+ const HEALTH_WARN_THRESHOLD = 0.4;
88
+
89
+ // Tier-mode weight bands (Phase 91 D-04 mapping).
90
+ // weight < BLEND_FLOOR -> Investigate (low confidence band)
91
+ // BLEND_FLOOR <= weight < BLEND_STRONG -> Blend / warn
92
+ // BLEND_STRONG <= weight < INSIGHT_FLOOR -> Blend / check
93
+ // weight >= INSIGHT_FLOOR + insight markers -> Insight / check
94
+ const BLEND_FLOOR = 0.3;
95
+ const BLEND_STRONG = 0.7;
96
+ const INSIGHT_FLOOR = 0.9;
97
+
98
+ // ---------- classifyHealth (Canon Part 2 mirror) ----------
99
+ //
100
+ // Mirrors lib/core/statusline-cache.cjs classifyHealth byte-identically.
101
+ // This is the canonical glyph vocabulary across L3 surfaces (statusline,
102
+ // hook systemMessage, /mos:status, the dial). Re-mirrored instead of
103
+ // require'd so this module stays dependency-free and three-surface.
104
+ function classifyHealth(score) {
105
+ if (typeof score !== 'number' || !Number.isFinite(score)) return '--';
106
+ if (score >= HEALTH_CHECK_THRESHOLD) return 'check';
107
+ if (score >= HEALTH_WARN_THRESHOLD) return 'warn';
108
+ return 'low';
109
+ }
110
+
111
+ // ---------- resolveDialPosition ----------
112
+
113
+ /**
114
+ * Map a decision-trace entry to a dial position.
115
+ *
116
+ * The trace shape is the same one Plan 91-02 writes and Plan 91-05 reads.
117
+ * The function never throws; every malformed input falls through to the
118
+ * Investigate / -- / null default ('no_trace_available' or 'malformed').
119
+ *
120
+ * @param {object|null} trace - decision-trace entry (last of traces[])
121
+ * @returns {{label: string, glyph: string, highlight: string|null, reason: string}}
122
+ */
123
+ function resolveDialPosition(trace) {
124
+ // Null / non-object trace -> default.
125
+ if (!trace || typeof trace !== 'object') {
126
+ return {
127
+ label: 'Investigate',
128
+ glyph: '--',
129
+ highlight: null,
130
+ reason: 'no_trace_available'
131
+ };
132
+ }
133
+
134
+ const tierMode = trace.brain_md_tier_mode;
135
+ const weight = trace.brain_md_weight_applied;
136
+ const rationale = typeof trace.chosen_rationale === 'string'
137
+ ? trace.chosen_rationale
138
+ : '';
139
+
140
+ // Tier 0: pre-engine, default investigate state. No highlight (the dial
141
+ // shows three positions but none is active until the engine has spoken).
142
+ if (tierMode === 'tier_0') {
143
+ return {
144
+ label: 'Investigate',
145
+ glyph: '--',
146
+ highlight: null,
147
+ reason: 'tier_0_fallback'
148
+ };
149
+ }
150
+
151
+ // Mode B: Brain offline. Engine running on local triple only. Investigate
152
+ // with a warn glyph -- the engine has spoken, but the signal is partial.
153
+ if (tierMode === 'mode_b') {
154
+ return {
155
+ label: 'Investigate',
156
+ glyph: 'warn',
157
+ highlight: 'active',
158
+ reason: 'Brain offline; investigating locally with MINTO + SQL only'
159
+ };
160
+ }
161
+
162
+ // Mode A: full triangulation. Weight band picks the position.
163
+ if (tierMode === 'mode_a') {
164
+ if (typeof weight !== 'number' || !Number.isFinite(weight)) {
165
+ // Missing weight on a mode_a trace is malformed; soft-fail to default.
166
+ return {
167
+ label: 'Investigate',
168
+ glyph: '--',
169
+ highlight: null,
170
+ reason: 'malformed_trace_missing_weight'
171
+ };
172
+ }
173
+
174
+ // Low-confidence band: still in investigate territory.
175
+ if (weight < BLEND_FLOOR) {
176
+ return {
177
+ label: 'Investigate',
178
+ glyph: 'warn',
179
+ highlight: 'active',
180
+ reason: 'low_confidence_or_offline'
181
+ };
182
+ }
183
+
184
+ // Mid blend band: Blend with warn glyph.
185
+ if (weight < BLEND_STRONG) {
186
+ return {
187
+ label: 'Blend',
188
+ glyph: 'warn',
189
+ highlight: 'active',
190
+ reason: 'Blending MINTO + Brain at ' + weight.toFixed(2) + ' weight'
191
+ };
192
+ }
193
+
194
+ // Strong blend band: Blend with check glyph.
195
+ if (weight < INSIGHT_FLOOR) {
196
+ return {
197
+ label: 'Blend',
198
+ glyph: 'check',
199
+ highlight: 'active',
200
+ reason: 'Strong MINTO + Brain agreement, blending'
201
+ };
202
+ }
203
+
204
+ // Insight band: weight >= 0.9. Promote to Insight only when rationale
205
+ // carries insight markers. Otherwise stay in Blend / check (high
206
+ // confidence routine framework lookup, not a synthesis moment).
207
+ const lower = rationale.toLowerCase();
208
+ let isInsight = false;
209
+ for (const marker of INSIGHT_MARKERS) {
210
+ if (lower.indexOf(marker) !== -1) {
211
+ isInsight = true;
212
+ break;
213
+ }
214
+ }
215
+ if (isInsight) {
216
+ return {
217
+ label: 'Insight',
218
+ glyph: 'check',
219
+ highlight: 'active',
220
+ reason: 'Converging signals, insight mode'
221
+ };
222
+ }
223
+ return {
224
+ label: 'Blend',
225
+ glyph: 'check',
226
+ highlight: 'active',
227
+ reason: 'High confidence, blending without explicit insight marker'
228
+ };
229
+ }
230
+
231
+ // Unknown tier_mode (forward-compat with future engine modes) -> default.
232
+ return {
233
+ label: 'Investigate',
234
+ glyph: '--',
235
+ highlight: null,
236
+ reason: 'unknown_tier_mode'
237
+ };
238
+ }
239
+
240
+ // ---------- formatDialSegment ----------
241
+
242
+ // De Stijl ANSI palette (mirror of lib/core/visual-ops.cjs ANSI struct;
243
+ // duplicated here so this module imports nothing). The five colors used
244
+ // by the dial are dim/muted (inactive label), green (check), yellow
245
+ // (warn), red (low), and bold (highlight).
246
+ const ANSI = {
247
+ reset: '\x1b[0m',
248
+ bold: '\x1b[1m',
249
+ dim: '\x1b[2m',
250
+ green: '\x1b[38;2;45;107;74m', // ds-green
251
+ yellow: '\x1b[38;2;200;164;60m', // ds-yellow
252
+ red: '\x1b[38;2;166;61;47m', // ds-red
253
+ muted: '\x1b[38;2;160;154;144m' // ds-muted
254
+ };
255
+
256
+ const DIAL_LABELS = ['Investigate', 'Blend', 'Insight'];
257
+
258
+ function glyphColor(glyph) {
259
+ if (glyph === 'check') return ANSI.green;
260
+ if (glyph === 'warn') return ANSI.yellow;
261
+ if (glyph === 'low') return ANSI.red;
262
+ return ANSI.muted;
263
+ }
264
+
265
+ /**
266
+ * Render the dial segment string for the statusline.
267
+ *
268
+ * Format (no highlight): 'Larry: Investigate | Blend | Insight'
269
+ * Format (highlighted): 'Larry: Investigate | [bold]Blend[/bold] | Insight'
270
+ * plus a leading colored glyph indicator on the active label.
271
+ *
272
+ * Visible byte-length stripped of ANSI is <= 60 chars (Test 10 contract).
273
+ * The longest variant is 'Larry: Investigate | Blend | Insight' = 36 chars,
274
+ * well under the budget. Highlight does not add visible chars.
275
+ *
276
+ * @param {{label: string, glyph: string, highlight: string|null}} position
277
+ * @returns {string} the formatted segment string ('' on null/invalid input)
278
+ */
279
+ function formatDialSegment(position) {
280
+ if (!position || typeof position !== 'object') return '';
281
+ if (typeof position.label !== 'string') return '';
282
+
283
+ const labels = DIAL_LABELS.map((label) => {
284
+ if (label === position.label && position.highlight === 'active') {
285
+ // Active label: bold + glyph color so the eye lands here.
286
+ return ANSI.bold + glyphColor(position.glyph) + label + ANSI.reset;
287
+ }
288
+ // Inactive label: dim/muted.
289
+ return ANSI.dim + ANSI.muted + label + ANSI.reset;
290
+ });
291
+
292
+ // Separator between labels.
293
+ const sep = ' ' + ANSI.muted + '|' + ANSI.reset + ' ';
294
+
295
+ // 'Larry:' prefix in dim white so it doesn't compete with the active
296
+ // label for attention.
297
+ const prefix = ANSI.dim + 'Larry:' + ANSI.reset + ' ';
298
+
299
+ return prefix + labels.join(sep);
300
+ }
301
+
302
+ // ---------- Exports ----------
303
+
304
+ module.exports = {
305
+ // Pure functions.
306
+ resolveDialPosition: resolveDialPosition,
307
+ formatDialSegment: formatDialSegment,
308
+ classifyHealth: classifyHealth,
309
+ // Frozen constants (exposed for tests + future composition).
310
+ INSIGHT_MARKERS: INSIGHT_MARKERS,
311
+ HEALTH_CHECK_THRESHOLD: HEALTH_CHECK_THRESHOLD,
312
+ HEALTH_WARN_THRESHOLD: HEALTH_WARN_THRESHOLD,
313
+ BLEND_FLOOR: BLEND_FLOOR,
314
+ BLEND_STRONG: BLEND_STRONG,
315
+ INSIGHT_FLOOR: INSIGHT_FLOOR
316
+ };
@@ -0,0 +1,15 @@
1
+ # lib/core/navigation/
2
+
3
+ Phase 109 navigation spine internal helpers. Each .cjs file in this directory is an internal helper that lib/core/navigation.cjs (Plan 109-04) re-exports as part of the closed 13-function API surface.
4
+
5
+ Files:
6
+ - focus.cjs - getActiveFocus + setFocus + computeAutoFocus (Plan 109-02 / NAV-109-01)
7
+ - neighborhood.cjs - getNeighborhood recursive CTE wrapper (Plan 109-04 / NAV-109-02; not yet shipped)
8
+ - insights.cjs - 7 insight query primitives (Plan 109-05 / NAV-109-04; not yet shipped)
9
+ - packet.cjs - buildBrainPacket + storeBrainSuggestions (Plans 109-07 + 109-08 / NAV-109-06 + NAV-109-07; not yet shipped)
10
+ - room-home.cjs - getRoomHomeView composition (Plan 109-09 / NAV-109-08; not yet shipped)
11
+ - transitions.cjs - promoteNodeStatus chokepoint (Plan 109-04 / NAV-109-05; not yet shipped)
12
+
13
+ All helpers accept the open db handle as the first parameter; never call openRoomDb internally (the chokepoint module owns the lifecycle).
14
+
15
+ Owner: Phase 109 SQL Context-Memory Navigation Spine.
@@ -0,0 +1,43 @@
1
+ 'use strict';
2
+ // Phase 109-05 templated explanation renderer. ZERO LLM in the loop per RESEARCH section 2.5.
3
+ // Closed kind enum; each kind has a deterministic template using typed edge labels.
4
+ //
5
+ // Canon Part 4: every choice is graph data; explanation strings render the typed
6
+ // edge labels (CONTRADICTS, SUPPORTS, DEPENDS_ON, ENABLES, EVIDENCES) directly so
7
+ // users can read "the graph paths AS the explanation".
8
+ // Canon Part 9: ZERO LLM in the loop; the "graph paths as explanation" pattern is
9
+ // the structural substitute for prompt-generated narrative.
10
+
11
+ function shortId(id) {
12
+ if (typeof id !== 'string') return String(id);
13
+ const parts = id.split(':');
14
+ if (parts.length < 2) return id;
15
+ return parts[0] + ':' + parts.slice(1).join(':');
16
+ }
17
+
18
+ function daysSince(epochMs) {
19
+ const dms = Date.now() - epochMs;
20
+ return Math.max(0, Math.floor(dms / (24 * 60 * 60 * 1000)));
21
+ }
22
+
23
+ function renderExplanation(kind, payload) {
24
+ const p = payload || {};
25
+ switch (kind) {
26
+ case 'contradiction':
27
+ return shortId(p.claimA) + ' CONTRADICTS ' + shortId(p.claimB) + ' (depth ' + (p.depth != null ? p.depth : 1) + ')';
28
+ case 'unsupported':
29
+ return shortId(p.claim) + ' is ' + (p.reviewStatus || 'confirmed') + ' but has no SUPPORTS edge (last touched ' + daysSince(p.lastSeenAt || Date.now()) + ' days ago)';
30
+ case 'blocking':
31
+ return shortId(p.assumption) + ' blocks ' + shortId(p.goal) + ' via path ' + (Array.isArray(p.cascadePath) ? p.cascadePath.map(shortId).join(' -> ') : '');
32
+ case 'stale':
33
+ return shortId(p.decision) + ' is confirmed but has not been touched in ' + daysSince(p.lastSeenAt) + ' days';
34
+ case 'open':
35
+ return shortId(p.question) + ' has been open for ' + daysSince(p.createdAt) + ' days with no SUPPORTS or EVIDENCES edge';
36
+ case 'opportunity':
37
+ return shortId(p.opportunityId) + ' (' + (p.hsiBand || 'unknown') + ' HSI band; ' + (p.jtbdMatch > 0 ? 'matches active JTBD' : 'no JTBD overlap') + '; ' + (p.depth != null ? p.depth : '?') + ' hop(s) from focus)';
38
+ default:
39
+ return '[explanation unavailable for kind=' + kind + ']';
40
+ }
41
+ }
42
+
43
+ module.exports = { renderExplanation, shortId, daysSince };
@@ -0,0 +1,135 @@
1
+ 'use strict';
2
+ // Phase 109-02 focus helpers. Internal to lib/core/navigation/.
3
+ // Re-exported by lib/core/navigation.cjs (Plan 109-04) as the closed surface.
4
+ //
5
+ // Canon Part 1: the focus node is the wicked navigator's working-memory
6
+ // anchor. Canon Part 4: every setFocus writes a focus_changed memory_event
7
+ // (audit trail). Canon Part 9: focus persists in room.db, never in process
8
+ // memory.
9
+
10
+ const path = require('node:path');
11
+ const crypto = require('node:crypto');
12
+
13
+ const VALID_SET_BY = new Set(['user', 'larry', 'auto-from-jtbd', 'auto-from-operator', 'auto-from-state']);
14
+
15
+ function getActiveFocus(db, sessionId) {
16
+ const row = db.prepare(
17
+ "SELECT sf.session_id, sf.focus_node_id, sf.focus_type, sf.set_at, sf.set_by " +
18
+ "FROM session_focus sf " +
19
+ "WHERE sf.session_id = ?"
20
+ ).get(sessionId);
21
+ if (!row) return null;
22
+ return {
23
+ sessionId: row.session_id,
24
+ focusNodeId: row.focus_node_id,
25
+ focusType: row.focus_type,
26
+ setAt: row.set_at,
27
+ setBy: row.set_by,
28
+ };
29
+ }
30
+
31
+ function lookupNodeType(db, nodeId) {
32
+ const row = db.prepare('SELECT type FROM nodes WHERE id = ?').get(nodeId);
33
+ return row ? row.type : null;
34
+ }
35
+
36
+ function setFocus(db, sessionId, nodeId, setBy) {
37
+ if (!VALID_SET_BY.has(setBy)) {
38
+ return { ok: false, reason: 'invalid_set_by' };
39
+ }
40
+ const nodeType = lookupNodeType(db, nodeId);
41
+ if (!nodeType) {
42
+ return { ok: false, reason: 'unknown_node' };
43
+ }
44
+ // Capture previous focus for the focus_changed event payload.
45
+ const prior = getActiveFocus(db, sessionId);
46
+ const previousId = prior ? prior.focusNodeId : null;
47
+ const nowMs = Date.now();
48
+ const eventId = 'memory_event:focus_changed:' + sessionId + ':' + nowMs + ':' + crypto.randomBytes(4).toString('hex');
49
+ db.exec('BEGIN');
50
+ try {
51
+ db.prepare(
52
+ "INSERT OR REPLACE INTO session_focus (session_id, focus_node_id, focus_type, set_at, set_by) VALUES (?, ?, ?, ?, ?)"
53
+ ).run(sessionId, nodeId, nodeType, nowMs, setBy);
54
+ const props = JSON.stringify({
55
+ event_type: 'focus_changed',
56
+ session_id: sessionId,
57
+ previous_focus_node_id: previousId,
58
+ new_focus_node_id: nodeId,
59
+ set_by: setBy,
60
+ });
61
+ db.prepare(
62
+ "INSERT INTO nodes (id, type, properties, source_path, created_by, confidence, review_status, created_at, last_seen_at) " +
63
+ "VALUES (?, 'memory_event', ?, ?, 'system', NULL, 'confirmed', ?, ?)"
64
+ ).run(eventId, props, 'session:' + sessionId, nowMs, nowMs);
65
+ db.exec('COMMIT');
66
+ } catch (err) {
67
+ db.exec('ROLLBACK');
68
+ return { ok: false, reason: err.message };
69
+ }
70
+ return { ok: true, eventId };
71
+ }
72
+
73
+ function loadJtbdState(roomDir, mocks) {
74
+ if (mocks && mocks.jtbd) return mocks.jtbd;
75
+ try {
76
+ return require(path.resolve(__dirname, '..', '..', 'hmi', 'jtbd-state.cjs'));
77
+ } catch (_) {
78
+ return null;
79
+ }
80
+ }
81
+
82
+ function loadOperator(roomDir, mocks) {
83
+ if (mocks && mocks.operator) return mocks.operator;
84
+ try {
85
+ return require(path.resolve(__dirname, '..', '..', 'conversation', 'operator.cjs'));
86
+ } catch (_) {
87
+ return null;
88
+ }
89
+ }
90
+
91
+ function ensureNodeExists(db, nodeId) {
92
+ const row = db.prepare('SELECT id FROM nodes WHERE id = ?').get(nodeId);
93
+ return Boolean(row);
94
+ }
95
+
96
+ function computeAutoFocus(db, roomDir, sessionId, opts) {
97
+ const options = opts || {};
98
+ const mocks = options._mocks;
99
+ const roomId = options.roomId || (roomDir ? path.basename(roomDir) : null);
100
+
101
+ // Rule 1: active JTBD.
102
+ const jtbdMod = loadJtbdState(roomDir, mocks);
103
+ const jtbd = jtbdMod ? jtbdMod.getCurrent(roomDir) : null;
104
+ if (jtbd && jtbd.current && jtbd.current.id) {
105
+ const candidate = 'jtbd:' + jtbd.current.id;
106
+ if (ensureNodeExists(db, candidate)) {
107
+ return { focusNodeId: candidate, focusType: 'jtbd', setBy: 'auto-from-jtbd' };
108
+ }
109
+ }
110
+
111
+ // Rule 2: operator DECISION_GATE -> most recent unconfirmed decision.
112
+ const opMod = loadOperator(roomDir, mocks);
113
+ const op = opMod ? opMod.getCurrent(roomDir) : null;
114
+ if (op && op.current === 'DECISION_GATE') {
115
+ const row = db.prepare(
116
+ "SELECT id, type FROM nodes WHERE type = 'decision' AND review_status IN ('proposed','needs_evidence') ORDER BY created_at DESC LIMIT 1"
117
+ ).get();
118
+ if (row) {
119
+ return { focusNodeId: row.id, focusType: row.type, setBy: 'auto-from-operator' };
120
+ }
121
+ }
122
+
123
+ // Rule 3: room root node.
124
+ if (roomId) {
125
+ const candidate = 'room:' + roomId;
126
+ if (ensureNodeExists(db, candidate)) {
127
+ return { focusNodeId: candidate, focusType: 'room', setBy: 'auto-from-state' };
128
+ }
129
+ }
130
+
131
+ // Rule 4: cold start.
132
+ return null;
133
+ }
134
+
135
+ module.exports = { getActiveFocus, setFocus, computeAutoFocus, VALID_SET_BY };