@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,280 @@
1
+ /*
2
+ * Copyright (c) 2026 Mindrian. BSL 1.1.
3
+ * Phase 89.5 Plan 01 -- Phase 4 commercial assessor (deterministic).
4
+ *
5
+ * Deterministic 3-field commercial layer consumed by the Phase 89.5-04
6
+ * top-level orchestrator (kickoff §5 Phase 4 Synthesis). Reads the post-
7
+ * breakthrough-scorer + post-fetcher rs_discovery shape and emits:
8
+ *
9
+ * {
10
+ * market_size_estimate: <string from frozen 5-bucket TAM/SAM table>,
11
+ * value_proposition: <string from frozen classification template table>,
12
+ * partnership_targets: <array derived from resolved_institutions + resolved_authors>,
13
+ * }
14
+ *
15
+ * Hard contract:
16
+ * 1. NO runtime LLM call (no fetch, no brain-client, no spawn of model
17
+ * process). Pure-function from a frozen table lookup + array map.
18
+ * 2. Deterministic: same input -> byte-identical JSON.stringify(output)
19
+ * across N invocations.
20
+ * 3. Edge-case safe: zero industry signals, single expert, missing
21
+ * breakthrough_score, missing classification all produce deterministic
22
+ * safe defaults; never throws on missing fields. Only throw paths are
23
+ * Canon Part 8 forbidden-pattern violations on adversarial input.
24
+ * 4. Canon Part 8 chokepoint: FIRST line of body is auditQueryObject on
25
+ * the (rs_discovery, opts) tuple. Any forbidden field anywhere in the
26
+ * tuple raises ExternalEgressViolation BEFORE any computation.
27
+ *
28
+ * Frozen tables:
29
+ * VALUE_PROP_TEMPLATES -- keyed on classification ('structural_transfer',
30
+ * 'semantic_implementation', 'hybrid', '_fallback'). Larry-style
31
+ * template stems with [bridge_concept] / [source] / [target] /
32
+ * [outcome] placeholders that are filled deterministically from
33
+ * rs_discovery scalars (no free-form generation).
34
+ *
35
+ * MARKET_SIZE_BUCKETS -- 5 frozen TAM/SAM proxy buckets keyed on the
36
+ * 2D quantile of (industry_signals_count, breakthrough_score):
37
+ * emerging-niche (signals <= 1, score < 5)
38
+ * small-targeted (signals 2-3, score 5-7)
39
+ * mid-market (signals 4-6, score 6-8)
40
+ * large-market (signals 7-10, score 8-9)
41
+ * platform-scale (signals > 10, score >= 9)
42
+ * Edge: missing breakthrough_score -> 'unknown-bucket' (deterministic).
43
+ *
44
+ * Bucket thresholds tuned conservatively for v1.11.0-beta.1; expanding
45
+ * the bucket vocabulary requires a Plan 89.5-01-N revision (canon-amend
46
+ * discipline).
47
+ *
48
+ * Pure CJS, zero npm deps, no Node built-ins beyond core require.
49
+ */
50
+ 'use strict';
51
+
52
+ const { ExternalEgressViolation } = require('./rs-egress-violations.cjs');
53
+ const { auditQueryObject } = require('./rs-egress-prompts.cjs');
54
+
55
+ // ---------- Frozen invariants ----------
56
+
57
+ // Larry-style value-proposition template stems keyed on classification.
58
+ // Each stem is a deterministic template with [PLACEHOLDER] tokens that
59
+ // are filled from rs_discovery scalars. NO free-form text generation.
60
+ //
61
+ // Stem-prefix design rule: the first 12 characters of each rendered
62
+ // template string MUST differ across the three real classifications +
63
+ // the fallback so T8 (classification table coverage) can verify table
64
+ // distinctness on the rendered output without coupling to internal stem
65
+ // keys. The leading words below ('Apply' / 'Implement' / 'Bridge' /
66
+ // 'Cross-domain') satisfy the 12-char-distinct invariant.
67
+ const VALUE_PROP_TEMPLATES = Object.freeze({
68
+ structural_transfer:
69
+ 'Apply [BRIDGE] from [SOURCE] to [TARGET] to unlock cross-domain advantage',
70
+ semantic_implementation:
71
+ 'Implement [BRIDGE] in [TARGET] to compress time from insight to validated decision',
72
+ hybrid:
73
+ 'Bridge [SOURCE] and [TARGET] via [BRIDGE] to unlock a defensible cross-domain moat',
74
+ _fallback:
75
+ 'Cross-domain opportunity: combine [SOURCE] and [TARGET] to address an underserved gap',
76
+ });
77
+
78
+ // 5-bucket TAM/SAM proxy table. Keyed on bucket-id; each entry is a
79
+ // frozen string. Bucket selection is deterministic via a 2D step-function
80
+ // over (industry_signals_count, breakthrough_score). See bucketize() below.
81
+ const MARKET_SIZE_BUCKETS = Object.freeze({
82
+ 'unknown-bucket':
83
+ 'unknown-bucket: insufficient signal to estimate market size',
84
+ 'emerging-niche':
85
+ 'emerging-niche: pre-market opportunity; demand signal not yet established',
86
+ 'small-targeted':
87
+ 'small-targeted: focused vertical with bounded TAM; early-stage adopters',
88
+ 'mid-market':
89
+ 'mid-market: established demand with measurable SAM; multi-segment reach',
90
+ 'large-market':
91
+ 'large-market: validated demand with broad SAM; cross-segment platform potential',
92
+ 'platform-scale':
93
+ 'platform-scale: category-defining opportunity with cross-vertical reach',
94
+ });
95
+
96
+ // Frozen safe-default scalars.
97
+ const SAFE_DEFAULT_BRIDGE = 'cross-domain bridge concept';
98
+ const SAFE_DEFAULT_SOURCE = 'source domain';
99
+ const SAFE_DEFAULT_TARGET = 'target domain';
100
+
101
+ // ---------- bucketize ----------
102
+ //
103
+ // 2D step-function over (signals, score). Pure deterministic lookup.
104
+ //
105
+ // Bucket selection rules (in order; first match wins):
106
+ // missing breakthrough_score (score === null) -> 'unknown-bucket'
107
+ // signals <= 1 AND score < 5 -> 'emerging-niche'
108
+ // signals between 2-3 AND score in [5, 7] -> 'small-targeted'
109
+ // signals between 4-6 AND score in [6, 8] -> 'mid-market'
110
+ // signals between 7-10 AND score in [8, 9] -> 'large-market'
111
+ // signals > 10 AND score >= 9 -> 'platform-scale'
112
+ // anything else -> nearest-neighbor by signals
113
+
114
+ function bucketize(signals, score) {
115
+ if (score === null || score === undefined) return 'unknown-bucket';
116
+ const s = (typeof signals === 'number' && isFinite(signals)) ? signals : 0;
117
+ const b = (typeof score === 'number' && isFinite(score)) ? score : 0;
118
+ // Top-down: pick the highest-bucket the input qualifies for. Each bucket
119
+ // requires BOTH signals AND score to satisfy its threshold pair so a
120
+ // single high dimension cannot inflate the estimate.
121
+ if (s > 10 && b >= 9) return 'platform-scale';
122
+ if (s >= 7 && b >= 8) return 'large-market';
123
+ if (s >= 4 && b >= 6) return 'mid-market';
124
+ if (s >= 2 && b >= 5) return 'small-targeted';
125
+ return 'emerging-niche';
126
+ }
127
+
128
+ // ---------- buildPartnershipTargets ----------
129
+ //
130
+ // Pure-function map from resolved_institutions + resolved_authors to a
131
+ // deterministic ordered array of partnership targets. Empty inputs yield
132
+ // [] (empty array). Authors precede institutions; both are sorted by the
133
+ // natural input order from the upstream fetcher (no re-sort here so
134
+ // upstream determinism propagates).
135
+
136
+ function buildPartnershipTargets(rs_discovery) {
137
+ if (!rs_discovery || typeof rs_discovery !== 'object') return [];
138
+ const out = [];
139
+ const authors = Array.isArray(rs_discovery.resolved_authors) ? rs_discovery.resolved_authors : [];
140
+ for (let i = 0; i < authors.length; i += 1) {
141
+ const a = authors[i];
142
+ if (!a || typeof a !== 'object') continue;
143
+ const name = (typeof a.name === 'string' && a.name.length > 0) ? a.name : null;
144
+ if (!name) continue;
145
+ out.push({
146
+ name: name,
147
+ type: 'author',
148
+ // Score = 1.0 - (i / authors.length) so the upstream-natural-order
149
+ // first author scores highest. Deterministic from input order.
150
+ score: 1.0 - (i / Math.max(authors.length, 1)),
151
+ });
152
+ }
153
+ const institutions = Array.isArray(rs_discovery.resolved_institutions) ? rs_discovery.resolved_institutions : [];
154
+ for (let i = 0; i < institutions.length; i += 1) {
155
+ const inst = institutions[i];
156
+ if (typeof inst !== 'string' || inst.length === 0) continue;
157
+ out.push({
158
+ name: inst,
159
+ type: 'institution',
160
+ score: 1.0 - (i / Math.max(institutions.length, 1)),
161
+ });
162
+ }
163
+ return out;
164
+ }
165
+
166
+ // ---------- buildValueProposition ----------
167
+ //
168
+ // Deterministic template-fill from frozen VALUE_PROP_TEMPLATES. Picks
169
+ // the template by classification (with '_fallback' for missing); fills
170
+ // [BRIDGE] / [SOURCE] / [TARGET] tokens from rs_discovery scalars when
171
+ // present (with safe defaults otherwise).
172
+
173
+ function buildValueProposition(rs_discovery) {
174
+ const cls = (rs_discovery && typeof rs_discovery.classification === 'string'
175
+ && (rs_discovery.classification in VALUE_PROP_TEMPLATES))
176
+ ? rs_discovery.classification
177
+ : '_fallback';
178
+ let stem = VALUE_PROP_TEMPLATES[cls];
179
+ const bridge = (rs_discovery && typeof rs_discovery.bridge_concept === 'string'
180
+ && rs_discovery.bridge_concept.length > 0)
181
+ ? rs_discovery.bridge_concept
182
+ : SAFE_DEFAULT_BRIDGE;
183
+ const source = (rs_discovery && typeof rs_discovery.query_concept === 'string'
184
+ && rs_discovery.query_concept.length > 0)
185
+ ? rs_discovery.query_concept
186
+ : SAFE_DEFAULT_SOURCE;
187
+ const target = (rs_discovery && typeof rs_discovery.doc_concept === 'string'
188
+ && rs_discovery.doc_concept.length > 0)
189
+ ? rs_discovery.doc_concept
190
+ : SAFE_DEFAULT_TARGET;
191
+ // Token replacement is deterministic global string replace; no regex
192
+ // escaping needed because tokens are frozen literals.
193
+ stem = stem.split('[BRIDGE]').join(bridge);
194
+ stem = stem.split('[SOURCE]').join(source);
195
+ stem = stem.split('[TARGET]').join(target);
196
+ return stem;
197
+ }
198
+
199
+ // ---------- buildMarketSizeEstimate ----------
200
+ //
201
+ // Pure-function lookup from frozen MARKET_SIZE_BUCKETS. Reads
202
+ // industry_signals_count + breakthrough_score; missing breakthrough_score
203
+ // yields 'unknown-bucket' (the safe-default path).
204
+
205
+ function buildMarketSizeEstimate(rs_discovery) {
206
+ if (!rs_discovery || typeof rs_discovery !== 'object') {
207
+ return MARKET_SIZE_BUCKETS['unknown-bucket'];
208
+ }
209
+ const signals = (typeof rs_discovery.industry_signals_count === 'number')
210
+ ? rs_discovery.industry_signals_count
211
+ : 0;
212
+ // Distinguish "explicitly missing breakthrough_score" (-> unknown-bucket)
213
+ // from "score = 0" (-> emerging-niche by bucketize). The hasOwnProperty
214
+ // check catches the missing case.
215
+ const hasScore = Object.prototype.hasOwnProperty.call(rs_discovery, 'breakthrough_score')
216
+ && rs_discovery.breakthrough_score !== undefined
217
+ && rs_discovery.breakthrough_score !== null;
218
+ const score = hasScore ? rs_discovery.breakthrough_score : null;
219
+ const bucketId = bucketize(signals, score);
220
+ return MARKET_SIZE_BUCKETS[bucketId];
221
+ }
222
+
223
+ // ---------- assess ----------
224
+ //
225
+ // Public entry point. FIRST line of body: auditQueryObject on the
226
+ // composite (rs_discovery, opts) tuple. Throws ExternalEgressViolation on
227
+ // any forbidden field BEFORE any computation. The chokepoint is the only
228
+ // throw path; all other branches return deterministic safe defaults.
229
+ //
230
+ // Inputs:
231
+ // rs_discovery optional object (post-breakthrough-scorer shape)
232
+ // opts optional object (caller-supplied configuration scalars)
233
+ //
234
+ // Output:
235
+ // {
236
+ // market_size_estimate: <string from MARKET_SIZE_BUCKETS>,
237
+ // value_proposition: <string from VALUE_PROP_TEMPLATES>,
238
+ // partnership_targets: <array of {name, type, score} entries>,
239
+ // }
240
+
241
+ function assess(rs_discovery, opts) {
242
+ // Canon Part 8 chokepoint: pre-input audit on the composite tuple.
243
+ // Throws ExternalEgressViolation BEFORE any field is touched. Empty
244
+ // tuple is permitted (no-args path); only the audit-on-non-empty
245
+ // branch is adversarial-relevant. We always audit so a malicious
246
+ // opts cannot smuggle through the no-args branch.
247
+ auditQueryObject({
248
+ rs_discovery: (rs_discovery === undefined ? null : rs_discovery),
249
+ opts: (opts === undefined ? null : opts),
250
+ }, 'rs-commercial-assessor-input');
251
+
252
+ // Safe-default path: no rs_discovery -> deterministic minimal output.
253
+ const safeIn = (rs_discovery && typeof rs_discovery === 'object') ? rs_discovery : {};
254
+
255
+ return {
256
+ market_size_estimate: buildMarketSizeEstimate(safeIn),
257
+ value_proposition: buildValueProposition(safeIn),
258
+ partnership_targets: buildPartnershipTargets(safeIn),
259
+ };
260
+ }
261
+
262
+ // ---------- Exports ----------
263
+
264
+ module.exports = {
265
+ assess: assess,
266
+ // Re-export sentinel so adversarial fixtures can reference the class
267
+ // without a second require() round-trip.
268
+ ExternalEgressViolation: ExternalEgressViolation,
269
+ _test: {
270
+ VALUE_PROP_TEMPLATES: VALUE_PROP_TEMPLATES,
271
+ MARKET_SIZE_BUCKETS: MARKET_SIZE_BUCKETS,
272
+ SAFE_DEFAULT_BRIDGE: SAFE_DEFAULT_BRIDGE,
273
+ SAFE_DEFAULT_SOURCE: SAFE_DEFAULT_SOURCE,
274
+ SAFE_DEFAULT_TARGET: SAFE_DEFAULT_TARGET,
275
+ bucketize: bucketize,
276
+ buildPartnershipTargets: buildPartnershipTargets,
277
+ buildValueProposition: buildValueProposition,
278
+ buildMarketSizeEstimate: buildMarketSizeEstimate,
279
+ },
280
+ };
@@ -0,0 +1,376 @@
1
+ /*
2
+ * Copyright (c) 2026 Mindrian. BSL 1.1.
3
+ * Phase 89.2 Plan 06 Task 3 -- Phase 3 dual-floor differential scorer.
4
+ *
5
+ * Pair-wise differential scorer per kickoff §5:
6
+ *
7
+ * pair passes IFF (diff > 0.3 AND LSA > 0.2 AND BERT > 0.2)
8
+ *
9
+ * where diff = |LSA - BERT|. Strict > comparisons throughout (Test 5
10
+ * verifies the exact-threshold case fails). The dual-floor filter is the
11
+ * detection signal that distinguishes structural-transfer pairs (LSA high,
12
+ * BERT low) from semantic-implementation pairs (BERT high, LSA low) from
13
+ * direct-intersection pairs (both high, low diff -- pruned by the diff floor).
14
+ *
15
+ * --------------------------------------------------------------------------
16
+ * CANON PART 7 CARVE-OUT (DELIBERATE, DOCUMENTED)
17
+ * --------------------------------------------------------------------------
18
+ *
19
+ * The pair-wise LSA cosine below uses an embedded sklearn TfidfVectorizer +
20
+ * TruncatedSVD subset inside lsaBridgeScript -- NOT rs_math.py's
21
+ * build_tfidf_svd. This is a deliberate exception to Reuse Before Build
22
+ * because rs_math.py's API is CORPUS-LEVEL: it expects Sequence[str] >= 3
23
+ * documents and fits a corpus-wide IDF + SVD basis. A pair-wise comparison
24
+ * (1 query_concept vs 1 doc_concept = 2-document mini-corpus) cannot consume
25
+ * that API without forcing degenerate corpus statistics that change the
26
+ * algorithm's semantics:
27
+ *
28
+ * - 2-document IDF is mathematically meaningless (IDF on a 2-document
29
+ * corpus collapses the whole vocabulary into one of two values; the
30
+ * "rare-term up-weighting" that motivates IDF stops working).
31
+ *
32
+ * - 1-component SVD (max for a 2-document matrix) does NOT correspond
33
+ * to Kwan 2023's algorithm, which fits ~80 components against a real
34
+ * corpus to capture topic structure.
35
+ *
36
+ * The pair-wise question requires a fresh per-pair TfidfVectorizer +
37
+ * TruncatedSVD fit specifically tuned for the pair-wise cosine -- which IS
38
+ * what lsaBridgeScript does. rs_math.py continues to be consumed in its
39
+ * CORPUS-MODE use case (e.g., scripts/rs-engine.py for corpus reverse-salient
40
+ * computation per Phase 89-01 / 89-03 / 89-05).
41
+ *
42
+ * To avoid future drift toward "all LSA must go through one path," this
43
+ * carve-out is documented in three locations:
44
+ *
45
+ * 1. The plan's must_haves block + objective (.planning/phases/89.2-.../
46
+ * 89.2-06-preprocessor-and-differential-scorer-PLAN.md)
47
+ * 2. This source file's header comment block (above)
48
+ * 3. The embedded Python lsaBridgeScript header (inside lsaBridgeScript)
49
+ *
50
+ * Acceptance grep enforces the carve-out comment block (>= 2 hits across
51
+ * the CJS header AND the embedded Python header) so refactors that strip
52
+ * one without the other are loud, not silent.
53
+ *
54
+ * --------------------------------------------------------------------------
55
+ *
56
+ * BERT cosine path (Canon Part 7 reuse, NO carve-out): consumes
57
+ * lib/core/rs-pinecone-bridge.cjs (Task 1 of this plan) which wraps the
58
+ * existing rs_cache.py::fetch_all_from_namespace primitive (Phase 89-03
59
+ * v1.10.16) for strict-1024-dim Pinecone-direct vector retrieval.
60
+ *
61
+ * Graceful degradation contract:
62
+ *
63
+ * bridge fails (no PINECONE_API_KEY, network error, namespace empty)
64
+ * -> {diff: <lsa>, lsa: <lsa>, bert: null, passes: lsa > LSA_FLOOR,
65
+ * warning: 'bert_unavailable'}
66
+ * -> NEVER throws on bridge failure
67
+ *
68
+ * LSA bridge fails (python3 missing, sklearn import error, parse error)
69
+ * -> {diff: null, lsa: null, bert: <bert>, passes: false,
70
+ * warning: 'lsa_unavailable'}
71
+ * -> Pessimistic: passes=false because LSA is the structural anchor;
72
+ * without LSA the differential signal is unrecoverable.
73
+ *
74
+ * Canon Part 8 (Graph Boundary): two defense-in-depth layers.
75
+ *
76
+ * Layer 1 -- pre-input scan: query_concept + doc_concept are passed
77
+ * through auditQueryString BEFORE either bridge is called. On
78
+ * FORBIDDEN_PATTERNS hit, throws ExternalEgressViolation; the bridges
79
+ * are NEVER invoked (Tests 9 + 10 verify call counts == 0).
80
+ *
81
+ * Layer 2 -- pre-return audit: composite output is passed through
82
+ * auditQueryObject before return. Throws ExternalEgressViolation on
83
+ * hit. Defense-in-depth so any forbidden pattern smuggled via the
84
+ * bridge response (warning fields, error fields) is caught at the gate.
85
+ *
86
+ * Pure CJS, zero npm deps, node built-ins only beyond the rs-egress-* +
87
+ * rs-pinecone-bridge primitives.
88
+ */
89
+ 'use strict';
90
+
91
+ const path = require('node:path');
92
+ const childProcess = require('child_process');
93
+ const { auditQueryString, auditQueryObject } = require('./rs-egress-prompts.cjs');
94
+ const pineconeBridge = require('./rs-pinecone-bridge.cjs');
95
+ // rs-egress-violations is required transitively by rs-egress-prompts; we do
96
+ // not throw ExternalEgressViolation directly from this module (the audit
97
+ // helpers do). The require below is a reachability witness for the audit chain.
98
+ require('./rs-egress-violations.cjs');
99
+
100
+ // ---------- Frozen invariants ----------
101
+
102
+ const REPO_ROOT = path.resolve(__dirname, '..', '..');
103
+ const PYTHON_BIN = process.env.MINDRIAN_PYTHON || 'python3';
104
+ const LSA_BRIDGE_TIMEOUT_MS = 30000;
105
+
106
+ // Dual-floor thresholds per kickoff §5. Strict > comparisons.
107
+ const DIFF_FLOOR = 0.3;
108
+ const LSA_FLOOR = 0.2;
109
+ const BERT_FLOOR = 0.2;
110
+
111
+ // ---------- Embedded Python LSA bridge script ----------
112
+ //
113
+ // CANON PART 7 CARVE-OUT (DELIBERATE, DOCUMENTED): see file header above
114
+ // for the complete justification. In short:
115
+ // rs_math.py::build_tfidf_svd is corpus-level (Sequence[str] >= 3 docs);
116
+ // pair-wise (1 vs 1) cosine cannot consume that API without forcing
117
+ // degenerate IDF + SVD. The script below fits a fresh per-pair
118
+ // TfidfVectorizer + TruncatedSVD specifically for the pair-wise question.
119
+ //
120
+ // The leading `# BSL 1.1` line plus the carve-out justification block
121
+ // constitute the Canon discipline marker on the embedded source surface
122
+ // (W4 fix per Plan 89.2-06). Acceptance grep enforces presence in both
123
+ // the CJS file header (above) AND this embedded Python block.
124
+
125
+ const lsaBridgeScript = [
126
+ '# BSL 1.1',
127
+ '# Copyright (c) 2026 Mindrian. Phase 89.2 Plan 06 Task 3 -- pair-wise LSA cosine.',
128
+ '#',
129
+ '# CANON PART 7 CARVE-OUT (DELIBERATE, DOCUMENTED): This script computes',
130
+ '# pair-wise (1 vs 1) LSA cosine. It does NOT call rs_math.py because',
131
+ '# rs_math.py::build_tfidf_svd is corpus-level (Sequence[str] >= 3',
132
+ '# documents) and would produce degenerate IDF + SVD on a 2-document pair.',
133
+ '# The embedded sklearn subset below fits a fresh per-pair TfidfVectorizer',
134
+ '# + TruncatedSVD specifically for the pair-wise question, which is the',
135
+ '# algorithmically correct path. rs_math.py is consumed in CORPUS mode by',
136
+ '# scripts/rs-engine.py.',
137
+ '#',
138
+ '# Protocol:',
139
+ '# stdin JSON {a: string, b: string}',
140
+ '# stdout JSON {success: true, cosine: number} OR {success: false, error: string}',
141
+ 'import sys, json',
142
+ 'try:',
143
+ ' from sklearn.feature_extraction.text import TfidfVectorizer',
144
+ ' from sklearn.metrics.pairwise import cosine_similarity as sk_cos',
145
+ ' from sklearn.decomposition import TruncatedSVD',
146
+ ' payload = json.loads(sys.stdin.read())',
147
+ ' a = str(payload.get("a", ""))',
148
+ ' b = str(payload.get("b", ""))',
149
+ ' if len(a.strip()) == 0 or len(b.strip()) == 0:',
150
+ ' sys.stdout.write(json.dumps({"success": True, "cosine": 0.0}))',
151
+ ' sys.exit(0)',
152
+ ' texts = [a, b]',
153
+ ' vec = TfidfVectorizer(stop_words="english").fit_transform(texts)',
154
+ ' if vec.shape[1] < 2:',
155
+ ' sys.stdout.write(json.dumps({"success": True, "cosine": 0.0}))',
156
+ ' sys.exit(0)',
157
+ ' n_components = max(1, min(80, vec.shape[1] - 1, vec.shape[0] - 1))',
158
+ ' svd = TruncatedSVD(n_components=n_components, random_state=256).fit(vec)',
159
+ ' reduced = svd.transform(vec)',
160
+ ' c = float(sk_cos(reduced[0:1], reduced[1:2])[0][0])',
161
+ ' # Clamp to [0, 1] for downstream dual-floor consistency. Negative LSA',
162
+ ' # cosines arise on degenerate SVD bases and are not interpretable as',
163
+ ' # similarity in the Kwan 2023 framework.',
164
+ ' sys.stdout.write(json.dumps({"success": True, "cosine": max(0.0, c)}))',
165
+ 'except Exception as e:',
166
+ ' sys.stdout.write(json.dumps({"success": False, "error": str(e)}))',
167
+ '',
168
+ ].join('\n');
169
+
170
+ // ---------- computeLsaCosine ----------
171
+ //
172
+ // Spawns python3 with the embedded lsaBridgeScript, passes the two strings
173
+ // via JSON-over-stdin, parses the response. Returns:
174
+ //
175
+ // {success: true, cosine: number}
176
+ // {success: false, error: 'python_unavailable'|'python_exit_<N>'|'parse_error'|'timeout'|...}
177
+
178
+ async function computeLsaCosine(a, b) {
179
+ const requestEnvelope = JSON.stringify({ a: a, b: b });
180
+ let res;
181
+ try {
182
+ res = childProcess.spawnSync(PYTHON_BIN, ['-c', lsaBridgeScript], {
183
+ input: requestEnvelope,
184
+ encoding: 'utf8',
185
+ timeout: LSA_BRIDGE_TIMEOUT_MS,
186
+ cwd: REPO_ROOT,
187
+ });
188
+ } catch (err) {
189
+ return { success: false, error: 'spawn_threw', detail: String(err && err.message) };
190
+ }
191
+
192
+ if (res && res.error) {
193
+ if (res.error.code === 'ENOENT') return { success: false, error: 'python_unavailable' };
194
+ if (res.error.code === 'ETIMEDOUT' || res.error.code === 'ERR_CHILD_PROCESS_TIMEOUT') {
195
+ return { success: false, error: 'timeout' };
196
+ }
197
+ return { success: false, error: 'spawn_error', detail: String(res.error.message) };
198
+ }
199
+
200
+ if (res && res.signal === 'SIGTERM') {
201
+ return { success: false, error: 'timeout' };
202
+ }
203
+
204
+ const stdout = (res && typeof res.stdout === 'string') ? res.stdout : '';
205
+ const stderr = (res && typeof res.stderr === 'string') ? res.stderr : '';
206
+
207
+ if (res && res.status !== 0) {
208
+ return {
209
+ success: false,
210
+ error: 'python_exit_' + res.status,
211
+ stderr: stderr.slice(0, 500),
212
+ };
213
+ }
214
+
215
+ let parsed;
216
+ try {
217
+ parsed = JSON.parse(stdout);
218
+ } catch (_e) {
219
+ return { success: false, error: 'parse_error', stdout_sample: stdout.slice(0, 200) };
220
+ }
221
+
222
+ if (!parsed || typeof parsed !== 'object') {
223
+ return { success: false, error: 'parse_error' };
224
+ }
225
+
226
+ if (parsed.success !== true) {
227
+ return { success: false, error: typeof parsed.error === 'string' ? parsed.error : 'bridge_error' };
228
+ }
229
+
230
+ if (typeof parsed.cosine !== 'number' || isNaN(parsed.cosine)) {
231
+ return { success: false, error: 'invalid_cosine' };
232
+ }
233
+
234
+ return { success: true, cosine: parsed.cosine };
235
+ }
236
+
237
+ // ---------- computeBertCosine ----------
238
+ //
239
+ // Twin queryPineconeWithVectors calls (one per concept), then pure-JS
240
+ // cosineSimilarity on the resulting 1024-dim vectors. Returns:
241
+ //
242
+ // {success: true, cosine: number}
243
+ // {success: false, error: 'namespace_required'|'bridge_failed'|'no_hits'|'shape_error'}
244
+
245
+ async function computeBertCosine(a, b, namespace) {
246
+ if (typeof namespace !== 'string' || namespace.length === 0) {
247
+ return { success: false, error: 'namespace_required' };
248
+ }
249
+
250
+ const resA = await pineconeBridge.queryPineconeWithVectors(namespace, a, 1);
251
+ if (!resA || resA.success !== true) {
252
+ return { success: false, error: 'bridge_failed_a', detail: resA && resA.error };
253
+ }
254
+ const resB = await pineconeBridge.queryPineconeWithVectors(namespace, b, 1);
255
+ if (!resB || resB.success !== true) {
256
+ return { success: false, error: 'bridge_failed_b', detail: resB && resB.error };
257
+ }
258
+
259
+ if (!Array.isArray(resA.hits) || resA.hits.length === 0) {
260
+ return { success: false, error: 'no_hits_a' };
261
+ }
262
+ if (!Array.isArray(resB.hits) || resB.hits.length === 0) {
263
+ return { success: false, error: 'no_hits_b' };
264
+ }
265
+
266
+ const va = resA.hits[0] && resA.hits[0].values;
267
+ const vb = resB.hits[0] && resB.hits[0].values;
268
+ if (!Array.isArray(va) || !Array.isArray(vb)) {
269
+ return { success: false, error: 'shape_error' };
270
+ }
271
+ if (va.length !== vb.length || va.length === 0) {
272
+ return { success: false, error: 'dim_mismatch' };
273
+ }
274
+
275
+ const cos = pineconeBridge.cosineSimilarity(va, vb);
276
+ return { success: true, cosine: cos };
277
+ }
278
+
279
+ // ---------- score ----------
280
+ //
281
+ // Public entry point. Pair-wise dual-floor differential scorer.
282
+ //
283
+ // Inputs:
284
+ // query_concept string the concept seeded from preprocessor.concepts[]
285
+ // doc_concept string the candidate concept (cross-domain or same-domain)
286
+ // opts optional:
287
+ // namespace string Pinecone namespace for BERT cosine (typically 'external:<topic-slug>')
288
+ //
289
+ // Output (happy path):
290
+ // {diff, lsa, bert, passes}
291
+ //
292
+ // Output (graceful degradation):
293
+ // {diff, lsa, bert: null, passes: lsa>0.2, warning: 'bert_unavailable'}
294
+ // {diff: null, lsa: null, bert, passes: false, warning: 'lsa_unavailable'}
295
+ //
296
+ // Throws (the only escape route -- Canon Part 8):
297
+ // ExternalEgressViolation if either concept matches FORBIDDEN_PATTERNS
298
+
299
+ async function score(query_concept, doc_concept, opts) {
300
+ // Canon Part 8 Layer 1: pre-input scan on user-controlled concepts.
301
+ // auditQueryString throws ExternalEgressViolation on hit; the bridges
302
+ // below are NEVER invoked when this throws. Tests 9 + 10 verify the
303
+ // call-count contract.
304
+ auditQueryString(typeof query_concept === 'string' ? query_concept : '', 'differential-scorer');
305
+ auditQueryString(typeof doc_concept === 'string' ? doc_concept : '', 'differential-scorer');
306
+
307
+ opts = opts || {};
308
+ const namespace = (typeof opts.namespace === 'string' && opts.namespace.length > 0)
309
+ ? opts.namespace
310
+ : null;
311
+
312
+ // Run both bridges in parallel. computeLsaCosine is cheap (single Python
313
+ // spawn); computeBertCosine spawns the Pinecone bridge twice. Promise.all
314
+ // means LSA does not block on BERT's spawnSync in the parallel mock-test
315
+ // case. Sequential await would be equivalent for correctness; parallel
316
+ // is the future-proofing for real Brain latency.
317
+ const [lsaResult, bertResult] = await Promise.all([
318
+ computeLsaCosine(query_concept, doc_concept),
319
+ computeBertCosine(query_concept, doc_concept, namespace),
320
+ ]);
321
+
322
+ let out;
323
+ if (lsaResult.success && bertResult.success) {
324
+ const lsa = lsaResult.cosine;
325
+ const bert = bertResult.cosine;
326
+ const diff = Math.abs(lsa - bert);
327
+ const passes = (diff > DIFF_FLOOR) && (lsa > LSA_FLOOR) && (bert > BERT_FLOOR);
328
+ out = { diff: diff, lsa: lsa, bert: bert, passes: passes };
329
+ } else if (lsaResult.success && !bertResult.success) {
330
+ // BERT unavailable: degrade to LSA-only. Per plan: bert=null, diff=lsa
331
+ // (treat as max divergence), passes=(lsa>LSA_FLOOR only since bert
332
+ // unavailable), warning='bert_unavailable'.
333
+ const lsa = lsaResult.cosine;
334
+ out = {
335
+ diff: lsa,
336
+ lsa: lsa,
337
+ bert: null,
338
+ passes: lsa > LSA_FLOOR,
339
+ warning: 'bert_unavailable',
340
+ };
341
+ } else {
342
+ // LSA failed (with or without BERT): pessimistic. Per plan: passes=false
343
+ // because LSA is the structural anchor; without LSA the differential
344
+ // signal is unrecoverable.
345
+ out = {
346
+ diff: null,
347
+ lsa: null,
348
+ bert: bertResult.success ? bertResult.cosine : null,
349
+ passes: false,
350
+ warning: 'lsa_unavailable',
351
+ };
352
+ }
353
+
354
+ // Canon Part 8 Layer 2: pre-return audit on composite output.
355
+ // Throws ExternalEgressViolation on any FORBIDDEN_PATTERNS hit.
356
+ auditQueryObject(out, 'differential-scorer');
357
+
358
+ return out;
359
+ }
360
+
361
+ // ---------- Exports ----------
362
+
363
+ module.exports = {
364
+ score: score,
365
+ _test: {
366
+ DIFF_FLOOR: DIFF_FLOOR,
367
+ LSA_FLOOR: LSA_FLOOR,
368
+ BERT_FLOOR: BERT_FLOOR,
369
+ LSA_BRIDGE_TIMEOUT_MS: LSA_BRIDGE_TIMEOUT_MS,
370
+ PYTHON_BIN: PYTHON_BIN,
371
+ REPO_ROOT: REPO_ROOT,
372
+ computeLsaCosine: computeLsaCosine,
373
+ computeBertCosine: computeBertCosine,
374
+ lsaBridgeScript: lsaBridgeScript,
375
+ },
376
+ };