@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,385 @@
1
+ /*
2
+ * Copyright (c) 2026 Mindrian. BSL 1.1.
3
+ * Phase 89.1 Plan 02 -- Sequential-Thinking-style domain analyzer.
4
+ *
5
+ * Deterministic decomposition: indexes Brain methodology substrate
6
+ * against topic n-grams; seeds the 7-field output (primary_domain,
7
+ * concepts, terminology, methods, breakthroughs, boundary_flag,
8
+ * adjacent_domains) from substrate metadata + topic intersection.
9
+ * NO runtime LLM call. NO Brain-write surface. analyzeDomain NEVER
10
+ * throws unless ExternalEgressViolation fires (Canon Part 8 third
11
+ * tripwire on output before return).
12
+ *
13
+ * Canon Part 7 (Reuse Before Build): wraps loadSubstrate from
14
+ * lib/core/rs-brain-substrate.cjs and FORBIDDEN_PATTERNS from
15
+ * lib/core/rs-brain-substrate-prompts.cjs. Both surfaces remain
16
+ * untouched; this module is a pure consumer.
17
+ *
18
+ * Canon Part 8 (Graph Boundary): output passes FORBIDDEN_PATTERNS
19
+ * scan before return. Topic also passes pre-input FORBIDDEN_PATTERNS
20
+ * scan; user-controlled inputs are scrubbed at the gate. Substrate
21
+ * metadata that contains forbidden patterns is either scrubbed
22
+ * (scalars become null) or causes ExternalEgressViolation at the
23
+ * pre-return audit. Reason: concepts/terminology/methods/breakthroughs/
24
+ * adjacent_domains will all flow downstream into 89.2 external
25
+ * fetchers (OpenAlex, arXiv, Tavily, Scopus, PubMed). Leaked user
26
+ * content here = leaked to public endpoints.
27
+ *
28
+ * Pure CJS, zero npm deps, node built-ins only.
29
+ */
30
+ 'use strict';
31
+
32
+ const rsBrainSubstrate = require('./rs-brain-substrate.cjs');
33
+ const prompts = require('./rs-brain-substrate-prompts.cjs');
34
+ const { FORBIDDEN_PATTERNS } = prompts;
35
+
36
+ // ---------- ExternalEgressViolation (Canon Part 8 sibling) ----------
37
+ //
38
+ // Sibling of BrainBoundaryViolation. The two surfaces are semantically
39
+ // distinct: BrainBoundaryViolation guards inbound queries to Brain;
40
+ // ExternalEgressViolation guards outbound flow to public external
41
+ // fetchers (OpenAlex / arXiv / Tavily / Scopus / PubMed). Sharing the
42
+ // class would conflate two different bottlenecks.
43
+
44
+ class ExternalEgressViolation extends Error {
45
+ constructor(message, meta) {
46
+ super(message);
47
+ this.name = 'ExternalEgressViolation';
48
+ this.meta = meta || {};
49
+ }
50
+ }
51
+
52
+ // ---------- Constants ----------
53
+
54
+ const TOPIC_MAX_LEN = 512;
55
+ const BOUNDARY_THRESHOLD_DEFAULT = 0.5;
56
+ const ADJACENT_DOMAINS_MAX = 5;
57
+ const CONCEPTS_MAX = 10;
58
+ const TERMINOLOGY_MAX = 10;
59
+ const METHODS_MAX = 10;
60
+ const BREAKTHROUGHS_MAX = 10;
61
+
62
+ // English stopwords for n-gram filtering. Frozen, deterministic.
63
+ const STOPWORDS = Object.freeze(new Set([
64
+ 'a', 'an', 'and', 'are', 'as', 'at', 'be', 'by', 'for', 'from',
65
+ 'has', 'have', 'in', 'is', 'it', 'its', 'of', 'on', 'or', 'that',
66
+ 'the', 'this', 'to', 'was', 'were', 'will', 'with',
67
+ 'i', 'you', 'we', 'they', 'he', 'she', 'our', 'their',
68
+ ]));
69
+
70
+ // ---------- tokenize ----------
71
+ //
72
+ // Lowercase, alpha+digit only, stopwords stripped, length >= 2.
73
+ // Deterministic: same input always produces same output.
74
+
75
+ function tokenize(s) {
76
+ if (typeof s !== 'string') return [];
77
+ return s.toLowerCase()
78
+ .replace(/[^a-z0-9\s_-]/g, ' ')
79
+ .split(/\s+/)
80
+ .filter(function (t) { return t.length >= 2 && !STOPWORDS.has(t); });
81
+ }
82
+
83
+ // ---------- ngrams ----------
84
+ //
85
+ // 1-grams + 2-grams as a Set for O(1) intersection lookup.
86
+
87
+ function ngrams(tokens) {
88
+ const out = new Set(tokens);
89
+ for (let i = 0; i < tokens.length - 1; i += 1) {
90
+ out.add(tokens[i] + ' ' + tokens[i + 1]);
91
+ }
92
+ return out;
93
+ }
94
+
95
+ // ---------- scrubScalar ----------
96
+ //
97
+ // Returns null if the input string contains any FORBIDDEN_PATTERNS hit;
98
+ // otherwise returns the input unchanged. Non-string inputs returned as-is.
99
+
100
+ function scrubScalar(s) {
101
+ if (typeof s !== 'string') return s;
102
+ for (const re of FORBIDDEN_PATTERNS) {
103
+ if (re.test(s)) return null;
104
+ }
105
+ return s;
106
+ }
107
+
108
+ // ---------- auditOutput ----------
109
+ //
110
+ // Final pre-return tripwire (Canon Part 8). JSON.stringifies the output
111
+ // and scans against FORBIDDEN_PATTERNS. Any hit throws ExternalEgressViolation.
112
+ // This is the third tripwire for the analyzer surface (after pre-input scan
113
+ // and per-scalar scrub) and guarantees that even composite output (where
114
+ // individual scalars passed) cannot smuggle a forbidden pattern via
115
+ // concatenation or reformatting.
116
+
117
+ function auditOutput(output) {
118
+ const json = JSON.stringify(output);
119
+ for (const re of FORBIDDEN_PATTERNS) {
120
+ if (re.test(json)) {
121
+ throw new ExternalEgressViolation(
122
+ 'analyzer output contains forbidden pattern: ' + re.source,
123
+ { pattern: re.source }
124
+ );
125
+ }
126
+ }
127
+ }
128
+
129
+ // ---------- validateTopic ----------
130
+ //
131
+ // Input gate. Returns {ok:true, topic:trimmed} on success, or a structured
132
+ // {ok:false, error, reason, ...} envelope on failure. Pre-input
133
+ // FORBIDDEN_PATTERNS scan blocks user-controlled topics that already carry
134
+ // forbidden bytes (Canon Part 8: user input scrubbing at the gate).
135
+
136
+ function validateTopic(topic) {
137
+ if (typeof topic !== 'string') {
138
+ return { ok: false, error: 'invalid_topic', reason: 'not_string' };
139
+ }
140
+ const trimmed = topic.trim();
141
+ if (trimmed.length === 0) {
142
+ return { ok: false, error: 'invalid_topic', reason: 'empty_or_whitespace' };
143
+ }
144
+ if (trimmed.length > TOPIC_MAX_LEN) {
145
+ return { ok: false, error: 'invalid_topic', reason: 'oversized', max: TOPIC_MAX_LEN };
146
+ }
147
+ for (const re of FORBIDDEN_PATTERNS) {
148
+ if (re.test(trimmed)) {
149
+ return { ok: false, error: 'invalid_topic', reason: 'forbidden_input' };
150
+ }
151
+ }
152
+ return { ok: true, topic: trimmed };
153
+ }
154
+
155
+ // ---------- scoreEntryAgainstTopic ----------
156
+ //
157
+ // Returns: substrate score (default 0) * (1 + token-intersection-overlap).
158
+ // Multiplier weights base substrate confidence by topic relevance.
159
+ // Deterministic: same inputs always produce same output.
160
+
161
+ function scoreEntryAgainstTopic(entry, topicNgrams, topicTokenCount) {
162
+ const baseScore = (typeof entry.score === 'number') ? entry.score : 0;
163
+ const entryText = [];
164
+ const md = entry && entry.metadata;
165
+ if (md && typeof md === 'object') {
166
+ for (const k of ['framework_name', 'title', 'text', 'tier']) {
167
+ if (typeof md[k] === 'string') entryText.push(md[k]);
168
+ }
169
+ }
170
+ const entryTokens = ngrams(tokenize(entryText.join(' ')));
171
+ let intersection = 0;
172
+ for (const tok of topicNgrams) {
173
+ if (entryTokens.has(tok)) intersection += 1;
174
+ }
175
+ const overlap = topicTokenCount > 0 ? (intersection / topicTokenCount) : 0;
176
+ return baseScore * (1 + overlap);
177
+ }
178
+
179
+ // ---------- analyzeDomain ----------
180
+ //
181
+ // Public entry point. Deterministic. NEVER throws except for
182
+ // ExternalEgressViolation (Canon Part 8). All other failure modes
183
+ // return structured-error envelopes.
184
+ //
185
+ // Inputs:
186
+ // topic string in (0, TOPIC_MAX_LEN] characters, scrubbed against
187
+ // FORBIDDEN_PATTERNS.
188
+ // opts optional object:
189
+ // roomDir string. Defaults to MINDRIAN_ROOM env or process.cwd().
190
+ // limit integer. Substrate pull limit. Default 100.
191
+ // forceRefresh boolean. Bypass cache. Default false.
192
+ // boundary_threshold number. Top-score floor. Default 0.5.
193
+ //
194
+ // Output (happy path):
195
+ // {
196
+ // primary_domain : string | null,
197
+ // concepts : string[],
198
+ // terminology : string[],
199
+ // methods : string[],
200
+ // breakthroughs : string[],
201
+ // boundary_flag : boolean,
202
+ // adjacent_domains : string[],
203
+ // warning? : string,
204
+ // }
205
+ //
206
+ // Output (input failure):
207
+ // {ok:false, error:'invalid_topic', reason:'...', max?:512}
208
+ //
209
+ // All scalars in the output are guaranteed to have passed FORBIDDEN_PATTERNS
210
+ // (per-field scrub) and the composite output is guaranteed to have passed
211
+ // the JSON.stringify audit. Any forbidden pattern reaching the boundary
212
+ // throws ExternalEgressViolation before egress.
213
+
214
+ async function analyzeDomain(topic, opts) {
215
+ opts = opts || {};
216
+ const topicCheck = validateTopic(topic);
217
+ if (!topicCheck.ok) return topicCheck;
218
+
219
+ const boundaryThreshold = (typeof opts.boundary_threshold === 'number')
220
+ ? opts.boundary_threshold
221
+ : BOUNDARY_THRESHOLD_DEFAULT;
222
+
223
+ // Pull substrate via 89.1a chokepoint. Canon Part 7 Reuse Before Build:
224
+ // we never call brain-client directly; loadSubstrate is the only path.
225
+ let substrateResult;
226
+ try {
227
+ substrateResult = await rsBrainSubstrate.loadSubstrate({
228
+ roomDir: opts.roomDir || process.env.MINDRIAN_ROOM || process.cwd(),
229
+ limit: opts.limit || 100,
230
+ forceRefresh: !!opts.forceRefresh,
231
+ });
232
+ } catch (err) {
233
+ // Defensive: loadSubstrate is contracted to never throw, but we still wrap.
234
+ const out = {
235
+ primary_domain: null,
236
+ concepts: [],
237
+ terminology: [],
238
+ methods: [],
239
+ breakthroughs: [],
240
+ boundary_flag: true,
241
+ adjacent_domains: [],
242
+ warning: 'substrate_load_failed: ' + String(err && err.message),
243
+ };
244
+ auditOutput(out);
245
+ return out;
246
+ }
247
+
248
+ const substrate = (substrateResult && Array.isArray(substrateResult.substrate))
249
+ ? substrateResult.substrate
250
+ : [];
251
+
252
+ // Tier-0 path: no substrate -> degraded valid output.
253
+ if (substrate.length === 0) {
254
+ const out = {
255
+ primary_domain: null,
256
+ concepts: [],
257
+ terminology: [],
258
+ methods: [],
259
+ breakthroughs: [],
260
+ boundary_flag: true,
261
+ adjacent_domains: [],
262
+ warning: 'substrate_empty_tier0',
263
+ };
264
+ auditOutput(out);
265
+ return out;
266
+ }
267
+
268
+ // Score and rank.
269
+ const topicTokens = tokenize(topicCheck.topic);
270
+ const topicNgramSet = ngrams(topicTokens);
271
+ const ranked = substrate
272
+ .map(function (e) {
273
+ return {
274
+ entry: e,
275
+ score: scoreEntryAgainstTopic(e, topicNgramSet, topicTokens.length),
276
+ };
277
+ })
278
+ .sort(function (a, b) { return b.score - a.score; });
279
+
280
+ const top = ranked[0];
281
+ const primaryName = (top && top.entry && top.entry.metadata &&
282
+ top.entry.metadata.framework_name) || null;
283
+ const primary = scrubScalar(primaryName);
284
+
285
+ // boundary_flag: top score below threshold OR primary scrubbed to null OR top missing.
286
+ const boundary_flag = (!top) || (top.score < boundaryThreshold) || primary === null;
287
+
288
+ // Seed lists. Deterministic: ranked order is stable; dedup via Set.
289
+ // Per-field scrubScalar guarantees individual entries are clean.
290
+ function seedFromMetadata(field, max) {
291
+ const seen = new Set();
292
+ const out = [];
293
+ for (const r of ranked) {
294
+ if (out.length >= max) break;
295
+ const v = r.entry && r.entry.metadata && r.entry.metadata[field];
296
+ const safe = scrubScalar(v);
297
+ if (typeof safe === 'string' && safe.length > 0 && !seen.has(safe)) {
298
+ seen.add(safe);
299
+ out.push(safe);
300
+ }
301
+ }
302
+ return out;
303
+ }
304
+
305
+ const concepts = seedFromMetadata('framework_name', CONCEPTS_MAX);
306
+ const terminology = seedFromMetadata('title', TERMINOLOGY_MAX);
307
+ const methods = seedFromMetadata('framework_name', METHODS_MAX);
308
+
309
+ // Breakthroughs: tier === 'core' subset (highest-confidence canonical methods).
310
+ const breakthroughs = (function () {
311
+ const seen = new Set();
312
+ const out = [];
313
+ for (const r of ranked) {
314
+ if (out.length >= BREAKTHROUGHS_MAX) break;
315
+ const md = r.entry && r.entry.metadata;
316
+ if (md && md.tier === 'core') {
317
+ const safe = scrubScalar(md.framework_name);
318
+ if (typeof safe === 'string' && safe.length > 0 && !seen.has(safe)) {
319
+ seen.add(safe);
320
+ out.push(safe);
321
+ }
322
+ }
323
+ }
324
+ return out;
325
+ })();
326
+
327
+ // Adjacent: top framework_names not equal to primary, capped at 5.
328
+ const adjacent_domains = (function () {
329
+ const seen = new Set();
330
+ const out = [];
331
+ for (const r of ranked) {
332
+ if (out.length >= ADJACENT_DOMAINS_MAX) break;
333
+ const safe = scrubScalar(
334
+ r.entry && r.entry.metadata && r.entry.metadata.framework_name
335
+ );
336
+ if (typeof safe === 'string' && safe.length > 0 &&
337
+ safe !== primary && !seen.has(safe)) {
338
+ seen.add(safe);
339
+ out.push(safe);
340
+ }
341
+ }
342
+ return out;
343
+ })();
344
+
345
+ const result = {
346
+ primary_domain: primary,
347
+ concepts: concepts,
348
+ terminology: terminology,
349
+ methods: methods,
350
+ breakthroughs: breakthroughs,
351
+ boundary_flag: boundary_flag,
352
+ adjacent_domains: adjacent_domains,
353
+ };
354
+
355
+ // Carry mode warning if degraded.
356
+ if (substrateResult && substrateResult.warning) {
357
+ result.warning = substrateResult.warning;
358
+ }
359
+
360
+ // Final pre-return audit (Canon Part 8 third tripwire on output side).
361
+ auditOutput(result);
362
+ return result;
363
+ }
364
+
365
+ // ---------- Exports ----------
366
+
367
+ module.exports = {
368
+ analyzeDomain: analyzeDomain,
369
+ ExternalEgressViolation: ExternalEgressViolation,
370
+ _test: {
371
+ tokenize: tokenize,
372
+ ngrams: ngrams,
373
+ scrubScalar: scrubScalar,
374
+ auditOutput: auditOutput,
375
+ validateTopic: validateTopic,
376
+ scoreEntryAgainstTopic: scoreEntryAgainstTopic,
377
+ TOPIC_MAX_LEN: TOPIC_MAX_LEN,
378
+ BOUNDARY_THRESHOLD_DEFAULT: BOUNDARY_THRESHOLD_DEFAULT,
379
+ ADJACENT_DOMAINS_MAX: ADJACENT_DOMAINS_MAX,
380
+ CONCEPTS_MAX: CONCEPTS_MAX,
381
+ TERMINOLOGY_MAX: TERMINOLOGY_MAX,
382
+ METHODS_MAX: METHODS_MAX,
383
+ BREAKTHROUGHS_MAX: BREAKTHROUGHS_MAX,
384
+ },
385
+ };
@@ -0,0 +1,113 @@
1
+ /*
2
+ * Copyright (c) 2026 Mindrian. BSL 1.1.
3
+ * Phase 89.2 Plan 01 -- egress prompts allow-list + audit helpers.
4
+ *
5
+ * The Canon Part 8 chokepoint shared by every Wave-2 fetcher
6
+ * (academic, patents, industry). Two helpers:
7
+ *
8
+ * auditQueryString(s, surface)
9
+ * -- scans a single outbound string against FORBIDDEN_PATTERNS;
10
+ * throws ExternalEgressViolation on hit; returns input on pass.
11
+ *
12
+ * auditQueryObject(obj, surface)
13
+ * -- JSON.stringify scans a structured outbound payload (query
14
+ * params, request body) against FORBIDDEN_PATTERNS; throws on hit;
15
+ * returns input on pass. Defense-in-depth so adversarial payloads
16
+ * nested inside objects (meta.contact, headers.authorization, etc.)
17
+ * cannot smuggle past per-field scrub.
18
+ *
19
+ * Re-exports FORBIDDEN_PATTERNS from lib/core/cross-room-aggregator.cjs
20
+ * BYTE-FOR-BYTE so any Canon amendment to the authoritative source is
21
+ * felt here with zero code change. Defensive guard at require-time so
22
+ * refactors are loud, not silent (mirrors 89.1a rs-brain-substrate-prompts
23
+ * pattern).
24
+ *
25
+ * Pure CJS, zero npm deps, no Node built-ins beyond core require.
26
+ */
27
+ 'use strict';
28
+
29
+ const crossRoomAggregator = require('./cross-room-aggregator.cjs');
30
+ const { ExternalEgressViolation } = require('./rs-egress-violations.cjs');
31
+
32
+ // FORBIDDEN_PATTERNS is re-exported BYTE-FOR-BYTE from cross-room-aggregator.
33
+ // The aggregator is the Canon authoritative source (lines 87-94). Re-exporting
34
+ // (instead of redefining) eliminates drift risk: one update site, one truth.
35
+ // Defensive guard at require-time so refactors are loud, not silent.
36
+ const FORBIDDEN_PATTERNS = crossRoomAggregator.FORBIDDEN_PATTERNS;
37
+ if (!Array.isArray(FORBIDDEN_PATTERNS) || FORBIDDEN_PATTERNS.length < 6) {
38
+ throw new Error(
39
+ 'rs-egress-prompts: FORBIDDEN_PATTERNS re-export failed; ' +
40
+ 'Canon Part 8 drift risk (expected >= 6 patterns from cross-room-aggregator)'
41
+ );
42
+ }
43
+
44
+ const SAMPLE_MAX = 40;
45
+
46
+ // ---------- auditQueryString ----------
47
+ //
48
+ // Pre-egress audit on a single outbound string. The chokepoint every
49
+ // fetcher MUST call before any fetch() invocation. Throws on any
50
+ // FORBIDDEN_PATTERNS hit; returns input on pass for callsite chaining.
51
+
52
+ function auditQueryString(s, surface) {
53
+ if (typeof s !== 'string') {
54
+ throw new TypeError('auditQueryString: input must be a string; got ' + typeof s);
55
+ }
56
+ const surfaceTag = (typeof surface === 'string' && surface.length > 0) ? surface : 'unknown';
57
+ for (const re of FORBIDDEN_PATTERNS) {
58
+ if (re.test(s)) {
59
+ throw new ExternalEgressViolation(
60
+ 'forbidden pattern in query string for surface ' + surfaceTag,
61
+ {
62
+ surface: surfaceTag,
63
+ matched_pattern: re.source,
64
+ sample: s.slice(0, SAMPLE_MAX),
65
+ }
66
+ );
67
+ }
68
+ }
69
+ return s;
70
+ }
71
+
72
+ // ---------- auditQueryObject ----------
73
+ //
74
+ // Pre-egress audit on a structured outbound payload. JSON.stringify
75
+ // flattens nested fields so adversarial content tucked inside meta /
76
+ // headers / params surfaces gets caught. Throws on hit; returns input
77
+ // on pass.
78
+
79
+ function auditQueryObject(obj, surface) {
80
+ if (obj === null || obj === undefined) {
81
+ throw new TypeError('auditQueryObject: input must be a non-null object');
82
+ }
83
+ if (typeof obj !== 'object') {
84
+ throw new TypeError('auditQueryObject: input must be an object; got ' + typeof obj);
85
+ }
86
+ const surfaceTag = (typeof surface === 'string' && surface.length > 0) ? surface : 'unknown';
87
+ let json;
88
+ try {
89
+ json = JSON.stringify(obj);
90
+ } catch (err) {
91
+ throw new TypeError('auditQueryObject: input not JSON-serializable: ' + err.message);
92
+ }
93
+ for (const re of FORBIDDEN_PATTERNS) {
94
+ if (re.test(json)) {
95
+ throw new ExternalEgressViolation(
96
+ 'forbidden pattern in query object for surface ' + surfaceTag,
97
+ {
98
+ surface: surfaceTag,
99
+ matched_pattern: re.source,
100
+ }
101
+ );
102
+ }
103
+ }
104
+ return obj;
105
+ }
106
+
107
+ // ---------- Exports ----------
108
+
109
+ module.exports = {
110
+ FORBIDDEN_PATTERNS,
111
+ auditQueryString,
112
+ auditQueryObject,
113
+ };