@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,264 @@
1
+ /*
2
+ * Copyright (c) 2026 Mindrian. BSL 1.1.
3
+ *
4
+ * Phase 99-02 -- conversation operator NL classifier
5
+ * ===================================================
6
+ * Heuristic, deterministic classifier. NO LLM round-trip
7
+ * (Phase 99 D-10). Same confidence threshold (transition_min_confidence
8
+ * sourced from classifier-rules.json) as Phase 100's JTBD classifier
9
+ * (D-12) -- single source of truth for "confident enough to act."
10
+ *
11
+ * Three input strata in order of weight (D-11):
12
+ * 1. Tool / command markers (weight 0.95-1.0; short-circuit)
13
+ * 2. User-message intent patterns (weight 0.3-0.7; accumulate per op)
14
+ * 3. Entity-introduction signals (weight 0.3 each; boost EXPLORE_CAPTURE)
15
+ *
16
+ * Public API:
17
+ * classify(input, currentState) -> { candidate_op, confidence, evidence, suggested_trigger }
18
+ *
19
+ * Rules externalized to lib/conversation/classifier-rules.json so the
20
+ * lexicon can be tuned without code edits. Schema documented in
21
+ * 99-02-PLAN.md task 1.
22
+ *
23
+ * Frame budget (Phase 99 D-23 corollary): classify() < 5ms target.
24
+ * Regexes pre-compiled at module load.
25
+ *
26
+ * Canon Part 8 (LOCAL ONLY):
27
+ * This module never queries Brain. Pure local string matching.
28
+ *
29
+ * Tier 0 fallback (Decision #8):
30
+ * If classifier-rules.json is missing or corrupt, classify() returns
31
+ * a null result with stratum='tier0' evidence. Never throws -- this
32
+ * is hot-path code consumed by Phase 99-04 hooks.
33
+ *
34
+ * Pure CJS, node built-ins only, zero npm dependencies (Phase 87 invariant).
35
+ *
36
+ * License: BSL 1.1.
37
+ */
38
+
39
+ 'use strict';
40
+
41
+ const fs = require('node:fs');
42
+ const path = require('node:path');
43
+ const { OPERATORS, TRIGGERS } = require('./operator.cjs');
44
+
45
+ const RULES_PATH = path.join(__dirname, 'classifier-rules.json');
46
+ const HOOK_EVENT_TO_TRIGGER = {
47
+ PostToolUse: 'hook_post_tool_use',
48
+ Stop: 'hook_stop',
49
+ SessionStart: 'session_start',
50
+ UserPromptSubmit: 'user_message',
51
+ AskUserQuestion: 'hook_post_tool_use',
52
+ };
53
+
54
+ let RULES = null;
55
+ let COMPILED = null; // { tool_markers: [{rule, matcher}], intent_patterns: [...], entity_signals: [...], thresholds }
56
+
57
+ function loadRules() {
58
+ try {
59
+ const raw = fs.readFileSync(RULES_PATH, 'utf8');
60
+ const parsed = JSON.parse(raw);
61
+ if (parsed.schema_version !== '1.0.0') {
62
+ process.stderr.write('[classifier] schema_version mismatch in ' + RULES_PATH + '\n');
63
+ process.stderr.write('[classifier] got ' + parsed.schema_version + ', expected 1.0.0\n');
64
+ process.stderr.write('[classifier] tier-0 fallback engaged\n');
65
+ return null;
66
+ }
67
+ return parsed;
68
+ } catch (e) {
69
+ process.stderr.write('[classifier] cannot load rules at ' + RULES_PATH + '\n');
70
+ process.stderr.write('[classifier] ' + e.message + '\n');
71
+ process.stderr.write('[classifier] tier-0 fallback engaged\n');
72
+ return null;
73
+ }
74
+ }
75
+
76
+ function compileRule(rule) {
77
+ const pt = rule.pattern_type;
78
+ if (pt === 'regex') return new RegExp(rule.pattern);
79
+ if (pt === 'regex_ci') return new RegExp(rule.pattern, 'i');
80
+ if (pt === 'literal') return rule.pattern; // string for indexOf
81
+ if (pt === 'literal_ci') return rule.pattern.toLowerCase(); // lowercase for indexOf on lowercased input
82
+ throw new Error('unknown pattern_type: ' + pt);
83
+ }
84
+
85
+ function compileRules(rules) {
86
+ if (!rules) return null;
87
+ const compile = (arr) => arr.map((r) => ({ rule: r, matcher: compileRule(r) }));
88
+ return {
89
+ tool_markers: compile(rules.tool_markers),
90
+ intent_patterns: compile(rules.intent_patterns),
91
+ entity_signals: compile(rules.entity_signals),
92
+ thresholds: rules.thresholds,
93
+ };
94
+ }
95
+
96
+ RULES = loadRules();
97
+ COMPILED = compileRules(RULES);
98
+
99
+ function matches(text, rule, matcher) {
100
+ if (!text) return null;
101
+ const pt = rule.pattern_type;
102
+ if (pt === 'regex' || pt === 'regex_ci') {
103
+ const m = matcher.exec(text);
104
+ return m ? m[0] : null;
105
+ }
106
+ if (pt === 'literal') {
107
+ return text.indexOf(matcher) !== -1 ? matcher : null;
108
+ }
109
+ if (pt === 'literal_ci') {
110
+ return text.toLowerCase().indexOf(matcher) !== -1 ? matcher : null;
111
+ }
112
+ return null;
113
+ }
114
+
115
+ function exceptionFires(text, rule) {
116
+ if (!rule.exceptions || !Array.isArray(rule.exceptions)) return false;
117
+ for (const ex of rule.exceptions) {
118
+ if (text && text.indexOf(ex) === 0) return true;
119
+ }
120
+ return false;
121
+ }
122
+
123
+ function tier0Result() {
124
+ return {
125
+ candidate_op: null,
126
+ confidence: 0,
127
+ evidence: [{ stratum: 'tier0', match: 'rules_unavailable', weight: 0 }],
128
+ suggested_trigger: null,
129
+ };
130
+ }
131
+
132
+ function classify(input, currentState) {
133
+ if (!COMPILED) return tier0Result();
134
+ if (!input || typeof input !== 'object') return tier0Result();
135
+
136
+ const userMessage = input.user_message || '';
137
+ const toolInvocation = input.tool_invocation || '';
138
+ const hookEvent = input.hook_event || null;
139
+ const currentOp = (currentState && currentState.current) || 'JUST_TALK';
140
+
141
+ // --- Programmatic DECISION_GATE shortcut ---
142
+ if (hookEvent === 'AskUserQuestion') {
143
+ return {
144
+ candidate_op: 'DECISION_GATE',
145
+ confidence: 1.0,
146
+ evidence: [{ stratum: 'programmatic', match: 'AskUserQuestion', weight: 1.0 }],
147
+ suggested_trigger: 'hook_post_tool_use',
148
+ };
149
+ }
150
+
151
+ // --- Stratum 1: Tool / command markers (short-circuit on match) ---
152
+ // Check tool_invocation first, then user_message starting at position 0.
153
+ const sourcesForMarkers = [];
154
+ if (toolInvocation) sourcesForMarkers.push(toolInvocation);
155
+ if (userMessage) sourcesForMarkers.push(userMessage);
156
+
157
+ for (const src of sourcesForMarkers) {
158
+ for (const item of COMPILED.tool_markers) {
159
+ const rule = item.rule;
160
+ const matcher = item.matcher;
161
+ const m = matches(src, rule, matcher);
162
+ if (!m) continue;
163
+ if (exceptionFires(src, rule)) continue;
164
+ if (rule.from_required && rule.from_required !== currentOp) continue;
165
+ // target_op === null means "matched a /mos: command but no operator change" (e.g., /mos:status, /mos:operator)
166
+ if (rule.target_op === null) {
167
+ // Stop scanning more general /mos: markers below this one (e.g. /mos:operator should
168
+ // NOT then match the general /mos:[a-z-]+ METHODOLOGY rule). Return a no-transition result.
169
+ return {
170
+ candidate_op: null,
171
+ confidence: 0,
172
+ evidence: [{ stratum: 'tool_marker', match: m, weight: 0, target_op: null, comment: rule.comment || 'no-op tool marker' }],
173
+ suggested_trigger: null,
174
+ };
175
+ }
176
+ const trigger = rule.trigger || (hookEvent ? HOOK_EVENT_TO_TRIGGER[hookEvent] : 'user_message');
177
+ return {
178
+ candidate_op: rule.target_op,
179
+ confidence: rule.weight,
180
+ evidence: [{ stratum: 'tool_marker', match: m, weight: rule.weight, target_op: rule.target_op }],
181
+ suggested_trigger: trigger,
182
+ };
183
+ }
184
+ }
185
+
186
+ // --- Stratum 2: Intent patterns (accumulate per op) ---
187
+ const scores = {}; // { JUST_TALK: 0.7, BUILD_ROOM: 0.0, ... }
188
+ const evidence = [];
189
+ for (const op of OPERATORS) scores[op] = 0;
190
+
191
+ for (const item of COMPILED.intent_patterns) {
192
+ const rule = item.rule;
193
+ const matcher = item.matcher;
194
+ const m = matches(userMessage, rule, matcher);
195
+ if (!m) continue;
196
+ if (rule.from_required && rule.from_required !== currentOp) continue;
197
+ scores[rule.target_op] = Math.min(0.95, scores[rule.target_op] + rule.weight);
198
+ evidence.push({
199
+ stratum: 'intent_pattern',
200
+ match: rule.pattern,
201
+ weight: rule.weight,
202
+ target_op: rule.target_op,
203
+ });
204
+ }
205
+
206
+ // --- Stratum 3: Entity signals (boost EXPLORE_CAPTURE / boost_op) ---
207
+ for (const item of COMPILED.entity_signals) {
208
+ const rule = item.rule;
209
+ const matcher = item.matcher;
210
+ const m = matches(userMessage, rule, matcher);
211
+ if (!m) continue;
212
+ scores[rule.boost_op] = Math.min(1.0, scores[rule.boost_op] + rule.weight);
213
+ evidence.push({
214
+ stratum: 'entity_signal',
215
+ match: m,
216
+ weight: rule.weight,
217
+ target_op: rule.boost_op,
218
+ name: rule.name,
219
+ });
220
+ }
221
+
222
+ // --- Resolve candidate ---
223
+ let bestOp = null;
224
+ let bestScore = 0;
225
+ for (const op of OPERATORS) {
226
+ if (scores[op] > bestScore) {
227
+ bestScore = scores[op];
228
+ bestOp = op;
229
+ }
230
+ }
231
+
232
+ // Same op as current -> no transition (operator.validate rejects same->same anyway).
233
+ if (bestOp === currentOp) {
234
+ return {
235
+ candidate_op: null,
236
+ confidence: bestScore,
237
+ evidence: evidence.sort((a, b) => b.weight - a.weight),
238
+ suggested_trigger: null,
239
+ };
240
+ }
241
+
242
+ if (bestScore < COMPILED.thresholds.transition_min_confidence) {
243
+ return {
244
+ candidate_op: null,
245
+ confidence: bestScore,
246
+ evidence: evidence.sort((a, b) => b.weight - a.weight),
247
+ suggested_trigger: null,
248
+ };
249
+ }
250
+
251
+ const trigger = hookEvent ? HOOK_EVENT_TO_TRIGGER[hookEvent] || 'user_message' : 'user_message';
252
+ return {
253
+ candidate_op: bestOp,
254
+ confidence: bestScore,
255
+ evidence: evidence.sort((a, b) => b.weight - a.weight),
256
+ suggested_trigger: trigger,
257
+ };
258
+ }
259
+
260
+ module.exports = {
261
+ classify,
262
+ // Internal helpers exported for testability ONLY.
263
+ _internal: { loadRules, compileRules, RULES_PATH, HOOK_EVENT_TO_TRIGGER },
264
+ };
@@ -0,0 +1,287 @@
1
+ /*
2
+ * Copyright (c) 2026 Mindrian. BSL 1.1.
3
+ *
4
+ * Phase 99-01 -- conversation operator state machine
5
+ * ===================================================
6
+ * Per-room conversation operator state primitive. Five operators
7
+ * (JUST_TALK, EXPLORE_CAPTURE, BUILD_ROOM, METHODOLOGY, DECISION_GATE)
8
+ * with 7 transition rules. State persists at
9
+ * <roomDir>/.mindrian/conversation-operator.json with schema_version
10
+ * "1.0.0". Atomic writes via mktemp + rename. Cold-start default
11
+ * JUST_TALK (Phase 99 D-04). History bounded at 50 entries with
12
+ * drop-oldest rotation (Phase 99 D-26).
13
+ *
14
+ * Every successful transition writes a typed OPERATOR_TRANSITION edge
15
+ * to the local graph (<roomDir>/.room-graph/room.db) per Canon Part 4.
16
+ * If the graph database is absent, the edge write is silently skipped;
17
+ * the state file write still succeeds (graceful degradation per
18
+ * Decision #8).
19
+ *
20
+ * Public API:
21
+ * getCurrent(roomDir) -> state object (or JUST_TALK default if file absent)
22
+ * transition(roomDir, to, trigger, contextDelta) -> { success, current, previous, entered_at } | { success: false, violations }
23
+ * validate(from, to, trigger) -> { valid: true } | { valid: false, reason }
24
+ *
25
+ * Frame budget (Phase 99 D-23, D-24):
26
+ * getCurrent < 1ms target
27
+ * transition < 5ms target
28
+ *
29
+ * Canon Part 8 (LOCAL ONLY):
30
+ * This module never queries Brain. Never writes to Brain. The
31
+ * five-operator vocabulary is generic; even if a future phase
32
+ * ever ships cross-room operator pattern queries, only the generic
33
+ * names would egress -- never user content. Phase 99 ships zero
34
+ * Brain surface.
35
+ *
36
+ * Pure CJS, node built-ins only, zero npm dependencies (Phase 87 invariant).
37
+ *
38
+ * License: BSL 1.1.
39
+ */
40
+
41
+ 'use strict';
42
+
43
+ const fs = require('node:fs');
44
+ const path = require('node:path');
45
+ const crypto = require('node:crypto');
46
+
47
+ // ---------- Constants ----------
48
+
49
+ const SCHEMA_VERSION = '1.0.0';
50
+ const OPERATORS = ['JUST_TALK', 'EXPLORE_CAPTURE', 'BUILD_ROOM', 'METHODOLOGY', 'DECISION_GATE'];
51
+ const TRIGGERS = ['session_start', 'user_message', 'mos_command', 'operator_change', 'hook_post_tool_use', 'hook_stop', 'manual_set', 'manual_reset'];
52
+ const HISTORY_MAX = 50;
53
+
54
+ // Transition rules (Phase 99 CONTEXT.md D-08).
55
+ // Format: { from: <operator>|'ANY', to: <operator>|'previous', triggers: [<allowed triggers>] }
56
+ //
57
+ // 9 rules total. The 2 ANY-source overrides (ANY -> BUILD_ROOM, ANY -> METHODOLOGY)
58
+ // were added during Phase 99 wave-1 integration (Canon Part 3 Decision-Gate verbs
59
+ // "Run Methodology" / "/mos:room <section>" are available at every gate; bypass the
60
+ // strict pedagogy progression). Plan 99-02 classifier T4 cross-check depends on
61
+ // these two rules existing.
62
+ const TRANSITION_RULES = [
63
+ { from: 'ANY', to: 'JUST_TALK', triggers: ['user_message', 'manual_set', 'manual_reset'] },
64
+ { from: 'JUST_TALK', to: 'EXPLORE_CAPTURE', triggers: ['user_message', 'manual_set'] },
65
+ { from: 'EXPLORE_CAPTURE', to: 'BUILD_ROOM', triggers: ['user_message', 'mos_command', 'manual_set'] },
66
+ { from: 'ANY', to: 'BUILD_ROOM', triggers: ['mos_command', 'user_message', 'manual_set'] },
67
+ { from: 'BUILD_ROOM', to: 'METHODOLOGY', triggers: ['mos_command', 'hook_post_tool_use', 'manual_set'] },
68
+ { from: 'ANY', to: 'METHODOLOGY', triggers: ['mos_command', 'manual_set'] },
69
+ { from: 'METHODOLOGY', to: 'BUILD_ROOM', triggers: ['mos_command', 'hook_post_tool_use', 'manual_set'] },
70
+ { from: 'ANY', to: 'DECISION_GATE', triggers: ['mos_command', 'hook_post_tool_use', 'manual_set'] },
71
+ { from: 'DECISION_GATE', to: 'previous', triggers: ['user_message', 'hook_post_tool_use', 'manual_set'] },
72
+ ];
73
+
74
+ // ---------- Validation ----------
75
+
76
+ function validate(from, to, trigger) {
77
+ if (!OPERATORS.includes(from)) {
78
+ return { valid: false, reason: `invalid 'from' operator: ${from}` };
79
+ }
80
+ if (to !== 'previous' && !OPERATORS.includes(to)) {
81
+ return { valid: false, reason: `invalid 'to' operator: ${to}` };
82
+ }
83
+ if (!TRIGGERS.includes(trigger)) {
84
+ return { valid: false, reason: `invalid trigger: ${trigger}` };
85
+ }
86
+ if (from === to) {
87
+ return { valid: false, reason: `no-op transition: ${from} -> ${to}` };
88
+ }
89
+ for (const rule of TRANSITION_RULES) {
90
+ const fromOk = rule.from === 'ANY' || rule.from === from;
91
+ const toOk = rule.to === to;
92
+ const trigOk = rule.triggers.includes(trigger);
93
+ if (fromOk && toOk && trigOk) return { valid: true };
94
+ }
95
+ return { valid: false, reason: `no rule matches: ${from} -> ${to} via ${trigger}` };
96
+ }
97
+
98
+ // ---------- State path + default ----------
99
+
100
+ function statePath(roomDir) {
101
+ return path.join(roomDir, '.mindrian', 'conversation-operator.json');
102
+ }
103
+
104
+ function defaultState(roomDir) {
105
+ return {
106
+ schema_version: SCHEMA_VERSION,
107
+ current: 'JUST_TALK',
108
+ previous: null,
109
+ entered_at: new Date().toISOString(),
110
+ context: {
111
+ active_room: path.basename(roomDir),
112
+ active_section: null,
113
+ methodology_in_flight: null,
114
+ decision_gate_pending: null,
115
+ },
116
+ history: [],
117
+ };
118
+ }
119
+
120
+ // ---------- getCurrent ----------
121
+
122
+ function getCurrent(roomDir) {
123
+ const p = statePath(roomDir);
124
+ if (!fs.existsSync(p)) return defaultState(roomDir);
125
+ let raw;
126
+ try {
127
+ raw = fs.readFileSync(p, 'utf8');
128
+ } catch (e) {
129
+ process.stderr.write(`[operator] read error at ${p}\n`);
130
+ process.stderr.write(`[operator] ${e.message}\n`);
131
+ process.stderr.write(`[operator] falling back to JUST_TALK default\n`);
132
+ return defaultState(roomDir);
133
+ }
134
+ let parsed;
135
+ try {
136
+ parsed = JSON.parse(raw);
137
+ } catch (e) {
138
+ process.stderr.write(`[operator] corrupt JSON at ${p}\n`);
139
+ process.stderr.write(`[operator] ${e.message}\n`);
140
+ process.stderr.write(`[operator] falling back to JUST_TALK default\n`);
141
+ return defaultState(roomDir);
142
+ }
143
+ if (parsed.schema_version !== SCHEMA_VERSION) {
144
+ process.stderr.write(`[operator] schema_version mismatch: got ${parsed.schema_version}, expected ${SCHEMA_VERSION}\n`);
145
+ process.stderr.write(`[operator] file ${p}\n`);
146
+ process.stderr.write(`[operator] falling back to JUST_TALK default\n`);
147
+ return defaultState(roomDir);
148
+ }
149
+ if (!OPERATORS.includes(parsed.current)) {
150
+ process.stderr.write(`[operator] invalid current operator: ${parsed.current}\n`);
151
+ process.stderr.write(`[operator] file ${p}\n`);
152
+ process.stderr.write(`[operator] falling back to JUST_TALK default\n`);
153
+ return defaultState(roomDir);
154
+ }
155
+ return parsed;
156
+ }
157
+
158
+ // ---------- Atomic write ----------
159
+
160
+ function writeStateAtomic(roomDir, state) {
161
+ const dir = path.join(roomDir, '.mindrian');
162
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
163
+ const finalPath = path.join(dir, 'conversation-operator.json');
164
+ // mktemp inside SAME directory for POSIX-atomic rename
165
+ const rand = crypto.randomBytes(6).toString('hex');
166
+ const tmpPath = path.join(dir, `.conversation-operator.json.${rand}`);
167
+ // Serialize with schema_version FIRST (D-06)
168
+ const ordered = {
169
+ schema_version: SCHEMA_VERSION,
170
+ current: state.current,
171
+ previous: state.previous,
172
+ entered_at: state.entered_at,
173
+ context: state.context,
174
+ history: state.history,
175
+ };
176
+ fs.writeFileSync(tmpPath, JSON.stringify(ordered, null, 2), 'utf8');
177
+ fs.renameSync(tmpPath, finalPath);
178
+ }
179
+
180
+ // ---------- OPERATOR_TRANSITION edge writer ----------
181
+
182
+ function writeOperatorTransitionEdge(roomDir, from, to, trigger, contextDelta) {
183
+ const graphDir = path.join(roomDir, '.room-graph');
184
+ const dbPath = path.join(graphDir, 'room.db');
185
+ if (!fs.existsSync(dbPath)) return; // graceful: no graph yet, skip
186
+ let db;
187
+ try {
188
+ // node:sqlite is available in Node 22+ (matches lib/core/lazygraph-ops.cjs).
189
+ // Phase 87 invariant: zero new runtime deps. Use node:sqlite (built-in) only.
190
+ const { DatabaseSync } = require('node:sqlite');
191
+ db = new DatabaseSync(dbPath);
192
+ } catch (_e) {
193
+ // Either node:sqlite unavailable (older Node) OR DB locked. Silent skip.
194
+ return;
195
+ }
196
+ try {
197
+ const props = JSON.stringify({
198
+ trigger,
199
+ timestamp: new Date().toISOString(),
200
+ entities_introduced: contextDelta && Array.isArray(contextDelta.entities_introduced) ? contextDelta.entities_introduced : [],
201
+ methodology: contextDelta && contextDelta.methodology_in_flight ? contextDelta.methodology_in_flight : null,
202
+ });
203
+ // Insert nodes (idempotent) before edge
204
+ const insNode = db.prepare(`INSERT OR IGNORE INTO nodes(id, type) VALUES (?, ?)`);
205
+ insNode.run(from, 'operator');
206
+ insNode.run(to, 'operator');
207
+ const stmt = db.prepare(`INSERT OR IGNORE INTO edges(source, target, type, properties) VALUES (?, ?, 'OPERATOR_TRANSITION', ?)`);
208
+ stmt.run(from, to, props);
209
+ } catch (_e) {
210
+ // Schema mismatch (e.g., older graph without nodes table) -- silent skip
211
+ } finally {
212
+ try { db.close(); } catch (_) { /* best-effort */ }
213
+ }
214
+ }
215
+
216
+ // ---------- transition ----------
217
+
218
+ function transition(roomDir, to, trigger, contextDelta = {}) {
219
+ const state = getCurrent(roomDir);
220
+ const from = state.current;
221
+
222
+ // Validate against the ORIGINAL `to` (which may be the literal string
223
+ // 'previous' for the DECISION_GATE -> previous rule per D-08). The rule
224
+ // table records `to: 'previous'` literally; resolving before validate
225
+ // would prevent the rule from matching.
226
+ const v = validate(from, to, trigger);
227
+ if (!v.valid) {
228
+ return { success: false, violations: [{ category: 'transition', severity: 'error', message: v.reason }] };
229
+ }
230
+
231
+ // Resolve `to === 'previous'` to state.previous for the actual write.
232
+ let resolvedTo = to;
233
+ if (to === 'previous') {
234
+ if (!state.previous) {
235
+ return { success: false, violations: [{ category: 'transition', severity: 'error', message: `cannot transition to 'previous': no previous operator recorded` }] };
236
+ }
237
+ resolvedTo = state.previous;
238
+ }
239
+
240
+ const now = new Date().toISOString();
241
+ const nextHistory = state.history.slice();
242
+ nextHistory.push({ op: resolvedTo, from, to: resolvedTo, trigger, ts: now });
243
+ if (nextHistory.length > HISTORY_MAX) {
244
+ nextHistory.splice(0, nextHistory.length - HISTORY_MAX); // drop-oldest (D-26)
245
+ }
246
+
247
+ const nextContext = Object.assign({}, state.context, contextDelta || {});
248
+ // Always reset active_room to current basename in case roomDir changed
249
+ nextContext.active_room = path.basename(roomDir);
250
+
251
+ const nextState = {
252
+ schema_version: SCHEMA_VERSION,
253
+ current: resolvedTo,
254
+ previous: from,
255
+ entered_at: now,
256
+ context: nextContext,
257
+ history: nextHistory,
258
+ };
259
+
260
+ try {
261
+ writeStateAtomic(roomDir, nextState);
262
+ } catch (e) {
263
+ return { success: false, violations: [{ category: 'io', severity: 'error', message: `atomic write failed: ${e.message}` }] };
264
+ }
265
+
266
+ // Best-effort graph edge write (silent on failure)
267
+ try { writeOperatorTransitionEdge(roomDir, from, resolvedTo, trigger, contextDelta); } catch (_) { /* graceful */ }
268
+
269
+ return { success: true, current: resolvedTo, previous: from, entered_at: now };
270
+ }
271
+
272
+ // ---------- Exports ----------
273
+
274
+ module.exports = {
275
+ // Public API
276
+ getCurrent,
277
+ transition,
278
+ validate,
279
+ // Constants (consumed by 99-02 classifier, 99-04 hooks, 99-05 command)
280
+ OPERATORS,
281
+ TRIGGERS,
282
+ TRANSITION_RULES,
283
+ SCHEMA_VERSION,
284
+ HISTORY_MAX,
285
+ // Internal helpers exported for testability ONLY (do not consume from production code)
286
+ _internal: { statePath, defaultState, writeStateAtomic, writeOperatorTransitionEdge },
287
+ };
@@ -0,0 +1,55 @@
1
+ 'use strict';
2
+
3
+ /*
4
+ * Phase 115 -- Owned Emotion Spec Strings (single source of truth)
5
+ * =================================================================
6
+ * Per 115-RESEARCH.md `## Pitfalls and Failure Modes` Pitfall 1 mitigation,
7
+ * every downstream surface rewrite imports from this file rather than
8
+ * hardcoding spec strings. Frozen at ship; D-20 rollback only mutates
9
+ * the per-string values, never the module shape.
10
+ *
11
+ * Sources:
12
+ * D-02..D-05 verbatim from the-owned-emotion.md `## Design implications`
13
+ * D-06..D-09 from 115-CONTEXT.md `<decisions>`
14
+ * D-17 default initialPrompt from 115-RESEARCH.md DISCRETION-02 Resolution
15
+ *
16
+ * Canon: Part 10 sub-claim 2 ("Conversation IS the surface").
17
+ *
18
+ * Hard rules (CLAUDE.md): no emoji, no em-dashes; hyphens only in copy.
19
+ * The string "can't" uses U+0027 APOSTROPHE; "Let's" uses U+0027.
20
+ * Spec strings are ASCII-7 except for the apostrophes which are U+0027.
21
+ */
22
+
23
+ const SPEC_STRINGS = Object.freeze({
24
+ // D-02 /mos:splash copy
25
+ SPLASH_COPY: "Stuck on a decision you can't name? Let's find the shape of it.",
26
+
27
+ // D-03 /mos:new-project first message
28
+ NEW_PROJECT_OPENER: "I'm Larry. What decision is stuck?",
29
+
30
+ // D-04 marketing line (also used as D-08 README hero + D-09 website hero)
31
+ MARKETING_LINE: "For founders stuck on a decision they can't name.",
32
+
33
+ // D-05 Dror 2.0 test subject criteria
34
+ DROR_TEST_CRITERIA: "a founder who is stuck on a decision right now and cannot name it.",
35
+
36
+ // D-06 / D-17 default initialPrompt (the platform-fired turn-1 string for
37
+ // agents/larry-extended.md; persona_variants.default echoes this verbatim
38
+ // per RESEARCH DISCRETION-02 resolution)
39
+ INITIAL_PROMPT_DEFAULT: "I'm Larry. What decision is stuck? (Tell me, or paste a doc/CV.)",
40
+
41
+ // D-07 /mos:onboard opening framing (lead-with-emotion paragraph; lands
42
+ // BEFORE methodology pitch in commands/onboard.md Step 1)
43
+ ONBOARD_OPENING_FRAMING: "Very simply -- if you're here, you're probably stuck on a decision you can't quite name. That's the feeling MindrianOS is built for. Let's find the shape of it together.",
44
+
45
+ // D-08 README hero tagline (alias of MARKETING_LINE; surface is the GitHub
46
+ // front door + marketplace listing source)
47
+ README_HERO_TAGLINE: "For founders stuck on a decision they can't name.",
48
+
49
+ // D-09 website hero tagline (alias of MARKETING_LINE; out-of-repo
50
+ // deliverable applied manually to ~/mindrian-website/ post-merge per
51
+ // CHANGELOG action item -- Pitfall 4)
52
+ WEBSITE_HERO_TAGLINE: "For founders stuck on a decision they can't name.",
53
+ });
54
+
55
+ module.exports = SPEC_STRINGS;
File without changes
@@ -0,0 +1,14 @@
1
+ 'use strict';
2
+ // Auto-generated by shallow-doc-parser.test.cjs. DO NOT edit by hand; the
3
+ // surface is defined to mirror lib/core/navigation.cjs as Phase 115-02
4
+ // expects to consume it (sessionId/nodeId/setBy form for setFocus,
5
+ // sessionId/eventType/payload form for recordMemoryEvent).
6
+ const calls = { setFocus: [], memoryEvents: [], getActiveFocus: [] };
7
+ function reset() { calls.setFocus.length = 0; calls.memoryEvents.length = 0; calls.getActiveFocus.length = 0; }
8
+ module.exports = {
9
+ setFocus: function (sid, nid, sb) { calls.setFocus.push({ sid: sid, nid: nid, sb: sb }); return { ok: true, eventId: 'stub-evt-' + calls.setFocus.length }; },
10
+ recordMemoryEvent: function (sid, type, payload) { calls.memoryEvents.push({ sid: sid, type: type, payload: payload }); return { ok: true, eventId: 'stub-mem-' + calls.memoryEvents.length }; },
11
+ getActiveFocus: function (sid) { calls.getActiveFocus.push({ sid: sid }); return null; },
12
+ __calls: calls,
13
+ __reset: reset,
14
+ };