@mindrian_os/cli 2.0.0-beta.3 → 2.0.0-beta.31

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 (1829) hide show
  1. package/.claude-plugin/plugin.json +21 -0
  2. package/.mcp.json +14 -0
  3. package/CHANGELOG.md +467 -0
  4. package/agents/analogy-query-fetcher.md +119 -0
  5. package/agents/brain-query.md +91 -0
  6. package/agents/competitor-watch-fetcher.md +94 -0
  7. package/agents/framework-runner.md +258 -0
  8. package/agents/grading.md +216 -0
  9. package/agents/grant-reviewer.md +191 -0
  10. package/agents/investor.md +141 -0
  11. package/agents/larry-extended.md +215 -0
  12. package/agents/meeting-perspective-extractor.md +94 -0
  13. package/agents/opportunity-scanner.md +105 -0
  14. package/agents/persona-analyst.md +201 -0
  15. package/agents/research.md +103 -0
  16. package/agents/reverse-salient-agent.md +42 -0
  17. package/agents/vault-section-reviewer.md +107 -0
  18. package/assets/banner-showcase.html +537 -0
  19. package/assets/fonts/BebasNeue-Regular.ttf +0 -0
  20. package/assets/fonts/Inter-Bold.ttf +0 -0
  21. package/assets/fonts/Inter-Regular.ttf +0 -0
  22. package/assets/logo.svg +10 -0
  23. package/bin/local-chain-recommender.cjs +256 -0
  24. package/bin/mindrian-brain-mcp-client.cjs +319 -0
  25. package/bin/mindrian-mcp-server.cjs +445 -0
  26. package/bin/mindrian-mcp-shim.cjs +100 -0
  27. package/bin/mindrian-tools.cjs +784 -0
  28. package/commands/act.md +529 -0
  29. package/commands/admin.md +439 -0
  30. package/commands/agentshield.md +49 -0
  31. package/commands/analyze-needs.md +78 -0
  32. package/commands/analyze-systems.md +73 -0
  33. package/commands/analyze-timing.md +98 -0
  34. package/commands/auto-explore.md +85 -0
  35. package/commands/beautiful-question.md +76 -0
  36. package/commands/bono.md +152 -0
  37. package/commands/brain-derive.md +137 -0
  38. package/commands/build-knowledge.md +121 -0
  39. package/commands/build-thesis.md +94 -0
  40. package/commands/causal.md +269 -0
  41. package/commands/challenge-assumptions.md +78 -0
  42. package/commands/compare-ventures.md +117 -0
  43. package/commands/correct-reference-now.md +88 -0
  44. package/commands/dashboard.md +144 -0
  45. package/commands/deck.md +117 -0
  46. package/commands/deep-grade.md +214 -0
  47. package/commands/diagnose.md +131 -0
  48. package/commands/diagnostics.md +195 -0
  49. package/commands/dial-memory-refresh.md +113 -0
  50. package/commands/diffusion.md +129 -0
  51. package/commands/discover.md +221 -0
  52. package/commands/doctor.md +271 -0
  53. package/commands/dogfood-flush.md +130 -0
  54. package/commands/dominant-designs.md +76 -0
  55. package/commands/eureka.md +315 -0
  56. package/commands/explain-decision.md +135 -0
  57. package/commands/explore-domains.md +78 -0
  58. package/commands/explore-futures.md +67 -0
  59. package/commands/explore-opportunity.md +172 -0
  60. package/commands/explore-trends.md +78 -0
  61. package/commands/export.md +128 -0
  62. package/commands/feynman-timeline-refresh.md +102 -0
  63. package/commands/file-meeting.md +1195 -0
  64. package/commands/find-analogies.md +369 -0
  65. package/commands/find-bottlenecks.md +108 -0
  66. package/commands/find-connections.md +111 -0
  67. package/commands/funding.md +114 -0
  68. package/commands/futures.md +128 -0
  69. package/commands/grade-grant.md +297 -0
  70. package/commands/grade.md +257 -0
  71. package/commands/graph.md +218 -0
  72. package/commands/hat-briefing.md +163 -0
  73. package/commands/heal.md +72 -0
  74. package/commands/help.md +176 -0
  75. package/commands/hmi-status.md +75 -0
  76. package/commands/ignite.md +229 -0
  77. package/commands/ingest-methodology.md +128 -0
  78. package/commands/intel-pipeline.md +133 -0
  79. package/commands/jtbd.md +262 -0
  80. package/commands/leadership.md +113 -0
  81. package/commands/lean-canvas.md +74 -0
  82. package/commands/macro-trends.md +88 -0
  83. package/commands/map-unknowns.md +76 -0
  84. package/commands/memory-cortex-reach.md +79 -0
  85. package/commands/memory.md +213 -0
  86. package/commands/models.md +200 -0
  87. package/commands/mos-reason.md +489 -0
  88. package/commands/mos.md +162 -0
  89. package/commands/mullins.md +155 -0
  90. package/commands/mva-brief.md +86 -0
  91. package/commands/mva-option.md +119 -0
  92. package/commands/mva-report.md +76 -0
  93. package/commands/new-project.md +633 -0
  94. package/commands/new-surface.md +116 -0
  95. package/commands/onboard.md +489 -0
  96. package/commands/operator.md +168 -0
  97. package/commands/opportunities.md +177 -0
  98. package/commands/organize.md +74 -0
  99. package/commands/persona.md +276 -0
  100. package/commands/pipeline.md +167 -0
  101. package/commands/present.md +125 -0
  102. package/commands/publish.md +227 -0
  103. package/commands/pws-brain.md +154 -0
  104. package/commands/qualify-opportunity.md +113 -0
  105. package/commands/query.md +70 -0
  106. package/commands/radar.md +110 -0
  107. package/commands/reanalyze.md +124 -0
  108. package/commands/research.md +467 -0
  109. package/commands/room.md +385 -0
  110. package/commands/rooms.md +682 -0
  111. package/commands/root-cause.md +77 -0
  112. package/commands/rs-experts.md +153 -0
  113. package/commands/rs-explain.md +134 -0
  114. package/commands/rs-fetch.md +119 -0
  115. package/commands/rs-thesis.md +131 -0
  116. package/commands/scenario-plan.md +80 -0
  117. package/commands/scheduled-tasks.md +308 -0
  118. package/commands/score-innovation.md +78 -0
  119. package/commands/scout.md +379 -0
  120. package/commands/setup.md +658 -0
  121. package/commands/show.md +71 -0
  122. package/commands/skill.md +108 -0
  123. package/commands/snapshot.md +179 -0
  124. package/commands/speakers.md +118 -0
  125. package/commands/splash.md +55 -0
  126. package/commands/stance.md +91 -0
  127. package/commands/status.md +109 -0
  128. package/commands/structure-argument.md +82 -0
  129. package/commands/suggest-next.md +141 -0
  130. package/commands/systems-thinking.md +224 -0
  131. package/commands/think-hats.md +86 -0
  132. package/commands/trending-to-absurd.md +151 -0
  133. package/commands/update.md +256 -0
  134. package/commands/user-needs.md +77 -0
  135. package/commands/validate.md +77 -0
  136. package/commands/value-proposition.md +116 -0
  137. package/commands/vault.md +330 -0
  138. package/commands/visualize.md +71 -0
  139. package/commands/whitespace.md +541 -0
  140. package/commands/wiki.md +96 -0
  141. package/data/ROOM.md +47 -0
  142. package/data/brain-census.generated.json +2617 -0
  143. package/data/brain-orchestration-projection.json +4973 -0
  144. package/data/brain-packet-schema.json +545 -0
  145. package/data/brain-surface-contract.json +32 -0
  146. package/data/capability-ledger.json +391 -0
  147. package/data/capability-map-registry.json +23 -0
  148. package/data/command-registry.json +2433 -0
  149. package/data/connector-coverage-ledger.json +1618 -0
  150. package/data/connector-out-of-spine-allowlist.json +71 -0
  151. package/data/connector-registry.json +3637 -0
  152. package/data/corpus-stats-source.json +11 -0
  153. package/data/corpus-stats.generated.json +10 -0
  154. package/data/cross-domain-analogues.json +15 -0
  155. package/data/deck-aliases.json +6 -0
  156. package/data/deck-styles.json +85 -0
  157. package/data/deployment-surfaces.json +69 -0
  158. package/data/dispatch-framework-map.json +18 -0
  159. package/data/doctor-modules.json +206 -0
  160. package/data/dual-graph-health-baseline.json +12 -0
  161. package/data/eureka-critic-tags.json +32 -0
  162. package/data/first-reward-surfaces.json +66 -0
  163. package/data/first-touch-surfaces.json +60 -0
  164. package/data/flagship-floor-set.json +37 -0
  165. package/data/framework-names.json +121 -0
  166. package/data/grant-rubric-fixtures/early-stage-pre-seed.json +18 -0
  167. package/data/grant-rubric-fixtures/early-stage-round-a.json +18 -0
  168. package/data/grant-rubric-fixtures/early-stage-seed.json +18 -0
  169. package/data/grant-rubric-fixtures/hybrid-seed-incentive.json +18 -0
  170. package/data/grant-rubric-fixtures/rd-fund.json +18 -0
  171. package/data/grant-rubric-fixtures/regional-innovation-incubators.json +18 -0
  172. package/data/grant-rubric-fixtures/technology-incubators.json +18 -0
  173. package/data/grant-rubric-fixtures/tnufa.json +167 -0
  174. package/data/grant-rubric-schema.json +33 -0
  175. package/data/harness-fixtures/converged-room/.context/ROOM.md +13 -0
  176. package/data/harness-fixtures/converged-room/.intelligence/ROOM.md +13 -0
  177. package/data/harness-fixtures/converged-room/.snapshots/ROOM.md +13 -0
  178. package/data/harness-fixtures/converged-room/MINTO.md +19 -0
  179. package/data/harness-fixtures/converged-room/STATE.md +73 -0
  180. package/data/harness-fixtures/converged-room/USER.md +23 -0
  181. package/data/harness-fixtures/converged-room/assets/ROOM.md +13 -0
  182. package/data/harness-fixtures/converged-room/business-model/CONTEXT.md +32 -0
  183. package/data/harness-fixtures/converged-room/business-model/ROOM.md +36 -0
  184. package/data/harness-fixtures/converged-room/competitive-analysis/CONTEXT.md +33 -0
  185. package/data/harness-fixtures/converged-room/competitive-analysis/ROOM.md +35 -0
  186. package/data/harness-fixtures/converged-room/financial-model/CONTEXT.md +30 -0
  187. package/data/harness-fixtures/converged-room/financial-model/ROOM.md +35 -0
  188. package/data/harness-fixtures/converged-room/funding/CONTEXT.md +41 -0
  189. package/data/harness-fixtures/converged-room/funding/ROOM.md +35 -0
  190. package/data/harness-fixtures/converged-room/legal-ip/CONTEXT.md +30 -0
  191. package/data/harness-fixtures/converged-room/legal-ip/ROOM.md +35 -0
  192. package/data/harness-fixtures/converged-room/market-analysis/CONTEXT.md +32 -0
  193. package/data/harness-fixtures/converged-room/market-analysis/ROOM.md +35 -0
  194. package/data/harness-fixtures/converged-room/opportunity-bank/CONTEXT.md +39 -0
  195. package/data/harness-fixtures/converged-room/opportunity-bank/ROOM.md +36 -0
  196. package/data/harness-fixtures/converged-room/problem-definition/CONTEXT.md +32 -0
  197. package/data/harness-fixtures/converged-room/problem-definition/ROOM.md +36 -0
  198. package/data/harness-fixtures/converged-room/references/ROOM.md +13 -0
  199. package/data/harness-fixtures/converged-room/references/SECTION-SCHEMA.md +213 -0
  200. package/data/harness-fixtures/converged-room/references/SUB-SCHEMAS.md +91 -0
  201. package/data/harness-fixtures/converged-room/solution-design/CONTEXT.md +36 -0
  202. package/data/harness-fixtures/converged-room/solution-design/ROOM.md +36 -0
  203. package/data/harness-fixtures/converged-room/strategy/CONTEXT.md +35 -0
  204. package/data/harness-fixtures/converged-room/strategy/ROOM.md +35 -0
  205. package/data/harness-fixtures/converged-room/team/ROOM.md +13 -0
  206. package/data/harness-fixtures/converged-room/team-execution/CONTEXT.md +36 -0
  207. package/data/harness-fixtures/converged-room/team-execution/ROOM.md +35 -0
  208. package/data/harness-manifest.json +74 -0
  209. package/data/harness-policies/CONTEXT.md +55 -0
  210. package/data/harness-policies/_schema.json +42 -0
  211. package/data/harness-policies/contract-parity-larry.json +63 -0
  212. package/data/harness-policies/gate-card-fire.json +13 -0
  213. package/data/harness-policies/gate-graph-derive-health.json +13 -0
  214. package/data/harness-policies/gate-shape-declaration.json +13 -0
  215. package/data/harness-policies/gate-tool-honesty.json +13 -0
  216. package/data/harness-policies/gate-worktree-hygiene.json +13 -0
  217. package/data/harness-policies/memory-write-policy.json +28 -0
  218. package/data/harness-policies/registry-drift.json +13 -0
  219. package/data/harness-policies/release-payload-ceiling.json +13 -0
  220. package/data/harness-policies/voice-backend-noun-free.json +13 -0
  221. package/data/harness-policies/voice-fork-as-card.json +13 -0
  222. package/data/harness-policies/voice-glyph-present.json +13 -0
  223. package/data/harness-policies/voice-hyphens-only.json +13 -0
  224. package/data/help-groups.json +236 -0
  225. package/data/hitl-shape-backfill.json +777 -0
  226. package/data/hitl-shape-declaration-fixtures/invalid-bad-shape.json +5 -0
  227. package/data/hitl-shape-declaration-fixtures/invalid-missing-why.json +4 -0
  228. package/data/hitl-shape-declaration-fixtures/invalid-ranker-contradiction.json +6 -0
  229. package/data/hitl-shape-declaration-fixtures/invalid-skill-gap.json +3 -0
  230. package/data/hitl-shape-declaration-fixtures/valid-multi-stage.json +7 -0
  231. package/data/hitl-shape-declaration-fixtures/valid-single-shape.json +5 -0
  232. package/data/hitl-shape-declaration-fixtures/valid-skill-exempt.json +5 -0
  233. package/data/hitl-shape-declaration-schema.json +34 -0
  234. package/data/hitl-stages-fixtures/bono.json +10 -0
  235. package/data/hitl-stages-fixtures/pipeline-1.json +9 -0
  236. package/data/hitl-stages-fixtures/pipeline-2.json +9 -0
  237. package/data/hitl-stages-fixtures/pipeline-3.json +10 -0
  238. package/data/hitl-stages-fixtures/research.json +10 -0
  239. package/data/hitl-stages-fixtures/rs-convergence.json +10 -0
  240. package/data/hitl-stages-fixtures/rs-family.json +11 -0
  241. package/data/hitl-stages-fixtures/rs-reverse-salient.json +10 -0
  242. package/data/hitl-stages-fixtures/trending-to-absurd.json +11 -0
  243. package/data/hitl-stages-schema.json +26 -0
  244. package/data/mcp-tool-connectors.json +464 -0
  245. package/data/mva-agent-prompts.json +31 -0
  246. package/data/mva-deck-template.html +15 -0
  247. package/data/mva-heuristic-keywords.json +35 -0
  248. package/data/orchestration-command-ledger.json +576 -0
  249. package/data/orchestration-unwired-allowlist.json +6 -0
  250. package/data/portfolio-ahp-matrix.json +16 -0
  251. package/data/publish-needs.json +76 -0
  252. package/data/render-coverage-registry.json +1152 -0
  253. package/data/research-sources.json +58 -0
  254. package/data/roadmap-type-chains.json +28 -0
  255. package/data/room-blueprints.json +156 -0
  256. package/data/subagent-dispatch-grants.json +150 -0
  257. package/hooks/hooks.json +493 -0
  258. package/hooks/run-hook.cmd +64 -0
  259. package/lib/__init__.py +0 -0
  260. package/lib/__pycache__/__init__.cpython-312.pyc +0 -0
  261. package/lib/agents/auto-explore-agent.cjs +1163 -0
  262. package/lib/agents/mva/brain-classic-traps.cjs +55 -0
  263. package/lib/agents/mva/brain-cross-domain.cjs +79 -0
  264. package/lib/agents/mva/brain-similar-ventures.cjs +93 -0
  265. package/lib/agents/mva/dashboard-graph-neighborhood.cjs +72 -0
  266. package/lib/agents/mva/index.cjs +42 -0
  267. package/lib/agents/mva/six-hats-red-black.cjs +137 -0
  268. package/lib/agents/mva/tavily-funding-scan.cjs +147 -0
  269. package/lib/agents/mva/test-all-six-agents.cjs +467 -0
  270. package/lib/agents/reverse-salient-agent.cjs +757 -0
  271. package/lib/agents/tension-hook-agent.cjs +586 -0
  272. package/lib/brain/ROOM.md +44 -0
  273. package/lib/brain/chain-recommender.cjs +784 -0
  274. package/lib/brain/curation-batch.cjs +519 -0
  275. package/lib/brain/framework-chain-slice.cjs +252 -0
  276. package/lib/brain/hypergraph-event-schema.cjs +184 -0
  277. package/lib/chat/chat-context.js +185 -0
  278. package/lib/chat/chat-panel.js +721 -0
  279. package/lib/chat/fabric-chat.cjs +288 -0
  280. package/lib/chat/generative-tools.js +219 -0
  281. package/lib/conversation/ROOM.md +39 -0
  282. package/lib/conversation/classifier-rules.json +38 -0
  283. package/lib/conversation/classifier.cjs +264 -0
  284. package/lib/conversation/operator-epistemic-cap.test.cjs +156 -0
  285. package/lib/conversation/operator.cjs +492 -0
  286. package/lib/conversation/operator.test.cjs +160 -0
  287. package/lib/copy/115-spec-strings.cjs +55 -0
  288. package/lib/core/__init__.py +0 -0
  289. package/lib/core/__nav-stub.cjs +14 -0
  290. package/lib/core/__pycache__/__init__.cpython-312.pyc +0 -0
  291. package/lib/core/__pycache__/rs-math.cpython-312.pyc +0 -0
  292. package/lib/core/__pycache__/rs_cache.cpython-312.pyc +0 -0
  293. package/lib/core/__pycache__/rs_corpus.cpython-312.pyc +0 -0
  294. package/lib/core/__pycache__/rs_corpus_exclude.cpython-312.pyc +0 -0
  295. package/lib/core/__pycache__/rs_hybrid.cpython-312.pyc +0 -0
  296. package/lib/core/__pycache__/rs_math.cpython-312.pyc +0 -0
  297. package/lib/core/__pycache__/rs_rooms.cpython-312.pyc +0 -0
  298. package/lib/core/abstraction-gate.cjs +133 -0
  299. package/lib/core/act-jtbd-blurb.cjs +231 -0
  300. package/lib/core/artifact-id.cjs +148 -0
  301. package/lib/core/asset-ops.cjs +151 -0
  302. package/lib/core/auto-commit-throttle.cjs +129 -0
  303. package/lib/core/bearer-token.cjs +199 -0
  304. package/lib/core/behavioral/observation-schema.cjs +86 -0
  305. package/lib/core/bono/cell-fanout.cjs +305 -0
  306. package/lib/core/bono/debate-composition.cjs +495 -0
  307. package/lib/core/bono/hat-governance.cjs +367 -0
  308. package/lib/core/bono/persona-research.cjs +288 -0
  309. package/lib/core/bono/reviewer-governance.cjs +331 -0
  310. package/lib/core/brain-client.cjs +2365 -0
  311. package/lib/core/brain-derivation-prompts.cjs +331 -0
  312. package/lib/core/brain-derivation-queue.cjs +535 -0
  313. package/lib/core/brain-derivation.cjs +740 -0
  314. package/lib/core/brain-md-schema.cjs +528 -0
  315. package/lib/core/brain-md-staleness.cjs +357 -0
  316. package/lib/core/brain-response-sanitize.cjs +396 -0
  317. package/lib/core/breakthrough/canary.cjs +134 -0
  318. package/lib/core/breakthrough/canary.test.cjs +136 -0
  319. package/lib/core/breakthrough/detectors.cjs +359 -0
  320. package/lib/core/breakthrough/detectors.test.cjs +333 -0
  321. package/lib/core/breakthrough/ethics-fence.cjs +129 -0
  322. package/lib/core/breakthrough/ethics-fence.test.cjs +178 -0
  323. package/lib/core/breakthrough/resurfacing.cjs +150 -0
  324. package/lib/core/breakthrough/resurfacing.test.cjs +233 -0
  325. package/lib/core/breakthrough/review-queue.cjs +168 -0
  326. package/lib/core/breakthrough/review-queue.test.cjs +160 -0
  327. package/lib/core/breakthrough/scanner-d17-d18.test.cjs +229 -0
  328. package/lib/core/breakthrough/scanner.cjs +435 -0
  329. package/lib/core/breakthrough/scanner.test.cjs +267 -0
  330. package/lib/core/breakthrough/schema.cjs +180 -0
  331. package/lib/core/breakthrough/schema.test.cjs +256 -0
  332. package/lib/core/breakthrough/scoring.cjs +293 -0
  333. package/lib/core/breakthrough/scoring.test.cjs +423 -0
  334. package/lib/core/breakthrough/verb-dispatch.cjs +230 -0
  335. package/lib/core/breakthrough/verb-dispatch.test.cjs +185 -0
  336. package/lib/core/breakthrough/voice-scaffold.cjs +249 -0
  337. package/lib/core/breakthrough/voice-scaffold.test.cjs +251 -0
  338. package/lib/core/bridge-writer.cjs +477 -0
  339. package/lib/core/cache-prune.cjs +314 -0
  340. package/lib/core/card-fire-gate.cjs +107 -0
  341. package/lib/core/card-fire-sidechannel.cjs +518 -0
  342. package/lib/core/chain-executor.cjs +939 -0
  343. package/lib/core/chain-retry.cjs +214 -0
  344. package/lib/core/chain-step-dispatcher.cjs +397 -0
  345. package/lib/core/chat-context-builder.cjs +253 -0
  346. package/lib/core/check-plugin-enabled.cjs +145 -0
  347. package/lib/core/close-loop-writer.cjs +492 -0
  348. package/lib/core/command-registration-check.cjs +246 -0
  349. package/lib/core/correlation-label-index.cjs +230 -0
  350. package/lib/core/correlation.cjs +112 -0
  351. package/lib/core/coverage-monitor.cjs +183 -0
  352. package/lib/core/coverage-rollup.cjs +232 -0
  353. package/lib/core/cross-room-aggregator.cjs +1127 -0
  354. package/lib/core/cross-room-store.cjs +292 -0
  355. package/lib/core/cross-room-triggers.cjs +222 -0
  356. package/lib/core/daily-briefing.cjs +438 -0
  357. package/lib/core/decision-axes.cjs +178 -0
  358. package/lib/core/decision-capture.cjs +618 -0
  359. package/lib/core/deck-design-rules.cjs +211 -0
  360. package/lib/core/deep-links.cjs +82 -0
  361. package/lib/core/directive-envelope.cjs +217 -0
  362. package/lib/core/directive-envelope.test.cjs +225 -0
  363. package/lib/core/dispatch-optimizer.cjs +354 -0
  364. package/lib/core/doc-text-extractor.cjs +133 -0
  365. package/lib/core/doctor/capability-ledger-module.cjs +170 -0
  366. package/lib/core/doctor/card-fire-health-module.cjs +159 -0
  367. package/lib/core/doctor/cascade-rooms-active-module.cjs +127 -0
  368. package/lib/core/doctor/cascade-rooms-module.cjs +184 -0
  369. package/lib/core/doctor/class-m-brain-smoke.cjs +479 -0
  370. package/lib/core/doctor/class-m-brain-smoke.test.cjs +448 -0
  371. package/lib/core/doctor/class-s-eureka-smoke.cjs +380 -0
  372. package/lib/core/doctor/deployment-surfaces-module.cjs +408 -0
  373. package/lib/core/doctor/deprecated-usage-module.cjs +155 -0
  374. package/lib/core/doctor/eureka-fts-health-module.cjs +236 -0
  375. package/lib/core/doctor/graph-derive-heal-retrofit-module.cjs +148 -0
  376. package/lib/core/doctor/graph-derive-health-module.cjs +486 -0
  377. package/lib/core/doctor/install-incomplete-module.cjs +320 -0
  378. package/lib/core/doctor/install-state-module.cjs +503 -0
  379. package/lib/core/doctor/mcp-surface-module.cjs +369 -0
  380. package/lib/core/doctor/mode-select-checkpoint-module.cjs +113 -0
  381. package/lib/core/doctor/plugin-enabled-state-module.cjs +86 -0
  382. package/lib/core/doctor/room-graph-density-module.cjs +181 -0
  383. package/lib/core/doctor/room-md-module.cjs +198 -0
  384. package/lib/core/doctor/shared.cjs +555 -0
  385. package/lib/core/doctor/stale-first-touch-copy-module.cjs +83 -0
  386. package/lib/core/doctor/statusline-visibility-module.cjs +295 -0
  387. package/lib/core/doctor/ui-compliance-module.cjs +223 -0
  388. package/lib/core/doctor/umbilical-module.cjs +486 -0
  389. package/lib/core/doctor/verify-surface-module.cjs +82 -0
  390. package/lib/core/doctor/voice-style-log-module.cjs +146 -0
  391. package/lib/core/domain-insight-sweep.cjs +224 -0
  392. package/lib/core/drift-baseline.cjs +362 -0
  393. package/lib/core/drift-runtime-reachability.cjs +283 -0
  394. package/lib/core/dual-path-detector.cjs +84 -0
  395. package/lib/core/dual-path-detector.test.cjs +334 -0
  396. package/lib/core/enrichment-queue.cjs +636 -0
  397. package/lib/core/eureka/ahp-weights.cjs +232 -0
  398. package/lib/core/eureka/analogy-fitness.cjs +326 -0
  399. package/lib/core/eureka/compression-meter.cjs +165 -0
  400. package/lib/core/eureka/embedding-classifier.cjs +226 -0
  401. package/lib/core/eureka/embedding-spine.cjs +563 -0
  402. package/lib/core/eureka/entity-classifier.cjs +232 -0
  403. package/lib/core/eureka/entity-extractor.cjs +356 -0
  404. package/lib/core/eureka/eureka-enable.cjs +228 -0
  405. package/lib/core/eureka/eureka-offer.cjs +225 -0
  406. package/lib/core/eureka/eureka-reach-runner.cjs +430 -0
  407. package/lib/core/eureka/explore-chain.cjs +834 -0
  408. package/lib/core/eureka/explored-artifact.cjs +456 -0
  409. package/lib/core/eureka/fts-index-lifecycle.cjs +265 -0
  410. package/lib/core/eureka/grade-grant-examine.cjs +544 -0
  411. package/lib/core/eureka/grade-grant.cjs +596 -0
  412. package/lib/core/eureka/hybrid-retrieve.cjs +256 -0
  413. package/lib/core/eureka/lateral-engine-adapter.cjs +118 -0
  414. package/lib/core/eureka/lexical-overlap.cjs +98 -0
  415. package/lib/core/eureka/online-pattern-query.cjs +142 -0
  416. package/lib/core/eureka/opportunity-harvest.cjs +752 -0
  417. package/lib/core/eureka/opportunity-statement.cjs +519 -0
  418. package/lib/core/eureka/portfolio-dimensions.cjs +255 -0
  419. package/lib/core/eureka/qualify-opportunity.cjs +607 -0
  420. package/lib/core/eureka/reasoning-mode.cjs +481 -0
  421. package/lib/core/eureka/report-html.cjs +368 -0
  422. package/lib/core/eureka/research-filing.cjs +547 -0
  423. package/lib/core/eureka/room-native-substrate.cjs +343 -0
  424. package/lib/core/eureka/tail-quadrant.cjs +177 -0
  425. package/lib/core/eureka/tri-modal-index.cjs +564 -0
  426. package/lib/core/eureka/vector-store.cjs +414 -0
  427. package/lib/core/eureka-critic.cjs +733 -0
  428. package/lib/core/eureka-deps-resolver.cjs +179 -0
  429. package/lib/core/expert-genesis.cjs +437 -0
  430. package/lib/core/expert-library.cjs +303 -0
  431. package/lib/core/exports-log.cjs +79 -0
  432. package/lib/core/feynman/ROOM.md +25 -0
  433. package/lib/core/feynman/dial-memory-renderer.cjs +279 -0
  434. package/lib/core/feynman/dial-memory-runner.cjs +173 -0
  435. package/lib/core/feynman/feynman-seed-writer.cjs +187 -0
  436. package/lib/core/feynman/timeline-renderer.cjs +197 -0
  437. package/lib/core/feynman/timeline-runner.cjs +281 -0
  438. package/lib/core/feynman-minto-invariants.cjs +609 -0
  439. package/lib/core/findings-wirer.cjs +360 -0
  440. package/lib/core/first-touch-version-stamper.cjs +113 -0
  441. package/lib/core/folder-memory-async.cjs +424 -0
  442. package/lib/core/folder-memory-shared.cjs +890 -0
  443. package/lib/core/folder-memory.cjs +546 -0
  444. package/lib/core/framework-chain-composer.cjs +583 -0
  445. package/lib/core/frontmatter-schemas.cjs +468 -0
  446. package/lib/core/fusion-router.cjs +540 -0
  447. package/lib/core/futures/causal-cue.cjs +91 -0
  448. package/lib/core/futures/orchestrator.cjs +1391 -0
  449. package/lib/core/futures/subsystem-render.cjs +164 -0
  450. package/lib/core/gate-relevance.cjs +278 -0
  451. package/lib/core/git-ops.cjs +141 -0
  452. package/lib/core/graph-backfill.cjs +562 -0
  453. package/lib/core/graph-candidate-producer.cjs +235 -0
  454. package/lib/core/graph-derivation.cjs +546 -0
  455. package/lib/core/graph-derive-classifier.cjs +352 -0
  456. package/lib/core/graph-ops.cjs +274 -0
  457. package/lib/core/graph-refine-loop.cjs +194 -0
  458. package/lib/core/graph-self-heal.cjs +289 -0
  459. package/lib/core/greeting-intent-detector.cjs +201 -0
  460. package/lib/core/grill-engine.cjs +459 -0
  461. package/lib/core/hat-persistence.cjs +274 -0
  462. package/lib/core/hsi-engine.cjs +439 -0
  463. package/lib/core/hsi-lsa.cjs +246 -0
  464. package/lib/core/hsi-spectral.cjs +554 -0
  465. package/lib/core/hsi-to-graph.test.cjs +168 -0
  466. package/lib/core/icm-forest.cjs +703 -0
  467. package/lib/core/ignite-branch-gate.cjs +66 -0
  468. package/lib/core/index.cjs +60 -0
  469. package/lib/core/insight-sensors.cjs +1000 -0
  470. package/lib/core/install-state.cjs +242 -0
  471. package/lib/core/integration-registry.cjs +232 -0
  472. package/lib/core/intel-pipeline.cjs +545 -0
  473. package/lib/core/intelligence-cascade.cjs +852 -0
  474. package/lib/core/issue-tree.cjs +269 -0
  475. package/lib/core/larry-thinness-acknowledgment.cjs +64 -0
  476. package/lib/core/larry-thinness-acknowledgment.test.cjs +97 -0
  477. package/lib/core/lazygraph-ops.cjs +1453 -0
  478. package/lib/core/lens-engine.cjs +434 -0
  479. package/lib/core/leverage-scan.cjs +218 -0
  480. package/lib/core/llm-name-suggester.cjs +194 -0
  481. package/lib/core/llm-name-suggester.test.cjs +132 -0
  482. package/lib/core/lru-cache.cjs +139 -0
  483. package/lib/core/mcp-dep-heal.cjs +475 -0
  484. package/lib/core/mcp-dep-heal.test.cjs +253 -0
  485. package/lib/core/mcp-profiles.cjs +185 -0
  486. package/lib/core/meeting-ops.cjs +54 -0
  487. package/lib/core/memory/governance-candidate-raiser.cjs +205 -0
  488. package/lib/core/memory/governance-candidate.cjs +95 -0
  489. package/lib/core/memory/reconcile-memory-runner.cjs +653 -0
  490. package/lib/core/memory-ops.cjs +641 -0
  491. package/lib/core/meter/gate-density-reader.cjs +112 -0
  492. package/lib/core/meter/transfer-reader.cjs +276 -0
  493. package/lib/core/meter/two-gauge.cjs +245 -0
  494. package/lib/core/methodology-ingest.cjs +346 -0
  495. package/lib/core/metrics/larryreach-loop-health.cjs +142 -0
  496. package/lib/core/migration-snapshot.cjs +287 -0
  497. package/lib/core/migration-snapshot.test.cjs +174 -0
  498. package/lib/core/migrations/ROOM.md +33 -0
  499. package/lib/core/migrations/phase-109-nodes-provenance.cjs +400 -0
  500. package/lib/core/migrations/phase-109-session-focus.cjs +99 -0
  501. package/lib/core/migrations/phase-160-nodes-bitemporal.cjs +168 -0
  502. package/lib/core/migrations/phase-160-nodes-bitemporal.test.cjs +140 -0
  503. package/lib/core/migrations/phase-162-section-nodes.cjs +156 -0
  504. package/lib/core/migrations/phase-222-ranker-weights.cjs +62 -0
  505. package/lib/core/migrations/phase-224-edge-review-status.cjs +87 -0
  506. package/lib/core/mindrian-brain-shim.test.cjs +221 -0
  507. package/lib/core/mode-select-sidechannel.cjs +259 -0
  508. package/lib/core/model-profiles.cjs +246 -0
  509. package/lib/core/mullins-scaffold.cjs +258 -0
  510. package/lib/core/mullins-scaffold.test.cjs +128 -0
  511. package/lib/core/mva-agent-contract.cjs +170 -0
  512. package/lib/core/mva-agent-contract.test.cjs +169 -0
  513. package/lib/core/mva-budget.cjs +75 -0
  514. package/lib/core/mva-budget.test.cjs +68 -0
  515. package/lib/core/mva-classifier.cjs +392 -0
  516. package/lib/core/mva-classifier.test.cjs +248 -0
  517. package/lib/core/mva-deck-builder.cjs +452 -0
  518. package/lib/core/mva-deck-builder.test.cjs +287 -0
  519. package/lib/core/mva-detect.smoke.test.cjs +209 -0
  520. package/lib/core/mva-dispatcher.cjs +110 -0
  521. package/lib/core/mva-dispatcher.test.cjs +216 -0
  522. package/lib/core/mva-option-router.cjs +414 -0
  523. package/lib/core/mva-option-router.test.cjs +483 -0
  524. package/lib/core/mva-orchestrator.cjs +365 -0
  525. package/lib/core/mva-orchestrator.test.cjs +916 -0
  526. package/lib/core/mva-progressive-renderer.cjs +194 -0
  527. package/lib/core/mva-progressive-renderer.test.cjs +157 -0
  528. package/lib/core/mva-rule-linter.cjs +458 -0
  529. package/lib/core/mva-rule-linter.test.cjs +484 -0
  530. package/lib/core/mva-state.cjs +159 -0
  531. package/lib/core/mva-telemetry.cjs +58 -0
  532. package/lib/core/mva-telemetry.test.cjs +196 -0
  533. package/lib/core/mva-vercel-deploy.cjs +168 -0
  534. package/lib/core/mva-vercel-deploy.test.cjs +239 -0
  535. package/lib/core/nav-dial.cjs +440 -0
  536. package/lib/core/navigation/ROOM.md +15 -0
  537. package/lib/core/navigation/abstraction-claim.cjs +185 -0
  538. package/lib/core/navigation/calibration-gate.cjs +284 -0
  539. package/lib/core/navigation/calibration-log.cjs +141 -0
  540. package/lib/core/navigation/confirm-node.cjs +73 -0
  541. package/lib/core/navigation/dashboard-helpers.cjs +145 -0
  542. package/lib/core/navigation/edges.cjs +1150 -0
  543. package/lib/core/navigation/evidence-claim.cjs +186 -0
  544. package/lib/core/navigation/explanation.cjs +48 -0
  545. package/lib/core/navigation/file-evidence-readback.cjs +242 -0
  546. package/lib/core/navigation/focus.cjs +155 -0
  547. package/lib/core/navigation/get-domains-for-trends.cjs +277 -0
  548. package/lib/core/navigation/governance.cjs +101 -0
  549. package/lib/core/navigation/grant-rubric.cjs +218 -0
  550. package/lib/core/navigation/graph-export.cjs +325 -0
  551. package/lib/core/navigation/ingestion.cjs +109 -0
  552. package/lib/core/navigation/insights-stale.test.cjs +127 -0
  553. package/lib/core/navigation/insights.cjs +574 -0
  554. package/lib/core/navigation/lens-nodes.cjs +315 -0
  555. package/lib/core/navigation/memory-artifacts.cjs +437 -0
  556. package/lib/core/navigation/memory-cortex-packet.cjs +274 -0
  557. package/lib/core/navigation/memory-events.cjs +811 -0
  558. package/lib/core/navigation/neighborhood.cjs +79 -0
  559. package/lib/core/navigation/packet.cjs +420 -0
  560. package/lib/core/navigation/planning-artifacts.cjs +219 -0
  561. package/lib/core/navigation/projections.cjs +295 -0
  562. package/lib/core/navigation/ranker-weights.cjs +133 -0
  563. package/lib/core/navigation/reasoning-write.cjs +211 -0
  564. package/lib/core/navigation/reconcile-guard.cjs +98 -0
  565. package/lib/core/navigation/reified-claim.cjs +287 -0
  566. package/lib/core/navigation/research-preflight.cjs +156 -0
  567. package/lib/core/navigation/room-birth.cjs +1213 -0
  568. package/lib/core/navigation/room-context.cjs +380 -0
  569. package/lib/core/navigation/room-home.cjs +142 -0
  570. package/lib/core/navigation/spine-events.cjs +548 -0
  571. package/lib/core/navigation/synthetic-expert.cjs +177 -0
  572. package/lib/core/navigation/transitions.cjs +253 -0
  573. package/lib/core/navigation/typed-claim.cjs +208 -0
  574. package/lib/core/navigation/typed-domain.cjs +249 -0
  575. package/lib/core/navigation/typed-entity.cjs +236 -0
  576. package/lib/core/navigation/typed-frame.cjs +257 -0
  577. package/lib/core/navigation/typed-open-question.cjs +130 -0
  578. package/lib/core/navigation/typed-opportunity.cjs +418 -0
  579. package/lib/core/navigation-engine-offer.cjs +776 -0
  580. package/lib/core/navigation-engine-shared.cjs +256 -0
  581. package/lib/core/navigation-engine.cjs +1696 -0
  582. package/lib/core/navigation.cjs +686 -0
  583. package/lib/core/nl-graph-queries.cjs +164 -0
  584. package/lib/core/node-insert-epistemic.test.cjs +212 -0
  585. package/lib/core/node-insert-overrides.test.cjs +273 -0
  586. package/lib/core/node-insert.cjs +274 -0
  587. package/lib/core/npm-cli-resolve.cjs +151 -0
  588. package/lib/core/npm-cli-resolve.test.cjs +153 -0
  589. package/lib/core/npm-install-lock.cjs +326 -0
  590. package/lib/core/npm-install-lock.test.cjs +379 -0
  591. package/lib/core/numeric/sklearn-stopwords-v1.json +325 -0
  592. package/lib/core/numeric/svd.cjs +377 -0
  593. package/lib/core/numeric/tfidf.cjs +241 -0
  594. package/lib/core/offer-presenter.cjs +406 -0
  595. package/lib/core/opportunity-extractor.cjs +183 -0
  596. package/lib/core/opportunity-ops.cjs +1423 -0
  597. package/lib/core/orchestration-candidate-lift.cjs +284 -0
  598. package/lib/core/part8-egress-guard.cjs +536 -0
  599. package/lib/core/part8-egress-guard.test.cjs +194 -0
  600. package/lib/core/part8-egress-ontology.cjs +174 -0
  601. package/lib/core/part8-egress-ontology.test.cjs +133 -0
  602. package/lib/core/persona-ops.cjs +692 -0
  603. package/lib/core/persona-override.cjs +327 -0
  604. package/lib/core/persona-taxonomy.cjs +328 -0
  605. package/lib/core/pinecone-inference.cjs +176 -0
  606. package/lib/core/pitch-feedback-schemas.cjs +303 -0
  607. package/lib/core/planning/artifact-brain-packet.cjs +212 -0
  608. package/lib/core/planning/reconcile-runner.cjs +347 -0
  609. package/lib/core/platform-gates.cjs +120 -0
  610. package/lib/core/platform.cjs +257 -0
  611. package/lib/core/proactive-intelligence.cjs +528 -0
  612. package/lib/core/problem-type-router.cjs +315 -0
  613. package/lib/core/publish-needs-default-lane.cjs +110 -0
  614. package/lib/core/ralph-loop-gate.cjs +48 -0
  615. package/lib/core/reader/ab-harness.cjs +177 -0
  616. package/lib/core/reader/decide-projection-reader.cjs +358 -0
  617. package/lib/core/reasoning-ops.cjs +639 -0
  618. package/lib/core/recipe-maps.cjs +442 -0
  619. package/lib/core/recovery/case-file.cjs +358 -0
  620. package/lib/core/recovery/controller.cjs +1008 -0
  621. package/lib/core/recovery/dispatcher.cjs +533 -0
  622. package/lib/core/recovery/result-semantics.cjs +488 -0
  623. package/lib/core/recovery/stage-envelope.cjs +338 -0
  624. package/lib/core/refusal-messaging.cjs +569 -0
  625. package/lib/core/refusal-messaging.test.cjs +220 -0
  626. package/lib/core/repo-version.cjs +134 -0
  627. package/lib/core/research-cache.cjs +165 -0
  628. package/lib/core/research-cache.test.cjs +137 -0
  629. package/lib/core/research-context-extractor.cjs +283 -0
  630. package/lib/core/research-corpus.cjs +814 -0
  631. package/lib/core/research-corpus.test.cjs +280 -0
  632. package/lib/core/research-filing-selector.cjs +189 -0
  633. package/lib/core/resolve-active-room.cjs +602 -0
  634. package/lib/core/resolve-brain-key.cjs +273 -0
  635. package/lib/core/resolve-umbilical-target.cjs +288 -0
  636. package/lib/core/resolve-vercel-key.cjs +107 -0
  637. package/lib/core/resolve-vercel-key.test.cjs +137 -0
  638. package/lib/core/reverse-salient-persona-suffix.cjs +115 -0
  639. package/lib/core/room-auto-create.cjs +318 -0
  640. package/lib/core/room-auto-create.test.cjs +198 -0
  641. package/lib/core/room-chooser.cjs +244 -0
  642. package/lib/core/room-classifier-strict-mode.cjs +235 -0
  643. package/lib/core/room-db.cjs +348 -0
  644. package/lib/core/room-discard-cascade.cjs +238 -0
  645. package/lib/core/room-discard-cascade.test.cjs +135 -0
  646. package/lib/core/room-name-validator.cjs +132 -0
  647. package/lib/core/room-name-validator.test.cjs +156 -0
  648. package/lib/core/room-naming-selector.cjs +357 -0
  649. package/lib/core/room-naming-selector.test.cjs +277 -0
  650. package/lib/core/room-open.cjs +259 -0
  651. package/lib/core/room-ops-async.cjs +92 -0
  652. package/lib/core/room-ops-shared.cjs +64 -0
  653. package/lib/core/room-ops-sync.cjs +70 -0
  654. package/lib/core/room-ops.cjs +32 -0
  655. package/lib/core/room-receipt-emit.cjs +63 -0
  656. package/lib/core/room-root.cjs +93 -0
  657. package/lib/core/room-skeleton-scaffold.cjs +669 -0
  658. package/lib/core/room-skeleton-scaffold.test.cjs +296 -0
  659. package/lib/core/room-type-detector.cjs +386 -0
  660. package/lib/core/rs-backend-dispatch.cjs +64 -0
  661. package/lib/core/rs-brain-substrate-prompts.cjs +129 -0
  662. package/lib/core/rs-brain-substrate.cjs +570 -0
  663. package/lib/core/rs-breakthrough-scorer.cjs +255 -0
  664. package/lib/core/rs-canon-violations.cjs +82 -0
  665. package/lib/core/rs-chain-feeder.cjs +381 -0
  666. package/lib/core/rs-commercial-assessor.cjs +280 -0
  667. package/lib/core/rs-corpus-quality-gate.cjs +62 -0
  668. package/lib/core/rs-differential-scorer.cjs +629 -0
  669. package/lib/core/rs-domain-analyzer.cjs +385 -0
  670. package/lib/core/rs-egress-prompts.cjs +113 -0
  671. package/lib/core/rs-egress-telemetry.cjs +225 -0
  672. package/lib/core/rs-egress-violations.cjs +53 -0
  673. package/lib/core/rs-engine.cjs +597 -0
  674. package/lib/core/rs-expert-brain-projection.cjs +280 -0
  675. package/lib/core/rs-expert-mapper.cjs +467 -0
  676. package/lib/core/rs-fetcher-academic.cjs +697 -0
  677. package/lib/core/rs-fetcher-experts.cjs +314 -0
  678. package/lib/core/rs-fetcher-industry.cjs +731 -0
  679. package/lib/core/rs-fetcher-patents.cjs +564 -0
  680. package/lib/core/rs-innovation-classifier.cjs +194 -0
  681. package/lib/core/rs-math.cjs +458 -0
  682. package/lib/core/rs-mind-map.cjs +656 -0
  683. package/lib/core/rs-neo4j-writer.cjs +388 -0
  684. package/lib/core/rs-nl-to-query.cjs +435 -0
  685. package/lib/core/rs-pinecone-bridge.cjs +344 -0
  686. package/lib/core/rs-preprocessor.cjs +350 -0
  687. package/lib/core/rs-query-matrix.cjs +316 -0
  688. package/lib/core/rs-query-to-text.cjs +438 -0
  689. package/lib/core/rs-sqlite-mirror.cjs +495 -0
  690. package/lib/core/rs-thesis-generator.cjs +188 -0
  691. package/lib/core/rs_cache.py +635 -0
  692. package/lib/core/rs_corpus.py +562 -0
  693. package/lib/core/rs_corpus_exclude.py +62 -0
  694. package/lib/core/rs_hybrid.py +589 -0
  695. package/lib/core/rs_math.py +287 -0
  696. package/lib/core/rs_rooms.py +196 -0
  697. package/lib/core/salient-governance.cjs +315 -0
  698. package/lib/core/scheduled-scanner.cjs +658 -0
  699. package/lib/core/scratchpad-ops.cjs +316 -0
  700. package/lib/core/seam-liveness.cjs +191 -0
  701. package/lib/core/seam-liveness.test.cjs +177 -0
  702. package/lib/core/section-8-trace-schema.cjs +138 -0
  703. package/lib/core/section-registry.cjs +167 -0
  704. package/lib/core/security/agentshield-adapters.test.cjs +104 -0
  705. package/lib/core/security/agentshield-run.cjs +343 -0
  706. package/lib/core/security/agentshield-scanner.cjs +314 -0
  707. package/lib/core/security/agentshield-scanner.test.cjs +259 -0
  708. package/lib/core/sensors/hat-scoping-table.cjs +103 -0
  709. package/lib/core/sensors/sensor-circularity.cjs +278 -0
  710. package/lib/core/sensors/sensor-content-relevance.cjs +407 -0
  711. package/lib/core/sensors/sensor-diffusion-adoption.cjs +230 -0
  712. package/lib/core/sensors/sensor-eureka.cjs +208 -0
  713. package/lib/core/sensors/sensor-expert-skill.cjs +293 -0
  714. package/lib/core/sensors/sensor-external-fact.cjs +184 -0
  715. package/lib/core/sensors/sensor-gate-approach.cjs +104 -0
  716. package/lib/core/sensors/sensor-jtbd-reweight.cjs +141 -0
  717. package/lib/core/sensors/sensor-lagging-component.cjs +115 -0
  718. package/lib/core/sensors/sensor-memory-cortex.cjs +111 -0
  719. package/lib/core/sensors/sensor-methodology-decision.cjs +131 -0
  720. package/lib/core/sensors/sensor-opportunity-harvest.cjs +195 -0
  721. package/lib/core/sensors/sensor-perspective-lock.cjs +174 -0
  722. package/lib/core/sensors/sensor-priority.cjs +183 -0
  723. package/lib/core/sensors/sensor-recency.cjs +151 -0
  724. package/lib/core/sensors/sensor-roadmap-type.cjs +421 -0
  725. package/lib/core/sensors/sensor-room-pick.cjs +238 -0
  726. package/lib/core/sensors/sensor-show-share.cjs +215 -0
  727. package/lib/core/sensors/sensor-temporal-blindness.cjs +123 -0
  728. package/lib/core/sensors/sensor-types.cjs +294 -0
  729. package/lib/core/sensors/sensor-url-ingest.cjs +234 -0
  730. package/lib/core/session-binding.cjs +208 -0
  731. package/lib/core/session-presence.cjs +404 -0
  732. package/lib/core/session-register.cjs +138 -0
  733. package/lib/core/session-state.cjs +144 -0
  734. package/lib/core/shallow-doc-parser.cjs +353 -0
  735. package/lib/core/shallow-doc-parser.test.cjs +226 -0
  736. package/lib/core/skill-activation-router.cjs +284 -0
  737. package/lib/core/skillopt-schemas.cjs +509 -0
  738. package/lib/core/stale-copy-scanner.cjs +190 -0
  739. package/lib/core/stance-state.cjs +153 -0
  740. package/lib/core/state-aware-router.cjs +78 -0
  741. package/lib/core/state-ops.cjs +80 -0
  742. package/lib/core/state-version.cjs +350 -0
  743. package/lib/core/statusline-cache.cjs +266 -0
  744. package/lib/core/statusline-liveness-gate.cjs +105 -0
  745. package/lib/core/surface-fence.cjs +127 -0
  746. package/lib/core/synthesizers/comparison-matrix.cjs +82 -0
  747. package/lib/core/synthesizers/convergence-map.cjs +107 -0
  748. package/lib/core/synthesizers/domain-hierarchy.cjs +138 -0
  749. package/lib/core/synthesizers/source-comparison.cjs +56 -0
  750. package/lib/core/synthesizers/tension-map.cjs +119 -0
  751. package/lib/core/synthetic-expert-behavior-gate.cjs +99 -0
  752. package/lib/core/synthetic-expert-construction-gate.cjs +170 -0
  753. package/lib/core/telemetry/schema.cjs +168 -0
  754. package/lib/core/telemetry/schema.test.cjs +124 -0
  755. package/lib/core/telemetry/validator.cjs +200 -0
  756. package/lib/core/telemetry/validator.test.cjs +188 -0
  757. package/lib/core/telemetry/writer.cjs +141 -0
  758. package/lib/core/telemetry/writer.test.cjs +331 -0
  759. package/lib/core/temporal/date-sync-gate.cjs +256 -0
  760. package/lib/core/temporal/date-sync-gate.test.cjs +191 -0
  761. package/lib/core/temporal/dual-stamp.cjs +172 -0
  762. package/lib/core/temporal/dual-stamp.test.cjs +172 -0
  763. package/lib/core/temporal/point-in-time.cjs +76 -0
  764. package/lib/core/temporal/point-in-time.test.cjs +169 -0
  765. package/lib/core/temporal/recency-decay.cjs +119 -0
  766. package/lib/core/temporal/recency-decay.test.cjs +140 -0
  767. package/lib/core/temporal/reference-now.cjs +281 -0
  768. package/lib/core/temporal/reference-now.test.cjs +225 -0
  769. package/lib/core/temporal/resolve-relative-time.cjs +116 -0
  770. package/lib/core/temporal/resolve-relative-time.test.cjs +138 -0
  771. package/lib/core/temporal/supersession.cjs +250 -0
  772. package/lib/core/temporal/supersession.test.cjs +103 -0
  773. package/lib/core/terminal-capability.cjs +88 -0
  774. package/lib/core/token-estimator.cjs +348 -0
  775. package/lib/core/tone-filter.cjs +147 -0
  776. package/lib/core/trending-to-absurd/orchestrator.cjs +341 -0
  777. package/lib/core/trending-to-absurd/stage7-roadmap.cjs +317 -0
  778. package/lib/core/trending-to-absurd/variance.cjs +169 -0
  779. package/lib/core/unknowns/bandit.cjs +332 -0
  780. package/lib/core/unknowns/corpus-adapter.cjs +327 -0
  781. package/lib/core/unknowns/dsp.cjs +356 -0
  782. package/lib/core/unknowns/edge-writer.cjs +211 -0
  783. package/lib/core/unknowns/iface.cjs +212 -0
  784. package/lib/core/unknowns/orchestrator.cjs +375 -0
  785. package/lib/core/unknowns/pattern-miner.cjs +214 -0
  786. package/lib/core/unknowns/rumsfeld-matrix.cjs +155 -0
  787. package/lib/core/unknowns/verdict.cjs +254 -0
  788. package/lib/core/update-path.cjs +57 -0
  789. package/lib/core/url-ingest.cjs +568 -0
  790. package/lib/core/user-archetype.cjs +284 -0
  791. package/lib/core/user-md-ops.cjs +578 -0
  792. package/lib/core/venture-shape-nudge.cjs +178 -0
  793. package/lib/core/venture-shape-nudge.test.cjs +266 -0
  794. package/lib/core/verb-reach-affinity.cjs +299 -0
  795. package/lib/core/visual-ops.cjs +692 -0
  796. package/lib/core/voice-transition-detector.cjs +125 -0
  797. package/lib/core/watched-sources.cjs +237 -0
  798. package/lib/core/write-lock.cjs +149 -0
  799. package/lib/graph/canvas-graph.js +467 -0
  800. package/lib/graph/constellation-config.cjs +299 -0
  801. package/lib/graph/graph-detail-panel.js +165 -0
  802. package/lib/hmi/ROOM.md +47 -0
  803. package/lib/hmi/across-session-memory.cjs +669 -0
  804. package/lib/hmi/agentshield-drift-gate.cjs +142 -0
  805. package/lib/hmi/brain-review-packet.cjs +221 -0
  806. package/lib/hmi/cortex-reach-adapter.cjs +271 -0
  807. package/lib/hmi/cross-room-memory.cjs +618 -0
  808. package/lib/hmi/decoy-tier.cjs +395 -0
  809. package/lib/hmi/depth-state.cjs +164 -0
  810. package/lib/hmi/dial-label-composer.cjs +410 -0
  811. package/lib/hmi/dial-presenter.cjs +508 -0
  812. package/lib/hmi/dial-reach-orchestrator.cjs +377 -0
  813. package/lib/hmi/dial-selector.cjs +239 -0
  814. package/lib/hmi/f1-pick-capture-cli.cjs +131 -0
  815. package/lib/hmi/f3-depth-capture-cli.cjs +77 -0
  816. package/lib/hmi/f4-scope-capture-cli.cjs +86 -0
  817. package/lib/hmi/f8-action-capture-cli.cjs +145 -0
  818. package/lib/hmi/f8-capture.test.cjs +77 -0
  819. package/lib/hmi/f9-ordered-capture-cli.cjs +138 -0
  820. package/lib/hmi/harvest-scope-state.cjs +202 -0
  821. package/lib/hmi/hats-persona-cache.cjs +142 -0
  822. package/lib/hmi/jtbd-classifier.cjs +219 -0
  823. package/lib/hmi/jtbd-state.cjs +263 -0
  824. package/lib/hmi/jtbd-taxonomy.json +402 -0
  825. package/lib/hmi/mindrian-ascii-logo.cjs +96 -0
  826. package/lib/hmi/part8-egress-gate.cjs +149 -0
  827. package/lib/hmi/reach-component-map.json +47 -0
  828. package/lib/hmi/reach-relevance-gate.cjs +147 -0
  829. package/lib/hmi/selector-dispatcher.cjs +1201 -0
  830. package/lib/hmi/selector-dispatcher.test.cjs +141 -0
  831. package/lib/hmi/selector-telemetry.cjs +269 -0
  832. package/lib/hmi/shape-f0-renderer.cjs +145 -0
  833. package/lib/hmi/shape-f1-fallback.cjs +80 -0
  834. package/lib/hmi/shape-f1-renderer.cjs +219 -0
  835. package/lib/hmi/shape-f2-renderer.cjs +132 -0
  836. package/lib/hmi/shape-f3-parity.test.cjs +64 -0
  837. package/lib/hmi/shape-f3-renderer.cjs +66 -0
  838. package/lib/hmi/shape-f4-parity.test.cjs +72 -0
  839. package/lib/hmi/shape-f4-renderer.cjs +72 -0
  840. package/lib/hmi/shape-f5-renderer.cjs +155 -0
  841. package/lib/hmi/shape-f6-plan-review-renderer.cjs +324 -0
  842. package/lib/hmi/shape-f6-renderer.cjs +144 -0
  843. package/lib/hmi/shape-f7-breakthrough-renderer.cjs +234 -0
  844. package/lib/hmi/shape-f7-breakthrough-renderer.test.cjs +233 -0
  845. package/lib/hmi/shape-f8-renderer.cjs +150 -0
  846. package/lib/hmi/shape-f8-renderer.test.cjs +70 -0
  847. package/lib/hmi/shape-f9-renderer.cjs +187 -0
  848. package/lib/hmi/shape-f9-renderer.test.cjs +80 -0
  849. package/lib/hmi/shape-g-renderer.cjs +219 -0
  850. package/lib/hmi/shape-h-renderer.cjs +222 -0
  851. package/lib/hmi/tier-check.cjs +63 -0
  852. package/lib/hmi/turn-text.cjs +268 -0
  853. package/lib/hmi/voice-color-mark.cjs +318 -0
  854. package/lib/hmi/voice-style-log.cjs +276 -0
  855. package/lib/import/PRECONDITIONS.md +41 -0
  856. package/lib/import/branding.cjs +210 -0
  857. package/lib/import/branding.test.cjs +235 -0
  858. package/lib/import/classifications-sync.cjs +104 -0
  859. package/lib/import/classifications-sync.test.cjs +129 -0
  860. package/lib/import/enricher.cjs +296 -0
  861. package/lib/import/enricher.test.cjs +273 -0
  862. package/lib/import/integration.test.cjs +376 -0
  863. package/lib/import/manifest.cjs +129 -0
  864. package/lib/import/manifest.schema.json +185 -0
  865. package/lib/import/manifest.test.cjs +123 -0
  866. package/lib/import/meeting-detector.cjs +92 -0
  867. package/lib/import/meeting-detector.test.cjs +100 -0
  868. package/lib/import/person-detector.cjs +229 -0
  869. package/lib/import/person-detector.test.cjs +149 -0
  870. package/lib/import/report.cjs +186 -0
  871. package/lib/import/report.test.cjs +186 -0
  872. package/lib/import/room-md-scaffolder.cjs +49 -0
  873. package/lib/import/router.cjs +224 -0
  874. package/lib/import/router.test.cjs +356 -0
  875. package/lib/import/run-all-tests.cjs +36 -0
  876. package/lib/import/smoke-test.cjs +213 -0
  877. package/lib/import/smoke-test.test.cjs +148 -0
  878. package/lib/import/undo.test.cjs +199 -0
  879. package/lib/import/vault-scanner.cjs +105 -0
  880. package/lib/import/vault-scanner.test.cjs +67 -0
  881. package/lib/lens-engine/correlation-resolver.cjs +174 -0
  882. package/lib/lens-engine/source-lens-driver.cjs +736 -0
  883. package/lib/mcp/adapter-client.cjs +103 -0
  884. package/lib/mcp/app-html/dashboard.html +316 -0
  885. package/lib/mcp/app-html/graph.html +428 -0
  886. package/lib/mcp/app-html/mindrian-platform.html +1841 -0
  887. package/lib/mcp/app-html/wiki.html +383 -0
  888. package/lib/mcp/app-views.cjs +322 -0
  889. package/lib/mcp/brain-composition-census.cjs +184 -0
  890. package/lib/mcp/brain-router.cjs +530 -0
  891. package/lib/mcp/capability-registry.cjs +62 -0
  892. package/lib/mcp/contract-version.cjs +59 -0
  893. package/lib/mcp/daemon-lifecycle.cjs +324 -0
  894. package/lib/mcp/gate-dedup.cjs +120 -0
  895. package/lib/mcp/gate-ledger.cjs +145 -0
  896. package/lib/mcp/gate-render.cjs +483 -0
  897. package/lib/mcp/hook-adapter-audit.cjs +199 -0
  898. package/lib/mcp/larry-context.cjs +42 -0
  899. package/lib/mcp/mcp-first-flag.cjs +147 -0
  900. package/lib/mcp/no-instructions.test.cjs +270 -0
  901. package/lib/mcp/pipeline-state.cjs +424 -0
  902. package/lib/mcp/prompts.cjs +421 -0
  903. package/lib/mcp/register-core-tools.cjs +78 -0
  904. package/lib/mcp/resources.cjs +359 -0
  905. package/lib/mcp/runtime-instructions.cjs +38 -0
  906. package/lib/mcp/session-catchup.cjs +349 -0
  907. package/lib/mcp/session-registry.cjs +113 -0
  908. package/lib/mcp/session-room.cjs +124 -0
  909. package/lib/mcp/sse-event-bus.cjs +98 -0
  910. package/lib/mcp/stop-gate-handler.cjs +589 -0
  911. package/lib/mcp/surface-detect.cjs +186 -0
  912. package/lib/mcp/tool-router.cjs +2113 -0
  913. package/lib/mcp/tools/chain.cjs +674 -0
  914. package/lib/mcp/tools/claim.cjs +180 -0
  915. package/lib/mcp/tools/context.cjs +92 -0
  916. package/lib/mcp/tools/dual-path.cjs +79 -0
  917. package/lib/mcp/tools/gate.cjs +392 -0
  918. package/lib/mcp/tools/graph-reason.cjs +130 -0
  919. package/lib/mcp/tools/graph.cjs +321 -0
  920. package/lib/mcp/tools/identity.cjs +174 -0
  921. package/lib/mcp/tools/room.cjs +449 -0
  922. package/lib/mcp/tools/sensors.cjs +450 -0
  923. package/lib/mcp/tools/status.cjs +183 -0
  924. package/lib/mcp/tools/stop-gate.cjs +103 -0
  925. package/lib/mcp/tools/views.cjs +382 -0
  926. package/lib/mcp/tree-watcher.cjs +199 -0
  927. package/lib/memory/.mindrian/auto-explore-mat-test-001.json +11 -0
  928. package/lib/memory/aaak-compress.cjs +403 -0
  929. package/lib/memory/aaak-compress.test.cjs +288 -0
  930. package/lib/memory/async-artifact-auto-commit.test.cjs +223 -0
  931. package/lib/memory/bearer-token.test.cjs +315 -0
  932. package/lib/memory/body-shape-coverage.test.cjs +268 -0
  933. package/lib/memory/brain-cache-lru.test.cjs +259 -0
  934. package/lib/memory/brain-client-query-shape.test.cjs +160 -0
  935. package/lib/memory/brain-cypher-chain-slice.test.cjs +368 -0
  936. package/lib/memory/brain-derivation-graceful-degradation.test.cjs +1019 -0
  937. package/lib/memory/brain-derivation-queue.test.cjs +553 -0
  938. package/lib/memory/brain-derivation.test.cjs +639 -0
  939. package/lib/memory/brain-derive-command.test.cjs +534 -0
  940. package/lib/memory/brain-derive-curation.test.cjs +243 -0
  941. package/lib/memory/brain-md-invariants-validator.test.cjs +704 -0
  942. package/lib/memory/brain-md-schema.test.cjs +467 -0
  943. package/lib/memory/brain-md-staleness.test.cjs +525 -0
  944. package/lib/memory/brain-server-resolution.test.cjs +314 -0
  945. package/lib/memory/brain-suggestion-template.test.cjs +200 -0
  946. package/lib/memory/chain-recommender-canonical.test.cjs +208 -0
  947. package/lib/memory/chain-recommender.test.cjs +233 -0
  948. package/lib/memory/chat-context.test.cjs +128 -0
  949. package/lib/memory/command-registry.test.cjs +220 -0
  950. package/lib/memory/connector-registry.test.cjs +94 -0
  951. package/lib/memory/correlation-label-index.test.cjs +119 -0
  952. package/lib/memory/correlation.test.cjs +253 -0
  953. package/lib/memory/cross-room-aggregator.test.cjs +909 -0
  954. package/lib/memory/curation-132-03-dedup-held-rename.test.cjs +251 -0
  955. package/lib/memory/curation-132-05-pseudonymize.test.cjs +205 -0
  956. package/lib/memory/curation-batch.test.cjs +213 -0
  957. package/lib/memory/dashboard-server.test.cjs +256 -0
  958. package/lib/memory/debouncer-drain-at-prompt.test.cjs +389 -0
  959. package/lib/memory/decision-capture.test.cjs +632 -0
  960. package/lib/memory/decision-capture.worker.cjs +70 -0
  961. package/lib/memory/doctor-deprecation-surface.test.cjs +188 -0
  962. package/lib/memory/dual-graph-health.test.cjs +485 -0
  963. package/lib/memory/explain-decision-command.test.cjs +521 -0
  964. package/lib/memory/explain-decision-footer.test.cjs +316 -0
  965. package/lib/memory/explored-materials-store.cjs +392 -0
  966. package/lib/memory/f-selector-ranker.test.cjs +593 -0
  967. package/lib/memory/feynman-minto-guardian.test.cjs +863 -0
  968. package/lib/memory/feynman-minto-invariants.test.cjs +554 -0
  969. package/lib/memory/feynman-prompts-drift.test.cjs +144 -0
  970. package/lib/memory/feynman-prompts.cjs +151 -0
  971. package/lib/memory/feynman-prompts.test.cjs +96 -0
  972. package/lib/memory/first-touch-version.test.cjs +198 -0
  973. package/lib/memory/folder-memory-quadruple.test.cjs +548 -0
  974. package/lib/memory/folder-memory.test.cjs +503 -0
  975. package/lib/memory/framework-chain-composer.test.cjs +549 -0
  976. package/lib/memory/frontmatter-schema-validator.test.cjs +344 -0
  977. package/lib/memory/guardian-onstop-reaches-user.test.cjs +396 -0
  978. package/lib/memory/heal-command.test.cjs +604 -0
  979. package/lib/memory/help-coverage.test.cjs +108 -0
  980. package/lib/memory/help-renderer.test.cjs +145 -0
  981. package/lib/memory/huji-run-one-async-parity.test.cjs +242 -0
  982. package/lib/memory/hypergraph-event-schema.test.cjs +116 -0
  983. package/lib/memory/index-artifact-transaction.test.cjs +333 -0
  984. package/lib/memory/lazygraph-rs-discoveries-view.test.cjs +122 -0
  985. package/lib/memory/local-chain-recommender.test.cjs +172 -0
  986. package/lib/memory/mcp-input-validation.test.cjs +240 -0
  987. package/lib/memory/mcp-server-brain-deps.test.cjs +270 -0
  988. package/lib/memory/mcp-stack-fallback.test.cjs +433 -0
  989. package/lib/memory/minto-debounce-consumer-census.test.cjs +567 -0
  990. package/lib/memory/minto-debouncer.test.cjs +407 -0
  991. package/lib/memory/minto-debouncer.worker.cjs +46 -0
  992. package/lib/memory/minto-migration-v88.test.cjs +265 -0
  993. package/lib/memory/minto-schema-v88.test.cjs +390 -0
  994. package/lib/memory/mos-status-renderer.test.cjs +631 -0
  995. package/lib/memory/narrative-schema.cjs +376 -0
  996. package/lib/memory/narrative-schema.test.cjs +209 -0
  997. package/lib/memory/nav-dial.test.cjs +414 -0
  998. package/lib/memory/navigation-engine-core.test.cjs +712 -0
  999. package/lib/memory/navigation-engine-offer.test.cjs +404 -0
  1000. package/lib/memory/navigation-hook-resolver.test.cjs +177 -0
  1001. package/lib/memory/navigation-invariants.test.cjs +483 -0
  1002. package/lib/memory/navigation-projections.test.cjs +241 -0
  1003. package/lib/memory/navigation-write-edge.test.cjs +206 -0
  1004. package/lib/memory/offer-closer.test.cjs +258 -0
  1005. package/lib/memory/offer-presenter.test.cjs +554 -0
  1006. package/lib/memory/on-stop-snapshot.test.cjs +404 -0
  1007. package/lib/memory/orchestration-projection.test.cjs +706 -0
  1008. package/lib/memory/packet-chain-hint.test.cjs +407 -0
  1009. package/lib/memory/packet-schema-validation.test.cjs +317 -0
  1010. package/lib/memory/palette-consistency.test.cjs +127 -0
  1011. package/lib/memory/pending-tension-store.cjs +453 -0
  1012. package/lib/memory/per-command-jtbd-derivation.test.cjs +130 -0
  1013. package/lib/memory/per-command-teaching.test.cjs +110 -0
  1014. package/lib/memory/post-compact-reinjection.test.cjs +854 -0
  1015. package/lib/memory/post-write-triple.test.cjs +317 -0
  1016. package/lib/memory/pre-compact-snapshot.test.cjs +495 -0
  1017. package/lib/memory/precommit-real-commit.test.cjs +301 -0
  1018. package/lib/memory/problem-type-router.test.cjs +656 -0
  1019. package/lib/memory/query-efficiency-telemetry.test.cjs +612 -0
  1020. package/lib/memory/recompile-room-references.test.cjs +392 -0
  1021. package/lib/memory/recompile-room-references.worker.cjs +42 -0
  1022. package/lib/memory/record-decision-dual-write.test.cjs +454 -0
  1023. package/lib/memory/render-v2-disposition.test.cjs +199 -0
  1024. package/lib/memory/room-classifier-strict-mode.test.cjs +430 -0
  1025. package/lib/memory/room-minto-hook.test.cjs +398 -0
  1026. package/lib/memory/rs-discovery-engine.test.cjs +323 -0
  1027. package/lib/memory/run-feynman-tests.cjs +2101 -0
  1028. package/lib/memory/security-trifecta.test.cjs +329 -0
  1029. package/lib/memory/selector-alias-map.test.cjs +172 -0
  1030. package/lib/memory/selector-decisions.test.cjs +417 -0
  1031. package/lib/memory/selector-miss.test.cjs +290 -0
  1032. package/lib/memory/session-start-brain-staleness.test.cjs +363 -0
  1033. package/lib/memory/session-start-triple-injection.test.cjs +514 -0
  1034. package/lib/memory/sessionstart-banner-formatter.cjs +318 -0
  1035. package/lib/memory/sessionstart-coordinator.test.cjs +446 -0
  1036. package/lib/memory/sessionstart-minto-banner.test.cjs +373 -0
  1037. package/lib/memory/skill-activation-router.test.cjs +465 -0
  1038. package/lib/memory/skill-vs-code-drift.test.cjs +257 -0
  1039. package/lib/memory/soft-alias.test.cjs +144 -0
  1040. package/lib/memory/spine-events-correlation.test.cjs +198 -0
  1041. package/lib/memory/stale-copy-scanner.test.cjs +294 -0
  1042. package/lib/memory/stamp-artifact-write.test.cjs +304 -0
  1043. package/lib/memory/state-aware-router.test.cjs +90 -0
  1044. package/lib/memory/statusline-active-room-write.test.cjs +245 -0
  1045. package/lib/memory/statusline-active-room.test.cjs +315 -0
  1046. package/lib/memory/statusline-minto-segment.test.cjs +292 -0
  1047. package/lib/memory/statusline-two-row.test.cjs +338 -0
  1048. package/lib/memory/suggest-next-workflow.test.cjs +176 -0
  1049. package/lib/memory/sync-async-entry-points.test.cjs +204 -0
  1050. package/lib/memory/terminal-capability.test.cjs +155 -0
  1051. package/lib/memory/test-bridge-writer-enhanced.cjs +452 -0
  1052. package/lib/memory/test-rs-brain-substrate-shape.cjs +529 -0
  1053. package/lib/memory/test-rs-brain-substrate.cjs +636 -0
  1054. package/lib/memory/test-rs-breakthrough-scorer.cjs +375 -0
  1055. package/lib/memory/test-rs-canon-violations.cjs +218 -0
  1056. package/lib/memory/test-rs-chain-feeder-core.cjs +344 -0
  1057. package/lib/memory/test-rs-chain-feeder-skill-spawn.cjs +297 -0
  1058. package/lib/memory/test-rs-commercial-assessor.cjs +385 -0
  1059. package/lib/memory/test-rs-differential-scorer.cjs +480 -0
  1060. package/lib/memory/test-rs-discovery-engine.cjs +648 -0
  1061. package/lib/memory/test-rs-domain-analyzer.cjs +492 -0
  1062. package/lib/memory/test-rs-egress-primitives.cjs +420 -0
  1063. package/lib/memory/test-rs-expert-mapper.cjs +547 -0
  1064. package/lib/memory/test-rs-explain-command.cjs +443 -0
  1065. package/lib/memory/test-rs-fetcher-academic.cjs +848 -0
  1066. package/lib/memory/test-rs-fetcher-experts.cjs +496 -0
  1067. package/lib/memory/test-rs-fetcher-industry.cjs +702 -0
  1068. package/lib/memory/test-rs-fetcher-patents.cjs +674 -0
  1069. package/lib/memory/test-rs-innovation-classifier.cjs +301 -0
  1070. package/lib/memory/test-rs-mind-map.cjs +646 -0
  1071. package/lib/memory/test-rs-neo4j-writer.cjs +518 -0
  1072. package/lib/memory/test-rs-nl-to-query.cjs +449 -0
  1073. package/lib/memory/test-rs-pinecone-bridge.cjs +282 -0
  1074. package/lib/memory/test-rs-preprocessor.cjs +433 -0
  1075. package/lib/memory/test-rs-query-matrix.cjs +391 -0
  1076. package/lib/memory/test-rs-query-to-text.cjs +551 -0
  1077. package/lib/memory/test-rs-sqlite-mirror.cjs +649 -0
  1078. package/lib/memory/test-rs-thesis-generator.cjs +360 -0
  1079. package/lib/memory/triple-context-formatter.cjs +473 -0
  1080. package/lib/memory/triple-context-formatter.test.cjs +442 -0
  1081. package/lib/memory/user-md-persona.test.cjs +565 -0
  1082. package/lib/memory/userpromptsubmit-integration.test.cjs +787 -0
  1083. package/lib/memory/validators/README.md +157 -0
  1084. package/lib/memory/validators/brain-md-invariants.cjs +475 -0
  1085. package/lib/memory/validators/brain-substrate-invariants.cjs +285 -0
  1086. package/lib/memory/validators/external-academic-invariants.cjs +249 -0
  1087. package/lib/memory/validators/external-industry-invariants.cjs +271 -0
  1088. package/lib/memory/validators/external-patents-invariants.cjs +266 -0
  1089. package/lib/memory/validators/minto-invariants.cjs +62 -0
  1090. package/lib/memory/validators/navigation-invariants.cjs +340 -0
  1091. package/lib/memory/validators/queue-health.cjs +95 -0
  1092. package/lib/memory/validators/snapshot-integrity.cjs +129 -0
  1093. package/lib/memory/validators/stale-lifecycle.cjs +116 -0
  1094. package/lib/memory/vault-section-minto-generator-atomic.test.cjs +556 -0
  1095. package/lib/memory/vault-section-minto-generator-atomic.worker.cjs +73 -0
  1096. package/lib/memory/workflow-layer-e2e.test.cjs +262 -0
  1097. package/lib/memory/write-lock-atomic.test.cjs +137 -0
  1098. package/lib/memory/write-lock-atomic.worker.cjs +55 -0
  1099. package/lib/parity/check-parity.cjs +83 -0
  1100. package/lib/presentation/presentation-server.cjs +101 -0
  1101. package/lib/presentation/presentation-watcher.cjs +123 -0
  1102. package/lib/quickview/hub-server.cjs +719 -0
  1103. package/lib/quickview/server.cjs +533 -0
  1104. package/lib/render/JTBD-PALETTES.md +145 -0
  1105. package/lib/render/ROOM.md +111 -0
  1106. package/lib/render/render-v2.cjs +532 -0
  1107. package/lib/render/render-v2.test.cjs +267 -0
  1108. package/lib/render/render.cjs +65 -0
  1109. package/lib/sessionstart/budget-compressor.cjs +130 -0
  1110. package/lib/sessionstart/contributor-interface.cjs +134 -0
  1111. package/lib/sessionstart/contributor-isolator.cjs +128 -0
  1112. package/lib/sessionstart/precedence-ladder.cjs +47 -0
  1113. package/lib/state/ROOM.md +46 -0
  1114. package/lib/state/state-md-parser.cjs +215 -0
  1115. package/lib/statusline/ROOM.md +38 -0
  1116. package/lib/statusline/banner-suppression.cjs +50 -0
  1117. package/lib/statusline/cockpit-renderer.cjs +443 -0
  1118. package/lib/statusline/cockpit-signals.cjs +312 -0
  1119. package/lib/statusline/cockpit-telemetry.cjs +152 -0
  1120. package/lib/statusline/ctx-window.cjs +135 -0
  1121. package/lib/statusline/governing-thought-truncator.cjs +45 -0
  1122. package/lib/statusline/next-move-cache.cjs +235 -0
  1123. package/lib/statusline/ratification-next.cjs +164 -0
  1124. package/lib/statusline/room-health-cache.cjs +200 -0
  1125. package/lib/statusline/surface-detect.cjs +85 -0
  1126. package/lib/statusline/two-row-renderer.cjs +207 -0
  1127. package/lib/statusline/version-resolver.cjs +81 -0
  1128. package/lib/ui/design-system.cjs +19 -0
  1129. package/lib/update-bootstrap.sh.template +145 -0
  1130. package/lib/vault/frontmatter-schema.cjs +297 -0
  1131. package/lib/vault/room-scanner.cjs +365 -0
  1132. package/lib/vault/wikilink-builder.cjs +231 -0
  1133. package/lib/vault/wikilink-builder.test.cjs +182 -0
  1134. package/lib/wiki/briefing.cjs +193 -0
  1135. package/lib/wiki/editor-dist/wiki-editor.css +1 -0
  1136. package/lib/wiki/editor-dist/wiki-editor.js +1327 -0
  1137. package/lib/wiki/graph-links.cjs +281 -0
  1138. package/lib/wiki/page-renderer.cjs +229 -0
  1139. package/lib/wiki/room-home.cjs +353 -0
  1140. package/lib/wiki/wiki-chat.cjs +81 -0
  1141. package/lib/wiki/wiki-export.cjs +364 -0
  1142. package/lib/wiki/wiki-layout.cjs +1143 -0
  1143. package/lib/wiki/wiki-search.cjs +142 -0
  1144. package/lib/wiki/wiki-server.cjs +748 -0
  1145. package/lib/wiki/wiki-watcher.cjs +105 -0
  1146. package/lib/workflow/ROOM.md +47 -0
  1147. package/lib/workflow/chain-source.cjs +179 -0
  1148. package/lib/workflow/command-resolver.cjs +155 -0
  1149. package/lib/workflow/command-resolver.test.cjs +235 -0
  1150. package/lib/workflow/cross-room-umbilical-closer.cjs +364 -0
  1151. package/lib/workflow/dial-close-reach.cjs +405 -0
  1152. package/lib/workflow/f-selector-ranker.cjs +1148 -0
  1153. package/lib/workflow/f1-pick-consumer.cjs +232 -0
  1154. package/lib/workflow/f3-depth-consumer.cjs +98 -0
  1155. package/lib/workflow/f4-scope-consumer.cjs +112 -0
  1156. package/lib/workflow/f8-consumer.test.cjs +82 -0
  1157. package/lib/workflow/f8-fanout-consumer.cjs +208 -0
  1158. package/lib/workflow/f9-consumer.test.cjs +71 -0
  1159. package/lib/workflow/f9-ordered-consumer.cjs +199 -0
  1160. package/lib/workflow/local-chain-recommender.cjs +330 -0
  1161. package/lib/workflow/memory-cascade-f9-adapter.cjs +273 -0
  1162. package/lib/workflow/memory-governance-closer.cjs +384 -0
  1163. package/lib/workflow/offer-closer.cjs +407 -0
  1164. package/lib/workflow/reach-hedge-ranker.cjs +809 -0
  1165. package/lib/workflow/reach-reject-reader.cjs +372 -0
  1166. package/lib/workflow/reconcile-f9-adapter.cjs +299 -0
  1167. package/lib/workflow/selector-decisions.cjs +478 -0
  1168. package/lib/workflow/session-binding-consumer.cjs +249 -0
  1169. package/npm-shrinkwrap.json +1544 -0
  1170. package/output-styles/destijl.md +67 -0
  1171. package/package.json +22 -4
  1172. package/pipelines/PWS_grading/01-deep-grade.md +48 -0
  1173. package/pipelines/PWS_grading/02-mullins.md +50 -0
  1174. package/pipelines/PWS_grading/03-build-thesis.md +60 -0
  1175. package/pipelines/PWS_grading/04-structure-argument.md +77 -0
  1176. package/pipelines/PWS_grading/CHAIN.md +79 -0
  1177. package/pipelines/analogy/01-decompose.md +80 -0
  1178. package/pipelines/analogy/02-abstract.md +87 -0
  1179. package/pipelines/analogy/03-search.md +135 -0
  1180. package/pipelines/analogy/04-transfer.md +101 -0
  1181. package/pipelines/analogy/05-validate.md +106 -0
  1182. package/pipelines/analogy/CHAIN.md +73 -0
  1183. package/pipelines/discovery/01-explore-domains.md +44 -0
  1184. package/pipelines/discovery/02-think-hats.md +50 -0
  1185. package/pipelines/discovery/03-analyze-needs.md +54 -0
  1186. package/pipelines/discovery/CHAIN.md +48 -0
  1187. package/pipelines/thesis/01-structure-argument.md +45 -0
  1188. package/pipelines/thesis/02-challenge-assumptions.md +48 -0
  1189. package/pipelines/thesis/03-build-thesis.md +54 -0
  1190. package/pipelines/thesis/CHAIN.md +48 -0
  1191. package/references/brain/causal-directives.md +91 -0
  1192. package/references/brain/causal-enrichment.cypher +165 -0
  1193. package/references/brain/command-triggers-schema.md +15 -0
  1194. package/references/brain/graph-architecture.md +317 -0
  1195. package/references/brain/query-patterns.md +504 -0
  1196. package/references/brain/room-hierarchy-schema.md +218 -0
  1197. package/references/brain/schema.md +86 -0
  1198. package/references/capability-radar/capabilities-index.md +269 -0
  1199. package/references/capability-radar/changelog-cache.md +95 -0
  1200. package/references/causal/causal-schema.md +103 -0
  1201. package/references/design/email-template-standard.md +169 -0
  1202. package/references/design/graph-visualization-standard.md +178 -0
  1203. package/references/design/newsletter-email-template.html +307 -0
  1204. package/references/document-generation.md +179 -0
  1205. package/references/hsi/HSI-TOOLS-REFERENCE.md +222 -0
  1206. package/references/import-config.md +141 -0
  1207. package/references/integrations/detection-patterns.md +101 -0
  1208. package/references/meeting/artifact-template.md +377 -0
  1209. package/references/meeting/cross-meeting-intelligence.md +216 -0
  1210. package/references/meeting/cross-relationship-patterns.md +202 -0
  1211. package/references/meeting/extraction-perspectives.md +225 -0
  1212. package/references/meeting/filing-protocol.md +222 -0
  1213. package/references/meeting/knowledge-typing.md +242 -0
  1214. package/references/meeting/live-join-interface.md +244 -0
  1215. package/references/meeting/section-mapping.md +192 -0
  1216. package/references/meeting/segment-classification.md +258 -0
  1217. package/references/meeting/speaker-profile-template.md +219 -0
  1218. package/references/meeting/summary-template.md +348 -0
  1219. package/references/meeting/transcript-patterns.md +226 -0
  1220. package/references/methodology/analyze-needs.md +135 -0
  1221. package/references/methodology/analyze-systems.md +121 -0
  1222. package/references/methodology/analyze-timing.md +149 -0
  1223. package/references/methodology/beautiful-question.md +109 -0
  1224. package/references/methodology/build-knowledge.md +161 -0
  1225. package/references/methodology/build-thesis-scored.md +60 -0
  1226. package/references/methodology/build-thesis.md +237 -0
  1227. package/references/methodology/causal-loop-diagrams.md +65 -0
  1228. package/references/methodology/challenge-assumptions.md +127 -0
  1229. package/references/methodology/diagnose.md +169 -0
  1230. package/references/methodology/dominant-designs.md +212 -0
  1231. package/references/methodology/explore-domains.md +147 -0
  1232. package/references/methodology/explore-futures.md +163 -0
  1233. package/references/methodology/explore-trends.md +129 -0
  1234. package/references/methodology/find-bottlenecks.md +131 -0
  1235. package/references/methodology/grade.md +211 -0
  1236. package/references/methodology/huji-stage-a-intake.md +246 -0
  1237. package/references/methodology/index.md +34 -0
  1238. package/references/methodology/leadership.md +200 -0
  1239. package/references/methodology/lean-canvas.md +116 -0
  1240. package/references/methodology/leverage-scan-signatures.md +83 -0
  1241. package/references/methodology/macro-trends.md +192 -0
  1242. package/references/methodology/map-unknowns.md +137 -0
  1243. package/references/methodology/mullins-7-domains.md +104 -0
  1244. package/references/methodology/problem-types.md +65 -0
  1245. package/references/methodology/root-cause.md +178 -0
  1246. package/references/methodology/rubric-huji.md +160 -0
  1247. package/references/methodology/sapphire-encoding.md +355 -0
  1248. package/references/methodology/scenario-plan.md +190 -0
  1249. package/references/methodology/score-innovation.md +154 -0
  1250. package/references/methodology/skillopt-judge-rubric.md +48 -0
  1251. package/references/methodology/skillopt-queries-rubric.md +60 -0
  1252. package/references/methodology/skillopt-refute-rubric.md +59 -0
  1253. package/references/methodology/skillopt-review-rubric.md +72 -0
  1254. package/references/methodology/skillopt-revise-rubric.md +48 -0
  1255. package/references/methodology/structure-argument.md +158 -0
  1256. package/references/methodology/systems-thinking.md +231 -0
  1257. package/references/methodology/think-hats.md +147 -0
  1258. package/references/methodology/triz-matrix.json +751 -0
  1259. package/references/methodology/triz-principles.md +501 -0
  1260. package/references/methodology/user-needs.md +199 -0
  1261. package/references/methodology/validate.md +163 -0
  1262. package/references/methodology/value-proposition.md +244 -0
  1263. package/references/opportunities/funding-lifecycle.md +103 -0
  1264. package/references/opportunities/grant-api-patterns.md +99 -0
  1265. package/references/opportunities/opportunity-template.md +84 -0
  1266. package/references/opportunities/tnufa-rubric.md +81 -0
  1267. package/references/personality/assessment-philosophy.md +72 -0
  1268. package/references/personality/lexicon.md +100 -0
  1269. package/references/personality/persona-chains.md +56 -0
  1270. package/references/personality/pws-lexicon-full.md +499 -0
  1271. package/references/personality/voice-dna.md +156 -0
  1272. package/references/personas/hat-perspectives.md +76 -0
  1273. package/references/personas/persona-template.md +63 -0
  1274. package/references/pipeline/act-output-contract.md +88 -0
  1275. package/references/pipeline/chains-index.md +39 -0
  1276. package/references/pws-profile-generation.md +79 -0
  1277. package/references/reasoning/reasoning-schema.md +143 -0
  1278. package/references/reasoning/reasoning-template.md +68 -0
  1279. package/references/reasoning/run-template.md +38 -0
  1280. package/references/research/RESEARCH_14_CLAUDE_CODE_SOURCE_ARCHITECTURE.md +209 -0
  1281. package/references/research/RESEARCH_15_V1.8_OPTIMIZATION_JTBD.md +375 -0
  1282. package/references/research/RESEARCH_16_NATIVE_FIRST_PLUGIN_ARCHITECTURE.md +575 -0
  1283. package/references/research/RESEARCH_17_MCP_UI_FRAMEWORKS.md +272 -0
  1284. package/references/security/agentshield-baseline.json +8 -0
  1285. package/references/security/cve-db.json +220 -0
  1286. package/references/taxonomy/TAXONOMY.md +192 -0
  1287. package/references/templates/MINTO.md +36 -0
  1288. package/references/user-research/2026-04-05-leah-lawrence-session.md +202 -0
  1289. package/references/vault-kit/README.md +35 -0
  1290. package/references/vault-kit/app.json +12 -0
  1291. package/references/vault-kit/appearance.json +12 -0
  1292. package/references/vault-kit/graph.json +35 -0
  1293. package/references/vault-kit/snippets/mindrian-destijl.css +297 -0
  1294. package/references/vault-kit/templates/new-artifact.md +37 -0
  1295. package/references/vault-kit/templates/new-meeting-note.md +35 -0
  1296. package/references/vault-kit/templates/new-team-profile.md +29 -0
  1297. package/references/vault-kit/templates/new-xref.md +35 -0
  1298. package/references/visual/ROOM.md +55 -0
  1299. package/references/visual/palette.json +54 -0
  1300. package/references/visual/symbol-system.md +151 -0
  1301. package/scripts/189-plurai-gate-check.cjs +88 -0
  1302. package/scripts/198-plurai-gate-check.cjs +118 -0
  1303. package/scripts/198-rollback-rehearsal.cjs +233 -0
  1304. package/scripts/83-scope-injection.test.cjs +648 -0
  1305. package/scripts/PYTHON_GATES.md +78 -0
  1306. package/scripts/__pycache__/compute-hsi.cpython-312.pyc +0 -0
  1307. package/scripts/__pycache__/detect-reverse-salients.cpython-312.pyc +0 -0
  1308. package/scripts/__pycache__/rs-engine.cpython-312.pyc +0 -0
  1309. package/scripts/act-command.cjs +518 -0
  1310. package/scripts/admin-brain-write.cjs +442 -0
  1311. package/scripts/admin-command-gate.cjs +178 -0
  1312. package/scripts/agentshield-scan-cli.cjs +226 -0
  1313. package/scripts/agentshield-sessionstart-scan.cjs +282 -0
  1314. package/scripts/analogy-fitness-report.cjs +266 -0
  1315. package/scripts/analyze-room +1079 -0
  1316. package/scripts/apply-teaching-content.cjs +298 -0
  1317. package/scripts/async-artifact-auto-commit.cjs +485 -0
  1318. package/scripts/audit-active-phase-resolver.cjs +160 -0
  1319. package/scripts/audit-body-shape-coverage.cjs +213 -0
  1320. package/scripts/auto-explore-drain.cjs +274 -0
  1321. package/scripts/auto-explore-fingerprint.cjs +354 -0
  1322. package/scripts/auto-explore-fire.cjs +359 -0
  1323. package/scripts/backfill-correlation-id.cjs +425 -0
  1324. package/scripts/backfill-hitl-shape.cjs +276 -0
  1325. package/scripts/backfill-hitl-shape.test.cjs +307 -0
  1326. package/scripts/backup-modifications +68 -0
  1327. package/scripts/banner +182 -0
  1328. package/scripts/brain-derivation-drain.cjs +291 -0
  1329. package/scripts/brain-derive-command.cjs +846 -0
  1330. package/scripts/brain-normalize-books.cypher +505 -0
  1331. package/scripts/brain-normalize-final.cypher +1355 -0
  1332. package/scripts/brain-normalize-problemtype.cypher +475 -0
  1333. package/scripts/brain-normalize-supplement.cypher +449 -0
  1334. package/scripts/brain-normalize-targeted.cypher +344 -0
  1335. package/scripts/brain-normalize-v194.cypher +61 -0
  1336. package/scripts/brain-normalize.cypher +530 -0
  1337. package/scripts/brain-response-sanitize-hook.cjs +165 -0
  1338. package/scripts/build-brain-census.cjs +957 -0
  1339. package/scripts/build-brain-packet-schema.cjs +225 -0
  1340. package/scripts/build-command-registry.cjs +587 -0
  1341. package/scripts/build-connector-registry.cjs +1331 -0
  1342. package/scripts/build-corpus-stats.cjs +408 -0
  1343. package/scripts/build-dist-bundles.cjs +495 -0
  1344. package/scripts/build-ecosystem-graph.cjs +490 -0
  1345. package/scripts/build-graph +1462 -0
  1346. package/scripts/build-graph-from-sqlite.cjs +97 -0
  1347. package/scripts/build-harness-manifest.cjs +1090 -0
  1348. package/scripts/build-jtbd-nudges +205 -0
  1349. package/scripts/build-new-surface.cjs +805 -0
  1350. package/scripts/build-orchestration-projection.cjs +1221 -0
  1351. package/scripts/build-render-coverage.cjs +637 -0
  1352. package/scripts/build-skill-mirrors.cjs +681 -0
  1353. package/scripts/cache-hitrate-report.cjs +216 -0
  1354. package/scripts/causal-to-graph.cjs +163 -0
  1355. package/scripts/check-abstraction-fixture-neutral.cjs +160 -0
  1356. package/scripts/check-admin-identity.cjs +212 -0
  1357. package/scripts/check-brain-tool-liveness.cjs +502 -0
  1358. package/scripts/check-card-fire.cjs +1809 -0
  1359. package/scripts/check-cirs-declaration.cjs +279 -0
  1360. package/scripts/check-deck-design.cjs +104 -0
  1361. package/scripts/check-dual-graph-health.cjs +645 -0
  1362. package/scripts/check-first-touch-drift.cjs +220 -0
  1363. package/scripts/check-flagship-floor.cjs +391 -0
  1364. package/scripts/check-framework-vocabulary-drift.cjs +563 -0
  1365. package/scripts/check-gate-seam.cjs +178 -0
  1366. package/scripts/check-graph-derive-health.cjs +208 -0
  1367. package/scripts/check-graph-export-typemap.cjs +118 -0
  1368. package/scripts/check-help-coverage.cjs +290 -0
  1369. package/scripts/check-hitl-stages.cjs +219 -0
  1370. package/scripts/check-hook-schema-compatibility.cjs +231 -0
  1371. package/scripts/check-hsi-deps +42 -0
  1372. package/scripts/check-kuzu-reintroduction.cjs +251 -0
  1373. package/scripts/check-onboard +43 -0
  1374. package/scripts/check-onboard-statusline.cjs +363 -0
  1375. package/scripts/check-palette-consistency.cjs +106 -0
  1376. package/scripts/check-pending-ambiguous.cjs +244 -0
  1377. package/scripts/check-pending-breakthrough.cjs +189 -0
  1378. package/scripts/check-pending-breakthrough.test.cjs +166 -0
  1379. package/scripts/check-pending-naming-decision.cjs +97 -0
  1380. package/scripts/check-plugin-path-anchoring.cjs +830 -0
  1381. package/scripts/check-publish-needs.cjs +126 -0
  1382. package/scripts/check-registry-drift.cjs +206 -0
  1383. package/scripts/check-release-payload-ceiling.cjs +269 -0
  1384. package/scripts/check-render-coverage.cjs +558 -0
  1385. package/scripts/check-research-isomorphism.cjs +446 -0
  1386. package/scripts/check-reward-before-investment.cjs +261 -0
  1387. package/scripts/check-room-blueprints.cjs +213 -0
  1388. package/scripts/check-schema-aliases.cjs +532 -0
  1389. package/scripts/check-shape-declaration.cjs +958 -0
  1390. package/scripts/check-shape-declaration.test.cjs +185 -0
  1391. package/scripts/check-skill-spec.cjs +312 -0
  1392. package/scripts/check-skill-vs-code-drift.cjs +178 -0
  1393. package/scripts/check-substrate.cjs +513 -0
  1394. package/scripts/check-tool-honesty.cjs +1601 -0
  1395. package/scripts/check-update +60 -0
  1396. package/scripts/check-version-and-sha.cjs +366 -0
  1397. package/scripts/check-voice-style.cjs +184 -0
  1398. package/scripts/check-worktree-hygiene.cjs +530 -0
  1399. package/scripts/classify-insight +59 -0
  1400. package/scripts/coherence-smoke-test.cjs +489 -0
  1401. package/scripts/compute-bayesian-surprise.py +175 -0
  1402. package/scripts/compute-blindspot-mass.py +209 -0
  1403. package/scripts/compute-disruption-index.py +211 -0
  1404. package/scripts/compute-element-novelty.py +254 -0
  1405. package/scripts/compute-external-whitespace.py +563 -0
  1406. package/scripts/compute-hsi.py +947 -0
  1407. package/scripts/compute-meetings-intelligence +716 -0
  1408. package/scripts/compute-opportunity-state +17 -0
  1409. package/scripts/compute-state +393 -0
  1410. package/scripts/compute-team +1112 -0
  1411. package/scripts/compute-whitespace-embeddings.py +464 -0
  1412. package/scripts/compute-whitespace-gaps.py +562 -0
  1413. package/scripts/compute_topic_forest.py +684 -0
  1414. package/scripts/consolidate-pinecone.py +265 -0
  1415. package/scripts/context-monitor +943 -0
  1416. package/scripts/create-speaker-profile +311 -0
  1417. package/scripts/cross-room-detect.cjs +195 -0
  1418. package/scripts/csv-to-idea-graph.cjs +755 -0
  1419. package/scripts/ctxl-eval.cjs +846 -0
  1420. package/scripts/curation-132-03-dedup-held-rename.cjs +395 -0
  1421. package/scripts/curation-132-05-pseudonymize.cjs +189 -0
  1422. package/scripts/derive-verb-reach-affinity.cjs +507 -0
  1423. package/scripts/detect-reverse-salients.py +242 -0
  1424. package/scripts/diagnostics-command.cjs +345 -0
  1425. package/scripts/dial-memory-refresh-command.cjs +147 -0
  1426. package/scripts/discover-analogy-whitespace.py +433 -0
  1427. package/scripts/discover-hsi-whitespace.py +352 -0
  1428. package/scripts/discover-rs-whitespace.py +327 -0
  1429. package/scripts/discovery-cycle.cjs +625 -0
  1430. package/scripts/disposition-render-v2.cjs +229 -0
  1431. package/scripts/doctor-preflight-format.cjs +101 -0
  1432. package/scripts/doctor.cjs +4327 -0
  1433. package/scripts/dogfood-bridge/append-to-queue.sh +59 -0
  1434. package/scripts/dogfood-bridge/path-filter.cjs +86 -0
  1435. package/scripts/dogfood-derive.cjs +158 -0
  1436. package/scripts/dogfood-emit.cjs +126 -0
  1437. package/scripts/empathy-observation-emit.cjs +108 -0
  1438. package/scripts/enrichment-queue-append.cjs +157 -0
  1439. package/scripts/ensure-brain-baseline.cjs +117 -0
  1440. package/scripts/entity-extract.cjs +1135 -0
  1441. package/scripts/eureka-command.cjs +687 -0
  1442. package/scripts/eureka-critic-run.cjs +662 -0
  1443. package/scripts/eureka-portfolio-report.cjs +2038 -0
  1444. package/scripts/eureka-room-report.cjs +419 -0
  1445. package/scripts/explain-decision-command.cjs +499 -0
  1446. package/scripts/export-pinecone-embeddings.cjs +516 -0
  1447. package/scripts/extract-room-intelligence.cjs +714 -0
  1448. package/scripts/fetch-brain-baseline.cjs +190 -0
  1449. package/scripts/fetch-brain-baseline.py +360 -0
  1450. package/scripts/feynman-minto-guardian.cjs +672 -0
  1451. package/scripts/feynman-timeline-refresh-command.cjs +270 -0
  1452. package/scripts/file-asset +253 -0
  1453. package/scripts/fire-sensor-event.cjs +83 -0
  1454. package/scripts/first-install-router.cjs +968 -0
  1455. package/scripts/frontmatter-schema-validator.cjs +339 -0
  1456. package/scripts/fts-index-drain.cjs +221 -0
  1457. package/scripts/generate-chat-embed.cjs +179 -0
  1458. package/scripts/generate-deck.cjs +322 -0
  1459. package/scripts/generate-export.cjs +474 -0
  1460. package/scripts/generate-hub.cjs +2553 -0
  1461. package/scripts/generate-lobby.cjs +718 -0
  1462. package/scripts/generate-presentation.cjs +988 -0
  1463. package/scripts/generate-presentation.test.cjs +405 -0
  1464. package/scripts/generate-section-intelligence.cjs +330 -0
  1465. package/scripts/generate-snapshot.cjs +1410 -0
  1466. package/scripts/generate-standalone +159 -0
  1467. package/scripts/git-ops +211 -0
  1468. package/scripts/graph-heal-pipeline.cjs +321 -0
  1469. package/scripts/gsd-artifact-graph-hook.cjs +219 -0
  1470. package/scripts/gsd-graph-derive-drain.cjs +571 -0
  1471. package/scripts/gsd-graph-derive-sweep.cjs +195 -0
  1472. package/scripts/heal-command.cjs +1365 -0
  1473. package/scripts/hedge-refit-pipeline.cjs +207 -0
  1474. package/scripts/help-renderer.cjs +303 -0
  1475. package/scripts/hmi-compliance-poll.cjs +451 -0
  1476. package/scripts/hmi-status-command.cjs +510 -0
  1477. package/scripts/hooked-rescore-117.cjs +224 -0
  1478. package/scripts/hooks/pre-commit +533 -0
  1479. package/scripts/hooks/pre-commit-room-minto-guard.cmd +43 -0
  1480. package/scripts/hooks/pre-commit-room-minto-guard.sh +533 -0
  1481. package/scripts/hsi-to-graph.cjs +194 -0
  1482. package/scripts/huji-batch.cjs +821 -0
  1483. package/scripts/huji-eval.cjs +1158 -0
  1484. package/scripts/huji-intake.cjs +563 -0
  1485. package/scripts/huji-pin-smoketest.cjs +454 -0
  1486. package/scripts/huji-run-one-async.cjs +305 -0
  1487. package/scripts/huji-run-one.cjs +671 -0
  1488. package/scripts/install-pre-commit.sh +113 -0
  1489. package/scripts/intent-classifier +106 -0
  1490. package/scripts/intent-classifier.cjs +3620 -0
  1491. package/scripts/interpret-whitespace.cjs +691 -0
  1492. package/scripts/jtbd-command.cjs +810 -0
  1493. package/scripts/jtbd-update.cjs +299 -0
  1494. package/scripts/label-topic-forest.cjs +667 -0
  1495. package/scripts/learn-from-usage +168 -0
  1496. package/scripts/lib/__pycache__/ensure_ml_deps.cpython-312.pyc +0 -0
  1497. package/scripts/lib/ensure_ml_deps.py +97 -0
  1498. package/scripts/load-embeddings-into-neo4j.cjs +569 -0
  1499. package/scripts/memory-artifact-graph-hook.cjs +191 -0
  1500. package/scripts/memory-command.cjs +687 -0
  1501. package/scripts/memory-completion-detector.cjs +217 -0
  1502. package/scripts/memory-lifecycle.cjs +620 -0
  1503. package/scripts/memory-resume-nudge.cjs +233 -0
  1504. package/scripts/methodology-ingest-local.sh +36 -0
  1505. package/scripts/migrate-brain-mcp-from-http-to-stdio.cjs +190 -0
  1506. package/scripts/migrate-brain-mcp-from-http-to-stdio.test.cjs +242 -0
  1507. package/scripts/migrate-hats-to-roomdb.cjs +217 -0
  1508. package/scripts/migrate-lazygraph.cjs +250 -0
  1509. package/scripts/migrate-minto-schema-v88.cjs +296 -0
  1510. package/scripts/migrate-plugin-root-refs.cjs +168 -0
  1511. package/scripts/migrate-room-sections-v275.cjs +556 -0
  1512. package/scripts/migrate-rooms +417 -0
  1513. package/scripts/migrate-skill-frontmatter.cjs +472 -0
  1514. package/scripts/migrate-stale-user-settings.cjs +296 -0
  1515. package/scripts/migrate-telemetry-v1.cjs +384 -0
  1516. package/scripts/migrate-telemetry-v1.test.cjs +356 -0
  1517. package/scripts/minto-debouncer.cjs +428 -0
  1518. package/scripts/mos-status.cjs +622 -0
  1519. package/scripts/mva-detect.cjs +229 -0
  1520. package/scripts/mva-run.cjs +36 -0
  1521. package/scripts/on-agent-complete +163 -0
  1522. package/scripts/on-cwd-changed +149 -0
  1523. package/scripts/on-file-changed +68 -0
  1524. package/scripts/on-stop +617 -0
  1525. package/scripts/on-task-complete +194 -0
  1526. package/scripts/operator-command.cjs +858 -0
  1527. package/scripts/operator-update.cjs +308 -0
  1528. package/scripts/part8-egress-guard-hook.cjs +229 -0
  1529. package/scripts/pipeline-command.cjs +271 -0
  1530. package/scripts/post-compact +383 -0
  1531. package/scripts/post-update-activation.cjs +339 -0
  1532. package/scripts/post-write +283 -0
  1533. package/scripts/power-demo-prompt.md +621 -0
  1534. package/scripts/pre-compact +273 -0
  1535. package/scripts/preflight-auto-explore.cjs +314 -0
  1536. package/scripts/preflight-doctor.cjs +225 -0
  1537. package/scripts/preflight-release-drift.cjs +168 -0
  1538. package/scripts/preflight-tension-surface.cjs +414 -0
  1539. package/scripts/probe-brain-contract.cjs +502 -0
  1540. package/scripts/publish-ops +346 -0
  1541. package/scripts/query-efficiency-telemetry.cjs +364 -0
  1542. package/scripts/query-semantic-scholar.cjs +545 -0
  1543. package/scripts/reapply-modifications +49 -0
  1544. package/scripts/reassign-primary.cjs +125 -0
  1545. package/scripts/recompile-room-references.cjs +601 -0
  1546. package/scripts/release-beta-preflight.sh +69 -0
  1547. package/scripts/render-pdf +588 -0
  1548. package/scripts/render-viz +190 -0
  1549. package/scripts/research-speaker +239 -0
  1550. package/scripts/resolve-room +204 -0
  1551. package/scripts/restore-post-compact-context.cjs +320 -0
  1552. package/scripts/room-auto-create-nudge.cjs +136 -0
  1553. package/scripts/room-naming-selector.cjs +201 -0
  1554. package/scripts/room-registry +767 -0
  1555. package/scripts/rs-discovery-engine.cjs +725 -0
  1556. package/scripts/rs-engine.py +2073 -0
  1557. package/scripts/rs-experts-command.cjs +300 -0
  1558. package/scripts/rs-explain-command.cjs +323 -0
  1559. package/scripts/rs-fetch-command.cjs +170 -0
  1560. package/scripts/rs-thesis-command.cjs +203 -0
  1561. package/scripts/rs-vector-bridge.cjs +410 -0
  1562. package/scripts/run-harness.cjs +890 -0
  1563. package/scripts/scout-cadence-guard.cjs +323 -0
  1564. package/scripts/scout-cadence-runner.cjs +509 -0
  1565. package/scripts/scout-telemetry-aggregator.cjs +268 -0
  1566. package/scripts/sealed-walker.py +96 -0
  1567. package/scripts/seed-brain-commands.cjs +324 -0
  1568. package/scripts/self-update +105 -0
  1569. package/scripts/sentinel-deadline-monitor +241 -0
  1570. package/scripts/sentinel-health-check +198 -0
  1571. package/scripts/sentinel-snapshot +42 -0
  1572. package/scripts/serve-dashboard +103 -0
  1573. package/scripts/serve-dashboard-live +932 -0
  1574. package/scripts/serve-presentation +97 -0
  1575. package/scripts/serve-wiki +90 -0
  1576. package/scripts/session-end-presence.cjs +79 -0
  1577. package/scripts/session-start +1942 -0
  1578. package/scripts/sessionstart-coordinator.cjs +249 -0
  1579. package/scripts/sessionstart-npm-reconcile.cjs +111 -0
  1580. package/scripts/sessionstart-post-update-preflight.cjs +303 -0
  1581. package/scripts/sessionstart-reference-now-seed.cjs +137 -0
  1582. package/scripts/setup-hooks.sh +112 -0
  1583. package/scripts/skillopt-codereview.cjs +830 -0
  1584. package/scripts/skillopt-eval.cjs +519 -0
  1585. package/scripts/skillopt-funnel.cjs +1076 -0
  1586. package/scripts/skillopt-genqueries.cjs +571 -0
  1587. package/scripts/skillopt-inventory.cjs +319 -0
  1588. package/scripts/skillopt-merge.cjs +656 -0
  1589. package/scripts/skillopt-triggerloop.cjs +1126 -0
  1590. package/scripts/soft-alias-runner.cjs +116 -0
  1591. package/scripts/stamp-artifact-write.cjs +276 -0
  1592. package/scripts/stamp-firing-block.cjs +325 -0
  1593. package/scripts/state-write.cjs +97 -0
  1594. package/scripts/statusline-fallback-echo.cjs +297 -0
  1595. package/scripts/statusline-mos +116 -0
  1596. package/scripts/statusline-mos-dispatch +127 -0
  1597. package/scripts/suggest-next-command.cjs +416 -0
  1598. package/scripts/sweep-skill-descriptions.cjs +263 -0
  1599. package/scripts/sync-rooms-brain +438 -0
  1600. package/scripts/sync-rooms-graph +264 -0
  1601. package/scripts/telemetry-command-invocation.cjs +120 -0
  1602. package/scripts/test-doctor-recovery.cjs +242 -0
  1603. package/scripts/test-fresh-install.md +140 -0
  1604. package/scripts/track-analytics +156 -0
  1605. package/scripts/transcribe-audio +148 -0
  1606. package/scripts/transcript-ingest.cjs +225 -0
  1607. package/scripts/update-icm-index +153 -0
  1608. package/scripts/v182-brain-optimize.cypher +1191 -0
  1609. package/scripts/validate-model-profiles +93 -0
  1610. package/scripts/vault-content-reformatter.cjs +581 -0
  1611. package/scripts/vault-export-orchestrator.cjs +400 -0
  1612. package/scripts/vault-footer-injector.cjs +315 -0
  1613. package/scripts/vault-import.cjs +839 -0
  1614. package/scripts/vault-integration-test.cjs +318 -0
  1615. package/scripts/vault-regenerate-all.cjs +216 -0
  1616. package/scripts/vault-regenerate-all.test.cjs +138 -0
  1617. package/scripts/vault-rules-generator.cjs +220 -0
  1618. package/scripts/vault-section-minto-generator.cjs +1642 -0
  1619. package/scripts/vault-section-minto-generator.integration.test.cjs +576 -0
  1620. package/scripts/vault-section-minto-generator.test.cjs +291 -0
  1621. package/scripts/vault-section-state-generator.cjs +385 -0
  1622. package/scripts/vault-welcome-generator.cjs +403 -0
  1623. package/scripts/vault-wikilink-injector.cjs +449 -0
  1624. package/scripts/verify-phase-132.cjs +338 -0
  1625. package/scripts/verify-release +744 -0
  1626. package/scripts/whitespace-command.cjs +831 -0
  1627. package/scripts/whitespace-to-brain.cjs +383 -0
  1628. package/scripts/whitespace-to-graph.cjs +220 -0
  1629. package/scripts/wikilink-batch.cjs +102 -0
  1630. package/scripts/wikilink-file.cjs +139 -0
  1631. package/scripts/write-bridge-artifacts.cjs +140 -0
  1632. package/scripts/write-scope-check +12 -0
  1633. package/scripts/write-scope-check.cjs +461 -0
  1634. package/scripts/write-whitespace-sections.cjs +483 -0
  1635. package/settings.json +7 -0
  1636. package/skills/act/SKILL.md +523 -0
  1637. package/skills/admin/SKILL.md +437 -0
  1638. package/skills/agentshield/SKILL.md +50 -0
  1639. package/skills/analyze-needs/SKILL.md +74 -0
  1640. package/skills/analyze-systems/SKILL.md +69 -0
  1641. package/skills/analyze-timing/SKILL.md +94 -0
  1642. package/skills/auto-explore/SKILL.md +84 -0
  1643. package/skills/beautiful-question/SKILL.md +72 -0
  1644. package/skills/bono/SKILL.md +146 -0
  1645. package/skills/brain-connector/SKILL.md +206 -0
  1646. package/skills/brain-derive/SKILL.md +140 -0
  1647. package/skills/build-knowledge/SKILL.md +118 -0
  1648. package/skills/build-thesis/SKILL.md +90 -0
  1649. package/skills/causal/SKILL.md +265 -0
  1650. package/skills/challenge-assumptions/SKILL.md +74 -0
  1651. package/skills/client-discovery-interview/SKILL.md +94 -0
  1652. package/skills/client-discovery-interview/discovery-scaffold.json +41 -0
  1653. package/skills/client-discovery-interview/question-bank.md +149 -0
  1654. package/skills/compare-ventures/SKILL.md +113 -0
  1655. package/skills/context-engine/SKILL.md +169 -0
  1656. package/skills/conversation-mode/SKILL.md +189 -0
  1657. package/skills/correct-reference-now/SKILL.md +86 -0
  1658. package/skills/dashboard/SKILL.md +142 -0
  1659. package/skills/deck/SKILL.md +113 -0
  1660. package/skills/deep-grade/SKILL.md +210 -0
  1661. package/skills/diagnose/SKILL.md +128 -0
  1662. package/skills/diagnostics/SKILL.md +193 -0
  1663. package/skills/dial-memory-refresh/SKILL.md +116 -0
  1664. package/skills/diffusion/SKILL.md +125 -0
  1665. package/skills/discover/SKILL.md +216 -0
  1666. package/skills/doctor/SKILL.md +269 -0
  1667. package/skills/dogfood-flush/SKILL.md +133 -0
  1668. package/skills/dominant-designs/SKILL.md +72 -0
  1669. package/skills/eureka/SKILL.md +313 -0
  1670. package/skills/explain-decision/SKILL.md +138 -0
  1671. package/skills/explore-domains/SKILL.md +74 -0
  1672. package/skills/explore-futures/SKILL.md +64 -0
  1673. package/skills/explore-opportunity/SKILL.md +168 -0
  1674. package/skills/explore-trends/SKILL.md +74 -0
  1675. package/skills/export/SKILL.md +126 -0
  1676. package/skills/feynman-timeline-refresh/SKILL.md +105 -0
  1677. package/skills/file-meeting/SKILL.md +1190 -0
  1678. package/skills/find-analogies/SKILL.md +360 -0
  1679. package/skills/find-bottlenecks/SKILL.md +104 -0
  1680. package/skills/find-connections/SKILL.md +108 -0
  1681. package/skills/funding/SKILL.md +110 -0
  1682. package/skills/futures/SKILL.md +124 -0
  1683. package/skills/grade/SKILL.md +252 -0
  1684. package/skills/grade-grant/SKILL.md +293 -0
  1685. package/skills/graph/SKILL.md +216 -0
  1686. package/skills/hat-briefing/SKILL.md +160 -0
  1687. package/skills/heal/SKILL.md +69 -0
  1688. package/skills/help/SKILL.md +172 -0
  1689. package/skills/hmi-status/SKILL.md +73 -0
  1690. package/skills/ignite/SKILL.md +225 -0
  1691. package/skills/ingest-methodology/SKILL.md +125 -0
  1692. package/skills/intel-pipeline/SKILL.md +128 -0
  1693. package/skills/intelligence-orchestrator/SKILL.md +262 -0
  1694. package/skills/jtbd/SKILL.md +261 -0
  1695. package/skills/larry-personality/SKILL.md +570 -0
  1696. package/skills/larry-personality/framework-chains.md +92 -0
  1697. package/skills/larry-personality/mode-engine.md +185 -0
  1698. package/skills/leadership/SKILL.md +109 -0
  1699. package/skills/lean-canvas/SKILL.md +70 -0
  1700. package/skills/macro-trends/SKILL.md +84 -0
  1701. package/skills/map-unknowns/SKILL.md +72 -0
  1702. package/skills/memory/SKILL.md +212 -0
  1703. package/skills/memory-cortex-reach/SKILL.md +80 -0
  1704. package/skills/models/SKILL.md +197 -0
  1705. package/skills/mos/SKILL.md +160 -0
  1706. package/skills/mos-deck-engine/SKILL.md +329 -0
  1707. package/skills/mos-reason/SKILL.md +484 -0
  1708. package/skills/mullins/SKILL.md +151 -0
  1709. package/skills/mullins-scaffold/SKILL.md +132 -0
  1710. package/skills/mullins-scaffold/scaffold.json +223 -0
  1711. package/skills/mva-brief/SKILL.md +87 -0
  1712. package/skills/mva-option/SKILL.md +120 -0
  1713. package/skills/mva-pipeline/SKILL.md +158 -0
  1714. package/skills/mva-report/SKILL.md +79 -0
  1715. package/skills/new-project/SKILL.md +629 -0
  1716. package/skills/new-surface/SKILL.md +112 -0
  1717. package/skills/onboard/SKILL.md +485 -0
  1718. package/skills/operator/SKILL.md +167 -0
  1719. package/skills/opportunities/SKILL.md +171 -0
  1720. package/skills/organize/SKILL.md +69 -0
  1721. package/skills/persona/SKILL.md +272 -0
  1722. package/skills/pipeline/SKILL.md +164 -0
  1723. package/skills/present/SKILL.md +123 -0
  1724. package/skills/publish/SKILL.md +224 -0
  1725. package/skills/pws-brain/SKILL.md +152 -0
  1726. package/skills/pws-methodology/SKILL.md +92 -0
  1727. package/skills/qualify-opportunity/SKILL.md +111 -0
  1728. package/skills/query/SKILL.md +68 -0
  1729. package/skills/radar/SKILL.md +106 -0
  1730. package/skills/reanalyze/SKILL.md +122 -0
  1731. package/skills/research/SKILL.md +462 -0
  1732. package/skills/room/SKILL.md +381 -0
  1733. package/skills/room-passive/SKILL.md +174 -0
  1734. package/skills/room-proactive/SKILL.md +344 -0
  1735. package/skills/rooms/SKILL.md +678 -0
  1736. package/skills/root-cause/SKILL.md +73 -0
  1737. package/skills/rs-experts/SKILL.md +151 -0
  1738. package/skills/rs-explain/SKILL.md +130 -0
  1739. package/skills/rs-fetch/SKILL.md +115 -0
  1740. package/skills/rs-thesis/SKILL.md +129 -0
  1741. package/skills/scenario-plan/SKILL.md +76 -0
  1742. package/skills/scheduled-tasks/SKILL.md +301 -0
  1743. package/skills/score-innovation/SKILL.md +74 -0
  1744. package/skills/scout/SKILL.md +370 -0
  1745. package/skills/setup/SKILL.md +654 -0
  1746. package/skills/show/SKILL.md +68 -0
  1747. package/skills/skill/SKILL.md +104 -0
  1748. package/skills/snapshot/SKILL.md +178 -0
  1749. package/skills/speakers/SKILL.md +116 -0
  1750. package/skills/splash/SKILL.md +54 -0
  1751. package/skills/stance/SKILL.md +89 -0
  1752. package/skills/status/SKILL.md +107 -0
  1753. package/skills/structure-argument/SKILL.md +78 -0
  1754. package/skills/suggest-next/SKILL.md +137 -0
  1755. package/skills/systems-thinking/SKILL.md +220 -0
  1756. package/skills/think-hats/SKILL.md +82 -0
  1757. package/skills/trending-to-absurd/SKILL.md +100 -0
  1758. package/skills/ui-system/SKILL.md +474 -0
  1759. package/skills/ui-system/design-system/M-OS-DESIGN-SYSTEM.md +273 -0
  1760. package/skills/ui-system/design-system/SPEC.md +72 -0
  1761. package/skills/ui-system/design-system/image-prompt-style.md +29 -0
  1762. package/skills/ui-system/design-system/mos-design-system.css +240 -0
  1763. package/skills/ui-system/rules/design-system.md +60 -0
  1764. package/skills/ui-system/rules/dual-palette.md +156 -0
  1765. package/skills/ui-system/rules/glyph-disambiguation.md +171 -0
  1766. package/skills/ui-system/rules/shape-f-zero-and-six.md +169 -0
  1767. package/skills/update/SKILL.md +254 -0
  1768. package/skills/user-needs/SKILL.md +73 -0
  1769. package/skills/validate/SKILL.md +73 -0
  1770. package/skills/value-proposition/SKILL.md +141 -0
  1771. package/skills/vault/SKILL.md +326 -0
  1772. package/skills/visualize/SKILL.md +69 -0
  1773. package/skills/whitespace/SKILL.md +539 -0
  1774. package/skills/wiki/SKILL.md +94 -0
  1775. package/templates/_base.html +20 -0
  1776. package/templates/chat-panel.html +205 -0
  1777. package/templates/constellation-chat-hooks.js +89 -0
  1778. package/templates/constellation.html +1272 -0
  1779. package/templates/destijl-base.css +268 -0
  1780. package/templates/discovery/discovery-brief-template.md +97 -0
  1781. package/templates/due-diligence.html +49 -0
  1782. package/templates/executive-summary.html +40 -0
  1783. package/templates/icm/CLAUDE.md +31 -0
  1784. package/templates/icm/GROUP-CLAUDE.md +33 -0
  1785. package/templates/icm/INDEX.md +26 -0
  1786. package/templates/import/stage-contracts/01-ingest.md +34 -0
  1787. package/templates/import/stage-contracts/02-classify.md +48 -0
  1788. package/templates/import/stage-contracts/03-route.md +42 -0
  1789. package/templates/import/stage-contracts/04-enrich.md +40 -0
  1790. package/templates/investment-thesis.html +25 -0
  1791. package/templates/meeting-report.html +361 -0
  1792. package/templates/presentation/dashboard.html +1150 -0
  1793. package/templates/presentation/deck.html +540 -0
  1794. package/templates/presentation/diagrams.html +437 -0
  1795. package/templates/presentation/graph.html +391 -0
  1796. package/templates/presentation/insights.html +548 -0
  1797. package/templates/presentation/wiki.html +533 -0
  1798. package/templates/profile.html +136 -0
  1799. package/templates/room-context/last-session.md +56 -0
  1800. package/templates/room-context/methodology-history.md +28 -0
  1801. package/templates/room-context/rejection-log.md +25 -0
  1802. package/templates/room-context/weekly-digest.md +54 -0
  1803. package/templates/room-skeleton/MINTO.md.tmpl +19 -0
  1804. package/templates/room-skeleton/ROOM.md.identity.tmpl +13 -0
  1805. package/templates/room-skeleton/ROOM.md.section.tmpl +33 -0
  1806. package/templates/room-skeleton/STATE.md.tmpl +33 -0
  1807. package/templates/room-skeleton/USER.md.tmpl +23 -0
  1808. package/templates/room-skeleton/references/.gitkeep +0 -0
  1809. package/templates/room-skeleton/references/SECTION-SCHEMA.md +213 -0
  1810. package/templates/room-skeleton/references/SUB-SCHEMAS.md +91 -0
  1811. package/templates/room-skeleton/section-contracts/.gitkeep +0 -0
  1812. package/templates/room-skeleton/section-contracts/business-model.md +32 -0
  1813. package/templates/room-skeleton/section-contracts/competitive-analysis.md +33 -0
  1814. package/templates/room-skeleton/section-contracts/financial-model.md +30 -0
  1815. package/templates/room-skeleton/section-contracts/funding.md +41 -0
  1816. package/templates/room-skeleton/section-contracts/legal-ip.md +30 -0
  1817. package/templates/room-skeleton/section-contracts/market-analysis.md +32 -0
  1818. package/templates/room-skeleton/section-contracts/opportunity-bank.md +39 -0
  1819. package/templates/room-skeleton/section-contracts/problem-definition.md +32 -0
  1820. package/templates/room-skeleton/section-contracts/solution-design.md +36 -0
  1821. package/templates/room-skeleton/section-contracts/strategy.md +35 -0
  1822. package/templates/room-skeleton/section-contracts/team-execution.md +36 -0
  1823. package/templates/shared.css +427 -0
  1824. package/templates/showcase/blueprint.html +432 -0
  1825. package/templates/showcase/library.html +571 -0
  1826. package/templates/showcase/narrative.html +361 -0
  1827. package/templates/showcase/overview.html +468 -0
  1828. package/templates/showcase/synthesis.html +473 -0
  1829. package/templates/signature-footer.html +34 -0
@@ -0,0 +1,2073 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ rs-engine.py -- Reverse Salient Engine (Phase 89)
4
+ ==================================================
5
+
6
+ Authoritative port of the Kwan 2023 reverse-salient algorithm. Runs on a
7
+ single room (Mode A) and produces .rs-engine-results.json with pairs scored
8
+ by abs(semantic - lsa) and classified by signed directionality.
9
+
10
+ Algorithmic signature (RESEARCH.md Q1, ALGORITHM-SOURCE.md):
11
+ - Structural similarity: TF-IDF + TruncatedSVD(80) + topic-keyword
12
+ membership counting + L1 pairwise distance + invert-and-rescale.
13
+ This is NOT cosine-on-SVD. See lib/core/rs_math.py docstrings.
14
+ - Semantic similarity: sentence-transformer embeddings (MiniLM local by
15
+ default; multilingual-e5-large via Pinecone inference when available).
16
+ - Detection: iterative argmax on |semantic - lsa| with symmetric cleanup.
17
+ - Classification: signed (semantic - lsa) -> structural_transfer or
18
+ semantic_implementation.
19
+
20
+ Embedding model is configurable per RESEARCH.md Q4:
21
+ - RS_EMBEDDING_MODEL unset (default) -> multilingual-e5-large via Pinecone
22
+ inference (Plan 89-03 wires the cold path).
23
+ - RS_EMBEDDING_MODEL=minilm -> local all-MiniLM-L6-v2.
24
+ - RS_EMBEDDING_MODEL=bert-large-cased -> explicit repro mode (heavy).
25
+
26
+ Mode A (this plan, 89-01): internal single-room scan.
27
+ Mode B/C extend this script in Plans 89-04 / 89-05 (multi-room + external
28
+ corpus + hybrid). The mode dispatch is already wired here so those plans
29
+ only add helpers.
30
+
31
+ Three-surface usage:
32
+ CLI: python scripts/rs-engine.py --mode internal --room ./room
33
+ Desktop: invoked by ReverseSalientAgent conversational trigger (Plan 89-07).
34
+ Cowork: writes symlink into 00_Context/rs-engine-results.json when
35
+ COWORK=1 is set.
36
+
37
+ License: BSL-1.1 (see LICENSE at repo root).
38
+ """
39
+
40
+ from __future__ import annotations
41
+
42
+ import argparse
43
+ import hashlib
44
+ import json
45
+ import os
46
+ import re
47
+ import sqlite3
48
+ import sys
49
+ from datetime import datetime, timezone
50
+ from pathlib import Path
51
+ from typing import Any, Dict, List, Optional, Sequence, Tuple
52
+
53
+ # Auto-install Python ML deps if missing (v1.10.9, plan 85-10, LAWRENCE-001).
54
+ # rs-engine.py is the direct entry point for /mos:find-bottlenecks (invoked by
55
+ # lib/agents/reverse-salient-agent.cjs); it never had this wiring even though
56
+ # sibling whitespace scripts did (RCA phase-134-python-elimination-false-
57
+ # complete -- Change 1). `requests` is included here (not just numpy) because
58
+ # it is a transitive import in lib/core/rs_corpus.py, loaded a few lines below
59
+ # this block -- and `requests` was the actual root cause of the original
60
+ # Windows tester 2026-05-23 silent-failure class this file's own comments
61
+ # reference (see runRsEngine's diagnostic-forwarding logic in
62
+ # reverse-salient-agent.cjs).
63
+ sys.path.insert(0, str(Path(__file__).resolve().parent / "lib"))
64
+ from ensure_ml_deps import ensure
65
+ ensure(["numpy", "requests"])
66
+
67
+ # --- Guarded imports ---------------------------------------------------------
68
+
69
+ try:
70
+ import numpy as np
71
+ except ImportError:
72
+ print(
73
+ "rs-engine requires numpy. Run: pip install -r requirements-hsi.txt",
74
+ file=sys.stderr,
75
+ )
76
+ sys.exit(1)
77
+
78
+ # Import shared math helpers. rs-engine.py is invoked from the repo root so
79
+ # the "lib.core.rs_math" package path is canonical (plan verify block uses
80
+ # this exact import).
81
+ _THIS_FILE = Path(__file__).resolve()
82
+ _REPO_ROOT = _THIS_FILE.parent.parent
83
+ if str(_REPO_ROOT) not in sys.path:
84
+ sys.path.insert(0, str(_REPO_ROOT))
85
+
86
+ from lib.core.rs_math import ( # noqa: E402
87
+ abs_diff_topk,
88
+ build_lsa_matrix,
89
+ classify_direction,
90
+ )
91
+ from lib.core.rs_corpus import ( # noqa: E402
92
+ fetch_corpus,
93
+ topic_slug,
94
+ semantic_gate,
95
+ SEMANTIC_FLOOR,
96
+ )
97
+ from lib.core.rs_rooms import ( # noqa: E402
98
+ load_multi_room_corpus,
99
+ summarize_corpus,
100
+ )
101
+ # Plan 89-05 wires Mode C (hybrid) via rs_hybrid. Import is optional at the
102
+ # top so Mode A / Mode B remain importable when rs_hybrid is missing; the
103
+ # hybrid dispatch in main() raises a clear error if the import failed.
104
+ try:
105
+ from lib.core.rs_hybrid import ( # noqa: E402
106
+ build_unified_corpus as _rs_hybrid_build,
107
+ filter_cross_corpus_pairs as _rs_hybrid_filter,
108
+ )
109
+ _RS_HYBRID_AVAILABLE = True
110
+ except Exception as _rs_hybrid_import_err: # pragma: no cover -- defensive
111
+ _RS_HYBRID_AVAILABLE = False
112
+ _rs_hybrid_import_err_msg = str(_rs_hybrid_import_err)
113
+ # Plan 89-03 wires the Pinecone rs-external cache for Mode B. The import is
114
+ # optional so Mode A (internal) remains usable without Pinecone installed --
115
+ # rs_cache has a guarded import of the pinecone SDK.
116
+ try:
117
+ from lib.core.rs_cache import ( # noqa: E402
118
+ namespace_slug as _rs_cache_namespace_slug,
119
+ get_namespace_freshness as _rs_cache_freshness,
120
+ upsert_corpus as _rs_cache_upsert,
121
+ fetch_all_from_namespace as _rs_cache_fetch_all,
122
+ is_fresh as _rs_cache_is_fresh,
123
+ TTL_DAYS as _RS_CACHE_TTL_DAYS,
124
+ )
125
+ # Module reference (not just the named re-exports above) so the SEED-018
126
+ # semantic gate can call rs_cache._embed_via_bridge directly and build its
127
+ # topic vector from the SAME local encoder that produced the record
128
+ # vectors it gates -- see _gate_records_cached below (Plan 296-05).
129
+ from lib.core import rs_cache
130
+ _RS_CACHE_AVAILABLE = True
131
+ except Exception as _rs_cache_import_err: # pragma: no cover -- defensive
132
+ _RS_CACHE_AVAILABLE = False
133
+ _rs_cache_import_err_msg = str(_rs_cache_import_err)
134
+
135
+
136
+ # --- Constants ---------------------------------------------------------------
137
+
138
+ DEFAULT_EMBEDDING_MODEL = "multilingual-e5-large"
139
+ # SKIP_FILES / SKIP_DIRS from the ONE shared source (Phase 200-01, SEED-018).
140
+ # Was a local copy that the other walkers drifted from; now single-sourced.
141
+ from lib.core.rs_corpus_exclude import SKIP_DIRS, SKIP_FILES # noqa: E402
142
+ CACHE_FILENAME = ".rs-engine-cache.json"
143
+ RESULTS_FILENAME = ".rs-engine-results.json"
144
+ DEFAULT_TOPK = 100
145
+ DEFAULT_THRESHOLD = 0.30
146
+ ENGINE_VERSION = "1"
147
+
148
+ # Mode C (hybrid) post-filter overshoot. After abs-diff top-k over the
149
+ # unified corpus, we discard any intra-corpus pair (room-room or
150
+ # external-external) and keep only cross-corpus pairs. An overshoot of
151
+ # 10x the requested topk gives enough headroom to reach topk on realistic
152
+ # corpora where room artifacts (O(100)) are dwarfed by external docs
153
+ # (O(2000)) and most of the strongest abs-diff pairs would be
154
+ # external-external by volume alone. Smaller overshoots silently shrink
155
+ # delivered pair count below topk; larger overshoots waste O(k log k)
156
+ # sort work. Plan 89-05 Detailed Steps specify 10x.
157
+ HYBRID_OVERSHOOT = 10
158
+
159
+
160
+ # --- Artifact discovery ------------------------------------------------------
161
+
162
+ def parse_frontmatter(content: str) -> Dict[str, str]:
163
+ fm_match = re.match(r"^---\n([\s\S]*?)\n---", content)
164
+ if not fm_match:
165
+ return {}
166
+ fields = {}
167
+ for line in fm_match.group(1).split("\n"):
168
+ if ":" in line:
169
+ key, _, val = line.partition(":")
170
+ fields[key.strip()] = val.strip().strip('"').strip("'")
171
+ return fields
172
+
173
+
174
+ def extract_title(content: str, filepath: Path) -> str:
175
+ match = re.search(r"^# (.+)$", content, re.MULTILINE)
176
+ if match:
177
+ return match.group(1).strip()
178
+ return filepath.stem.replace("-", " ").title()
179
+
180
+
181
+ def extract_body(content: str) -> str:
182
+ fm_match = re.match(r"^---\n[\s\S]*?\n---\n?", content)
183
+ if fm_match:
184
+ return content[fm_match.end():]
185
+ return content
186
+
187
+
188
+ def discover_artifacts(room_dir: Path) -> List[Dict]:
189
+ """Walk room_dir for .md artifacts. Mirrors compute-hsi.py pattern.
190
+
191
+ The authoritative source's artifact loader assumed a flat SQLite
192
+ "artifacts" table. The real MindrianOS schema (lib/core/lazygraph-ops.cjs)
193
+ keeps artifacts on disk as .md files and tracks them in the nodes table
194
+ by reference. Plan 89-01 said to read room.db artifacts directly; that
195
+ table does not exist. We walk the filesystem instead (same pattern as
196
+ compute-hsi.py) so the port works against real rooms, and cache
197
+ embeddings in a JSON sidecar below. This is a documented Rule 3 fix.
198
+ """
199
+ artifacts: List[Dict] = []
200
+ room_path = room_dir.resolve()
201
+
202
+ for root, dirs, files in os.walk(room_path):
203
+ dirs[:] = [d for d in dirs if d not in SKIP_DIRS]
204
+ rel_root = Path(root).relative_to(room_path)
205
+ if str(rel_root) == ".":
206
+ # Skip room-root files -- not part of any section.
207
+ continue
208
+ section = str(rel_root).split(os.sep)[0]
209
+ for fname in sorted(files):
210
+ if not fname.endswith(".md"):
211
+ continue
212
+ if fname in SKIP_FILES:
213
+ continue
214
+ fpath = Path(root) / fname
215
+ try:
216
+ content = fpath.read_text(encoding="utf-8")
217
+ except (OSError, UnicodeDecodeError):
218
+ continue
219
+ body = extract_body(content).strip()
220
+ if len(body) < 50:
221
+ continue
222
+ artifact_id = str(rel_root / Path(fname).stem).replace(os.sep, "/")
223
+ artifacts.append({
224
+ "id": artifact_id,
225
+ "section": section,
226
+ "title": extract_title(content, fpath),
227
+ "path": str(fpath.relative_to(room_path)),
228
+ "text": body,
229
+ })
230
+ return artifacts
231
+
232
+
233
+ # --- Embedding path ---------------------------------------------------------
234
+
235
+ def _content_hash(text: str) -> str:
236
+ return hashlib.sha256(text.encode("utf-8")).hexdigest()[:16]
237
+
238
+
239
+ def _load_embedding_cache(room_dir: Path) -> Dict[str, Dict]:
240
+ cache_path = room_dir / CACHE_FILENAME
241
+ if not cache_path.exists():
242
+ return {}
243
+ try:
244
+ raw = json.loads(cache_path.read_text(encoding="utf-8"))
245
+ if not isinstance(raw, dict) or raw.get("version") != ENGINE_VERSION:
246
+ return {}
247
+ embeddings = raw.get("embeddings", {})
248
+ return embeddings if isinstance(embeddings, dict) else {}
249
+ except (json.JSONDecodeError, OSError):
250
+ return {}
251
+
252
+
253
+ def _save_embedding_cache(
254
+ room_dir: Path,
255
+ cache: Dict[str, Dict],
256
+ model_name: str,
257
+ ) -> None:
258
+ cache_path = room_dir / CACHE_FILENAME
259
+ payload = {
260
+ "version": ENGINE_VERSION,
261
+ "updated_at": datetime.now(timezone.utc).isoformat(),
262
+ "model": model_name,
263
+ "embeddings": cache,
264
+ }
265
+ try:
266
+ tmp_path = cache_path.with_suffix(cache_path.suffix + ".tmp")
267
+ tmp_path.write_text(json.dumps(payload, indent=2), encoding="utf-8")
268
+ tmp_path.replace(cache_path)
269
+ except OSError as e:
270
+ print(f"rs-engine: cache write failed: {e}", file=sys.stderr)
271
+
272
+
273
+ def _embed_local_minilm(texts: Sequence[str]) -> Optional[np.ndarray]:
274
+ try:
275
+ from sentence_transformers import SentenceTransformer
276
+ except ImportError:
277
+ print(
278
+ "rs-engine: sentence-transformers not installed; "
279
+ "run `pip install -r requirements-hsi.txt`",
280
+ file=sys.stderr,
281
+ )
282
+ return None
283
+ model = SentenceTransformer("all-MiniLM-L6-v2")
284
+ vectors = model.encode(list(texts), show_progress_bar=False)
285
+ return np.asarray(vectors, dtype=np.float32)
286
+
287
+
288
+ def _embed_via_pinecone_inference(texts: Sequence[str]) -> Optional[np.ndarray]:
289
+ """Cold path: call Pinecone inference API for multilingual-e5-large.
290
+
291
+ Plan-check Gap 1 (PLAN-CHECK.md) explicitly documents that this entry is
292
+ stubbed in Plan 89-01 and completed in Plans 89-03 / 89-05. Raising
293
+ NotImplementedError keeps the failure loud and localizable if 89-03 is
294
+ skipped, rather than silently falling back to MiniLM.
295
+
296
+ The plan authorizes this stub: PLAN-CHECK Gap 1 resolution says "89-01
297
+ must stub with NotImplementedError for the cold path, documented as
298
+ 'completed in 89-03 / 89-05.'"
299
+ """
300
+ raise NotImplementedError(
301
+ "Pinecone inference embedding is wired in Plan 89-03 / 89-05. "
302
+ "For Plan 89-01 (Mode A internal), set RS_EMBEDDING_MODEL=minilm "
303
+ "or rely on cached embeddings in .rs-engine-cache.json."
304
+ )
305
+
306
+
307
+ def compute_embeddings(
308
+ artifacts: Sequence[Dict],
309
+ room_dir: Path,
310
+ ) -> Tuple[Optional[np.ndarray], str]:
311
+ """Return (embedding_matrix, model_name). Uses cache where possible.
312
+
313
+ Precedence:
314
+ 1. RS_EMBEDDING_MODEL=minilm OR default-but-Pinecone-unavailable
315
+ -> local MiniLM.
316
+ 2. RS_EMBEDDING_MODEL=bert-large-cased -> repro path (not implemented
317
+ in 89-01; deferred to a future plan).
318
+ 3. Default (no env var) AND Pinecone inference wired
319
+ -> multilingual-e5-large (stub raises; see docstring).
320
+ """
321
+ model_env = os.environ.get("RS_EMBEDDING_MODEL", "").strip().lower()
322
+
323
+ # Fall back to MiniLM when Pinecone stub cannot serve the cold path.
324
+ cold_model = "all-MiniLM-L6-v2" if model_env in ("", "minilm") else model_env
325
+ cache = _load_embedding_cache(room_dir)
326
+
327
+ # Resolve cache hits vs misses.
328
+ missing_indices: List[int] = []
329
+ dim: Optional[int] = None
330
+ vectors: List[Optional[np.ndarray]] = [None] * len(artifacts)
331
+ for idx, art in enumerate(artifacts):
332
+ digest = _content_hash(art["text"])
333
+ cache_entry = cache.get(art["id"])
334
+ if (
335
+ isinstance(cache_entry, dict)
336
+ and cache_entry.get("hash") == digest
337
+ and cache_entry.get("model") == cold_model
338
+ and isinstance(cache_entry.get("vector"), list)
339
+ ):
340
+ vec = np.asarray(cache_entry["vector"], dtype=np.float32)
341
+ vectors[idx] = vec
342
+ if dim is None:
343
+ dim = vec.shape[0]
344
+ else:
345
+ missing_indices.append(idx)
346
+
347
+ if missing_indices:
348
+ missing_texts = [artifacts[i]["text"] for i in missing_indices]
349
+ new_vectors: Optional[np.ndarray] = None
350
+ model_used = cold_model
351
+
352
+ if model_env == "minilm" or model_env == "" and cold_model == "all-MiniLM-L6-v2":
353
+ # MiniLM is the honest default until 89-03 wires Pinecone.
354
+ new_vectors = _embed_local_minilm(missing_texts)
355
+ model_used = "all-MiniLM-L6-v2"
356
+ elif model_env == DEFAULT_EMBEDDING_MODEL or model_env == "e5-large":
357
+ # Pinecone inference path. Plan 89-01 stub -> NotImplementedError.
358
+ new_vectors = _embed_via_pinecone_inference(missing_texts)
359
+ model_used = DEFAULT_EMBEDDING_MODEL
360
+ elif model_env == "bert-large-cased":
361
+ # Repro path -- not wired in 89-01; raise clear error.
362
+ raise NotImplementedError(
363
+ "RS_EMBEDDING_MODEL=bert-large-cased is not wired in Plan 89-01. "
364
+ "Use RS_EMBEDDING_MODEL=minilm for this plan."
365
+ )
366
+ else:
367
+ # Unknown model name -- default to MiniLM with a warning.
368
+ print(
369
+ f"rs-engine: unknown RS_EMBEDDING_MODEL={model_env!r}; "
370
+ "falling back to local MiniLM",
371
+ file=sys.stderr,
372
+ )
373
+ new_vectors = _embed_local_minilm(missing_texts)
374
+ model_used = "all-MiniLM-L6-v2"
375
+
376
+ if new_vectors is None:
377
+ return None, model_used
378
+
379
+ for offset, idx in enumerate(missing_indices):
380
+ vec = new_vectors[offset]
381
+ vectors[idx] = vec
382
+ if dim is None:
383
+ dim = vec.shape[0]
384
+ cache[artifacts[idx]["id"]] = {
385
+ "hash": _content_hash(artifacts[idx]["text"]),
386
+ "model": model_used,
387
+ "vector": vec.astype(np.float32).tolist(),
388
+ }
389
+ _save_embedding_cache(room_dir, cache, model_used)
390
+ cold_model = model_used
391
+
392
+ matrix = np.vstack([v for v in vectors if v is not None])
393
+ return matrix, cold_model
394
+
395
+
396
+ def semantic_similarity_matrix(embeddings: np.ndarray) -> np.ndarray:
397
+ """Cosine similarity on row-normalized embedding vectors."""
398
+ from sklearn.metrics.pairwise import cosine_similarity
399
+ sim = cosine_similarity(embeddings)
400
+ return np.clip(sim, 0.0, 1.0).astype(np.float32)
401
+
402
+
403
+ # --- SQLite edge writer ------------------------------------------------------
404
+
405
+ # System provenance defaults for rs-engine's own node writes. Mirrors
406
+ # lib/core/node-insert.cjs's SYSTEM_SOURCE_PATH / SYSTEM_CREATED_BY, using a
407
+ # distinct source_path handle ('system:rs-engine' vs the JS module's
408
+ # 'system:hsi-to-graph') so RS-written nodes stay distinguishable from
409
+ # HSI-written ones per the RCA's Change 1 requirement.
410
+ RS_ENGINE_SOURCE_PATH = "system:rs-engine"
411
+ RS_ENGINE_CREATED_BY = "system"
412
+
413
+
414
+ def _now_ms() -> int:
415
+ """Epoch milliseconds, matching the INTEGER created_at/last_seen_at
416
+ columns the Phase-109 migration writes (see phase-109-nodes-provenance.cjs,
417
+ which stores JS Date.now()-shaped epoch-ms integers)."""
418
+ return int(datetime.now(timezone.utc).timestamp() * 1000)
419
+
420
+
421
+ def _nodes_table_is_migrated(conn: sqlite3.Connection) -> bool:
422
+ """Detect the Phase-109 provenance schema on the nodes table.
423
+
424
+ Mirrors lib/core/node-insert.cjs's isMigratedSchema: PRAGMA table_info(nodes)
425
+ and check for the source_path column. Defensive: any PRAGMA failure falls
426
+ back to the legacy 3-column shape (the wide insert would throw on a real
427
+ legacy db, so defaulting to legacy is the safe choice -- same rationale as
428
+ the JS helper).
429
+ """
430
+ try:
431
+ cols = conn.execute("PRAGMA table_info(nodes)").fetchall()
432
+ # PRAGMA table_info row shape: (cid, name, type, notnull, dflt_value, pk)
433
+ return any(row[1] == "source_path" for row in cols)
434
+ except sqlite3.Error:
435
+ return False
436
+
437
+
438
+ def _upsert_node(
439
+ conn: sqlite3.Connection,
440
+ migrated: bool,
441
+ node_id: str,
442
+ node_type: str,
443
+ properties_json: str,
444
+ ) -> None:
445
+ """NOT-NULL-safe node upsert (RCA rs-engine-python-insert-not-null-and-detail-drop-regression).
446
+
447
+ Mirrors lib/core/node-insert.cjs's insertNode contract in Python. The bare
448
+ 3-column insert this replaces crashed with
449
+ `NOT NULL constraint failed: nodes.source_path` on any room.db carrying
450
+ the Phase-109 wide nodes schema, since node-insert.cjs's Phase 140-01 fix
451
+ only covers its 4 JS call sites and this script is Python.
452
+
453
+ On the migrated (wide) schema, supplies the four NOT NULL provenance
454
+ columns with rs-engine's own system-write defaults. On the legacy
455
+ 3-column schema, keeps the original bare insert unchanged.
456
+ """
457
+ if migrated:
458
+ now_ms = _now_ms()
459
+ conn.execute(
460
+ "INSERT INTO nodes "
461
+ "(id, type, properties, source_path, created_by, created_at, last_seen_at) "
462
+ "VALUES (?, ?, ?, ?, ?, ?, ?) "
463
+ "ON CONFLICT(id) DO UPDATE SET "
464
+ "properties = excluded.properties, last_seen_at = excluded.last_seen_at",
465
+ (
466
+ node_id,
467
+ node_type,
468
+ properties_json,
469
+ RS_ENGINE_SOURCE_PATH,
470
+ RS_ENGINE_CREATED_BY,
471
+ now_ms,
472
+ now_ms,
473
+ ),
474
+ )
475
+ return
476
+ conn.execute(
477
+ "INSERT INTO nodes (id, type, properties) VALUES (?, ?, ?) "
478
+ "ON CONFLICT(id) DO UPDATE SET properties = excluded.properties",
479
+ (node_id, node_type, properties_json),
480
+ )
481
+
482
+
483
+ def write_reverse_salient_edges(
484
+ room_dir: Path,
485
+ pairs: Sequence[Dict],
486
+ ) -> int:
487
+ """Insert REVERSE_SALIENT edges into room.db carrying source='rs-engine'.
488
+
489
+ Plan 89-01 said to ALTER the REVERSE_SALIENT table to add a `source`
490
+ column; REVERSE_SALIENT is an edge TYPE not a table. The real schema
491
+ (lib/core/lazygraph-ops.cjs) uses a single `edges` table with a
492
+ flexible `properties` JSON column. Rule 3 adaptation: we namespace our
493
+ edges by writing `source: 'rs-engine'` inside properties, and we DO NOT
494
+ delete edges written by hsi-to-graph.cjs (which carry source='hsi'
495
+ implicitly or via future backfill). Coexistence is the RESEARCH.md Q1
496
+ decision (b) invariant.
497
+
498
+ Returns the number of edges actually inserted.
499
+ """
500
+ db_path = room_dir / ".mindrian" / "room.db"
501
+ if not db_path.exists():
502
+ # Room has no graph yet -- skip silently; JSON output is still the
503
+ # authoritative artifact for Plan 89-01.
504
+ return 0
505
+
506
+ conn = sqlite3.connect(str(db_path))
507
+ try:
508
+ conn.execute("PRAGMA journal_mode=WAL")
509
+ # Ensure the edges table exists (rooms initialized outside lazygraph).
510
+ conn.execute(
511
+ """
512
+ CREATE TABLE IF NOT EXISTS edges (
513
+ source TEXT NOT NULL,
514
+ target TEXT NOT NULL,
515
+ type TEXT NOT NULL,
516
+ properties TEXT DEFAULT '{}',
517
+ PRIMARY KEY (source, target, type)
518
+ )
519
+ """
520
+ )
521
+ conn.execute(
522
+ """
523
+ CREATE TABLE IF NOT EXISTS nodes (
524
+ id TEXT PRIMARY KEY,
525
+ type TEXT NOT NULL,
526
+ properties TEXT DEFAULT '{}'
527
+ )
528
+ """
529
+ )
530
+
531
+ # Cleanup: remove only rs-engine-sourced edges (json_extract safely
532
+ # returns NULL on missing key, so non-rs-engine edges are preserved).
533
+ conn.execute(
534
+ "DELETE FROM edges WHERE type = 'REVERSE_SALIENT' "
535
+ "AND json_extract(properties, '$.source') = 'rs-engine'"
536
+ )
537
+
538
+ upsert_edge = (
539
+ "INSERT INTO edges (source, target, type, properties) "
540
+ "VALUES (?, ?, ?, ?) ON CONFLICT(source, target, type) "
541
+ "DO UPDATE SET properties = excluded.properties"
542
+ )
543
+ # Detect schema ONCE per invocation (D-02a both-schema safety, mirrors
544
+ # node-insert.cjs's per-call PRAGMA check): a migrated db requires the
545
+ # wide insert, a legacy 3-col db (created by the CREATE TABLE IF NOT
546
+ # EXISTS above, on a room with no prior migration) rejects it.
547
+ migrated = _nodes_table_is_migrated(conn)
548
+
549
+ written = 0
550
+ for pair in pairs:
551
+ src = pair.get("source_artifact_id")
552
+ tgt = pair.get("target_artifact_id")
553
+ if not src or not tgt:
554
+ continue
555
+ # Upsert artifact nodes as a courtesy so downstream readers can
556
+ # resolve them without relying on compute-hsi having run first.
557
+ _upsert_node(
558
+ conn,
559
+ migrated,
560
+ src,
561
+ "Artifact",
562
+ json.dumps({
563
+ "title": pair.get("source_title", ""),
564
+ "section": pair.get("source_section", ""),
565
+ }),
566
+ )
567
+ _upsert_node(
568
+ conn,
569
+ migrated,
570
+ tgt,
571
+ "Artifact",
572
+ json.dumps({
573
+ "title": pair.get("target_title", ""),
574
+ "section": pair.get("target_section", ""),
575
+ }),
576
+ )
577
+ props = json.dumps({
578
+ "source": "rs-engine",
579
+ "lsa_score": pair["lsa_score"],
580
+ "semantic_score": pair["semantic_score"],
581
+ "signed_diff": pair["signed_diff"],
582
+ "abs_diff": pair["abs_diff"],
583
+ "direction": pair["direction"],
584
+ "innovation_type": pair["direction"],
585
+ })
586
+ conn.execute(upsert_edge, (src, tgt, "REVERSE_SALIENT", props))
587
+ written += 1
588
+ conn.commit()
589
+ return written
590
+ finally:
591
+ conn.close()
592
+
593
+
594
+ # --- Mode A runner -----------------------------------------------------------
595
+
596
+ def run_mode_internal(
597
+ room_dir: Path,
598
+ topk: int,
599
+ threshold: float,
600
+ no_thesis: bool,
601
+ ) -> Dict:
602
+ artifacts = discover_artifacts(room_dir)
603
+ if len(artifacts) < 2:
604
+ return {
605
+ "metadata": {
606
+ "mode": "internal",
607
+ "room_dir": str(room_dir),
608
+ "artifact_count": len(artifacts),
609
+ "timestamp": datetime.now(timezone.utc).isoformat(),
610
+ "engine_version": ENGINE_VERSION,
611
+ },
612
+ "pairs": [],
613
+ }
614
+
615
+ texts = [f"{a['title']}\n{a['text']}" for a in artifacts]
616
+
617
+ # Structural signal: authoritative topic-keyword-membership LSA.
618
+ lsa_matrix = build_lsa_matrix(texts)
619
+
620
+ # Semantic signal: embedding cosine.
621
+ embeddings, model_used = compute_embeddings(artifacts, room_dir)
622
+ if embeddings is None:
623
+ # Fallback: treat semantic as identity so abs_diff collapses to 1-lsa.
624
+ # This keeps the engine honest when no embedder is available.
625
+ print(
626
+ "rs-engine: no embedder available; semantic matrix set to identity",
627
+ file=sys.stderr,
628
+ )
629
+ n = len(artifacts)
630
+ sem_matrix = np.eye(n, dtype=np.float32)
631
+ else:
632
+ sem_matrix = semantic_similarity_matrix(embeddings)
633
+
634
+ top_pairs = abs_diff_topk(lsa_matrix, sem_matrix, k=topk)
635
+
636
+ pair_dicts: List[Dict] = []
637
+ for i, j, signed, absv in top_pairs:
638
+ if absv < threshold:
639
+ continue
640
+ a_i, a_j = artifacts[i], artifacts[j]
641
+ pair_dicts.append({
642
+ "source_artifact_id": a_i["id"],
643
+ "source_title": a_i["title"],
644
+ "source_section": a_i["section"],
645
+ "target_artifact_id": a_j["id"],
646
+ "target_title": a_j["title"],
647
+ "target_section": a_j["section"],
648
+ "lsa_score": round(float(lsa_matrix[i, j]), 4),
649
+ "semantic_score": round(float(sem_matrix[i, j]), 4),
650
+ "signed_diff": round(float(signed), 4),
651
+ "abs_diff": round(float(absv), 4),
652
+ "direction": classify_direction(signed),
653
+ })
654
+
655
+ edges_written = write_reverse_salient_edges(room_dir, pair_dicts)
656
+
657
+ result = {
658
+ "metadata": {
659
+ "mode": "internal",
660
+ "room_dir": str(room_dir),
661
+ "artifact_count": len(artifacts),
662
+ "topk_requested": topk,
663
+ "threshold": threshold,
664
+ "embedding_model": model_used,
665
+ "thesis_generated": False, # Plan 89-01 always cost-free.
666
+ "no_thesis": bool(no_thesis),
667
+ "edges_written": edges_written,
668
+ "timestamp": datetime.now(timezone.utc).isoformat(),
669
+ "engine_version": ENGINE_VERSION,
670
+ },
671
+ "pairs": pair_dicts,
672
+ }
673
+ return result
674
+
675
+
676
+ # --- Cross-room (Mode A multi-room) runner -----------------------------------
677
+
678
+ # Overshoot multiplier for cross-room filtering. After abs-diff top-k, we
679
+ # discard any pair whose two artifacts live in the same room. A modest 3x
680
+ # overshoot keeps the post-filter yield close to the requested topk even when
681
+ # a few of the strongest pairs happen to be intra-room. Larger overshoots
682
+ # pay an O(k log k) cost but are wasted if yield is already >= topk.
683
+ CROSS_ROOM_OVERSHOOT = 3
684
+ CROSS_ROOM_WARN_SHARE = 0.05 # warn when any room contributes < 5% of corpus
685
+
686
+
687
+ def run_mode_cross_room(
688
+ room_paths: Sequence[str],
689
+ topk: int,
690
+ threshold: float,
691
+ no_thesis: bool,
692
+ ) -> Dict:
693
+ """Mode A multi-room: scan N rooms and keep only cross-room pairs.
694
+
695
+ Output contract (per plan):
696
+ - metadata.mode == "cross-room"
697
+ - metadata.rooms == [room_id, ...] in input order
698
+ - every pair has source_room != target_room
699
+ - pairs carry source_room / target_room / source_artifact / target_artifact
700
+
701
+ The cross-room summary table is printed to stderr by the caller; this
702
+ function only computes the payload.
703
+ """
704
+ corpus = load_multi_room_corpus(room_paths)
705
+ room_ids = []
706
+ seen = set()
707
+ for art in corpus:
708
+ rid = art["room_id"]
709
+ if rid not in seen:
710
+ room_ids.append(rid)
711
+ seen.add(rid)
712
+
713
+ if len(corpus) < 10:
714
+ # The authoritative algorithm's LSA fit needs enough documents to
715
+ # produce stable topic keywords. Below 10, cross-room signal is
716
+ # unreliable. Plan's canonical threshold.
717
+ print(
718
+ f"[rs-engine] Only {len(corpus)} artifacts across "
719
+ f"{len(room_paths)} rooms. Need >= 10 for cross-room mode.",
720
+ file=sys.stderr,
721
+ )
722
+ return {
723
+ "metadata": {
724
+ "mode": "cross-room",
725
+ "rooms": room_ids,
726
+ "room_paths": [str(Path(rp).resolve()) for rp in room_paths],
727
+ "artifact_count": len(corpus),
728
+ "room_counts": summarize_corpus(corpus),
729
+ "topk_requested": topk,
730
+ "threshold": threshold,
731
+ "no_thesis": bool(no_thesis),
732
+ "thesis_generated": False,
733
+ "pair_matrix": {},
734
+ "timestamp": datetime.now(timezone.utc).isoformat(),
735
+ "engine_version": ENGINE_VERSION,
736
+ },
737
+ "pairs": [],
738
+ }
739
+
740
+ if len({a["room_id"] for a in corpus}) < 2:
741
+ # All usable artifacts came from a single room; no cross-room pair
742
+ # is possible by construction. Emit an empty-pairs result with a
743
+ # clear message rather than silently running the algorithm.
744
+ print(
745
+ "[rs-engine] All artifacts come from a single room; "
746
+ "cross-room filter yields zero pairs by construction.",
747
+ file=sys.stderr,
748
+ )
749
+ return {
750
+ "metadata": {
751
+ "mode": "cross-room",
752
+ "rooms": room_ids,
753
+ "room_paths": [str(Path(rp).resolve()) for rp in room_paths],
754
+ "artifact_count": len(corpus),
755
+ "room_counts": summarize_corpus(corpus),
756
+ "topk_requested": topk,
757
+ "threshold": threshold,
758
+ "no_thesis": bool(no_thesis),
759
+ "thesis_generated": False,
760
+ "pair_matrix": {},
761
+ "timestamp": datetime.now(timezone.utc).isoformat(),
762
+ "engine_version": ENGINE_VERSION,
763
+ },
764
+ "pairs": [],
765
+ }
766
+
767
+ # Share-skew warning (plan Risk 1). Any room contributing < 5% of the
768
+ # corpus can skew LSA toward the dominant rooms' vocabulary.
769
+ room_counts = summarize_corpus(corpus)
770
+ total = len(corpus)
771
+ for rid, count in room_counts.items():
772
+ share = count / total if total else 0.0
773
+ if share < CROSS_ROOM_WARN_SHARE:
774
+ print(
775
+ f"[rs-engine] Warning: room {rid!r} contributes "
776
+ f"{count}/{total} artifacts ({share:.1%}); LSA may skew "
777
+ f"away from it.",
778
+ file=sys.stderr,
779
+ )
780
+
781
+ # Build the multi-room corpus as if it were one flat artifact list. The
782
+ # engine's LSA fit + abs-diff top-k run byte-identical to Mode A; only
783
+ # the post-filter step is new.
784
+ texts = [f"{a['title']}\n{a['text']}" for a in corpus]
785
+
786
+ lsa_matrix = build_lsa_matrix(texts)
787
+
788
+ # Semantic signal: use the same path as Mode A single-room. We embed
789
+ # into a transient cache in the FIRST room's .mindrian-less root. The
790
+ # cache lives alongside the cross-room results file so multi-room
791
+ # embeddings cannot collide with a single-room Mode A cache on the same
792
+ # first-room path (different artifact-id shapes).
793
+ first_room_dir = Path(room_paths[0]).resolve()
794
+ cache_dir = first_room_dir / ".rs-engine-cross-room-cache"
795
+ cache_dir.mkdir(parents=True, exist_ok=True)
796
+ # Remap to the compute_embeddings contract (it expects artifact["id"]).
797
+ # Use global_id so cache keys stay unique across rooms.
798
+ cache_artifacts = [
799
+ {"id": a["global_id"], "text": a["text"]}
800
+ for a in corpus
801
+ ]
802
+ embeddings, model_used = compute_embeddings(cache_artifacts, cache_dir)
803
+ if embeddings is None:
804
+ print(
805
+ "rs-engine: no embedder available; semantic matrix set to identity",
806
+ file=sys.stderr,
807
+ )
808
+ n = len(corpus)
809
+ sem_matrix = np.eye(n, dtype=np.float32)
810
+ else:
811
+ sem_matrix = semantic_similarity_matrix(embeddings)
812
+
813
+ # Overshoot so post-filter still yields topk when some pairs are intra-room.
814
+ overshoot_k = max(topk * CROSS_ROOM_OVERSHOOT, topk + 10)
815
+ top_pairs = abs_diff_topk(lsa_matrix, sem_matrix, k=overshoot_k)
816
+
817
+ # Cross-room filter + pair matrix accumulator.
818
+ pair_dicts: List[Dict] = []
819
+ pair_matrix: Dict[str, int] = {}
820
+ for i, j, signed, absv in top_pairs:
821
+ if absv < threshold:
822
+ continue
823
+ a_i, a_j = corpus[i], corpus[j]
824
+ if a_i["room_id"] == a_j["room_id"]:
825
+ continue # intra-room pair -- discard.
826
+ src_room = a_i["room_id"]
827
+ tgt_room = a_j["room_id"]
828
+ # Canonical pair-matrix key: sort room_ids so (A, B) == (B, A) counts.
829
+ pm_key = " x ".join(sorted([src_room, tgt_room]))
830
+ pair_matrix[pm_key] = pair_matrix.get(pm_key, 0) + 1
831
+ pair_dicts.append({
832
+ "source_artifact_id": a_i["global_id"],
833
+ "source_artifact": a_i["artifact_id"],
834
+ "source_room": src_room,
835
+ "source_title": a_i["title"],
836
+ "source_section": a_i["section"],
837
+ "source_path": a_i["path"],
838
+ "target_artifact_id": a_j["global_id"],
839
+ "target_artifact": a_j["artifact_id"],
840
+ "target_room": tgt_room,
841
+ "target_title": a_j["title"],
842
+ "target_section": a_j["section"],
843
+ "target_path": a_j["path"],
844
+ "lsa_score": round(float(lsa_matrix[i, j]), 4),
845
+ "semantic_score": round(float(sem_matrix[i, j]), 4),
846
+ "signed_diff": round(float(signed), 4),
847
+ "abs_diff": round(float(absv), 4),
848
+ "direction": classify_direction(signed),
849
+ })
850
+ if len(pair_dicts) >= topk:
851
+ break
852
+
853
+ result = {
854
+ "metadata": {
855
+ "mode": "cross-room",
856
+ "rooms": room_ids,
857
+ "room_paths": [str(Path(rp).resolve()) for rp in room_paths],
858
+ "artifact_count": len(corpus),
859
+ "room_counts": room_counts,
860
+ "topk_requested": topk,
861
+ "threshold": threshold,
862
+ "embedding_model": model_used,
863
+ "thesis_generated": False,
864
+ "no_thesis": bool(no_thesis),
865
+ "edges_written": 0, # Mode A multi-room does NOT write room.db edges.
866
+ "pair_matrix": pair_matrix,
867
+ "timestamp": datetime.now(timezone.utc).isoformat(),
868
+ "engine_version": ENGINE_VERSION,
869
+ },
870
+ "pairs": pair_dicts,
871
+ }
872
+ return result
873
+
874
+
875
+ def _print_cross_room_summary(result: Dict) -> None:
876
+ """Print the plan-canonical Room-A x Room-B | Bridges table to stderr."""
877
+ matrix = result.get("metadata", {}).get("pair_matrix") or {}
878
+ if not matrix:
879
+ print("[rs-engine] No cross-room bridges found.", file=sys.stderr)
880
+ return
881
+ # Sort pair keys by bridge count desc, then alphabetically for stability.
882
+ rows = sorted(matrix.items(), key=lambda kv: (-kv[1], kv[0]))
883
+ max_key_len = max(len(k) for k, _ in rows)
884
+ header_key = "Room pair".ljust(max_key_len)
885
+ print(f"\n{header_key} | Bridges", file=sys.stderr)
886
+ print(f"{'-' * max_key_len}-+--------", file=sys.stderr)
887
+ for key, count in rows:
888
+ print(f"{key.ljust(max_key_len)} | {count}", file=sys.stderr)
889
+ print("", file=sys.stderr)
890
+
891
+
892
+ # --- Mode B runner -----------------------------------------------------------
893
+
894
+ def _write_corpus_jsonl(corpus_dir: Path, docs: Sequence[Dict]) -> Path:
895
+ """Persist the raw fetched corpus for provenance.
896
+
897
+ One JSON document per line keeps the file streaming-friendly and easy to
898
+ diff. Plan 89-03 will key the Pinecone upsert on (source, external_id)
899
+ read directly from this file.
900
+ """
901
+ corpus_dir.mkdir(parents=True, exist_ok=True)
902
+ path = corpus_dir / "_corpus.jsonl"
903
+ with path.open("w", encoding="utf-8") as fh:
904
+ for doc in docs:
905
+ fh.write(json.dumps(doc, ensure_ascii=False) + "\n")
906
+ return path
907
+
908
+
909
+ def _corpus_docs_to_artifacts(docs: Sequence[Dict]) -> List[Dict]:
910
+ """Shape fetched docs into the artifact dict the rest of the engine
911
+ expects (id, section, title, path, text)."""
912
+ artifacts: List[Dict] = []
913
+ for doc in docs:
914
+ external_id = doc.get("external_id") or ""
915
+ source = doc.get("source") or "external"
916
+ # Build an artifact id that is stable across runs and unique within
917
+ # the corpus. External ids can contain URL characters; stripping to
918
+ # an id-friendly slug keeps downstream SQLite/Pinecone keys predictable.
919
+ eid_slug = re.sub(r"[^a-zA-Z0-9]+", "-", external_id).strip("-")
920
+ if not eid_slug:
921
+ eid_slug = re.sub(r"[^a-zA-Z0-9]+", "-", doc.get("title") or "untitled").strip("-")
922
+ artifact_id = f"{source}/{eid_slug}"
923
+ text = (doc.get("abstract") or "").strip()
924
+ if not text:
925
+ continue
926
+ artifacts.append({
927
+ "id": artifact_id,
928
+ "section": source,
929
+ "title": (doc.get("title") or "").strip() or external_id,
930
+ "path": doc.get("url") or external_id,
931
+ "text": text,
932
+ "year": doc.get("year"),
933
+ "authors": doc.get("authors", []),
934
+ "doi": doc.get("doi"),
935
+ })
936
+ return artifacts
937
+
938
+
939
+ def _records_to_artifacts(records: Sequence[Dict]) -> List[Dict]:
940
+ """Shape rs_cache records (id + values + metadata) into artifact dicts.
941
+
942
+ Plan 296-05 warm path: records come straight from the per-room local
943
+ signal cache (lib.core.rs_cache) and carry the abstract in
944
+ metadata['abstract'], the public DOI in metadata['doi'], and the human
945
+ title in metadata['title']. The local encoder's vectors live in
946
+ record['values']; we attach them so the caller can build the semantic
947
+ matrix directly without re-embedding.
948
+ """
949
+ artifacts: List[Dict] = []
950
+ for rec in records:
951
+ rid = rec.get("id") or ""
952
+ meta = rec.get("metadata", {}) or {}
953
+ abstract = (meta.get("abstract") or "").strip()
954
+ if not abstract:
955
+ # A namespace record without a usable abstract cannot feed LSA;
956
+ # silently drop, matching the 89-02 empty-abstract filter.
957
+ continue
958
+ source = (meta.get("source") or "external").strip() or "external"
959
+ title = (meta.get("title") or "").strip() or rid
960
+ # Reconstruct a stable artifact id matching Mode B's cold path shape
961
+ # (source/slug). This keeps pair ids comparable between warm and
962
+ # cold runs over the same topic.
963
+ eid_slug = re.sub(r"[^a-zA-Z0-9]+", "-", rid).strip("-")
964
+ if not eid_slug:
965
+ eid_slug = re.sub(r"[^a-zA-Z0-9]+", "-", title or "untitled").strip("-")
966
+ artifact_id = f"{source}/{eid_slug}"
967
+ artifacts.append({
968
+ "id": artifact_id,
969
+ "section": source,
970
+ "title": title,
971
+ "path": f"https://doi.org/{meta['doi']}" if meta.get("doi") else rid,
972
+ "text": abstract,
973
+ "year": meta.get("year") or None,
974
+ "authors": [],
975
+ "doi": meta.get("doi") or None,
976
+ "_cached_values": rec.get("values") or [],
977
+ })
978
+ return artifacts
979
+
980
+
981
+ def _signal_cache_available(room_dir: Optional[Any] = None) -> Tuple[bool, str]:
982
+ """Return (ok, reason). Reason is empty on success, explanatory on skip.
983
+
984
+ Renamed from the prior remote-key gate (Plan 296-05). The former hosted
985
+ API-key presence check and the RS_EMBEDDING_MODEL=minilm opt-out are both
986
+ DROPPED here: neither means anything against a per-room local sidecar
987
+ cache, and leaving the key check in place would make the local path
988
+ unreachable for the overwhelming majority of users, who have no key. In
989
+ their place: the room must resolve, since the local cache is scoped to a
990
+ room by construction (lib.core.rs_cache, closes SEED-029 finding F8).
991
+ """
992
+ if not _RS_CACHE_AVAILABLE:
993
+ return False, f"rs_cache import failed: {globals().get('_rs_cache_import_err_msg', 'unknown')}"
994
+ if not room_dir:
995
+ return False, "no room scope for the signal cache"
996
+ return True, ""
997
+
998
+
999
+ def _build_sem_matrix_from_records(artifacts: Sequence[Dict]) -> Optional[np.ndarray]:
1000
+ """Build the pairwise cosine similarity matrix from cached embeddings.
1001
+
1002
+ Returns None if any artifact is missing a vector (triggers fallback to
1003
+ local embedding path). All vectors must share dimensionality.
1004
+ """
1005
+ vectors: List[List[float]] = []
1006
+ for a in artifacts:
1007
+ v = a.get("_cached_values") or []
1008
+ if not v:
1009
+ return None
1010
+ vectors.append(list(v))
1011
+ if not vectors:
1012
+ return None
1013
+ dim = len(vectors[0])
1014
+ if any(len(v) != dim for v in vectors):
1015
+ return None
1016
+ matrix = np.asarray(vectors, dtype=np.float32)
1017
+ return semantic_similarity_matrix(matrix)
1018
+
1019
+
1020
+ # --- SEED-018 H2 semantic-floor gate: LIVE production wiring ----------------
1021
+ #
1022
+ # The gate itself lives in lib/core/rs_corpus.semantic_gate (implemented + unit
1023
+ # tested in Plan 200-01). Until this wiring it had NO production caller -- it was
1024
+ # dormant. The helpers below call it on the two live Mode B corpus paths:
1025
+ #
1026
+ # 1. Local signal-cache (warm/cold) path: gate the raw `records` (each carrying
1027
+ # its local-encoder vector in record['values']) against a topic vector from
1028
+ # the SAME encoder (rs_cache._embed_via_bridge), BEFORE _records_to_artifacts.
1029
+ # Plan 296-05: rerouted off Pinecone inference -- after the repoint, records
1030
+ # carry local 384-dim vectors, so a topic vector from a different encoder
1031
+ # would either produce a dimension mismatch or a meaningless cosine, and in
1032
+ # both cases the gate would stop filtering without raising.
1033
+ # 2. Local fallback path (Plan 89-02): gate the fetched `docs` using the reused
1034
+ # local MiniLM encoder (_embed_local_minilm), batched so the model loads once.
1035
+ #
1036
+ # Safe-by-default (this is the core scoring input):
1037
+ # - No-op when the topic vector cannot be obtained (encode / inference absent).
1038
+ # - Reuses SEMANTIC_FLOOR (default 0.15, tunable via RS_SEMANTIC_FLOOR).
1039
+ # - STARVATION GUARD: never drops the usable count below the differential
1040
+ # minimum (the engine early-outs under 2 artifacts). Worst case a no-op,
1041
+ # never a regression.
1042
+ # - Reuses the EXISTING encoders only (Pinecone inference + MiniLM). No new
1043
+ # encoder, no new npm/pip package, no new egress class.
1044
+
1045
+ # The engine early-outs when fewer than this many artifacts survive (see the
1046
+ # `len(artifacts) < 2` guard in run_mode_external). The gate must never push the
1047
+ # corpus below it.
1048
+ _DIFFERENTIAL_MIN_ARTIFACTS = 2
1049
+
1050
+
1051
+ def _semantic_cosine(a: Sequence[float], b: Sequence[float]) -> float:
1052
+ """Minimal cosine similarity for the starvation-guard ranking. Returns 0.0
1053
+ on shape mismatch or a zero-norm vector."""
1054
+ if not a or not b or len(a) != len(b):
1055
+ return 0.0
1056
+ dot = 0.0
1057
+ na = 0.0
1058
+ nb = 0.0
1059
+ for x, y in zip(a, b):
1060
+ dot += x * y
1061
+ na += x * x
1062
+ nb += y * y
1063
+ if na == 0.0 or nb == 0.0:
1064
+ return 0.0
1065
+ return dot / ((na ** 0.5) * (nb ** 0.5))
1066
+
1067
+
1068
+ def _gate_with_starvation_guard(
1069
+ topic_vec: Optional[Sequence[float]],
1070
+ candidates: List[Dict],
1071
+ encode_fn,
1072
+ floor: Optional[float] = None,
1073
+ min_keep: int = _DIFFERENTIAL_MIN_ARTIFACTS,
1074
+ label: str = "corpus",
1075
+ ) -> List[Dict]:
1076
+ """Apply the H2 semantic-floor gate with a mandatory starvation guard.
1077
+
1078
+ Delegates the actual floor filtering to rs_corpus.semantic_gate (the single
1079
+ gate implementation) so both live paths share one tested code path. When the
1080
+ floor would push the survivor count below the differential minimum on an
1081
+ otherwise-sufficient corpus, keep the top-N candidates by similarity instead
1082
+ of starving score(), and log the skip to stderr.
1083
+ """
1084
+ if not topic_vec or not callable(encode_fn):
1085
+ # No usable topic vector / encoder -> safe no-op pass-through.
1086
+ return list(candidates)
1087
+
1088
+ original_n = len(candidates)
1089
+ # Production caller of the SEED-018 H2 gate (rs_corpus.semantic_gate).
1090
+ kept = semantic_gate(topic_vec, candidates, encode_fn, floor)
1091
+
1092
+ if len(kept) >= min_keep or original_n < min_keep:
1093
+ return kept
1094
+
1095
+ # Starvation guard: the floor would collapse the corpus below the
1096
+ # differential minimum. Preserve the top-N most-similar candidates so the
1097
+ # differential still runs. Worst case the gate is a no-op, never a
1098
+ # regression that starves the scorer.
1099
+ ranked = sorted(
1100
+ candidates,
1101
+ key=lambda c: _semantic_cosine(topic_vec, encode_fn(c)),
1102
+ reverse=True,
1103
+ )
1104
+ keep_n = max(min_keep, len(kept))
1105
+ guarded = ranked[:keep_n]
1106
+ print(
1107
+ f"[rs-engine] semantic gate skipped: would starve corpus "
1108
+ f"(kept {len(guarded)})",
1109
+ file=sys.stderr,
1110
+ )
1111
+ return guarded
1112
+
1113
+
1114
+ def _embed_topic_via_signal_cache(topic: str) -> Optional[List[float]]:
1115
+ """Embed `topic` through rs_cache's local encoder (Plan 296-05).
1116
+
1117
+ Reuses the SAME local encoder (rs_cache._embed_via_bridge, which wraps
1118
+ scripts/rs-vector-bridge.cjs -> lib/core/eureka/embedding-spine.cjs) that
1119
+ produced the record vectors this topic vector is compared against. This
1120
+ is the load-bearing part of the reroute: after the repoint, records carry
1121
+ local 384-dim vectors, so a topic vector from ANY other encoder either
1122
+ produces a dimension mismatch or a meaningless cosine -- and in both
1123
+ cases the gate stops filtering off-topic documents without raising.
1124
+
1125
+ Returns a plain float list, or None on ANY failure (rs_cache unavailable,
1126
+ bridge unreachable, unexpected shape) so the caller degrades to a safe
1127
+ no-op. Adds no new encoder and no new egress class -- the bridge is the
1128
+ same local encoder the rest of this repoint already uses.
1129
+ """
1130
+ if not _RS_CACHE_AVAILABLE:
1131
+ return None
1132
+ try:
1133
+ vectors, provenance = rs_cache._embed_via_bridge([topic])
1134
+ except Exception as e: # pragma: no cover -- defensive
1135
+ print(
1136
+ f"[rs-engine] semantic gate: topic embed unavailable ({e}); "
1137
+ f"gate no-op for this run.",
1138
+ file=sys.stderr,
1139
+ )
1140
+ return None
1141
+ if not vectors or provenance is None:
1142
+ return None
1143
+ return [float(x) for x in vectors[0]]
1144
+
1145
+
1146
+ def _gate_records_cached(topic: str, records: List[Dict]) -> List[Dict]:
1147
+ """Gate local signal-cache `records` by the semantic floor before
1148
+ _records_to_artifacts.
1149
+
1150
+ Renamed from the prior remote-cache gate (Plan 296-05). Each record carries
1151
+ its local-encoder vector in record['values']; the topic vector now comes
1152
+ from the SAME encoder via _embed_topic_via_signal_cache, not a different
1153
+ one. No-op (returns records unchanged) when the topic vector is
1154
+ unavailable.
1155
+ """
1156
+ if not records:
1157
+ return records
1158
+ topic_vec = _embed_topic_via_signal_cache(topic)
1159
+ if not topic_vec:
1160
+ return records
1161
+ return _gate_with_starvation_guard(
1162
+ topic_vec,
1163
+ records,
1164
+ lambda rec: rec.get("values") or [],
1165
+ label="signal-cache-records",
1166
+ )
1167
+
1168
+
1169
+ def _gate_docs_local(topic: str, docs: List[Dict]) -> List[Dict]:
1170
+ """Gate local-fallback `docs` by the semantic floor using the reused local
1171
+ MiniLM encoder. Batched so SentenceTransformer loads once. Clean no-op when
1172
+ sentence-transformers is absent (encode returns None)."""
1173
+ if not docs:
1174
+ return docs
1175
+ topic_arr = _embed_local_minilm([topic])
1176
+ if topic_arr is None:
1177
+ # sentence-transformers not installed -> safe no-op (Tri-Polar degrade).
1178
+ return docs
1179
+ texts = [
1180
+ f"{d.get('title', '')}\n{d.get('abstract', '')}".strip() for d in docs
1181
+ ]
1182
+ cand_arr = _embed_local_minilm(texts)
1183
+ if cand_arr is None or len(cand_arr) != len(docs):
1184
+ return docs
1185
+ topic_vec = [float(x) for x in topic_arr[0]]
1186
+ vec_by_id = {id(d): [float(x) for x in cand_arr[i]] for i, d in enumerate(docs)}
1187
+ return _gate_with_starvation_guard(
1188
+ topic_vec,
1189
+ docs,
1190
+ lambda d: vec_by_id.get(id(d), []),
1191
+ label="local-fallback",
1192
+ )
1193
+
1194
+
1195
+ def run_mode_external(
1196
+ room_dir: Path,
1197
+ topic: str,
1198
+ topk: int,
1199
+ threshold: float,
1200
+ no_thesis: bool,
1201
+ ) -> Tuple[Dict, Path]:
1202
+ """Mode B: fetch external corpus (cached in the per-room local signal
1203
+ cache), run LSA + abs_diff.
1204
+
1205
+ Plan 296-05 wiring: lib.core.rs_cache's per-room local sidecar caches
1206
+ embedded corpora per topic, scoped to room_dir. On each call:
1207
+ 1. Compute namespace for topic (rs_cache.namespace_slug).
1208
+ 2. Check freshness, scoped to this room. If < 30 days, skip fetch and
1209
+ use the cached vectors directly (warm path).
1210
+ 3. Else, fetch_corpus -> upsert_corpus -> fetch_all_from_namespace
1211
+ (cold path; embeds through the local encoder bridge, then re-reads
1212
+ so the vectors used for scoring came from the cache, not a
1213
+ from-memory list).
1214
+ 4. Fall back to the Plan 89-02 local path (fetch_corpus + local
1215
+ MiniLM embedding) when the signal cache is unavailable (rs_cache
1216
+ import failed, or the room does not resolve).
1217
+
1218
+ Returns (result dict, corpus_dir) -- CLI writes results JSON inside
1219
+ corpus_dir at {room}/research/{topic-slug}/.rs-engine-results.json.
1220
+ """
1221
+ slug = topic_slug(topic)
1222
+ if not slug:
1223
+ raise ValueError("topic slug resolved to empty string")
1224
+ corpus_dir = room_dir / "research" / slug
1225
+ corpus_dir.mkdir(parents=True, exist_ok=True)
1226
+
1227
+ # Overshoot target_n so dedup + threshold filtering can still hit topk.
1228
+ target_n = max(topk * 20, topk * 2)
1229
+
1230
+ # Freshness + cache decision.
1231
+ signal_ok, signal_skip_reason = _signal_cache_available(room_dir=room_dir)
1232
+ cache_mode = "bypass"
1233
+ cache_age_days: Optional[float] = None
1234
+ cache_namespace: Optional[str] = None
1235
+ records: List[Dict] = []
1236
+ docs: List[Dict] = []
1237
+
1238
+ if signal_ok:
1239
+ ns = _rs_cache_namespace_slug(topic)
1240
+ cache_namespace = ns
1241
+ try:
1242
+ cache_age_days = _rs_cache_freshness(ns, room_dir=room_dir)
1243
+ except Exception as e:
1244
+ print(f"rs-engine: signal cache freshness check failed ({e})", file=sys.stderr)
1245
+ cache_age_days = None
1246
+
1247
+ if _rs_cache_is_fresh(cache_age_days, ttl_days=_RS_CACHE_TTL_DAYS):
1248
+ # WARM path: namespace is within TTL. Skip fetch.
1249
+ cache_mode = "warm"
1250
+ print(
1251
+ f"[rs-engine] Cache hit (age={cache_age_days:.1f} days, "
1252
+ f"ttl={_RS_CACHE_TTL_DAYS}). Using local signal cache {ns}.",
1253
+ file=sys.stderr,
1254
+ )
1255
+ try:
1256
+ records = _rs_cache_fetch_all(ns, limit=target_n, room_dir=room_dir)
1257
+ except Exception as e:
1258
+ print(
1259
+ f"rs-engine: warm-path fetch failed ({e}); "
1260
+ f"falling back to cold path.",
1261
+ file=sys.stderr,
1262
+ )
1263
+ records = []
1264
+ cache_mode = "bypass"
1265
+
1266
+ if cache_mode != "warm":
1267
+ # COLD path: fetch from external APIs, upsert to the local
1268
+ # signal cache, then re-fetch so the vectors used for scoring
1269
+ # come from the cache's own round-trip (not a from-memory list).
1270
+ age_label = "unset" if cache_age_days is None else f"{cache_age_days:.1f} days"
1271
+ print(
1272
+ f"[rs-engine] Cache miss (age={age_label}). "
1273
+ f"Fetching corpus for topic {topic!r}...",
1274
+ file=sys.stderr,
1275
+ )
1276
+ docs = fetch_corpus(topic, target_n=target_n)
1277
+ if len(docs) >= 2:
1278
+ try:
1279
+ _rs_cache_upsert(topic, docs, room_dir=room_dir)
1280
+ cache_mode = "cold"
1281
+ # Re-read from the local signal cache so the semantic
1282
+ # matrix uses the cached (round-tripped) local vectors.
1283
+ records = _rs_cache_fetch_all(ns, limit=target_n, room_dir=room_dir)
1284
+ except Exception as e:
1285
+ print(
1286
+ f"rs-engine: local signal cache upsert/fetch failed ({e}); "
1287
+ f"falling back to local embedding path.",
1288
+ file=sys.stderr,
1289
+ )
1290
+ records = []
1291
+ cache_mode = "bypass"
1292
+ else:
1293
+ # Signal cache path not available -- preserve Plan 89-02 behavior.
1294
+ print(
1295
+ f"[rs-engine] Signal cache skipped ({signal_skip_reason}); "
1296
+ f"using Plan 89-02 local embedding path.",
1297
+ file=sys.stderr,
1298
+ )
1299
+
1300
+ # Provenance sidecar: keep _corpus.jsonl in both paths.
1301
+ # Warm path has no fresh fetch; docs stays empty but we still want the
1302
+ # sidecar to exist (stale from prior cold run). If absent, skip quietly
1303
+ # so the warm path does not accidentally wipe prior provenance.
1304
+ if docs:
1305
+ corpus_path = _write_corpus_jsonl(corpus_dir, docs)
1306
+ else:
1307
+ corpus_path = corpus_dir / "_corpus.jsonl"
1308
+ if not corpus_path.exists():
1309
+ # Warm path with no prior sidecar (first time the namespace is
1310
+ # warm on this machine). Create an empty file so downstream
1311
+ # readers do not trip on a missing path.
1312
+ corpus_path.write_text("", encoding="utf-8")
1313
+
1314
+ # Build artifacts + texts depending on path taken.
1315
+ if records:
1316
+ # SEED-018 H2 LIVE-WIRE (local signal-cache path): drop off-topic records
1317
+ # using the local-encoder vectors they already carry vs a topic vector
1318
+ # from the SAME encoder, BEFORE they become artifacts and reach the
1319
+ # differential. Starvation-guarded + no-op when the topic vector is
1320
+ # unavailable.
1321
+ records = _gate_records_cached(topic, records)
1322
+ artifacts = _records_to_artifacts(records)
1323
+ else:
1324
+ # Fallback to Plan 89-02 behavior.
1325
+ if not docs:
1326
+ docs = fetch_corpus(topic, target_n=target_n)
1327
+ corpus_path = _write_corpus_jsonl(corpus_dir, docs)
1328
+ # SEED-018 H2 LIVE-WIRE (local fallback): gate off-topic docs with the
1329
+ # reused local MiniLM encoder before they reach the differential.
1330
+ docs = _gate_docs_local(topic, docs)
1331
+ artifacts = _corpus_docs_to_artifacts(docs)
1332
+
1333
+ # Early out if the usable-artifact count collapses.
1334
+ if len(artifacts) < 2:
1335
+ return (
1336
+ {
1337
+ "metadata": {
1338
+ "mode": "external",
1339
+ "topic": topic,
1340
+ "topic_slug": slug,
1341
+ "room_dir": str(room_dir),
1342
+ "corpus_dir": str(corpus_dir),
1343
+ "corpus_path": str(corpus_path),
1344
+ "corpus_size": len(docs) if docs else len(records),
1345
+ "artifact_count": len(artifacts),
1346
+ "tier_counts": _count_by_source(docs) if docs else {},
1347
+ "cache_mode": cache_mode,
1348
+ "cache_age_days": round(cache_age_days, 2) if cache_age_days is not None else None,
1349
+ "cache_namespace": cache_namespace,
1350
+ "cache_ttl_days": _RS_CACHE_TTL_DAYS if signal_ok else None,
1351
+ "topk_requested": topk,
1352
+ "threshold": threshold,
1353
+ "no_thesis": bool(no_thesis),
1354
+ "thesis_generated": False,
1355
+ "timestamp": datetime.now(timezone.utc).isoformat(),
1356
+ "engine_version": ENGINE_VERSION,
1357
+ },
1358
+ "pairs": [],
1359
+ },
1360
+ corpus_dir,
1361
+ )
1362
+
1363
+ texts = [f"{a['title']}\n{a['text']}" for a in artifacts]
1364
+
1365
+ # Structural signal (authoritative topic-keyword-membership LSA).
1366
+ lsa_matrix = build_lsa_matrix(texts)
1367
+
1368
+ # Semantic signal. Warm/cold path: vectors come straight from Pinecone.
1369
+ # Bypass path: fall back to Plan 89-02's local embedder.
1370
+ sem_matrix: Optional[np.ndarray] = None
1371
+ model_used: str
1372
+ if cache_mode in ("warm", "cold") and records:
1373
+ sem_matrix = _build_sem_matrix_from_records(artifacts)
1374
+ if sem_matrix is not None:
1375
+ model_used = "multilingual-e5-large"
1376
+ else:
1377
+ # Vectors missing -- rare but defensible. Drop to local path.
1378
+ print(
1379
+ "rs-engine: cached records missing values; "
1380
+ "falling back to local embedding for semantic matrix.",
1381
+ file=sys.stderr,
1382
+ )
1383
+ embeddings, model_used = compute_embeddings(artifacts, corpus_dir)
1384
+ sem_matrix = (
1385
+ semantic_similarity_matrix(embeddings)
1386
+ if embeddings is not None
1387
+ else np.eye(len(artifacts), dtype=np.float32)
1388
+ )
1389
+ else:
1390
+ embeddings, model_used = compute_embeddings(artifacts, corpus_dir)
1391
+ if embeddings is None:
1392
+ print(
1393
+ "rs-engine: no embedder available for Mode B; "
1394
+ "semantic matrix set to identity.",
1395
+ file=sys.stderr,
1396
+ )
1397
+ sem_matrix = np.eye(len(artifacts), dtype=np.float32)
1398
+ else:
1399
+ sem_matrix = semantic_similarity_matrix(embeddings)
1400
+
1401
+ top_pairs = abs_diff_topk(lsa_matrix, sem_matrix, k=topk)
1402
+
1403
+ pair_dicts: List[Dict] = []
1404
+ for i, j, signed, absv in top_pairs:
1405
+ if absv < threshold:
1406
+ continue
1407
+ a_i, a_j = artifacts[i], artifacts[j]
1408
+ pair_dicts.append({
1409
+ "source_artifact_id": a_i["id"],
1410
+ "source_title": a_i["title"],
1411
+ "source_section": a_i["section"],
1412
+ "source_url": a_i.get("path", ""),
1413
+ "source_doi": a_i.get("doi"),
1414
+ "target_artifact_id": a_j["id"],
1415
+ "target_title": a_j["title"],
1416
+ "target_section": a_j["section"],
1417
+ "target_url": a_j.get("path", ""),
1418
+ "target_doi": a_j.get("doi"),
1419
+ "lsa_score": round(float(lsa_matrix[i, j]), 4),
1420
+ "semantic_score": round(float(sem_matrix[i, j]), 4),
1421
+ "signed_diff": round(float(signed), 4),
1422
+ "abs_diff": round(float(absv), 4),
1423
+ "direction": classify_direction(signed),
1424
+ })
1425
+
1426
+ result = {
1427
+ "metadata": {
1428
+ "mode": "external",
1429
+ "topic": topic,
1430
+ "topic_slug": slug,
1431
+ "room_dir": str(room_dir),
1432
+ "corpus_dir": str(corpus_dir),
1433
+ "corpus_path": str(corpus_path),
1434
+ "corpus_size": len(docs) if docs else len(records),
1435
+ "artifact_count": len(artifacts),
1436
+ "tier_counts": _count_by_source(docs) if docs else {},
1437
+ "cache_mode": cache_mode,
1438
+ "cache_age_days": round(cache_age_days, 2) if cache_age_days is not None else None,
1439
+ "cache_namespace": cache_namespace,
1440
+ "cache_ttl_days": _RS_CACHE_TTL_DAYS if signal_ok else None,
1441
+ "topk_requested": topk,
1442
+ "threshold": threshold,
1443
+ "embedding_model": model_used,
1444
+ "thesis_generated": False,
1445
+ "no_thesis": bool(no_thesis),
1446
+ "edges_written": 0, # Mode B does NOT write room.db edges.
1447
+ "timestamp": datetime.now(timezone.utc).isoformat(),
1448
+ "engine_version": ENGINE_VERSION,
1449
+ },
1450
+ "pairs": pair_dicts,
1451
+ }
1452
+ return result, corpus_dir
1453
+
1454
+
1455
+ def _count_by_source(docs: Sequence[Dict]) -> Dict[str, int]:
1456
+ counts: Dict[str, int] = {}
1457
+ for d in docs:
1458
+ src = d.get("source") or "unknown"
1459
+ counts[src] = counts.get(src, 0) + 1
1460
+ return counts
1461
+
1462
+
1463
+ # --- Mode C (hybrid) runner --------------------------------------------------
1464
+
1465
+ # Design note on semantic similarity for the unified corpus (Plan 89-05,
1466
+ # updated Plan 296-05): the external side used to carry cached 1024-dim
1467
+ # multilingual-e5-large vectors from Pinecone, which would have been a
1468
+ # dimensional bug (plan Risk 1) if mixed directly with the room side's
1469
+ # 384-dim local MiniLM vectors. Plan 296-05's repoint of lib.core.rs_cache
1470
+ # onto the local signal cache CLOSES that hazard by construction: the
1471
+ # external side now also carries local 384-dim vectors from the same
1472
+ # encoder as the room side. The safe path below is UNCHANGED regardless --
1473
+ # embed the entire unified corpus in a single model space (local MiniLM via
1474
+ # compute_embeddings()) so the pairwise cosine is well-defined -- because
1475
+ # doing so also lets a run with a cold, empty, or unavailable signal cache
1476
+ # degrade the same way it always has, rather than depending on the cache
1477
+ # having already run.
1478
+
1479
+
1480
+ def run_mode_hybrid(
1481
+ room_dir: Path,
1482
+ topic: str,
1483
+ topk: int,
1484
+ threshold: float,
1485
+ no_thesis: bool,
1486
+ external_target: int = 2000,
1487
+ ) -> Tuple[Dict, Path]:
1488
+ """Mode C: unified room + external corpus with cross-corpus filter.
1489
+
1490
+ The killer feature of Phase 89: rediscovers external-domain concepts
1491
+ that have a structural match in the user's room but never entered the
1492
+ room's vocabulary, and vice versa. Consumed downstream by the Plan
1493
+ 89-06 bridge-writer for Obsidian rendering.
1494
+
1495
+ Returns (result dict, corpus_dir) -- CLI writes results JSON inside
1496
+ corpus_dir at {room}/research/{topic-slug}/.rs-engine-results.json.
1497
+
1498
+ Cross-corpus contract:
1499
+ - metadata.mode == "hybrid"
1500
+ - metadata.hybrid == True (explicit flag per plan must_haves[2])
1501
+ - every pair has origin mismatch: one room side, one external side
1502
+ - pair_dicts carry both room_artifact_id and external_doc fields
1503
+ - direction is the standard Mode A / Mode B signed classification
1504
+
1505
+ Edge cases:
1506
+ - rs_hybrid import failed: raise NotImplementedError early so the
1507
+ CLI surfaces a clear "cannot run Mode C" message.
1508
+ - Empty room corpus: return empty pairs with metadata preserved so
1509
+ downstream readers do not trip on missing keys.
1510
+ - Empty external corpus (rare -- cold fetch returned nothing):
1511
+ same empty-pairs result. Caller sees metadata.external_count=0.
1512
+ - Unified corpus < 10 artifacts: skip LSA (same threshold the
1513
+ cross-room path uses). LSA topic keywords are unstable below
1514
+ this size.
1515
+ """
1516
+ if not _RS_HYBRID_AVAILABLE:
1517
+ raise NotImplementedError(
1518
+ "rs-engine: --mode hybrid requires lib.core.rs_hybrid. "
1519
+ f"Import failed: {globals().get('_rs_hybrid_import_err_msg', 'unknown')}"
1520
+ )
1521
+
1522
+ # Signal-cache availability check (mirrors run_mode_external's gate,
1523
+ # Plan 296-05). Not blocking: build_unified_corpus's own
1524
+ # _load_external_records degrades to an empty external side
1525
+ # (cache_mode="bypass") on its own when the signal cache cannot be
1526
+ # reached, via the room_dir it now threads through. This call exists so
1527
+ # the reason is narrated up front instead of only discoverable later in
1528
+ # hybrid_meta.
1529
+ signal_ok, signal_skip_reason = _signal_cache_available(room_dir=str(room_dir))
1530
+ if not signal_ok:
1531
+ print(
1532
+ f"[rs-engine hybrid] Signal cache skipped ({signal_skip_reason}); "
1533
+ f"external side of the unified corpus will be empty this run.",
1534
+ file=sys.stderr,
1535
+ )
1536
+
1537
+ # Build the unified corpus + origin mask via rs_hybrid.
1538
+ corpus, origin_mask, hybrid_meta = _rs_hybrid_build(
1539
+ str(room_dir),
1540
+ topic,
1541
+ external_target=external_target,
1542
+ )
1543
+ slug = hybrid_meta.get("topic_slug") or topic_slug(topic)
1544
+ if not slug:
1545
+ raise ValueError("topic slug resolved to empty string")
1546
+ corpus_dir = room_dir / "research" / slug
1547
+ corpus_dir.mkdir(parents=True, exist_ok=True)
1548
+
1549
+ room_count = int(hybrid_meta.get("room_count", 0))
1550
+ external_count = int(hybrid_meta.get("external_count", 0))
1551
+
1552
+ def _empty_result(reason: str) -> Tuple[Dict, Path]:
1553
+ print(f"[rs-engine hybrid] {reason}", file=sys.stderr)
1554
+ return (
1555
+ {
1556
+ "metadata": {
1557
+ "mode": "hybrid",
1558
+ "hybrid": True,
1559
+ "topic": topic,
1560
+ "topic_slug": slug,
1561
+ "room_dir": str(room_dir),
1562
+ "corpus_dir": str(corpus_dir),
1563
+ "room_id": hybrid_meta.get("room_id"),
1564
+ "room_count": room_count,
1565
+ "external_count": external_count,
1566
+ "artifact_count": room_count + external_count,
1567
+ "cache_mode": hybrid_meta.get("cache_mode"),
1568
+ "cache_age_days": hybrid_meta.get("cache_age_days"),
1569
+ "cache_namespace": hybrid_meta.get("cache_namespace"),
1570
+ "cache_ttl_days": hybrid_meta.get("cache_ttl_days"),
1571
+ "topk_requested": topk,
1572
+ "threshold": threshold,
1573
+ "no_thesis": bool(no_thesis),
1574
+ "thesis_generated": False,
1575
+ "edges_written": 0,
1576
+ "timestamp": datetime.now(timezone.utc).isoformat(),
1577
+ "engine_version": ENGINE_VERSION,
1578
+ "skip_reason": reason,
1579
+ },
1580
+ "pairs": [],
1581
+ },
1582
+ corpus_dir,
1583
+ )
1584
+
1585
+ # Edge: no room artifacts -- cross-corpus filter yields zero pairs by
1586
+ # construction; save the LSA compute.
1587
+ if room_count == 0:
1588
+ return _empty_result(
1589
+ "Room has no indexable .md artifacts; cross-corpus filter "
1590
+ "yields zero pairs by construction."
1591
+ )
1592
+ # Edge: no external corpus.
1593
+ if external_count == 0:
1594
+ return _empty_result(
1595
+ f"External corpus for topic {topic!r} is empty (cache_mode="
1596
+ f"{hybrid_meta.get('cache_mode')}); cross-corpus filter "
1597
+ f"yields zero pairs by construction."
1598
+ )
1599
+ # Edge: combined corpus too small for stable LSA topic-keyword fit.
1600
+ if len(corpus) < 10:
1601
+ return _empty_result(
1602
+ f"Unified corpus has only {len(corpus)} artifacts; need >= 10 "
1603
+ f"for stable LSA fit."
1604
+ )
1605
+
1606
+ # Structural signal over the unified vocabulary.
1607
+ texts = [f"{a.get('title','')}\n{a['text']}" for a in corpus]
1608
+ lsa_matrix = build_lsa_matrix(texts)
1609
+
1610
+ # Semantic signal: embed the full unified corpus in one model space so
1611
+ # the sem_matrix is dimensionally homogeneous. Room and external share
1612
+ # the SAME model by construction (Plan Risk 1 mitigation). We reuse
1613
+ # compute_embeddings (MiniLM-or-cache) and scope the cache to the
1614
+ # research/{slug}/ directory to avoid polluting Mode A's room-root
1615
+ # .rs-engine-cache.json -- different corpus shape, different keys.
1616
+ cache_artifacts = [
1617
+ {"id": c["global_id"], "text": t}
1618
+ for c, t in zip(corpus, texts)
1619
+ ]
1620
+ embeddings, model_used = compute_embeddings(cache_artifacts, corpus_dir)
1621
+ if embeddings is None:
1622
+ print(
1623
+ "rs-engine hybrid: no embedder available; "
1624
+ "semantic matrix set to identity.",
1625
+ file=sys.stderr,
1626
+ )
1627
+ n = len(corpus)
1628
+ sem_matrix = np.eye(n, dtype=np.float32)
1629
+ else:
1630
+ sem_matrix = semantic_similarity_matrix(embeddings)
1631
+
1632
+ # Overshoot top-k, then post-filter to cross-corpus only.
1633
+ overshoot_k = max(topk * HYBRID_OVERSHOOT, topk + 10)
1634
+ raw_pairs = abs_diff_topk(lsa_matrix, sem_matrix, k=overshoot_k)
1635
+
1636
+ cross_pairs = _rs_hybrid_filter(raw_pairs, origin_mask, topk)
1637
+
1638
+ # Apply threshold + build full pair dicts with room_artifact / external_doc.
1639
+ pair_dicts: List[Dict] = []
1640
+ for cp in cross_pairs:
1641
+ absv = cp["abs_diff"]
1642
+ if absv < threshold:
1643
+ continue
1644
+ i, j = cp["i"], cp["j"]
1645
+ room_idx = cp["room_side"]
1646
+ ext_idx = cp["external_side"]
1647
+ room_art = corpus[room_idx]
1648
+ ext_doc = corpus[ext_idx]
1649
+ signed = cp["signed_diff"]
1650
+
1651
+ # Preserve the standard Mode A / Mode B fields (source_*/target_*)
1652
+ # so the bridge-writer resolvePairIdentity picks them up without
1653
+ # per-mode branches. Canonical orientation: source = room side,
1654
+ # target = external side. This maps the signed-direction
1655
+ # interpretation from plan must_haves[3]:
1656
+ # structural_transfer (signed > 0):
1657
+ # "your work has the vocabulary, world has the concept"
1658
+ # semantic_implementation (signed < 0):
1659
+ # "your concept exists in the world's vocabulary"
1660
+ pair_dicts.append({
1661
+ "source_artifact_id": room_art["global_id"],
1662
+ "source_artifact": room_art.get("artifact_id") or room_art["global_id"],
1663
+ "source_room": room_art.get("room_id"),
1664
+ "source_section": room_art.get("section"),
1665
+ "source_title": room_art.get("title", ""),
1666
+ "source_path": room_art.get("path", ""),
1667
+ "target_artifact_id": ext_doc["global_id"],
1668
+ "target_external_id": ext_doc.get("external_id") or ext_doc["global_id"],
1669
+ "target_doi": ext_doc.get("doi"),
1670
+ "target_source": ext_doc.get("source"),
1671
+ "target_title": ext_doc.get("title", ""),
1672
+ "target_url": ext_doc.get("path", ""),
1673
+ "target_year": ext_doc.get("year"),
1674
+ # Rich cross-corpus annotations consumed by Plan 89-06 bridge
1675
+ # writer and Plan 89-07 release dashboard.
1676
+ "room_artifact": {
1677
+ "global_id": room_art["global_id"],
1678
+ "artifact_id": room_art.get("artifact_id"),
1679
+ "room_id": room_art.get("room_id"),
1680
+ "section": room_art.get("section"),
1681
+ "title": room_art.get("title", ""),
1682
+ "path": room_art.get("path", ""),
1683
+ },
1684
+ "external_doc": {
1685
+ "global_id": ext_doc["global_id"],
1686
+ "external_id": ext_doc.get("external_id"),
1687
+ "source": ext_doc.get("source"),
1688
+ "title": ext_doc.get("title", ""),
1689
+ "doi": ext_doc.get("doi"),
1690
+ "year": ext_doc.get("year"),
1691
+ "url": ext_doc.get("path", ""),
1692
+ },
1693
+ "lsa_score": round(float(lsa_matrix[i, j]), 4),
1694
+ "semantic_score": round(float(sem_matrix[i, j]), 4),
1695
+ "signed_diff": round(float(signed), 4),
1696
+ "abs_diff": round(float(absv), 4),
1697
+ "direction": classify_direction(signed),
1698
+ })
1699
+
1700
+ result = {
1701
+ "metadata": {
1702
+ "mode": "hybrid",
1703
+ "hybrid": True,
1704
+ "topic": topic,
1705
+ "topic_slug": slug,
1706
+ "room_dir": str(room_dir),
1707
+ "corpus_dir": str(corpus_dir),
1708
+ "room_id": hybrid_meta.get("room_id"),
1709
+ "room_count": room_count,
1710
+ "external_count": external_count,
1711
+ "artifact_count": len(corpus),
1712
+ "cache_mode": hybrid_meta.get("cache_mode"),
1713
+ "cache_age_days": hybrid_meta.get("cache_age_days"),
1714
+ "cache_namespace": hybrid_meta.get("cache_namespace"),
1715
+ "cache_ttl_days": hybrid_meta.get("cache_ttl_days"),
1716
+ "topk_requested": topk,
1717
+ "threshold": threshold,
1718
+ "embedding_model": model_used,
1719
+ "no_thesis": bool(no_thesis),
1720
+ "thesis_generated": False,
1721
+ # Mode C does NOT write REVERSE_SALIENT edges into room.db.
1722
+ # Plan 89-06 bridge-writer produces the user-visible artifact
1723
+ # surface; Plan 89-07 wires the optional room.db edge with
1724
+ # properties.source='rs-engine-hybrid' alongside the agent.
1725
+ "edges_written": 0,
1726
+ "hybrid_overshoot": HYBRID_OVERSHOOT,
1727
+ "external_target": external_target,
1728
+ "timestamp": datetime.now(timezone.utc).isoformat(),
1729
+ "engine_version": ENGINE_VERSION,
1730
+ },
1731
+ "pairs": pair_dicts,
1732
+ }
1733
+ return result, corpus_dir
1734
+
1735
+
1736
+ # --- Cowork tri-polar surface ------------------------------------------------
1737
+
1738
+ def _write_cowork_symlink(room_dir: Path, results_path: Path) -> None:
1739
+ """When COWORK=1, expose results under 00_Context/ for team visibility."""
1740
+ if os.environ.get("COWORK") != "1":
1741
+ return
1742
+ cowork_dir = room_dir / "00_Context"
1743
+ if not cowork_dir.is_dir():
1744
+ return
1745
+ symlink_path = cowork_dir / "rs-engine-results.json"
1746
+ try:
1747
+ if symlink_path.is_symlink() or symlink_path.exists():
1748
+ symlink_path.unlink()
1749
+ os.symlink(results_path, symlink_path)
1750
+ except OSError as e:
1751
+ print(f"rs-engine: cowork symlink skipped: {e}", file=sys.stderr)
1752
+
1753
+
1754
+ # --- CLI ---------------------------------------------------------------------
1755
+
1756
+ def _write_results(room_dir: Path, result: Dict, output: Optional[str]) -> Path:
1757
+ path = Path(output).resolve() if output else (room_dir / RESULTS_FILENAME)
1758
+ path.write_text(json.dumps(result, indent=2), encoding="utf-8")
1759
+ return path
1760
+
1761
+
1762
+ def build_parser() -> argparse.ArgumentParser:
1763
+ parser = argparse.ArgumentParser(
1764
+ prog="rs-engine",
1765
+ description=(
1766
+ "Reverse Salient Engine (Phase 89). Faithfully ports the Kwan 2023 "
1767
+ "topic-keyword-membership LSA + signed abs-diff detection "
1768
+ "algorithm. Mode A runs on a single room; Mode B fetches an "
1769
+ "external research corpus (OpenAlex, arXiv, Tavily); Mode C "
1770
+ "(hybrid) unifies the room with an external corpus and keeps only "
1771
+ "cross-corpus pairs -- the killer feature of Phase 89."
1772
+ ),
1773
+ epilog=(
1774
+ "Three-surface usage:\n"
1775
+ " CLI python scripts/rs-engine.py --mode internal --room ./room\n"
1776
+ " python scripts/rs-engine.py --rooms ~/rooms/a ~/rooms/b ~/rooms/c --topk 50\n"
1777
+ " python scripts/rs-engine.py --mode external --topic 'quantum biology' --room ./room\n"
1778
+ " python scripts/rs-engine.py --mode hybrid --topic 'quantum biology' --room ./room --topk 30\n"
1779
+ " Desktop invoked by ReverseSalientAgent conversational trigger\n"
1780
+ " (Plan 89-07).\n"
1781
+ " Cowork set COWORK=1 to symlink results under 00_Context/.\n"
1782
+ ),
1783
+ formatter_class=argparse.RawDescriptionHelpFormatter,
1784
+ )
1785
+ parser.add_argument(
1786
+ "--mode",
1787
+ choices=["internal", "external", "hybrid"],
1788
+ default="internal",
1789
+ help=(
1790
+ "internal=Mode A (single room, Plan 89-01); "
1791
+ "external=Mode B (research corpus, Plan 89-02); "
1792
+ "hybrid=Mode C (room x external unified matrix, Plan 89-05)."
1793
+ ),
1794
+ )
1795
+ parser.add_argument("--room", required=False, help="Path to room directory (Mode A / B / C).")
1796
+ parser.add_argument(
1797
+ "--rooms",
1798
+ nargs="+",
1799
+ required=False,
1800
+ help=(
1801
+ "Two or more room paths for cross-room Mode A (Plan 89-04). "
1802
+ "Rediscovers bridges between user projects. Mutually exclusive "
1803
+ "with --room. Results land in the FIRST room's .rs-engine-results.json "
1804
+ "with metadata.mode='cross-room'."
1805
+ ),
1806
+ )
1807
+ parser.add_argument(
1808
+ "--topic",
1809
+ required=False,
1810
+ help=(
1811
+ "Free-text research topic (required for --mode external). "
1812
+ "Normalized to a kebab-case slug via lib.core.rs_corpus.topic_slug "
1813
+ "for consistent {room}/research/{topic-slug}/ paths."
1814
+ ),
1815
+ )
1816
+ parser.add_argument(
1817
+ "--topk",
1818
+ type=int,
1819
+ default=DEFAULT_TOPK,
1820
+ help=f"Maximum number of pairs to keep (default {DEFAULT_TOPK}).",
1821
+ )
1822
+ parser.add_argument(
1823
+ "--threshold",
1824
+ type=float,
1825
+ default=DEFAULT_THRESHOLD,
1826
+ help=(
1827
+ f"Minimum abs(semantic - lsa) to keep a pair (default {DEFAULT_THRESHOLD}). "
1828
+ "0.0 disables filtering."
1829
+ ),
1830
+ )
1831
+ parser.add_argument(
1832
+ "--no-thesis",
1833
+ action="store_true",
1834
+ help=(
1835
+ "Skip LLM innovation-thesis generation (RESEARCH Q6). Plan 89-01 always "
1836
+ "runs cost-free; this flag is accepted for compatibility with later plans."
1837
+ ),
1838
+ )
1839
+ parser.add_argument(
1840
+ "--external-target",
1841
+ type=int,
1842
+ default=2000,
1843
+ help=(
1844
+ "Max external docs to include in --mode hybrid's unified corpus "
1845
+ "(default 2000; clamped to rs_hybrid.MAX_EXTERNAL_TARGET). "
1846
+ "Ignored for Mode A / Mode B."
1847
+ ),
1848
+ )
1849
+ parser.add_argument(
1850
+ "--output",
1851
+ default=None,
1852
+ help=f"Output JSON path (default: {{room}}/{RESULTS_FILENAME}).",
1853
+ )
1854
+ return parser
1855
+
1856
+
1857
+ def main(argv: Optional[Sequence[str]] = None) -> int:
1858
+ parser = build_parser()
1859
+ args = parser.parse_args(argv)
1860
+
1861
+ # Cross-room Mode A multi-room (Plan 89-04). --rooms is mutually
1862
+ # exclusive with --room. When --rooms is set, --mode is ignored
1863
+ # (cross-room is implicitly "internal multi-room").
1864
+ if args.rooms:
1865
+ if args.room:
1866
+ print(
1867
+ "rs-engine: --rooms and --room are mutually exclusive. "
1868
+ "Pick one.",
1869
+ file=sys.stderr,
1870
+ )
1871
+ return 2
1872
+ if len(args.rooms) < 2:
1873
+ print(
1874
+ "rs-engine: --rooms requires at least two room paths for "
1875
+ "cross-room mode.",
1876
+ file=sys.stderr,
1877
+ )
1878
+ return 2
1879
+ if args.mode == "external":
1880
+ print(
1881
+ "rs-engine: --mode external is incompatible with --rooms. "
1882
+ "Use --room for external mode.",
1883
+ file=sys.stderr,
1884
+ )
1885
+ return 2
1886
+ if args.mode == "hybrid":
1887
+ print(
1888
+ "rs-engine: --mode hybrid is incompatible with --rooms. "
1889
+ "Hybrid unifies ONE room with an external corpus; use --room "
1890
+ "for hybrid mode.",
1891
+ file=sys.stderr,
1892
+ )
1893
+ return 2
1894
+
1895
+ topk = max(1, args.topk)
1896
+ threshold = max(0.0, args.threshold)
1897
+
1898
+ try:
1899
+ result = run_mode_cross_room(
1900
+ args.rooms,
1901
+ topk=topk,
1902
+ threshold=threshold,
1903
+ no_thesis=args.no_thesis,
1904
+ )
1905
+ except NotImplementedError as e:
1906
+ print(f"rs-engine: {e}", file=sys.stderr)
1907
+ return 3
1908
+ except ValueError as e:
1909
+ print(f"rs-engine: {e}", file=sys.stderr)
1910
+ return 2
1911
+ except Exception as e: # pragma: no cover -- defensive envelope
1912
+ print(f"rs-engine: error: {e}", file=sys.stderr)
1913
+ return 1
1914
+
1915
+ # Output lands in the FIRST room's .rs-engine-results.json by
1916
+ # default (per plan). --output overrides if supplied.
1917
+ first_room_dir = Path(args.rooms[0]).resolve()
1918
+ if not first_room_dir.is_dir():
1919
+ print(
1920
+ f"rs-engine: first room {first_room_dir} is not a directory; "
1921
+ f"cannot write results.",
1922
+ file=sys.stderr,
1923
+ )
1924
+ return 1
1925
+ output_path = _write_results(first_room_dir, result, args.output)
1926
+
1927
+ _write_cowork_symlink(first_room_dir, output_path)
1928
+ _print_cross_room_summary(result)
1929
+
1930
+ meta = result["metadata"]
1931
+ print(
1932
+ f"rs-engine: {len(result['pairs'])} cross-room pairs from "
1933
+ f"{meta['artifact_count']} artifacts across "
1934
+ f"{len(meta['rooms'])} rooms written to {output_path} "
1935
+ f"(model={meta.get('embedding_model', 'n/a')})",
1936
+ file=sys.stderr,
1937
+ )
1938
+ return 0
1939
+
1940
+ if not args.room:
1941
+ print(
1942
+ f"rs-engine: --room is required for --mode {args.mode} "
1943
+ f"(or pass --rooms for cross-room mode)",
1944
+ file=sys.stderr,
1945
+ )
1946
+ return 2
1947
+
1948
+ room_dir = Path(args.room).resolve()
1949
+ # Allow the room directory to be auto-created for Mode B when it does
1950
+ # not exist yet. Mode A still requires an existing room. This matches
1951
+ # the plan's end-to-end smoke which targets /tmp/test-room. Hybrid
1952
+ # Mode C requires an existing room (its whole point is room x external).
1953
+ if args.mode == "external" and not room_dir.exists():
1954
+ try:
1955
+ room_dir.mkdir(parents=True, exist_ok=True)
1956
+ except OSError as e:
1957
+ print(f"rs-engine: could not create {room_dir}: {e}", file=sys.stderr)
1958
+ return 1
1959
+ if not room_dir.is_dir():
1960
+ print(f"rs-engine: {room_dir} is not a directory", file=sys.stderr)
1961
+ return 1
1962
+
1963
+ topk = max(1, args.topk)
1964
+ threshold = max(0.0, args.threshold)
1965
+
1966
+ try:
1967
+ if args.mode == "internal":
1968
+ result = run_mode_internal(
1969
+ room_dir,
1970
+ topk=topk,
1971
+ threshold=threshold,
1972
+ no_thesis=args.no_thesis,
1973
+ )
1974
+ output_path = _write_results(room_dir, result, args.output)
1975
+ elif args.mode == "hybrid":
1976
+ if not args.topic:
1977
+ print(
1978
+ "rs-engine: --topic is required for --mode hybrid",
1979
+ file=sys.stderr,
1980
+ )
1981
+ return 2
1982
+ result, corpus_dir = run_mode_hybrid(
1983
+ room_dir,
1984
+ topic=args.topic,
1985
+ topk=topk,
1986
+ threshold=threshold,
1987
+ no_thesis=args.no_thesis,
1988
+ external_target=args.external_target,
1989
+ )
1990
+ default_path = corpus_dir / RESULTS_FILENAME
1991
+ if args.output:
1992
+ output_path = Path(args.output).resolve()
1993
+ output_path.parent.mkdir(parents=True, exist_ok=True)
1994
+ output_path.write_text(
1995
+ json.dumps(result, indent=2), encoding="utf-8",
1996
+ )
1997
+ else:
1998
+ default_path.parent.mkdir(parents=True, exist_ok=True)
1999
+ default_path.write_text(
2000
+ json.dumps(result, indent=2), encoding="utf-8",
2001
+ )
2002
+ output_path = default_path
2003
+ else: # args.mode == "external"
2004
+ if not args.topic:
2005
+ print(
2006
+ "rs-engine: --topic is required for --mode external",
2007
+ file=sys.stderr,
2008
+ )
2009
+ return 2
2010
+ result, corpus_dir = run_mode_external(
2011
+ room_dir,
2012
+ topic=args.topic,
2013
+ topk=topk,
2014
+ threshold=threshold,
2015
+ no_thesis=args.no_thesis,
2016
+ )
2017
+ # Default external output: {room}/research/{topic-slug}/.rs-engine-results.json
2018
+ default_path = corpus_dir / RESULTS_FILENAME
2019
+ if args.output:
2020
+ output_path = Path(args.output).resolve()
2021
+ output_path.parent.mkdir(parents=True, exist_ok=True)
2022
+ output_path.write_text(
2023
+ json.dumps(result, indent=2), encoding="utf-8",
2024
+ )
2025
+ else:
2026
+ default_path.parent.mkdir(parents=True, exist_ok=True)
2027
+ default_path.write_text(
2028
+ json.dumps(result, indent=2), encoding="utf-8",
2029
+ )
2030
+ output_path = default_path
2031
+ except NotImplementedError as e:
2032
+ print(f"rs-engine: {e}", file=sys.stderr)
2033
+ return 3
2034
+ except ValueError as e:
2035
+ print(f"rs-engine: {e}", file=sys.stderr)
2036
+ return 2
2037
+ except Exception as e: # pragma: no cover - defensive envelope
2038
+ print(f"rs-engine: error: {e}", file=sys.stderr)
2039
+ return 1
2040
+
2041
+ _write_cowork_symlink(room_dir, output_path)
2042
+
2043
+ meta = result["metadata"]
2044
+ if args.mode == "internal":
2045
+ print(
2046
+ f"rs-engine: {len(result['pairs'])}/{meta['artifact_count']} pairs written to "
2047
+ f"{output_path} (model={meta['embedding_model']}, edges={meta['edges_written']})",
2048
+ file=sys.stderr,
2049
+ )
2050
+ elif args.mode == "hybrid":
2051
+ print(
2052
+ f"rs-engine: {len(result['pairs'])} cross-corpus pairs from "
2053
+ f"{meta.get('room_count', 0)} room + {meta.get('external_count', 0)} "
2054
+ f"external = {meta.get('artifact_count', 0)} artifacts "
2055
+ f"(cache={meta.get('cache_mode', 'n/a')}) written to {output_path} "
2056
+ f"(model={meta.get('embedding_model', 'n/a')})",
2057
+ file=sys.stderr,
2058
+ )
2059
+ else:
2060
+ tiers = meta.get("tier_counts", {})
2061
+ tier_str = ", ".join(f"{k}={v}" for k, v in tiers.items()) or "empty"
2062
+ print(
2063
+ f"rs-engine: {len(result['pairs'])} pairs from "
2064
+ f"{meta.get('artifact_count', 0)} artifacts (corpus={meta.get('corpus_size', 0)}, "
2065
+ f"{tier_str}) written to {output_path} "
2066
+ f"(model={meta.get('embedding_model', 'n/a')})",
2067
+ file=sys.stderr,
2068
+ )
2069
+ return 0
2070
+
2071
+
2072
+ if __name__ == "__main__":
2073
+ sys.exit(main())