@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,375 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /*
5
+ * Copyright (c) 2026 Mindrian. BSL 1.1.
6
+ * Phase 89.2 Plan 07 Task 2 -- breakthrough scorer fixture suite.
7
+ *
8
+ * 10 scenarios for the Phase 3 deterministic 5-dimension 0-10 rubric:
9
+ *
10
+ * feasibility 0-2 from substrate.tier (core=2, applied=1.5, theoretical=1)
11
+ * market 0-2 from industry signal count (0=0, 1-3=0.5, 4-9=1.0,
12
+ * 10-19=1.5, 20+=2.0)
13
+ * magnitude 0-2 from diff value (>=0.7=2, >=0.5=1.5, >=0.3=1.0, else 0)
14
+ * advantage 0-2 from cross-domain pair rarity (2 * (1 - density), clamped)
15
+ * impact 0-2 from BERT score (>=0.8=2, >=0.6=1.5, >=0.4=1.0,
16
+ * >=0.2=0.5, else 0)
17
+ *
18
+ * Test 1 full rubric all-max -- score=10, dominant='feasibility' (frozen-order tie)
19
+ * Test 2 full rubric all-min (theoretical) -- score=1, dominant='feasibility' (only non-zero)
20
+ * Test 3 substrate tier 'applied' -- feasibility=1.5
21
+ * Test 4 industry signals 1-3 -- market=0.5
22
+ * Test 5 industry signals 4-9 -- market=1.0
23
+ * Test 6 industry signals 10-19 -- market=1.5
24
+ * Test 7 industry signals 20+ -- market=2.0
25
+ * Test 8 determinism (two invocations -> JSON.stringify identical)
26
+ * Test 9 CANON PART 8 adversarial: forbidden in classified_pair.query_concept
27
+ * Test 10 CANON PART 8 adversarial: forbidden in opts.substrate_metadata.title
28
+ *
29
+ * Suite-end audit:
30
+ * A1 walk every captured scoreBreakthrough output; JSON.stringify scan
31
+ * against FORBIDDEN_PATTERNS + DANGEROUS_SUBSTRINGS; ZERO hits.
32
+ *
33
+ * Pure CJS, zero npm deps, node built-ins only.
34
+ */
35
+
36
+ const assert = require('node:assert/strict');
37
+ const path = require('node:path');
38
+
39
+ const REPO_ROOT = path.resolve(__dirname, '..', '..');
40
+
41
+ const crossRoomAggregator = require('../core/cross-room-aggregator.cjs');
42
+ const FORBIDDEN_PATTERNS = crossRoomAggregator.FORBIDDEN_PATTERNS;
43
+
44
+ const DANGEROUS_SUBSTRINGS = Object.freeze([
45
+ 'Lawrence',
46
+ '5.2M',
47
+ 'meeting with',
48
+ 'jonathan@mindrian.com',
49
+ '123-45-6789',
50
+ ]);
51
+
52
+ // ---------- Suite bookkeeping ----------
53
+
54
+ let passed = 0;
55
+ let failed = 0;
56
+ const failures = [];
57
+ const SCENARIO_RESULTS = [];
58
+
59
+ function captureOutput(name, output) {
60
+ SCENARIO_RESULTS.push({ scenario: name, output: output });
61
+ }
62
+
63
+ function resetRequireCache() {
64
+ const targets = [
65
+ '../core/rs-egress-violations.cjs',
66
+ '../core/rs-egress-prompts.cjs',
67
+ '../core/rs-breakthrough-scorer.cjs',
68
+ ];
69
+ for (const t of targets) {
70
+ try {
71
+ const p = require.resolve(t);
72
+ delete require.cache[p];
73
+ } catch (_e) { /* best effort */ }
74
+ }
75
+ }
76
+
77
+ function runScenario(name, fn) {
78
+ const start = Date.now();
79
+ try {
80
+ fn();
81
+ passed += 1;
82
+ process.stdout.write(' ok ' + name + ' (' + (Date.now() - start) + 'ms)\n');
83
+ } catch (err) {
84
+ failed += 1;
85
+ failures.push({ name: name, err: err });
86
+ process.stderr.write(' FAIL ' + name + '\n');
87
+ process.stderr.write(' ' + (err && err.stack ? err.stack : err) + '\n');
88
+ } finally {
89
+ resetRequireCache();
90
+ }
91
+ }
92
+
93
+ // ---------- Helper: build a baseline classified_pair (post-classifier shape) ----------
94
+
95
+ function baselineClassifiedPair(overrides) {
96
+ const base = {
97
+ query_concept: 'cancer immunotherapy',
98
+ doc_concept: 'checkpoint inhibitor PD-1',
99
+ diff: 0.4, lsa: 0.5, bert: 0.1, passes: true,
100
+ classification: 'structural_transfer',
101
+ bridge_concept: 'cross-domain isomorphism',
102
+ };
103
+ if (overrides) {
104
+ for (const k of Object.keys(overrides)) base[k] = overrides[k];
105
+ }
106
+ return base;
107
+ }
108
+
109
+ // ---------- Scenarios ----------
110
+
111
+ function scenario1AllMax() {
112
+ const m = require('../core/rs-breakthrough-scorer.cjs');
113
+ const cp = baselineClassifiedPair({ diff: 0.8, bert: 0.9 });
114
+ const opts = {
115
+ substrate_metadata: { tier: 'core' },
116
+ industry_signal_count: 20,
117
+ pair_density: 0,
118
+ };
119
+ const out = m.scoreBreakthrough(cp, opts);
120
+ captureOutput('1-all-max', out);
121
+ assert.ok(out.breakthrough, 'has breakthrough field');
122
+ assert.equal(out.breakthrough.score, 10, 'all-max score should be 10; got ' + out.breakthrough.score);
123
+ assert.equal(out.breakthrough.breakdown.feasibility, 2.0);
124
+ assert.equal(out.breakthrough.breakdown.market, 2.0);
125
+ assert.equal(out.breakthrough.breakdown.magnitude, 2.0);
126
+ assert.equal(out.breakthrough.breakdown.advantage, 2.0);
127
+ assert.equal(out.breakthrough.breakdown.impact, 2.0);
128
+ // Frozen-order tie-break: feasibility first.
129
+ assert.equal(out.breakthrough.dominant_dimension, 'feasibility',
130
+ 'all-tied dominant should be feasibility (frozen-order tie-break first); got ' +
131
+ out.breakthrough.dominant_dimension);
132
+ }
133
+
134
+ function scenario2AllMin() {
135
+ const m = require('../core/rs-breakthrough-scorer.cjs');
136
+ const cp = baselineClassifiedPair({ diff: 0.1, bert: 0.1 });
137
+ const opts = {
138
+ substrate_metadata: { tier: 'theoretical' },
139
+ industry_signal_count: 0,
140
+ pair_density: 1.0,
141
+ };
142
+ const out = m.scoreBreakthrough(cp, opts);
143
+ captureOutput('2-all-min', out);
144
+ // theoretical -> feasibility=1; signals=0 -> market=0; diff=0.1 -> magnitude=0;
145
+ // density=1 -> advantage=0; bert=0.1 -> impact=0. Total = 1.
146
+ assert.equal(out.breakthrough.score, 1, 'all-min score should be 1; got ' + out.breakthrough.score);
147
+ assert.equal(out.breakthrough.breakdown.feasibility, 1.0);
148
+ assert.equal(out.breakthrough.breakdown.market, 0.0);
149
+ assert.equal(out.breakthrough.breakdown.magnitude, 0.0);
150
+ assert.equal(out.breakthrough.breakdown.advantage, 0.0);
151
+ assert.equal(out.breakthrough.breakdown.impact, 0.0);
152
+ assert.equal(out.breakthrough.dominant_dimension, 'feasibility',
153
+ 'only non-zero dim is feasibility; got ' + out.breakthrough.dominant_dimension);
154
+ }
155
+
156
+ function scenario3SubstrateTierApplied() {
157
+ const m = require('../core/rs-breakthrough-scorer.cjs');
158
+ const cp = baselineClassifiedPair({ diff: 0.1, bert: 0.1 });
159
+ const opts = {
160
+ substrate_metadata: { tier: 'applied' },
161
+ industry_signal_count: 0,
162
+ pair_density: 1.0,
163
+ };
164
+ const out = m.scoreBreakthrough(cp, opts);
165
+ captureOutput('3-substrate-applied', out);
166
+ assert.equal(out.breakthrough.breakdown.feasibility, 1.5,
167
+ 'applied tier -> feasibility 1.5; got ' + out.breakthrough.breakdown.feasibility);
168
+ assert.equal(out.breakthrough.score, 1.5, 'total = 1.5');
169
+ }
170
+
171
+ function scenario4IndustrySignals1to3() {
172
+ const m = require('../core/rs-breakthrough-scorer.cjs');
173
+ const cp = baselineClassifiedPair({ diff: 0.1, bert: 0.1 });
174
+ const opts = {
175
+ substrate_metadata: { tier: 'theoretical' },
176
+ industry_signal_count: 2,
177
+ pair_density: 1.0,
178
+ };
179
+ const out = m.scoreBreakthrough(cp, opts);
180
+ captureOutput('4-signals-1to3', out);
181
+ assert.equal(out.breakthrough.breakdown.market, 0.5,
182
+ '1-3 signals -> market 0.5; got ' + out.breakthrough.breakdown.market);
183
+ }
184
+
185
+ function scenario5IndustrySignals4to9() {
186
+ const m = require('../core/rs-breakthrough-scorer.cjs');
187
+ const cp = baselineClassifiedPair({ diff: 0.1, bert: 0.1 });
188
+ const opts = {
189
+ substrate_metadata: { tier: 'theoretical' },
190
+ industry_signal_count: 7,
191
+ pair_density: 1.0,
192
+ };
193
+ const out = m.scoreBreakthrough(cp, opts);
194
+ captureOutput('5-signals-4to9', out);
195
+ assert.equal(out.breakthrough.breakdown.market, 1.0,
196
+ '4-9 signals -> market 1.0; got ' + out.breakthrough.breakdown.market);
197
+ }
198
+
199
+ function scenario6IndustrySignals10to19() {
200
+ const m = require('../core/rs-breakthrough-scorer.cjs');
201
+ const cp = baselineClassifiedPair({ diff: 0.1, bert: 0.1 });
202
+ const opts = {
203
+ substrate_metadata: { tier: 'theoretical' },
204
+ industry_signal_count: 15,
205
+ pair_density: 1.0,
206
+ };
207
+ const out = m.scoreBreakthrough(cp, opts);
208
+ captureOutput('6-signals-10to19', out);
209
+ assert.equal(out.breakthrough.breakdown.market, 1.5,
210
+ '10-19 signals -> market 1.5; got ' + out.breakthrough.breakdown.market);
211
+ }
212
+
213
+ function scenario7IndustrySignals20Plus() {
214
+ const m = require('../core/rs-breakthrough-scorer.cjs');
215
+ const cp = baselineClassifiedPair({ diff: 0.1, bert: 0.1 });
216
+ const opts = {
217
+ substrate_metadata: { tier: 'theoretical' },
218
+ industry_signal_count: 35,
219
+ pair_density: 1.0,
220
+ };
221
+ const out = m.scoreBreakthrough(cp, opts);
222
+ captureOutput('7-signals-20plus', out);
223
+ assert.equal(out.breakthrough.breakdown.market, 2.0,
224
+ '20+ signals -> market 2.0; got ' + out.breakthrough.breakdown.market);
225
+ }
226
+
227
+ function scenario8Determinism() {
228
+ const m = require('../core/rs-breakthrough-scorer.cjs');
229
+ const cp = baselineClassifiedPair({ diff: 0.45, bert: 0.55 });
230
+ const opts = {
231
+ substrate_metadata: { tier: 'applied' },
232
+ industry_signal_count: 8,
233
+ pair_density: 0.4,
234
+ };
235
+ const out1 = m.scoreBreakthrough(cp, opts);
236
+ const out2 = m.scoreBreakthrough(cp, opts);
237
+ captureOutput('8-determinism-1', out1);
238
+ captureOutput('8-determinism-2', out2);
239
+ assert.equal(JSON.stringify(out1), JSON.stringify(out2),
240
+ 'determinism: same input must produce byte-identical output');
241
+ // Score in [0, 10].
242
+ assert.ok(out1.breakthrough.score >= 0 && out1.breakthrough.score <= 10,
243
+ 'score in [0,10]; got ' + out1.breakthrough.score);
244
+ }
245
+
246
+ function scenario9AdversarialQueryConcept() {
247
+ const m = require('../core/rs-breakthrough-scorer.cjs');
248
+ // FORBIDDEN_PATTERNS[2]: "Lawrence said" / "Jonathan said" etc.
249
+ const cp = baselineClassifiedPair({
250
+ query_concept: 'Lawrence said cancer immunotherapy is the future',
251
+ });
252
+ const opts = {
253
+ substrate_metadata: { tier: 'core' },
254
+ industry_signal_count: 10,
255
+ pair_density: 0.5,
256
+ };
257
+ let threw = null;
258
+ try {
259
+ m.scoreBreakthrough(cp, opts);
260
+ } catch (err) {
261
+ threw = err;
262
+ }
263
+ assert.ok(threw, 'must throw on forbidden in query_concept');
264
+ assert.equal(threw.name, 'ExternalEgressViolation',
265
+ 'must throw ExternalEgressViolation; got ' + (threw && threw.name));
266
+ captureOutput('9-adv-query-throw', { thrown: threw.name });
267
+ }
268
+
269
+ function scenario10AdversarialSubstrateTitle() {
270
+ const m = require('../core/rs-breakthrough-scorer.cjs');
271
+ const cp = baselineClassifiedPair();
272
+ // FORBIDDEN_PATTERNS[0]: email regex.
273
+ const opts = {
274
+ substrate_metadata: {
275
+ tier: 'core',
276
+ title: 'Strategy paper from jonathan@mindrian.com archive',
277
+ },
278
+ industry_signal_count: 10,
279
+ pair_density: 0.5,
280
+ };
281
+ let threw = null;
282
+ let out = null;
283
+ try {
284
+ out = m.scoreBreakthrough(cp, opts);
285
+ } catch (err) {
286
+ threw = err;
287
+ }
288
+ // Either the scorer threw on the smuggled email, OR the output does
289
+ // not contain it (Layer 2 audit catches via auditQueryObject; for the
290
+ // scorer to embed substrate_metadata.title in its output is a design
291
+ // choice -- if the field is not propagated, no leak; if it is
292
+ // propagated, Layer 2 must catch). Both satisfy Canon Part 8.
293
+ if (threw) {
294
+ assert.equal(threw.name, 'ExternalEgressViolation',
295
+ 'must throw ExternalEgressViolation; got ' + (threw && threw.name));
296
+ captureOutput('10-adv-substrate-throw', { thrown: threw.name });
297
+ } else {
298
+ captureOutput('10-adv-substrate-scrubbed', out);
299
+ const json = JSON.stringify(out);
300
+ assert.ok(!/jonathan@mindrian\.com/i.test(json),
301
+ 'output must not contain leaked email; got: ' + json);
302
+ }
303
+ }
304
+
305
+ // ---------- A1 end-of-suite sweep ----------
306
+
307
+ function a1Sweep() {
308
+ let hits = 0;
309
+ for (const rec of SCENARIO_RESULTS) {
310
+ const json = JSON.stringify(rec.output);
311
+ for (const re of FORBIDDEN_PATTERNS) {
312
+ if (re.test(json)) {
313
+ hits += 1;
314
+ process.stderr.write(
315
+ ' A1 HIT scenario=' + rec.scenario +
316
+ ' pattern=' + re.source + '\n'
317
+ );
318
+ }
319
+ }
320
+ for (const sub of DANGEROUS_SUBSTRINGS) {
321
+ if (json.indexOf(sub) !== -1) {
322
+ hits += 1;
323
+ process.stderr.write(
324
+ ' A1 HIT scenario=' + rec.scenario +
325
+ ' substring=' + sub + '\n'
326
+ );
327
+ }
328
+ }
329
+ }
330
+ return hits;
331
+ }
332
+
333
+ // ---------- Main ----------
334
+
335
+ (function main() {
336
+ process.stdout.write('=== 89.2-07-breakthrough suite (REPO_ROOT=' +
337
+ REPO_ROOT + ') ===\n');
338
+
339
+ runScenario('1-all-max', scenario1AllMax);
340
+ runScenario('2-all-min', scenario2AllMin);
341
+ runScenario('3-substrate-applied', scenario3SubstrateTierApplied);
342
+ runScenario('4-signals-1to3', scenario4IndustrySignals1to3);
343
+ runScenario('5-signals-4to9', scenario5IndustrySignals4to9);
344
+ runScenario('6-signals-10to19', scenario6IndustrySignals10to19);
345
+ runScenario('7-signals-20plus', scenario7IndustrySignals20Plus);
346
+ runScenario('8-determinism', scenario8Determinism);
347
+ runScenario('9-adversarial-query-concept', scenario9AdversarialQueryConcept);
348
+ runScenario('10-adversarial-substrate-title', scenario10AdversarialSubstrateTitle);
349
+
350
+ const sweepHits = a1Sweep();
351
+ if (sweepHits > 0) {
352
+ failed += 1;
353
+ failures.push({
354
+ name: 'A1-sweep',
355
+ err: new Error('A1 sweep found ' + sweepHits + ' forbidden-pattern hits'),
356
+ });
357
+ process.stderr.write(' FAIL A1-sweep (' + sweepHits + ' hits)\n');
358
+ } else {
359
+ process.stdout.write(' ok A1-sweep (zero forbidden-pattern hits)\n');
360
+ }
361
+
362
+ process.stdout.write('=== 89.2-07-breakthrough suite: ' +
363
+ passed + '/10 passed' +
364
+ (failed > 0 ? ' (' + failed + ' failed)' : '') +
365
+ ' ===\n');
366
+
367
+ if (failed > 0) {
368
+ for (const f of failures) {
369
+ process.stderr.write(' FAILURE: ' + f.name + ': ' +
370
+ (f.err && f.err.message ? f.err.message : String(f.err)) + '\n');
371
+ }
372
+ process.exit(1);
373
+ }
374
+ process.exit(0);
375
+ })();
@@ -0,0 +1,218 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /*
5
+ * Copyright (c) 2026 Mindrian. BSL 1.1.
6
+ * Phase 89.4 Plan 01 -- Canon Part 3 closed-vocabulary fixture suite.
7
+ *
8
+ * 8 scenarios covering the Wave-1 foundation module:
9
+ * lib/core/rs-canon-violations.cjs
10
+ *
11
+ * Test 1 (10 valid verbs pass): every CANONICAL_VERBS entry round-trips
12
+ * through validateVerb verbatim.
13
+ * Test 2 (invalid verb throws): 'Cancel' throws CanonVerbViolation;
14
+ * err.name + err.meta.attempted_verb verified.
15
+ * Test 3 (empty string throws CanonVerbViolation): NOT TypeError;
16
+ * err.meta.attempted_verb === ''.
17
+ * Test 4 (non-string number throws TypeError): with message containing
18
+ * 'must be a string'.
19
+ * Test 5 (null + undefined throw TypeError): both inputs raise TypeError.
20
+ * Test 6 (CANONICAL_VERBS frozen): Object.isFrozen + length === 10
21
+ * + mutation throws in strict mode.
22
+ * Test 7 (canonical order verified): 10 strings exact-match in
23
+ * canon-mandated order.
24
+ * Test 8 (surface tag propagation): err.meta.surface populated when caller
25
+ * supplies; defaults to 'unknown' otherwise.
26
+ *
27
+ * Pure CJS, zero npm deps, node built-ins only (assert).
28
+ */
29
+
30
+ const assert = require('node:assert/strict');
31
+
32
+ // ---------- Suite bookkeeping ----------
33
+
34
+ let passed = 0;
35
+ let failed = 0;
36
+ const failures = [];
37
+
38
+ function record(name, fn) {
39
+ try {
40
+ fn();
41
+ passed++;
42
+ process.stdout.write('PASS ' + name + '\n');
43
+ } catch (err) {
44
+ failed++;
45
+ failures.push({ name, message: err && err.message ? err.message : String(err) });
46
+ process.stdout.write('FAIL ' + name + ': ' + (err && err.message ? err.message : String(err)) + '\n');
47
+ }
48
+ }
49
+
50
+ // Helper: assert a function throws CanonVerbViolation with expected attempted_verb.
51
+ function assertThrowsCanonVerbViolation(fn, expectedAttemptedVerb) {
52
+ let caught = null;
53
+ try {
54
+ fn();
55
+ } catch (e) {
56
+ caught = e;
57
+ }
58
+ assert.ok(caught !== null, 'expected throw, got none');
59
+ assert.equal(caught.name, 'CanonVerbViolation', 'expected err.name CanonVerbViolation, got ' + caught.name);
60
+ assert.ok(caught.meta && typeof caught.meta === 'object', 'expected err.meta to be object');
61
+ assert.equal(caught.meta.attempted_verb, expectedAttemptedVerb,
62
+ 'expected err.meta.attempted_verb=' + JSON.stringify(expectedAttemptedVerb)
63
+ + ', got ' + JSON.stringify(caught.meta.attempted_verb));
64
+ return caught;
65
+ }
66
+
67
+ // Helper: assert a function throws TypeError.
68
+ function assertThrowsTypeError(fn, messageSubstring) {
69
+ let caught = null;
70
+ try {
71
+ fn();
72
+ } catch (e) {
73
+ caught = e;
74
+ }
75
+ assert.ok(caught !== null, 'expected throw, got none');
76
+ assert.ok(caught instanceof TypeError, 'expected TypeError, got ' + (caught && caught.name));
77
+ if (messageSubstring) {
78
+ assert.ok(
79
+ caught.message.indexOf(messageSubstring) !== -1,
80
+ 'expected TypeError message to contain ' + JSON.stringify(messageSubstring)
81
+ + ', got ' + JSON.stringify(caught.message)
82
+ );
83
+ }
84
+ return caught;
85
+ }
86
+
87
+ // ---------- Module under test ----------
88
+
89
+ const mod = require('../core/rs-canon-violations.cjs');
90
+ const { CanonVerbViolation, CANONICAL_VERBS, validateVerb } = mod;
91
+
92
+ // ---------- Canonical 10-verb authoritative source ----------
93
+ // (per docs/MINDRIAN-CANON.md Part 3 lines 153-162)
94
+ const EXPECTED_VERBS = [
95
+ 'Run Methodology',
96
+ 'Reformulate',
97
+ 'Spawn Sub-Agent',
98
+ 'Navigate Graph',
99
+ "Devil's Advocate",
100
+ 'Scenario Plan',
101
+ 'Synthesize',
102
+ 'Bank Opportunity',
103
+ 'Defer',
104
+ 'Free-Text',
105
+ ];
106
+
107
+ // ---------- Tests ----------
108
+
109
+ record('T1 all 10 valid verbs pass validateVerb (returns input verbatim)', function () {
110
+ assert.ok(Array.isArray(CANONICAL_VERBS), 'CANONICAL_VERBS must be array');
111
+ assert.equal(CANONICAL_VERBS.length, 10, 'CANONICAL_VERBS.length must be 10');
112
+ for (const verb of CANONICAL_VERBS) {
113
+ const result = validateVerb(verb);
114
+ assert.equal(result, verb, 'validateVerb(' + JSON.stringify(verb) + ') must return input verbatim');
115
+ }
116
+ });
117
+
118
+ record('T2 invalid verb Cancel throws CanonVerbViolation with meta.attempted_verb', function () {
119
+ const err = assertThrowsCanonVerbViolation(function () {
120
+ validateVerb('Cancel');
121
+ }, 'Cancel');
122
+ assert.ok(err instanceof CanonVerbViolation, 'err must be instanceof CanonVerbViolation');
123
+ assert.ok(err instanceof Error, 'err must also be instanceof Error');
124
+ });
125
+
126
+ record('T3 empty string throws CanonVerbViolation (NOT TypeError)', function () {
127
+ const err = assertThrowsCanonVerbViolation(function () {
128
+ validateVerb('');
129
+ }, '');
130
+ assert.ok(err instanceof CanonVerbViolation, 'empty string must produce CanonVerbViolation, not TypeError');
131
+ });
132
+
133
+ record('T4 non-string number 42 throws TypeError with must be a string', function () {
134
+ assertThrowsTypeError(function () {
135
+ validateVerb(42);
136
+ }, 'must be a string');
137
+ });
138
+
139
+ record('T5 null and undefined throw TypeError', function () {
140
+ assertThrowsTypeError(function () {
141
+ validateVerb(null);
142
+ }, 'must be a string');
143
+ assertThrowsTypeError(function () {
144
+ validateVerb(undefined);
145
+ }, 'must be a string');
146
+ });
147
+
148
+ record('T6 CANONICAL_VERBS frozen + length 10 + mutation throws in strict mode', function () {
149
+ assert.equal(Object.isFrozen(CANONICAL_VERBS), true, 'CANONICAL_VERBS must be frozen');
150
+ assert.equal(CANONICAL_VERBS.length, 10, 'CANONICAL_VERBS.length must equal 10');
151
+ // Test file is in strict mode; mutation must throw.
152
+ let mutationThrew = false;
153
+ try {
154
+ CANONICAL_VERBS[0] = 'Hijacked';
155
+ } catch (e) {
156
+ mutationThrew = true;
157
+ }
158
+ assert.ok(mutationThrew, 'mutation of frozen array must throw in strict mode');
159
+ assert.equal(CANONICAL_VERBS[0], 'Run Methodology', 'CANONICAL_VERBS[0] must remain Run Methodology');
160
+ });
161
+
162
+ record('T7 CANONICAL_VERBS contains exact required strings in canonical order', function () {
163
+ for (let i = 0; i < EXPECTED_VERBS.length; i++) {
164
+ assert.equal(
165
+ CANONICAL_VERBS[i],
166
+ EXPECTED_VERBS[i],
167
+ 'CANONICAL_VERBS[' + i + '] must equal ' + JSON.stringify(EXPECTED_VERBS[i])
168
+ + ', got ' + JSON.stringify(CANONICAL_VERBS[i])
169
+ );
170
+ }
171
+ });
172
+
173
+ record('T8 surface tag propagation: provided populates meta.surface; omitted defaults to unknown', function () {
174
+ // With surface provided
175
+ let withSurfaceErr = null;
176
+ try {
177
+ validateVerb('NotAVerb', 'navigation-engine');
178
+ } catch (e) {
179
+ withSurfaceErr = e;
180
+ }
181
+ assert.ok(withSurfaceErr !== null, 'expected throw');
182
+ assert.equal(withSurfaceErr.name, 'CanonVerbViolation');
183
+ assert.equal(
184
+ withSurfaceErr.meta.surface,
185
+ 'navigation-engine',
186
+ 'err.meta.surface must equal supplied surface tag'
187
+ );
188
+
189
+ // Without surface (omitted)
190
+ let omittedErr = null;
191
+ try {
192
+ validateVerb('NotAVerb');
193
+ } catch (e) {
194
+ omittedErr = e;
195
+ }
196
+ assert.ok(omittedErr !== null, 'expected throw');
197
+ assert.equal(omittedErr.name, 'CanonVerbViolation');
198
+ assert.equal(
199
+ omittedErr.meta.surface,
200
+ 'unknown',
201
+ 'err.meta.surface must default to unknown when surface omitted'
202
+ );
203
+ });
204
+
205
+ // ---------- Suite report ----------
206
+
207
+ const total = passed + failed;
208
+ process.stdout.write('\n');
209
+ if (failed === 0) {
210
+ process.stdout.write('=== 89.4-01 rs-canon-violations suite: ' + passed + '/' + total + ' passed ===\n');
211
+ process.exit(0);
212
+ } else {
213
+ process.stdout.write('=== 89.4-01 rs-canon-violations suite: ' + passed + '/' + total + ' passed (' + failed + ' failed) ===\n');
214
+ for (const f of failures) {
215
+ process.stdout.write(' FAIL ' + f.name + ': ' + f.message + '\n');
216
+ }
217
+ process.exit(1);
218
+ }