@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,483 @@
1
+ /*
2
+ * Copyright (c) 2026 Mindrian. BSL 1.1.
3
+ * Phase 91-09 -- navigation-invariants validator test suite.
4
+ *
5
+ * Tests the registry-compatible drop-in validator that converts silent
6
+ * Phase 91 navigation failure modes into first-class health signals.
7
+ * Validator surfaces:
8
+ * INV-1 trace_missing_field (any of 8 Section 8 brain_md_* fields absent)
9
+ * INV-2 recommended_in_wrong_mode (RECOMMENDED rendered in mode_b/tier_0)
10
+ * INV-3 weight_clamp_breach (brain_md_weight_applied outside [0.0, 1.0])
11
+ * INV-4 trace_file_malformed (unparseable JSON in decision-traces dir)
12
+ * INV-5 unknown_verb_passed (fire_skill not in CANONICAL_VERBS)
13
+ *
14
+ * Plus registry compatibility (id/severity_map/scope/validate shape),
15
+ * room-scope dispatch verification through the actual guardian, and
16
+ * fail-open inheritance (a malformed sibling validator does NOT prevent
17
+ * navigation-invariants from running).
18
+ *
19
+ * Three-surface compatibility: pure CJS + node built-ins + spawnSync into
20
+ * the production guardian. No surface-specific branches.
21
+ */
22
+
23
+ 'use strict';
24
+
25
+ const assert = require('node:assert');
26
+ const crypto = require('node:crypto');
27
+ const fs = require('node:fs');
28
+ const os = require('node:os');
29
+ const path = require('node:path');
30
+ const { spawnSync } = require('node:child_process');
31
+
32
+ const REPO_ROOT = path.resolve(__dirname, '..', '..');
33
+ const VALIDATOR_PATH = path.join(REPO_ROOT, 'lib', 'memory', 'validators',
34
+ 'navigation-invariants.cjs');
35
+ const GUARDIAN_PATH = path.join(REPO_ROOT, 'scripts', 'feynman-minto-guardian.cjs');
36
+ const SHARED_PATH = path.join(REPO_ROOT, 'lib', 'core', 'navigation-engine-shared.cjs');
37
+
38
+ // Lazy-loaded validator (deleted from cache before each suite run so a
39
+ // fresh require() always reflects the latest implementation).
40
+ function loadValidator() {
41
+ delete require.cache[require.resolve(VALIDATOR_PATH)];
42
+ return require(VALIDATOR_PATH);
43
+ }
44
+
45
+ // 8 Section 8 fields per navigation-engine-brain-interface v1.
46
+ const REQUIRED_FIELDS = [
47
+ 'brain_md_version',
48
+ 'brain_md_staleness',
49
+ 'brain_md_stale_reason',
50
+ 'brain_md_weight_applied',
51
+ 'brain_md_recommended_confidence',
52
+ 'brain_md_recommended_marker_rendered',
53
+ 'brain_md_tier_mode',
54
+ 'brain_md_sections_consumed',
55
+ ];
56
+
57
+ // ----------- fixture helpers -----------
58
+
59
+ function freshRoom(label) {
60
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'nav-inv-' + label + '-'));
61
+ // Minimum: a section with ROOM.md so guardian's walkSections sees it.
62
+ const sec = path.join(dir, 'sec1');
63
+ fs.mkdirSync(sec, { recursive: true });
64
+ fs.writeFileSync(path.join(sec, 'ROOM.md'), '# sec1\n');
65
+ fs.writeFileSync(path.join(sec, 'MINTO.md'),
66
+ '---\ngoverning_thought: "stub"\n---\n\n# stub\n');
67
+ return dir;
68
+ }
69
+
70
+ function makeTrace(overrides) {
71
+ // Returns a synthetic trace ENTRY (a single element of traces[]). The
72
+ // entry shape mirrors what scripts/intent-classifier.cjs persists per
73
+ // turn -- decision_trace fields merged with turn/at metadata.
74
+ const base = {
75
+ turn: 1,
76
+ at: new Date().toISOString(),
77
+ brain_md_version: 1,
78
+ brain_md_staleness: 'fresh',
79
+ brain_md_stale_reason: null,
80
+ brain_md_weight_applied: 1.0,
81
+ brain_md_recommended_confidence: 0.85,
82
+ brain_md_recommended_marker_rendered: false,
83
+ brain_md_tier_mode: 'mode_a',
84
+ brain_md_sections_consumed: ['pattern_matches'],
85
+ icm_scope: { sectionPath: 'sec1' },
86
+ sql_signals: null,
87
+ minto_reasoning: null,
88
+ intent_persona: null,
89
+ chosen_rationale: 'stub',
90
+ };
91
+ return Object.assign(base, overrides || {});
92
+ }
93
+
94
+ function writeTraceFile(roomDir, sessionId, traces) {
95
+ const dir = path.join(roomDir, '.mindrian', 'decision-traces');
96
+ fs.mkdirSync(dir, { recursive: true });
97
+ const filePath = path.join(dir, sessionId + '.json');
98
+ const data = { version: 1, session_id: sessionId, traces: traces };
99
+ fs.writeFileSync(filePath, JSON.stringify(data, null, 2));
100
+ return filePath;
101
+ }
102
+
103
+ function ctxFor(roomDir, mode) {
104
+ return { roomDir: roomDir, kind: mode || 'session-start', now: Date.now() };
105
+ }
106
+
107
+ function rmrf(dir) {
108
+ try { fs.rmSync(dir, { recursive: true, force: true }); } catch (_) {}
109
+ }
110
+
111
+ // ----------- runner -----------
112
+
113
+ let pass = 0;
114
+ let fail = 0;
115
+ const failures = [];
116
+
117
+ function test(name, fn) {
118
+ try {
119
+ fn();
120
+ pass += 1;
121
+ process.stdout.write('PASS ' + name + '\n');
122
+ } catch (e) {
123
+ fail += 1;
124
+ failures.push({ name: name, error: e });
125
+ process.stderr.write('FAIL ' + name + '\n ' + (e && e.stack || e) + '\n');
126
+ }
127
+ }
128
+
129
+ // =====================================================================
130
+ // Test 1: validator shape contract
131
+ // =====================================================================
132
+
133
+ test('Test 1: validator exports id/severity_map/scope/validate', () => {
134
+ const v = loadValidator();
135
+ assert.equal(typeof v, 'object', 'export is object');
136
+ assert.equal(v.id, 'navigation-invariants', 'id matches');
137
+ assert.equal(v.scope, 'room', 'scope is room');
138
+ assert.equal(typeof v.validate, 'function', 'validate is function');
139
+ assert.equal(typeof v.severity_map, 'object', 'severity_map present');
140
+ });
141
+
142
+ // =====================================================================
143
+ // Test 2: severity_map covers documented categories
144
+ // =====================================================================
145
+
146
+ test('Test 2: severity_map has all 6 documented categories at valid severities', () => {
147
+ const v = loadValidator();
148
+ const validSeverities = new Set(['critical', 'error', 'warning', 'info']);
149
+ const required = [
150
+ 'trace_missing_field',
151
+ 'recommended_in_wrong_mode',
152
+ 'weight_clamp_breach',
153
+ 'unknown_verb_passed',
154
+ 'trace_file_malformed',
155
+ 'session_file_absent',
156
+ ];
157
+ for (const k of required) {
158
+ const sev = v.severity_map[k];
159
+ assert.ok(validSeverities.has(sev),
160
+ 'category ' + k + ' has valid severity (got ' + sev + ')');
161
+ }
162
+ });
163
+
164
+ // =====================================================================
165
+ // Test 3: INV-1 missing trace field -> trace_missing_field violation
166
+ // =====================================================================
167
+
168
+ test('Test 3: INV-1 missing brain_md_stale_reason yields violation', () => {
169
+ const room = freshRoom('t3');
170
+ try {
171
+ const trace = makeTrace();
172
+ delete trace.brain_md_stale_reason;
173
+ writeTraceFile(room, 'sess-t3', [trace]);
174
+ const v = loadValidator();
175
+ const result = v.validate(room, ctxFor(room));
176
+ assert.ok(result && Array.isArray(result.violations), 'returns shape');
177
+ const missing = result.violations.filter(function (x) {
178
+ return x.category === 'trace_missing_field' && x.field === 'brain_md_stale_reason';
179
+ });
180
+ assert.equal(missing.length, 1, 'exactly one trace_missing_field violation');
181
+ assert.equal(missing[0].severity, 'error', 'severity is error');
182
+ assert.equal(missing[0].validator, 'navigation-invariants', 'self-tagged');
183
+ } finally { rmrf(room); }
184
+ });
185
+
186
+ // =====================================================================
187
+ // Test 4: INV-1 all 8 fields present -> zero completeness violations
188
+ // =====================================================================
189
+
190
+ test('Test 4: INV-1 all fields present yields zero trace_missing_field', () => {
191
+ const room = freshRoom('t4');
192
+ try {
193
+ writeTraceFile(room, 'sess-t4', [makeTrace()]);
194
+ const v = loadValidator();
195
+ const result = v.validate(room, ctxFor(room));
196
+ const missing = result.violations.filter(function (x) {
197
+ return x.category === 'trace_missing_field';
198
+ });
199
+ assert.equal(missing.length, 0,
200
+ 'no missing-field violations: got ' + JSON.stringify(missing));
201
+ } finally { rmrf(room); }
202
+ });
203
+
204
+ // =====================================================================
205
+ // Test 5: INV-2 RECOMMENDED rendered in mode_b -> violation
206
+ // =====================================================================
207
+
208
+ test('Test 5: INV-2 RECOMMENDED rendered in mode_b -> recommended_in_wrong_mode', () => {
209
+ const room = freshRoom('t5');
210
+ try {
211
+ const trace = makeTrace({
212
+ brain_md_tier_mode: 'mode_b',
213
+ brain_md_recommended_marker_rendered: true,
214
+ });
215
+ writeTraceFile(room, 'sess-t5', [trace]);
216
+ const v = loadValidator();
217
+ const result = v.validate(room, ctxFor(room));
218
+ const wrong = result.violations.filter(function (x) {
219
+ return x.category === 'recommended_in_wrong_mode';
220
+ });
221
+ assert.equal(wrong.length, 1, 'exactly one recommended_in_wrong_mode');
222
+ assert.equal(wrong[0].severity, 'error', 'severity is error');
223
+ } finally { rmrf(room); }
224
+ });
225
+
226
+ // =====================================================================
227
+ // Test 6: INV-2 RECOMMENDED rendered in tier_0 -> violation
228
+ // =====================================================================
229
+
230
+ test('Test 6: INV-2 RECOMMENDED rendered in tier_0 -> recommended_in_wrong_mode', () => {
231
+ const room = freshRoom('t6');
232
+ try {
233
+ const trace = makeTrace({
234
+ brain_md_tier_mode: 'tier_0',
235
+ brain_md_recommended_marker_rendered: true,
236
+ });
237
+ writeTraceFile(room, 'sess-t6', [trace]);
238
+ const v = loadValidator();
239
+ const result = v.validate(room, ctxFor(room));
240
+ const wrong = result.violations.filter(function (x) {
241
+ return x.category === 'recommended_in_wrong_mode';
242
+ });
243
+ assert.equal(wrong.length, 1, 'exactly one recommended_in_wrong_mode in tier_0');
244
+ } finally { rmrf(room); }
245
+ });
246
+
247
+ // =====================================================================
248
+ // Test 7: INV-2 RECOMMENDED in mode_a -> zero violation
249
+ // =====================================================================
250
+
251
+ test('Test 7: INV-2 RECOMMENDED in mode_a OK', () => {
252
+ const room = freshRoom('t7');
253
+ try {
254
+ const trace = makeTrace({
255
+ brain_md_tier_mode: 'mode_a',
256
+ brain_md_recommended_marker_rendered: true,
257
+ });
258
+ writeTraceFile(room, 'sess-t7', [trace]);
259
+ const v = loadValidator();
260
+ const result = v.validate(room, ctxFor(room));
261
+ const wrong = result.violations.filter(function (x) {
262
+ return x.category === 'recommended_in_wrong_mode';
263
+ });
264
+ assert.equal(wrong.length, 0,
265
+ 'mode_a + recommended is allowed: got ' + JSON.stringify(wrong));
266
+ } finally { rmrf(room); }
267
+ });
268
+
269
+ // =====================================================================
270
+ // Test 8: INV-3 weight clamp breach (over and under)
271
+ // =====================================================================
272
+
273
+ test('Test 8: INV-3 weight outside [0.0, 1.0] -> weight_clamp_breach', () => {
274
+ const room = freshRoom('t8');
275
+ try {
276
+ writeTraceFile(room, 'sess-t8a', [makeTrace({ brain_md_weight_applied: 1.5 })]);
277
+ writeTraceFile(room, 'sess-t8b', [makeTrace({ brain_md_weight_applied: -0.1 })]);
278
+ const v = loadValidator();
279
+ const result = v.validate(room, ctxFor(room));
280
+ const breaches = result.violations.filter(function (x) {
281
+ return x.category === 'weight_clamp_breach';
282
+ });
283
+ assert.equal(breaches.length, 2, 'one breach per offending trace; got ' + breaches.length);
284
+ for (const b of breaches) {
285
+ assert.equal(b.severity, 'error', 'breach severity is error');
286
+ }
287
+ } finally { rmrf(room); }
288
+ });
289
+
290
+ // =====================================================================
291
+ // Test 9: INV-4 malformed trace file -> trace_file_malformed
292
+ // =====================================================================
293
+
294
+ test('Test 9: INV-4 malformed JSON yields trace_file_malformed; valid sibling still scanned', () => {
295
+ const room = freshRoom('t9');
296
+ try {
297
+ // Write a valid file alongside a garbage file. Ensure both are processed.
298
+ writeTraceFile(room, 'sess-t9-good', [makeTrace({ brain_md_weight_applied: 1.5 })]);
299
+ const dir = path.join(room, '.mindrian', 'decision-traces');
300
+ fs.writeFileSync(path.join(dir, 'sess-t9-bad.json'), 'not-json{{{');
301
+ const v = loadValidator();
302
+ const result = v.validate(room, ctxFor(room));
303
+ const malformed = result.violations.filter(function (x) {
304
+ return x.category === 'trace_file_malformed';
305
+ });
306
+ assert.equal(malformed.length, 1, 'one malformed violation');
307
+ assert.equal(malformed[0].severity, 'error', 'malformed severity is error');
308
+ // Verify the good file's weight breach still surfaced (sibling scan).
309
+ const breaches = result.violations.filter(function (x) {
310
+ return x.category === 'weight_clamp_breach';
311
+ });
312
+ assert.equal(breaches.length, 1, 'valid sibling scanned despite malformed peer');
313
+ } finally { rmrf(room); }
314
+ });
315
+
316
+ // =====================================================================
317
+ // Test 10: INV-5 unknown verb -> unknown_verb_passed warning
318
+ // =====================================================================
319
+
320
+ test('Test 10: INV-5 unknown fire_skill verb yields warning', () => {
321
+ const room = freshRoom('t10');
322
+ try {
323
+ const trace = makeTrace({ fire_skill: 'Invent New Verb' });
324
+ writeTraceFile(room, 'sess-t10', [trace]);
325
+ const v = loadValidator();
326
+ const result = v.validate(room, ctxFor(room));
327
+ const unknown = result.violations.filter(function (x) {
328
+ return x.category === 'unknown_verb_passed';
329
+ });
330
+ assert.equal(unknown.length, 1, 'one unknown_verb_passed violation');
331
+ assert.equal(unknown[0].severity, 'warning', 'severity is warning');
332
+ } finally { rmrf(room); }
333
+ });
334
+
335
+ // =====================================================================
336
+ // Test 10b: INV-5 known canonical verb -> zero violation (negative path)
337
+ // =====================================================================
338
+
339
+ test('Test 10b: INV-5 canonical verb passes silently', () => {
340
+ const room = freshRoom('t10b');
341
+ try {
342
+ // Use a verb known to be in the frozen 10-verb canon.
343
+ const sharedMod = require(SHARED_PATH);
344
+ assert.ok(Array.isArray(sharedMod.CANONICAL_VERBS) && sharedMod.CANONICAL_VERBS.length > 0,
345
+ 'shared exports CANONICAL_VERBS');
346
+ const verb = sharedMod.CANONICAL_VERBS[0];
347
+ writeTraceFile(room, 'sess-t10b', [makeTrace({ fire_skill: verb })]);
348
+ const v = loadValidator();
349
+ const result = v.validate(room, ctxFor(room));
350
+ const unknown = result.violations.filter(function (x) {
351
+ return x.category === 'unknown_verb_passed';
352
+ });
353
+ assert.equal(unknown.length, 0, 'canonical verb does not flag: got ' + JSON.stringify(unknown));
354
+ } finally { rmrf(room); }
355
+ });
356
+
357
+ // =====================================================================
358
+ // Test 10c: session_file_absent when decision-traces dir is missing
359
+ // =====================================================================
360
+
361
+ test('Test 10c: missing decision-traces dir -> session_file_absent info', () => {
362
+ const room = freshRoom('t10c');
363
+ try {
364
+ const v = loadValidator();
365
+ const result = v.validate(room, ctxFor(room));
366
+ const absent = result.violations.filter(function (x) {
367
+ return x.category === 'session_file_absent';
368
+ });
369
+ assert.equal(absent.length, 1, 'one session_file_absent info');
370
+ assert.equal(absent[0].severity, 'info', 'severity is info');
371
+ // No noise: no other categories from this run.
372
+ assert.equal(result.violations.length, 1, 'only the absent info; total: ' +
373
+ JSON.stringify(result.violations));
374
+ } finally { rmrf(room); }
375
+ });
376
+
377
+ // =====================================================================
378
+ // Test 11: registry integration -- guardian on-stop picks up validator
379
+ // =====================================================================
380
+
381
+ test('Test 11: registry integration via on-stop guardian + GUARDIAN_VALIDATORS_DIR', () => {
382
+ const room = freshRoom('t11');
383
+ // Stage isolated validators dir with ONLY navigation-invariants present.
384
+ const validatorsDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nav-inv-vdir-t11-'));
385
+ try {
386
+ fs.copyFileSync(VALIDATOR_PATH, path.join(validatorsDir, 'navigation-invariants.cjs'));
387
+ // Seed a malformed trace + a clean trace so the on-stop pass produces
388
+ // an invariant-report with our validator's signature.
389
+ const trace = makeTrace({ brain_md_weight_applied: 5.0 });
390
+ writeTraceFile(room, 'sess-t11', [trace]);
391
+ const result = spawnSync(process.execPath,
392
+ [GUARDIAN_PATH, 'on-stop', room],
393
+ { env: Object.assign({}, process.env, { GUARDIAN_VALIDATORS_DIR: validatorsDir }) }
394
+ );
395
+ assert.equal(result.status, 0, 'guardian on-stop exits 0; stderr=' +
396
+ (result.stderr && result.stderr.toString()));
397
+ const reportPath = path.join(room, '.mindrian', 'invariant-report.json');
398
+ assert.ok(fs.existsSync(reportPath), 'invariant-report.json written');
399
+ const report = JSON.parse(fs.readFileSync(reportPath, 'utf8'));
400
+ assert.ok(report.sections && report.sections.__room__,
401
+ '__room__ section in report');
402
+ const viols = report.sections.__room__.violations || [];
403
+ const tagged = viols.filter(function (v) { return v.validator === 'navigation-invariants'; });
404
+ assert.ok(tagged.length >= 1, 'navigation-invariants tagged in report; got ' +
405
+ JSON.stringify(viols));
406
+ } finally {
407
+ rmrf(room);
408
+ rmrf(validatorsDir);
409
+ }
410
+ });
411
+
412
+ // =====================================================================
413
+ // Test 12: fail-open inheritance from Phase 88-13 registry
414
+ // =====================================================================
415
+
416
+ test('Test 12: malformed sibling validator does not prevent navigation-invariants', () => {
417
+ const room = freshRoom('t12');
418
+ const validatorsDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nav-inv-vdir-t12-'));
419
+ try {
420
+ // 1) Drop a deliberately malformed validator (missing required exports).
421
+ fs.writeFileSync(path.join(validatorsDir, 'broken-validator.cjs'),
422
+ "module.exports = { id: 'broken' /* no validate, no severity_map */ };");
423
+ // 2) Drop our validator alongside.
424
+ fs.copyFileSync(VALIDATOR_PATH, path.join(validatorsDir, 'navigation-invariants.cjs'));
425
+ // 3) Seed a violation we can recognize.
426
+ writeTraceFile(room, 'sess-t12', [makeTrace({ brain_md_weight_applied: 7.0 })]);
427
+ const result = spawnSync(process.execPath,
428
+ [GUARDIAN_PATH, 'on-stop', room],
429
+ { env: Object.assign({}, process.env, { GUARDIAN_VALIDATORS_DIR: validatorsDir }) }
430
+ );
431
+ assert.equal(result.status, 0, 'guardian still exits 0 despite broken sibling');
432
+ const reportPath = path.join(room, '.mindrian', 'invariant-report.json');
433
+ assert.ok(fs.existsSync(reportPath), 'invariant-report still written');
434
+ const report = JSON.parse(fs.readFileSync(reportPath, 'utf8'));
435
+ const viols = (report.sections.__room__ && report.sections.__room__.violations) || [];
436
+ const tagged = viols.filter(function (v) { return v.validator === 'navigation-invariants'; });
437
+ assert.ok(tagged.length >= 1,
438
+ 'navigation-invariants ran despite broken sibling; got ' + JSON.stringify(viols));
439
+ } finally {
440
+ rmrf(room);
441
+ rmrf(validatorsDir);
442
+ }
443
+ });
444
+
445
+ // =====================================================================
446
+ // Test 13: Canon Part 8 source scan -- validator is LOCAL only
447
+ // =====================================================================
448
+
449
+ test('Test 13: validator source has zero network surface (Canon Part 8)', () => {
450
+ const src = fs.readFileSync(VALIDATOR_PATH, 'utf8');
451
+ // Forbid Brain client, fetch, https/http modules, child_process curl.
452
+ const forbidden = [
453
+ /require\(\s*['"]https?['"]\s*\)/,
454
+ /require\(\s*['"]node:https?['"]\s*\)/,
455
+ /\bfetch\s*\(/,
456
+ /brain[-_]?client/i,
457
+ /smartSearch|brainQuery/i,
458
+ ];
459
+ for (const re of forbidden) {
460
+ assert.ok(!re.test(src),
461
+ 'forbidden network reference matched ' + re + ' in navigation-invariants.cjs');
462
+ }
463
+ });
464
+
465
+ // =====================================================================
466
+ // Test 14: BSL header present
467
+ // =====================================================================
468
+
469
+ test('Test 14: BSL 1.1 header on validator', () => {
470
+ const src = fs.readFileSync(VALIDATOR_PATH, 'utf8');
471
+ const head = src.split('\n').slice(0, 20).join('\n');
472
+ assert.ok(/BSL\s*1\.1/i.test(head), 'BSL 1.1 mentioned in first 20 lines');
473
+ });
474
+
475
+ // ----------- summary -----------
476
+
477
+ const total = pass + fail;
478
+ process.stdout.write('\n' + pass + '/' + total + ' passed\n');
479
+ if (fail > 0) {
480
+ process.stdout.write(fail + ' failed:\n');
481
+ for (const f of failures) process.stdout.write(' - ' + f.name + '\n');
482
+ }
483
+ process.exit(fail === 0 ? 0 : 1);