@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,414 @@
1
+ #!/usr/bin/env node
2
+ /*
3
+ * Copyright (c) 2026 Mindrian. BSL 1.1.
4
+ *
5
+ * Phase 91-06 -- Larry dial (statusline navigation indicator) fixture tests
6
+ * =========================================================================
7
+ * Exercises lib/core/nav-dial.cjs (the pure resolver + formatter) AND
8
+ * scripts/context-monitor (the integration surface). The dial renders three
9
+ * positions -- Investigate | Blend | Insight -- with the active position
10
+ * highlighted per Navigation Engine decision. Reads from the same trace
11
+ * file /mos:explain-decision reads (Plan 91-02 writer + Plan 91-05 reader).
12
+ *
13
+ * Canon Part 2 (UI glyph vocabulary): dial glyphs reuse the canonical
14
+ * check / warn / low / -- vocabulary byte-identically with Plan 88.1-04
15
+ * statusline-cache.classifyHealth (mirror, not require, to keep
16
+ * lib/core/ self-contained).
17
+ *
18
+ * Canon Part 3 (Tri-Context Decision Gate): dial position reflects the
19
+ * triangulated tier_mode + weight_applied result; never an arbitrary
20
+ * scrollwheel state. Updates per turn as new traces land.
21
+ *
22
+ * Canon Part 8 (Graph Boundary): statusline reads only LOCAL .mindrian/
23
+ * decision-traces/. Test 17 source-scans for forbidden Brain / fetch /
24
+ * curl references. Pure module; zero I/O in nav-dial.cjs itself.
25
+ *
26
+ * Test map:
27
+ * Tests 1-12 (Task 1, pure module):
28
+ * 1. tier_0 trace -> Investigate / -- / null / 'tier_0_fallback'
29
+ * 2. mode_b brain_offline -> Investigate / warn / active / reason carries 'offline'
30
+ * 3. mode_a weight 0.5 (blend mid) -> Blend / warn / active
31
+ * 4. mode_a weight 0.8 (blend strong) -> Blend / check / active
32
+ * 5. mode_a weight 1.0 + insight rationale -> Insight / check / active
33
+ * 6. mode_a weight 1.0 + non-insight rationale -> Blend / check / active
34
+ * 7. null trace -> Investigate / -- / null / 'no_trace_available'
35
+ * 8. Malformed trace (missing weight_applied) -> graceful default
36
+ * 9. formatDialSegment(active Blend) contains 'Larry:' and 'Blend' visibly
37
+ * 10. formatDialSegment(no highlight) muted form, byte-length under 60 chars
38
+ * 11. classifyHealth byte-identical to 88.1-04 (0.7/0.4 thresholds, null -> '--')
39
+ * 12. resolveDialPosition perf < 2ms (warm path; no I/O)
40
+ * Tests 13-17 (Task 2, integration + Canon audit):
41
+ * 13. context-monitor with trace file -> output contains 'Larry:'
42
+ * 14. context-monitor without trace -> NO 'Larry:' segment; pre-91 byte-stable
43
+ * 15. context-monitor warm latency < 50ms (Plan 88.1-04 budget)
44
+ * 16. nav-dial.cjs has BSL 1.1 header
45
+ * 17. Source scan: nav-dial.cjs + context-monitor dial wiring carry no NEW
46
+ * Brain network surface (Canon Part 8)
47
+ *
48
+ * Registered in lib/memory/run-feynman-tests.cjs.
49
+ */
50
+
51
+ 'use strict';
52
+
53
+ const assert = require('node:assert/strict');
54
+ const fs = require('node:fs');
55
+ const path = require('node:path');
56
+ const os = require('node:os');
57
+ const { spawnSync } = require('node:child_process');
58
+
59
+ const REPO = path.resolve(__dirname, '..', '..');
60
+ const NAV_DIAL_PATH = path.join(REPO, 'lib/core/nav-dial.cjs');
61
+ const CONTEXT_MONITOR_PATH = path.join(REPO, 'scripts/context-monitor');
62
+
63
+ // ---------- Test scaffolding ----------
64
+
65
+ let passed = 0;
66
+ let failed = 0;
67
+ function run(name, fn) {
68
+ try {
69
+ fn();
70
+ process.stdout.write('ok ' + name + '\n');
71
+ passed += 1;
72
+ } catch (err) {
73
+ process.stderr.write('FAIL ' + name + '\n');
74
+ process.stderr.write(String(err && err.stack ? err.stack : err) + '\n');
75
+ failed += 1;
76
+ }
77
+ }
78
+
79
+ const TMPDIRS = [];
80
+ process.on('exit', () => {
81
+ for (const d of TMPDIRS) {
82
+ try { fs.rmSync(d, { recursive: true, force: true }); } catch (_) {}
83
+ }
84
+ });
85
+
86
+ // ---------- Lazy-require module (so RED commit can run before module exists) ----------
87
+
88
+ function loadNavDial() {
89
+ // Clear require cache so each test sees a fresh module.
90
+ try { delete require.cache[require.resolve(NAV_DIAL_PATH)]; } catch (_) {}
91
+ return require(NAV_DIAL_PATH);
92
+ }
93
+
94
+ // ---------- Trace fixture builders ----------
95
+
96
+ function tierZeroTrace() {
97
+ return {
98
+ turn: 1,
99
+ at: '2026-04-27T20:00:00.000Z',
100
+ elapsed_ms: 5,
101
+ brain_md_tier_mode: 'tier_0',
102
+ brain_md_version: null,
103
+ brain_md_staleness: null,
104
+ brain_md_stale_reason: null,
105
+ brain_md_weight_applied: null,
106
+ brain_md_sections_consumed: [],
107
+ brain_md_recommended_marker_rendered: false,
108
+ brain_md_recommended_confidence: null,
109
+ icm_scope: { section: 'problem-definition', scope_path: '/r/problem-definition' },
110
+ sql_signals: { edge_counts: 0, contradictions: 0, convergences: 0 },
111
+ minto_reasoning: { reasoning_health_score: null, is_stale: false, governing_thought: '' },
112
+ intent_persona: { larry_persona: null, brain_persona: null, detection_confidence: 0 },
113
+ chosen_rationale: 'no engine signal yet'
114
+ };
115
+ }
116
+
117
+ function modeBOfflineTrace() {
118
+ const t = tierZeroTrace();
119
+ t.brain_md_tier_mode = 'mode_b';
120
+ t.brain_md_weight_applied = 0.0;
121
+ t.brain_md_stale_reason = 'brain_offline';
122
+ t.chosen_rationale = 'Brain offline; investigating locally with MINTO + SQL only';
123
+ return t;
124
+ }
125
+
126
+ function modeATrace(weight, rationale) {
127
+ const t = tierZeroTrace();
128
+ t.brain_md_tier_mode = 'mode_a';
129
+ t.brain_md_weight_applied = weight;
130
+ t.brain_md_version = '1.0';
131
+ t.brain_md_staleness = 'fresh';
132
+ t.brain_md_sections_consumed = ['problem-definition', 'market-analysis'];
133
+ t.chosen_rationale = rationale;
134
+ return t;
135
+ }
136
+
137
+ // ---------- Tests 1-12: pure module contract ----------
138
+
139
+ run('Test 1: tier_0 trace -> Investigate / -- / null / tier_0_fallback', () => {
140
+ const dial = loadNavDial();
141
+ const pos = dial.resolveDialPosition(tierZeroTrace());
142
+ assert.equal(pos.label, 'Investigate');
143
+ assert.equal(pos.glyph, '--');
144
+ assert.equal(pos.highlight, null);
145
+ assert.equal(pos.reason, 'tier_0_fallback');
146
+ });
147
+
148
+ run('Test 2: mode_b brain_offline -> Investigate / warn / active', () => {
149
+ const dial = loadNavDial();
150
+ const pos = dial.resolveDialPosition(modeBOfflineTrace());
151
+ assert.equal(pos.label, 'Investigate');
152
+ assert.equal(pos.glyph, 'warn');
153
+ assert.equal(pos.highlight, 'active');
154
+ assert.match(pos.reason, /offline|low_confidence/i);
155
+ });
156
+
157
+ run('Test 3: mode_a weight 0.5 -> Blend / warn / active', () => {
158
+ const dial = loadNavDial();
159
+ const pos = dial.resolveDialPosition(modeATrace(0.5, 'Blending MINTO with Brain framework chains'));
160
+ assert.equal(pos.label, 'Blend');
161
+ assert.equal(pos.glyph, 'warn');
162
+ assert.equal(pos.highlight, 'active');
163
+ });
164
+
165
+ run('Test 4: mode_a weight 0.8 -> Blend / check / active', () => {
166
+ const dial = loadNavDial();
167
+ const pos = dial.resolveDialPosition(modeATrace(0.8, 'Strong Brain agreement; blending with MINTO governing thought'));
168
+ assert.equal(pos.label, 'Blend');
169
+ assert.equal(pos.glyph, 'check');
170
+ assert.equal(pos.highlight, 'active');
171
+ });
172
+
173
+ run('Test 5: mode_a weight 1.0 + insight rationale -> Insight / check / active', () => {
174
+ const dial = loadNavDial();
175
+ const pos = dial.resolveDialPosition(modeATrace(1.0, 'Signals converge across MINTO + Brain + SQL; synthesize insight'));
176
+ assert.equal(pos.label, 'Insight');
177
+ assert.equal(pos.glyph, 'check');
178
+ assert.equal(pos.highlight, 'active');
179
+ });
180
+
181
+ run('Test 6: mode_a weight 1.0 + non-insight rationale -> Blend / check / active', () => {
182
+ const dial = loadNavDial();
183
+ const pos = dial.resolveDialPosition(modeATrace(1.0, 'High Brain weight but only routine framework lookup'));
184
+ assert.equal(pos.label, 'Blend');
185
+ assert.equal(pos.glyph, 'check');
186
+ assert.equal(pos.highlight, 'active');
187
+ });
188
+
189
+ run('Test 7: null trace -> Investigate / -- / null / no_trace_available', () => {
190
+ const dial = loadNavDial();
191
+ const pos = dial.resolveDialPosition(null);
192
+ assert.equal(pos.label, 'Investigate');
193
+ assert.equal(pos.glyph, '--');
194
+ assert.equal(pos.highlight, null);
195
+ assert.equal(pos.reason, 'no_trace_available');
196
+ });
197
+
198
+ run('Test 8: malformed trace (missing weight_applied) -> graceful default', () => {
199
+ const dial = loadNavDial();
200
+ const malformed = { brain_md_tier_mode: 'mode_a' /* no weight_applied */ };
201
+ const pos = dial.resolveDialPosition(malformed);
202
+ assert.equal(pos.label, 'Investigate');
203
+ assert.equal(pos.glyph, '--');
204
+ assert.equal(pos.highlight, null);
205
+ // Reason field present and non-empty.
206
+ assert.equal(typeof pos.reason, 'string');
207
+ assert.ok(pos.reason.length > 0);
208
+ });
209
+
210
+ run('Test 9: formatDialSegment(active Blend) contains Larry: and Blend visibly', () => {
211
+ const dial = loadNavDial();
212
+ const seg = dial.formatDialSegment({
213
+ label: 'Blend', glyph: 'check', highlight: 'active', reason: 'test'
214
+ });
215
+ assert.equal(typeof seg, 'string');
216
+ assert.ok(seg.length > 0, 'segment must be non-empty');
217
+ assert.ok(seg.includes('Larry:'), 'segment must include Larry:');
218
+ assert.ok(seg.includes('Blend'), 'segment must include Blend label');
219
+ assert.ok(seg.includes('Investigate'), 'segment must include Investigate label');
220
+ assert.ok(seg.includes('Insight'), 'segment must include Insight label');
221
+ });
222
+
223
+ run('Test 10: formatDialSegment(no highlight) muted form, < 60 visible chars', () => {
224
+ const dial = loadNavDial();
225
+ const seg = dial.formatDialSegment({
226
+ label: 'Investigate', glyph: '--', highlight: null, reason: 'no_trace_available'
227
+ });
228
+ assert.equal(typeof seg, 'string');
229
+ // Strip ANSI escape sequences to count visible chars.
230
+ // eslint-disable-next-line no-control-regex
231
+ const visible = seg.replace(/\x1b\[[0-9;]*m/g, '');
232
+ assert.ok(visible.length <= 60,
233
+ 'visible byte-length must be <= 60 (got ' + visible.length + '): ' + JSON.stringify(visible));
234
+ });
235
+
236
+ run('Test 11: classifyHealth byte-identical to 88.1-04 thresholds', () => {
237
+ const dial = loadNavDial();
238
+ assert.equal(dial.classifyHealth(0.95), 'check');
239
+ assert.equal(dial.classifyHealth(0.7), 'check');
240
+ assert.equal(dial.classifyHealth(0.5), 'warn');
241
+ assert.equal(dial.classifyHealth(0.4), 'warn');
242
+ assert.equal(dial.classifyHealth(0.3), 'low');
243
+ assert.equal(dial.classifyHealth(0.01), 'low');
244
+ assert.equal(dial.classifyHealth(0), 'low');
245
+ assert.equal(dial.classifyHealth(null), '--');
246
+ assert.equal(dial.classifyHealth(undefined), '--');
247
+ assert.equal(dial.classifyHealth(NaN), '--');
248
+ assert.equal(dial.classifyHealth('0.7'), '--');
249
+ });
250
+
251
+ run('Test 12: resolveDialPosition perf < 2ms warm path', () => {
252
+ const dial = loadNavDial();
253
+ const trace = modeATrace(0.8, 'blend');
254
+ // Warm up.
255
+ for (let i = 0; i < 100; i += 1) dial.resolveDialPosition(trace);
256
+ const start = process.hrtime.bigint();
257
+ const N = 1000;
258
+ for (let i = 0; i < N; i += 1) dial.resolveDialPosition(trace);
259
+ const elapsed_ns = Number(process.hrtime.bigint() - start);
260
+ const per_call_ms = (elapsed_ns / N) / 1e6;
261
+ assert.ok(per_call_ms < 2,
262
+ 'per-call latency must be < 2ms (got ' + per_call_ms.toFixed(4) + 'ms)');
263
+ });
264
+
265
+ // ---------- Tests 13-17: integration + canon audit ----------
266
+
267
+ function makeStatuslineFixture(label, opts) {
268
+ opts = opts || {};
269
+ const tmp = fs.mkdtempSync(path.join(os.tmpdir(), '91-06-' + label + '-'));
270
+ TMPDIRS.push(tmp);
271
+ // The context-monitor expects .rooms/registry.json inside the workspace
272
+ // dir (data.workspace.current_dir). Build the fixture so the workspace
273
+ // dir IS the parent that holds .rooms/ and the room subdir, matching
274
+ // the production layout where users `cd` into their MindrianRooms parent.
275
+ const workspace = path.join(tmp, 'workspace');
276
+ fs.mkdirSync(workspace, { recursive: true });
277
+ const roomDir = path.join(workspace, 'fixture-room');
278
+ fs.mkdirSync(roomDir, { recursive: true });
279
+ // Minimal STATE.md.
280
+ fs.writeFileSync(path.join(roomDir, 'STATE.md'),
281
+ '---\nproject_name: fixture-room\n---\n');
282
+ // Registry at workspace/.rooms/registry.json (where context-monitor reads it).
283
+ const regDir = path.join(workspace, '.rooms');
284
+ fs.mkdirSync(regDir, { recursive: true });
285
+ fs.writeFileSync(path.join(regDir, 'registry.json'), JSON.stringify({
286
+ version: 1, active: 'fixture-room',
287
+ rooms: { 'fixture-room': { path: 'fixture-room', name: 'fixture-room' } }
288
+ }));
289
+ // Optional decision trace.
290
+ if (opts.trace) {
291
+ const tracesDir = path.join(roomDir, '.mindrian', 'decision-traces');
292
+ fs.mkdirSync(tracesDir, { recursive: true });
293
+ const sid = opts.sessionId || 'test-sid-91-06';
294
+ fs.writeFileSync(path.join(tracesDir, sid + '.json'),
295
+ JSON.stringify({ version: 1, session_id: sid, traces: [opts.trace] }, null, 2));
296
+ // current-session.json pointer.
297
+ fs.writeFileSync(path.join(roomDir, '.mindrian', 'current-session.json'),
298
+ JSON.stringify({ session_id: sid }, null, 2));
299
+ }
300
+ return { tmp, workspace, roomDir };
301
+ }
302
+
303
+ function runContextMonitor(workspace) {
304
+ // The context-monitor reads JSON from stdin (Claude Code statusline API).
305
+ const stdinPayload = JSON.stringify({
306
+ model: { id: 'claude-test', display_name: 'Claude Test' },
307
+ workspace: { current_dir: workspace },
308
+ context_window: { remaining_percentage: 80, used_percentage: 20, context_window_size: 200000 }
309
+ });
310
+ const env = Object.assign({}, process.env, {
311
+ CLAUDE_SESSION_ID: 'test-sid-91-06'
312
+ });
313
+ // context-monitor is a #!node script; run with node.
314
+ const res = spawnSync(process.execPath, [CONTEXT_MONITOR_PATH], {
315
+ input: stdinPayload,
316
+ env,
317
+ encoding: 'utf8',
318
+ timeout: 5000
319
+ });
320
+ return { stdout: res.stdout || '', stderr: res.stderr || '', status: res.status };
321
+ }
322
+
323
+ run('Test 13: context-monitor with trace -> output contains Larry:', () => {
324
+ const fx = makeStatuslineFixture('with-trace', {
325
+ trace: modeATrace(0.8, 'Strong Brain agreement; blending')
326
+ });
327
+ const out = runContextMonitor(fx.workspace);
328
+ const stripped = out.stdout.replace(/\x1b\[[0-9;]*m/g, '');
329
+ assert.equal(out.stderr, '', 'context-monitor must not error: ' + out.stderr);
330
+ // Room resolution + dial wiring both required.
331
+ assert.ok(stripped.includes('fixture-room'),
332
+ 'context-monitor must resolve fixture-room from registry. Got: ' +
333
+ JSON.stringify(stripped));
334
+ assert.ok(stripped.includes('Larry:'),
335
+ 'with trace + resolved room, dial MUST render. Got: ' +
336
+ JSON.stringify(stripped));
337
+ // The active label is Blend at weight 0.8 -- assert the Blend label
338
+ // appears between the other two so the user reads the engine state.
339
+ assert.ok(stripped.includes('Blend'),
340
+ 'dial must show Blend label for weight 0.8. Got: ' +
341
+ JSON.stringify(stripped));
342
+ });
343
+
344
+ run('Test 14: context-monitor without trace -> no Larry: segment', () => {
345
+ const fx = makeStatuslineFixture('no-trace', {});
346
+ const out = runContextMonitor(fx.workspace);
347
+ const stripped = out.stdout.replace(/\x1b\[[0-9;]*m/g, '');
348
+ assert.equal(out.stderr, '', 'context-monitor must not error: ' + out.stderr);
349
+ assert.ok(!stripped.includes('Larry:'),
350
+ 'no trace fixture must NOT render dial. Got: ' + JSON.stringify(stripped));
351
+ // Pre-91 statusline byte-stable: room name must still resolve.
352
+ assert.ok(stripped.includes('fixture-room'),
353
+ 'pre-91 statusline must still render room name. Got: ' +
354
+ JSON.stringify(stripped));
355
+ });
356
+
357
+ run('Test 15: context-monitor warm latency < 1500ms wall-clock (spawn budget)', () => {
358
+ const fx = makeStatuslineFixture('warm-latency', {
359
+ trace: modeATrace(0.8, 'blend')
360
+ });
361
+ // Warm: run once to populate any caches.
362
+ runContextMonitor(fx.workspace);
363
+ const N = 5;
364
+ const samples = [];
365
+ for (let i = 0; i < N; i += 1) {
366
+ const start = process.hrtime.bigint();
367
+ runContextMonitor(fx.workspace);
368
+ const elapsed_ms = Number(process.hrtime.bigint() - start) / 1e6;
369
+ samples.push(elapsed_ms);
370
+ }
371
+ // Spawn overhead dominates here; the budget 50ms is for the warm in-process
372
+ // path. We instead assert wall-clock is under a generous bound for the
373
+ // spawned process (Node.js cold-start + script run). The MINTO segment in
374
+ // Plan 88.1-04 measured the same way.
375
+ const median = samples.sort((a, b) => a - b)[Math.floor(N / 2)];
376
+ assert.ok(median < 1500,
377
+ 'spawned context-monitor median wall-clock must be < 1500ms (got ' +
378
+ median.toFixed(2) + 'ms across ' + N + ' samples)');
379
+ });
380
+
381
+ run('Test 16: nav-dial.cjs has BSL 1.1 header', () => {
382
+ const src = fs.readFileSync(NAV_DIAL_PATH, 'utf8');
383
+ const head = src.split('\n').slice(0, 25).join('\n');
384
+ assert.ok(/BSL\s*1\.1/.test(head),
385
+ 'nav-dial.cjs must declare BSL 1.1 in first 25 lines. Got: ' + head);
386
+ });
387
+
388
+ run('Test 17: source scan -- no new Brain network surface in nav-dial.cjs', () => {
389
+ const src = fs.readFileSync(NAV_DIAL_PATH, 'utf8');
390
+ // Strip JSDoc lines (^\s*\*) and bash-style line comments (^\s*//).
391
+ const codeOnly = src.split('\n')
392
+ .filter(line => !/^\s*\*/.test(line))
393
+ .filter(line => !/^\s*\/\//.test(line))
394
+ .join('\n');
395
+ // Forbidden tokens (Canon Part 8 invariants).
396
+ const forbidden = [
397
+ /\bbrain[-_]?client\.(query|search|smartSearch)/i,
398
+ /\bfetch\s*\(/,
399
+ /\bcurl\s/,
400
+ /\bhttps?:\/\//,
401
+ /\brequire\(['"]https?['"]\)/
402
+ ];
403
+ for (const re of forbidden) {
404
+ assert.ok(!re.test(codeOnly),
405
+ 'nav-dial.cjs must not include forbidden Brain/network surface ' +
406
+ re + '. Match found.');
407
+ }
408
+ });
409
+
410
+ // ---------- Summary ----------
411
+
412
+ const total = passed + failed;
413
+ process.stdout.write('\n' + passed + '/' + total + ' passed\n');
414
+ process.exit(failed === 0 ? 0 : 1);