@hongmaple0820/med-scale-research-os 0.43.0

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 (1104) hide show
  1. package/.scale/mcp-servers.yaml +144 -0
  2. package/.scale/skills.json +830 -0
  3. package/.scale/verification.json +52 -0
  4. package/LICENSE +15 -0
  5. package/README.en.md +156 -0
  6. package/README.md +156 -0
  7. package/dist/adapters/AiderAdapter.d.ts +22 -0
  8. package/dist/adapters/AiderAdapter.js +262 -0
  9. package/dist/adapters/AiderAdapter.js.map +1 -0
  10. package/dist/adapters/AntigravityAdapter.d.ts +4 -0
  11. package/dist/adapters/AntigravityAdapter.js +21 -0
  12. package/dist/adapters/AntigravityAdapter.js.map +1 -0
  13. package/dist/adapters/ClaudeCodeAdapter.d.ts +54 -0
  14. package/dist/adapters/ClaudeCodeAdapter.js +185 -0
  15. package/dist/adapters/ClaudeCodeAdapter.js.map +1 -0
  16. package/dist/adapters/ClineAdapter.d.ts +4 -0
  17. package/dist/adapters/ClineAdapter.js +20 -0
  18. package/dist/adapters/ClineAdapter.js.map +1 -0
  19. package/dist/adapters/CodexAdapter.d.ts +15 -0
  20. package/dist/adapters/CodexAdapter.js +160 -0
  21. package/dist/adapters/CodexAdapter.js.map +1 -0
  22. package/dist/adapters/CursorAdapter.d.ts +14 -0
  23. package/dist/adapters/CursorAdapter.js +171 -0
  24. package/dist/adapters/CursorAdapter.js.map +1 -0
  25. package/dist/adapters/DeepSeekTuiAdapter.d.ts +19 -0
  26. package/dist/adapters/DeepSeekTuiAdapter.js +263 -0
  27. package/dist/adapters/DeepSeekTuiAdapter.js.map +1 -0
  28. package/dist/adapters/DoubaoAdapter.d.ts +14 -0
  29. package/dist/adapters/DoubaoAdapter.js +184 -0
  30. package/dist/adapters/DoubaoAdapter.js.map +1 -0
  31. package/dist/adapters/GeminiAdapter.d.ts +14 -0
  32. package/dist/adapters/GeminiAdapter.js +163 -0
  33. package/dist/adapters/GeminiAdapter.js.map +1 -0
  34. package/dist/adapters/GenericProjectAgentAdapter.d.ts +29 -0
  35. package/dist/adapters/GenericProjectAgentAdapter.js +204 -0
  36. package/dist/adapters/GenericProjectAgentAdapter.js.map +1 -0
  37. package/dist/adapters/HermesAdapter.d.ts +14 -0
  38. package/dist/adapters/HermesAdapter.js +163 -0
  39. package/dist/adapters/HermesAdapter.js.map +1 -0
  40. package/dist/adapters/JCodeAdapter.d.ts +4 -0
  41. package/dist/adapters/JCodeAdapter.js +19 -0
  42. package/dist/adapters/JCodeAdapter.js.map +1 -0
  43. package/dist/adapters/KiloCodeAdapter.d.ts +4 -0
  44. package/dist/adapters/KiloCodeAdapter.js +20 -0
  45. package/dist/adapters/KiloCodeAdapter.js.map +1 -0
  46. package/dist/adapters/KimiAdapter.d.ts +14 -0
  47. package/dist/adapters/KimiAdapter.js +183 -0
  48. package/dist/adapters/KimiAdapter.js.map +1 -0
  49. package/dist/adapters/KiroAdapter.d.ts +14 -0
  50. package/dist/adapters/KiroAdapter.js +180 -0
  51. package/dist/adapters/KiroAdapter.js.map +1 -0
  52. package/dist/adapters/OpenClawAdapter.d.ts +14 -0
  53. package/dist/adapters/OpenClawAdapter.js +163 -0
  54. package/dist/adapters/OpenClawAdapter.js.map +1 -0
  55. package/dist/adapters/OpenCodeAdapter.d.ts +14 -0
  56. package/dist/adapters/OpenCodeAdapter.js +172 -0
  57. package/dist/adapters/OpenCodeAdapter.js.map +1 -0
  58. package/dist/adapters/QCoderAdapter.d.ts +14 -0
  59. package/dist/adapters/QCoderAdapter.js +159 -0
  60. package/dist/adapters/QCoderAdapter.js.map +1 -0
  61. package/dist/adapters/QoderAdapter.d.ts +4 -0
  62. package/dist/adapters/QoderAdapter.js +21 -0
  63. package/dist/adapters/QoderAdapter.js.map +1 -0
  64. package/dist/adapters/TraeAdapter.d.ts +14 -0
  65. package/dist/adapters/TraeAdapter.js +159 -0
  66. package/dist/adapters/TraeAdapter.js.map +1 -0
  67. package/dist/adapters/VSCAdapter.d.ts +14 -0
  68. package/dist/adapters/VSCAdapter.js +159 -0
  69. package/dist/adapters/VSCAdapter.js.map +1 -0
  70. package/dist/adapters/WindsurfAdapter.d.ts +14 -0
  71. package/dist/adapters/WindsurfAdapter.js +185 -0
  72. package/dist/adapters/WindsurfAdapter.js.map +1 -0
  73. package/dist/adapters/WorkBuddyAdapter.d.ts +14 -0
  74. package/dist/adapters/WorkBuddyAdapter.js +159 -0
  75. package/dist/adapters/WorkBuddyAdapter.js.map +1 -0
  76. package/dist/adapters/index.d.ts +32 -0
  77. package/dist/adapters/index.js +87 -0
  78. package/dist/adapters/index.js.map +1 -0
  79. package/dist/agents/AgentChannel.d.ts +43 -0
  80. package/dist/agents/AgentChannel.js +136 -0
  81. package/dist/agents/AgentChannel.js.map +1 -0
  82. package/dist/agents/AgentCoordinator.d.ts +29 -0
  83. package/dist/agents/AgentCoordinator.js +136 -0
  84. package/dist/agents/AgentCoordinator.js.map +1 -0
  85. package/dist/agents/AgentDispatcher.d.ts +24 -0
  86. package/dist/agents/AgentDispatcher.js +112 -0
  87. package/dist/agents/AgentDispatcher.js.map +1 -0
  88. package/dist/agents/AgentManager.d.ts +14 -0
  89. package/dist/agents/AgentManager.js +85 -0
  90. package/dist/agents/AgentManager.js.map +1 -0
  91. package/dist/agents/AgentPool.d.ts +59 -0
  92. package/dist/agents/AgentPool.js +192 -0
  93. package/dist/agents/AgentPool.js.map +1 -0
  94. package/dist/agents/AgentRegistry.d.ts +20 -0
  95. package/dist/agents/AgentRegistry.js +36 -0
  96. package/dist/agents/AgentRegistry.js.map +1 -0
  97. package/dist/agents/AgentSourceLoader.d.ts +73 -0
  98. package/dist/agents/AgentSourceLoader.js +103 -0
  99. package/dist/agents/AgentSourceLoader.js.map +1 -0
  100. package/dist/agents/IAgent.d.ts +53 -0
  101. package/dist/agents/IAgent.js +4 -0
  102. package/dist/agents/IAgent.js.map +1 -0
  103. package/dist/agents/LeadershipPresets.d.ts +16 -0
  104. package/dist/agents/LeadershipPresets.js +152 -0
  105. package/dist/agents/LeadershipPresets.js.map +1 -0
  106. package/dist/agents/definitions/debugger.d.ts +2 -0
  107. package/dist/agents/definitions/debugger.js +6 -0
  108. package/dist/agents/definitions/debugger.js.map +1 -0
  109. package/dist/agents/definitions/doc-writer.d.ts +2 -0
  110. package/dist/agents/definitions/doc-writer.js +6 -0
  111. package/dist/agents/definitions/doc-writer.js.map +1 -0
  112. package/dist/agents/definitions/implementer.d.ts +2 -0
  113. package/dist/agents/definitions/implementer.js +6 -0
  114. package/dist/agents/definitions/implementer.js.map +1 -0
  115. package/dist/agents/definitions/planner.d.ts +2 -0
  116. package/dist/agents/definitions/planner.js +6 -0
  117. package/dist/agents/definitions/planner.js.map +1 -0
  118. package/dist/agents/definitions/researcher.d.ts +2 -0
  119. package/dist/agents/definitions/researcher.js +6 -0
  120. package/dist/agents/definitions/researcher.js.map +1 -0
  121. package/dist/agents/definitions/reviewer.d.ts +2 -0
  122. package/dist/agents/definitions/reviewer.js +6 -0
  123. package/dist/agents/definitions/reviewer.js.map +1 -0
  124. package/dist/agents/definitions/security.d.ts +2 -0
  125. package/dist/agents/definitions/security.js +6 -0
  126. package/dist/agents/definitions/security.js.map +1 -0
  127. package/dist/agents/definitions/tester.d.ts +2 -0
  128. package/dist/agents/definitions/tester.js +6 -0
  129. package/dist/agents/definitions/tester.js.map +1 -0
  130. package/dist/agents/index.d.ts +23 -0
  131. package/dist/agents/index.js +44 -0
  132. package/dist/agents/index.js.map +1 -0
  133. package/dist/agents/profiles.d.ts +26 -0
  134. package/dist/agents/profiles.js +197 -0
  135. package/dist/agents/profiles.js.map +1 -0
  136. package/dist/agents/types.d.ts +262 -0
  137. package/dist/agents/types.js +4 -0
  138. package/dist/agents/types.js.map +1 -0
  139. package/dist/api/cli.d.ts +2 -0
  140. package/dist/api/cli.js +6678 -0
  141. package/dist/api/cli.js.map +1 -0
  142. package/dist/api/doctor.d.ts +83 -0
  143. package/dist/api/doctor.js +982 -0
  144. package/dist/api/doctor.js.map +1 -0
  145. package/dist/api/mcp.d.ts +32 -0
  146. package/dist/api/mcp.js +223 -0
  147. package/dist/api/mcp.js.map +1 -0
  148. package/dist/api/medscale.d.ts +2 -0
  149. package/dist/api/medscale.js +20 -0
  150. package/dist/api/medscale.js.map +1 -0
  151. package/dist/api/quickstart.d.ts +86 -0
  152. package/dist/api/quickstart.js +291 -0
  153. package/dist/api/quickstart.js.map +1 -0
  154. package/dist/artifact/fsm.d.ts +41 -0
  155. package/dist/artifact/fsm.js +221 -0
  156. package/dist/artifact/fsm.js.map +1 -0
  157. package/dist/artifact/fsmDefinitions.d.ts +18 -0
  158. package/dist/artifact/fsmDefinitions.js +296 -0
  159. package/dist/artifact/fsmDefinitions.js.map +1 -0
  160. package/dist/artifact/sqliteStore.d.ts +61 -0
  161. package/dist/artifact/sqliteStore.js +381 -0
  162. package/dist/artifact/sqliteStore.js.map +1 -0
  163. package/dist/artifact/store.d.ts +49 -0
  164. package/dist/artifact/store.js +116 -0
  165. package/dist/artifact/store.js.map +1 -0
  166. package/dist/artifact/types.d.ts +535 -0
  167. package/dist/artifact/types.js +74 -0
  168. package/dist/artifact/types.js.map +1 -0
  169. package/dist/bootstrap/DependencyBootstrap.d.ts +112 -0
  170. package/dist/bootstrap/DependencyBootstrap.js +1046 -0
  171. package/dist/bootstrap/DependencyBootstrap.js.map +1 -0
  172. package/dist/bootstrap/DependencyBootstrapRenderer.d.ts +3 -0
  173. package/dist/bootstrap/DependencyBootstrapRenderer.js +138 -0
  174. package/dist/bootstrap/DependencyBootstrapRenderer.js.map +1 -0
  175. package/dist/bridge/PythonBridge.d.ts +80 -0
  176. package/dist/bridge/PythonBridge.js +437 -0
  177. package/dist/bridge/PythonBridge.js.map +1 -0
  178. package/dist/bridge/index.d.ts +2 -0
  179. package/dist/bridge/index.js +7 -0
  180. package/dist/bridge/index.js.map +1 -0
  181. package/dist/bridge/medicalWorkflows.d.ts +29 -0
  182. package/dist/bridge/medicalWorkflows.js +156 -0
  183. package/dist/bridge/medicalWorkflows.js.map +1 -0
  184. package/dist/bridge/types.d.ts +381 -0
  185. package/dist/bridge/types.js +113 -0
  186. package/dist/bridge/types.js.map +1 -0
  187. package/dist/cache/ScanCache.d.ts +41 -0
  188. package/dist/cache/ScanCache.js +120 -0
  189. package/dist/cache/ScanCache.js.map +1 -0
  190. package/dist/capabilities/BrowserCapability.d.ts +30 -0
  191. package/dist/capabilities/BrowserCapability.js +73 -0
  192. package/dist/capabilities/BrowserCapability.js.map +1 -0
  193. package/dist/capabilities/BrowserQACapability.d.ts +165 -0
  194. package/dist/capabilities/BrowserQACapability.js +438 -0
  195. package/dist/capabilities/BrowserQACapability.js.map +1 -0
  196. package/dist/capabilities/CapabilityRegistry.d.ts +17 -0
  197. package/dist/capabilities/CapabilityRegistry.js +65 -0
  198. package/dist/capabilities/CapabilityRegistry.js.map +1 -0
  199. package/dist/capabilities/ComputerCapability.d.ts +28 -0
  200. package/dist/capabilities/ComputerCapability.js +40 -0
  201. package/dist/capabilities/ComputerCapability.js.map +1 -0
  202. package/dist/capabilities/InstalledSkillsIntegration.d.ts +69 -0
  203. package/dist/capabilities/InstalledSkillsIntegration.js +240 -0
  204. package/dist/capabilities/InstalledSkillsIntegration.js.map +1 -0
  205. package/dist/capabilities/SearchCapability.d.ts +46 -0
  206. package/dist/capabilities/SearchCapability.js +88 -0
  207. package/dist/capabilities/SearchCapability.js.map +1 -0
  208. package/dist/capabilities/index.d.ts +6 -0
  209. package/dist/capabilities/index.js +9 -0
  210. package/dist/capabilities/index.js.map +1 -0
  211. package/dist/capabilities/types.d.ts +92 -0
  212. package/dist/capabilities/types.js +7 -0
  213. package/dist/capabilities/types.js.map +1 -0
  214. package/dist/cli/autofixCommands.d.ts +22 -0
  215. package/dist/cli/autofixCommands.js +32 -0
  216. package/dist/cli/autofixCommands.js.map +1 -0
  217. package/dist/cli/cortexCommands.d.ts +71 -0
  218. package/dist/cli/cortexCommands.js +335 -0
  219. package/dist/cli/cortexCommands.js.map +1 -0
  220. package/dist/cli/costCommands.d.ts +13 -0
  221. package/dist/cli/costCommands.js +48 -0
  222. package/dist/cli/costCommands.js.map +1 -0
  223. package/dist/cli/evolutionCommands.d.ts +112 -0
  224. package/dist/cli/evolutionCommands.js +246 -0
  225. package/dist/cli/evolutionCommands.js.map +1 -0
  226. package/dist/cli/gateStatusCommands.d.ts +1 -0
  227. package/dist/cli/gateStatusCommands.js +52 -0
  228. package/dist/cli/gateStatusCommands.js.map +1 -0
  229. package/dist/cli/liteCommands.d.ts +81 -0
  230. package/dist/cli/liteCommands.js +148 -0
  231. package/dist/cli/liteCommands.js.map +1 -0
  232. package/dist/cli/orchCommands.d.ts +43 -0
  233. package/dist/cli/orchCommands.js +135 -0
  234. package/dist/cli/orchCommands.js.map +1 -0
  235. package/dist/cli/phaseCommands.d.ts +248 -0
  236. package/dist/cli/phaseCommands.js +1878 -0
  237. package/dist/cli/phaseCommands.js.map +1 -0
  238. package/dist/cli/promptCommands.d.ts +1 -0
  239. package/dist/cli/promptCommands.js +57 -0
  240. package/dist/cli/promptCommands.js.map +1 -0
  241. package/dist/cli/qaCommands.d.ts +22 -0
  242. package/dist/cli/qaCommands.js +84 -0
  243. package/dist/cli/qaCommands.js.map +1 -0
  244. package/dist/cli/quickstartCommands.d.ts +17 -0
  245. package/dist/cli/quickstartCommands.js +47 -0
  246. package/dist/cli/quickstartCommands.js.map +1 -0
  247. package/dist/cli/runCommand.d.ts +39 -0
  248. package/dist/cli/runCommand.js +113 -0
  249. package/dist/cli/runCommand.js.map +1 -0
  250. package/dist/cli/scoreCommands.d.ts +1 -0
  251. package/dist/cli/scoreCommands.js +112 -0
  252. package/dist/cli/scoreCommands.js.map +1 -0
  253. package/dist/cli/shieldCommands.d.ts +30 -0
  254. package/dist/cli/shieldCommands.js +212 -0
  255. package/dist/cli/shieldCommands.js.map +1 -0
  256. package/dist/cli/targetCommands.d.ts +552 -0
  257. package/dist/cli/targetCommands.js +3173 -0
  258. package/dist/cli/targetCommands.js.map +1 -0
  259. package/dist/cli/tuiCommands.d.ts +7 -0
  260. package/dist/cli/tuiCommands.js +33 -0
  261. package/dist/cli/tuiCommands.js.map +1 -0
  262. package/dist/cli/vibeCommands.d.ts +64 -0
  263. package/dist/cli/vibeCommands.js +221 -0
  264. package/dist/cli/vibeCommands.js.map +1 -0
  265. package/dist/codegraph/CodeIntelligence.d.ts +147 -0
  266. package/dist/codegraph/CodeIntelligence.js +681 -0
  267. package/dist/codegraph/CodeIntelligence.js.map +1 -0
  268. package/dist/config/profiles.d.ts +64 -0
  269. package/dist/config/profiles.js +223 -0
  270. package/dist/config/profiles.js.map +1 -0
  271. package/dist/context/AntiPatternRegistry.d.ts +38 -0
  272. package/dist/context/AntiPatternRegistry.js +203 -0
  273. package/dist/context/AntiPatternRegistry.js.map +1 -0
  274. package/dist/context/CavemanCompressor.d.ts +20 -0
  275. package/dist/context/CavemanCompressor.js +14 -0
  276. package/dist/context/CavemanCompressor.js.map +1 -0
  277. package/dist/context/ContextBudget.d.ts +128 -0
  278. package/dist/context/ContextBudget.js +423 -0
  279. package/dist/context/ContextBudget.js.map +1 -0
  280. package/dist/context/ContextBuilder.d.ts +71 -0
  281. package/dist/context/ContextBuilder.js +372 -0
  282. package/dist/context/ContextBuilder.js.map +1 -0
  283. package/dist/context/ContextCompiler.d.ts +34 -0
  284. package/dist/context/ContextCompiler.js +120 -0
  285. package/dist/context/ContextCompiler.js.map +1 -0
  286. package/dist/context/ProjectAnatomy.d.ts +18 -0
  287. package/dist/context/ProjectAnatomy.js +287 -0
  288. package/dist/context/ProjectAnatomy.js.map +1 -0
  289. package/dist/context/SessionStartSequence.d.ts +54 -0
  290. package/dist/context/SessionStartSequence.js +162 -0
  291. package/dist/context/SessionStartSequence.js.map +1 -0
  292. package/dist/core/ExternalCommand.d.ts +9 -0
  293. package/dist/core/ExternalCommand.js +70 -0
  294. package/dist/core/ExternalCommand.js.map +1 -0
  295. package/dist/core/GbrainRuntime.d.ts +25 -0
  296. package/dist/core/GbrainRuntime.js +270 -0
  297. package/dist/core/GbrainRuntime.js.map +1 -0
  298. package/dist/core/container.d.ts +14 -0
  299. package/dist/core/container.js +35 -0
  300. package/dist/core/container.js.map +1 -0
  301. package/dist/core/eventBus.d.ts +60 -0
  302. package/dist/core/eventBus.js +157 -0
  303. package/dist/core/eventBus.js.map +1 -0
  304. package/dist/core/logger.d.ts +5 -0
  305. package/dist/core/logger.js +51 -0
  306. package/dist/core/logger.js.map +1 -0
  307. package/dist/cortex/GovernanceMetrics.d.ts +66 -0
  308. package/dist/cortex/GovernanceMetrics.js +230 -0
  309. package/dist/cortex/GovernanceMetrics.js.map +1 -0
  310. package/dist/cortex/InstinctExtractor.d.ts +61 -0
  311. package/dist/cortex/InstinctExtractor.js +184 -0
  312. package/dist/cortex/InstinctExtractor.js.map +1 -0
  313. package/dist/cortex/InstinctStore.d.ts +54 -0
  314. package/dist/cortex/InstinctStore.js +266 -0
  315. package/dist/cortex/InstinctStore.js.map +1 -0
  316. package/dist/cortex/ReflexionEngine.d.ts +34 -0
  317. package/dist/cortex/ReflexionEngine.js +157 -0
  318. package/dist/cortex/ReflexionEngine.js.map +1 -0
  319. package/dist/cortex/SessionInjector.d.ts +44 -0
  320. package/dist/cortex/SessionInjector.js +127 -0
  321. package/dist/cortex/SessionInjector.js.map +1 -0
  322. package/dist/cortex/adapters/ClaudeAdapter.d.ts +17 -0
  323. package/dist/cortex/adapters/ClaudeAdapter.js +61 -0
  324. package/dist/cortex/adapters/ClaudeAdapter.js.map +1 -0
  325. package/dist/cortex/adapters/CodexAdapter.d.ts +10 -0
  326. package/dist/cortex/adapters/CodexAdapter.js +52 -0
  327. package/dist/cortex/adapters/CodexAdapter.js.map +1 -0
  328. package/dist/cortex/adapters/CursorAdapter.d.ts +10 -0
  329. package/dist/cortex/adapters/CursorAdapter.js +46 -0
  330. package/dist/cortex/adapters/CursorAdapter.js.map +1 -0
  331. package/dist/cortex/adapters/GeminiAdapter.d.ts +11 -0
  332. package/dist/cortex/adapters/GeminiAdapter.js +48 -0
  333. package/dist/cortex/adapters/GeminiAdapter.js.map +1 -0
  334. package/dist/dashboard/DashboardServer.d.ts +86 -0
  335. package/dist/dashboard/DashboardServer.js +380 -0
  336. package/dist/dashboard/DashboardServer.js.map +1 -0
  337. package/dist/dashboard/MedicalWorkflowData.d.ts +155 -0
  338. package/dist/dashboard/MedicalWorkflowData.js +664 -0
  339. package/dist/dashboard/MedicalWorkflowData.js.map +1 -0
  340. package/dist/dashboard/MetricsAggregator.d.ts +38 -0
  341. package/dist/dashboard/MetricsAggregator.js +99 -0
  342. package/dist/dashboard/MetricsAggregator.js.map +1 -0
  343. package/dist/dashboard/index.d.ts +4 -0
  344. package/dist/dashboard/index.js +3 -0
  345. package/dist/dashboard/index.js.map +1 -0
  346. package/dist/dashboard/server.d.ts +52 -0
  347. package/dist/dashboard/server.js +84 -0
  348. package/dist/dashboard/server.js.map +1 -0
  349. package/dist/env/EnvironmentDoctor.d.ts +66 -0
  350. package/dist/env/EnvironmentDoctor.js +581 -0
  351. package/dist/env/EnvironmentDoctor.js.map +1 -0
  352. package/dist/eval/BenchmarkPublisher.d.ts +25 -0
  353. package/dist/eval/BenchmarkPublisher.js +27 -0
  354. package/dist/eval/BenchmarkPublisher.js.map +1 -0
  355. package/dist/eval/WorkflowEval.d.ts +161 -0
  356. package/dist/eval/WorkflowEval.js +377 -0
  357. package/dist/eval/WorkflowEval.js.map +1 -0
  358. package/dist/evolution/AutoDefectCreator.d.ts +43 -0
  359. package/dist/evolution/AutoDefectCreator.js +157 -0
  360. package/dist/evolution/AutoDefectCreator.js.map +1 -0
  361. package/dist/evolution/BehaviorTracker.d.ts +46 -0
  362. package/dist/evolution/BehaviorTracker.js +67 -0
  363. package/dist/evolution/BehaviorTracker.js.map +1 -0
  364. package/dist/evolution/EvolutionEngine.d.ts +102 -0
  365. package/dist/evolution/EvolutionEngine.js +326 -0
  366. package/dist/evolution/EvolutionEngine.js.map +1 -0
  367. package/dist/evolution/EvolutionEvaluator.d.ts +61 -0
  368. package/dist/evolution/EvolutionEvaluator.js +118 -0
  369. package/dist/evolution/EvolutionEvaluator.js.map +1 -0
  370. package/dist/evolution/LessonValidator.d.ts +36 -0
  371. package/dist/evolution/LessonValidator.js +132 -0
  372. package/dist/evolution/LessonValidator.js.map +1 -0
  373. package/dist/evolution/PatternExtractor.d.ts +40 -0
  374. package/dist/evolution/PatternExtractor.js +83 -0
  375. package/dist/evolution/PatternExtractor.js.map +1 -0
  376. package/dist/evolution/RuleMaturity.d.ts +39 -0
  377. package/dist/evolution/RuleMaturity.js +70 -0
  378. package/dist/evolution/RuleMaturity.js.map +1 -0
  379. package/dist/evolution/SessionLearnings.d.ts +70 -0
  380. package/dist/evolution/SessionLearnings.js +217 -0
  381. package/dist/evolution/SessionLearnings.js.map +1 -0
  382. package/dist/evolution/SkillCreator.d.ts +75 -0
  383. package/dist/evolution/SkillCreator.js +219 -0
  384. package/dist/evolution/SkillCreator.js.map +1 -0
  385. package/dist/fsm/FSMAgentBridge.d.ts +59 -0
  386. package/dist/fsm/FSMAgentBridge.js +193 -0
  387. package/dist/fsm/FSMAgentBridge.js.map +1 -0
  388. package/dist/fsm/index.d.ts +2 -0
  389. package/dist/fsm/index.js +3 -0
  390. package/dist/fsm/index.js.map +1 -0
  391. package/dist/governance/GovernanceRoi.d.ts +30 -0
  392. package/dist/governance/GovernanceRoi.js +102 -0
  393. package/dist/governance/GovernanceRoi.js.map +1 -0
  394. package/dist/governance/ProgressiveGovernance.d.ts +22 -0
  395. package/dist/governance/ProgressiveGovernance.js +159 -0
  396. package/dist/governance/ProgressiveGovernance.js.map +1 -0
  397. package/dist/guardrails/ActiveRedTeam.d.ts +46 -0
  398. package/dist/guardrails/ActiveRedTeam.js +203 -0
  399. package/dist/guardrails/ActiveRedTeam.js.map +1 -0
  400. package/dist/guardrails/DependencyAuditor.d.ts +68 -0
  401. package/dist/guardrails/DependencyAuditor.js +378 -0
  402. package/dist/guardrails/DependencyAuditor.js.map +1 -0
  403. package/dist/guardrails/DetectorEnhanced.d.ts +111 -0
  404. package/dist/guardrails/DetectorEnhanced.js +202 -0
  405. package/dist/guardrails/DetectorEnhanced.js.map +1 -0
  406. package/dist/guardrails/GateEvaluator.d.ts +18 -0
  407. package/dist/guardrails/GateEvaluator.js +129 -0
  408. package/dist/guardrails/GateEvaluator.js.map +1 -0
  409. package/dist/guardrails/Gateway.d.ts +26 -0
  410. package/dist/guardrails/Gateway.js +56 -0
  411. package/dist/guardrails/Gateway.js.map +1 -0
  412. package/dist/guardrails/OWASPDetector.d.ts +58 -0
  413. package/dist/guardrails/OWASPDetector.js +508 -0
  414. package/dist/guardrails/OWASPDetector.js.map +1 -0
  415. package/dist/guardrails/ReviewEnforcer.d.ts +52 -0
  416. package/dist/guardrails/ReviewEnforcer.js +117 -0
  417. package/dist/guardrails/ReviewEnforcer.js.map +1 -0
  418. package/dist/guardrails/advancedDetectors.d.ts +38 -0
  419. package/dist/guardrails/advancedDetectors.js +188 -0
  420. package/dist/guardrails/advancedDetectors.js.map +1 -0
  421. package/dist/guardrails/detectors.d.ts +34 -0
  422. package/dist/guardrails/detectors.js +332 -0
  423. package/dist/guardrails/detectors.js.map +1 -0
  424. package/dist/guardrails/roles.d.ts +4 -0
  425. package/dist/guardrails/roles.js +54 -0
  426. package/dist/guardrails/roles.js.map +1 -0
  427. package/dist/hooks/BugPatternDetector.d.ts +36 -0
  428. package/dist/hooks/BugPatternDetector.js +207 -0
  429. package/dist/hooks/BugPatternDetector.js.map +1 -0
  430. package/dist/hooks/HookDeployer.d.ts +44 -0
  431. package/dist/hooks/HookDeployer.js +144 -0
  432. package/dist/hooks/HookDeployer.js.map +1 -0
  433. package/dist/hooks/HookGeneratorEnhanced.d.ts +67 -0
  434. package/dist/hooks/HookGeneratorEnhanced.js +641 -0
  435. package/dist/hooks/HookGeneratorEnhanced.js.map +1 -0
  436. package/dist/hooks/WorkflowHooksManager.d.ts +30 -0
  437. package/dist/hooks/WorkflowHooksManager.js +160 -0
  438. package/dist/hooks/WorkflowHooksManager.js.map +1 -0
  439. package/dist/hooks/index.d.ts +6 -0
  440. package/dist/hooks/index.js +5 -0
  441. package/dist/hooks/index.js.map +1 -0
  442. package/dist/i18n/Language.d.ts +9 -0
  443. package/dist/i18n/Language.js +38 -0
  444. package/dist/i18n/Language.js.map +1 -0
  445. package/dist/index.d.ts +101 -0
  446. package/dist/index.js +104 -0
  447. package/dist/index.js.map +1 -0
  448. package/dist/knowledge/CerebrumManager.d.ts +25 -0
  449. package/dist/knowledge/CerebrumManager.js +127 -0
  450. package/dist/knowledge/CerebrumManager.js.map +1 -0
  451. package/dist/knowledge/GraphifyKnowledgeBase.d.ts +38 -0
  452. package/dist/knowledge/GraphifyKnowledgeBase.js +409 -0
  453. package/dist/knowledge/GraphifyKnowledgeBase.js.map +1 -0
  454. package/dist/knowledge/KnowledgeBase.d.ts +51 -0
  455. package/dist/knowledge/KnowledgeBase.js +182 -0
  456. package/dist/knowledge/KnowledgeBase.js.map +1 -0
  457. package/dist/knowledge/SQLiteKnowledgeBase.d.ts +29 -0
  458. package/dist/knowledge/SQLiteKnowledgeBase.js +203 -0
  459. package/dist/knowledge/SQLiteKnowledgeBase.js.map +1 -0
  460. package/dist/knowledge/TfidfIndex.d.ts +50 -0
  461. package/dist/knowledge/TfidfIndex.js +177 -0
  462. package/dist/knowledge/TfidfIndex.js.map +1 -0
  463. package/dist/knowledge/UbiquitousLanguageManager.d.ts +49 -0
  464. package/dist/knowledge/UbiquitousLanguageManager.js +133 -0
  465. package/dist/knowledge/UbiquitousLanguageManager.js.map +1 -0
  466. package/dist/memory/MemoryBrain.d.ts +146 -0
  467. package/dist/memory/MemoryBrain.js +679 -0
  468. package/dist/memory/MemoryBrain.js.map +1 -0
  469. package/dist/memory/MemoryFabric.d.ts +130 -0
  470. package/dist/memory/MemoryFabric.js +317 -0
  471. package/dist/memory/MemoryFabric.js.map +1 -0
  472. package/dist/memory/MemoryIntelligence.d.ts +42 -0
  473. package/dist/memory/MemoryIntelligence.js +215 -0
  474. package/dist/memory/MemoryIntelligence.js.map +1 -0
  475. package/dist/memory/MemoryLearning.d.ts +62 -0
  476. package/dist/memory/MemoryLearning.js +209 -0
  477. package/dist/memory/MemoryLearning.js.map +1 -0
  478. package/dist/memory/MemoryProviders.d.ts +165 -0
  479. package/dist/memory/MemoryProviders.js +940 -0
  480. package/dist/memory/MemoryProviders.js.map +1 -0
  481. package/dist/memory/MemoryReview.d.ts +65 -0
  482. package/dist/memory/MemoryReview.js +260 -0
  483. package/dist/memory/MemoryReview.js.map +1 -0
  484. package/dist/memory/index.d.ts +6 -0
  485. package/dist/memory/index.js +7 -0
  486. package/dist/memory/index.js.map +1 -0
  487. package/dist/orchestration/EffectsWiring.d.ts +8 -0
  488. package/dist/orchestration/EffectsWiring.js +87 -0
  489. package/dist/orchestration/EffectsWiring.js.map +1 -0
  490. package/dist/orchestrator/OrchestratorDaemon.d.ts +44 -0
  491. package/dist/orchestrator/OrchestratorDaemon.js +150 -0
  492. package/dist/orchestrator/OrchestratorDaemon.js.map +1 -0
  493. package/dist/orchestrator/PolicyLoader.d.ts +80 -0
  494. package/dist/orchestrator/PolicyLoader.js +229 -0
  495. package/dist/orchestrator/PolicyLoader.js.map +1 -0
  496. package/dist/orchestrator/ReconciliationLoop.d.ts +71 -0
  497. package/dist/orchestrator/ReconciliationLoop.js +266 -0
  498. package/dist/orchestrator/ReconciliationLoop.js.map +1 -0
  499. package/dist/orchestrator/TrackerAdapter.d.ts +60 -0
  500. package/dist/orchestrator/TrackerAdapter.js +147 -0
  501. package/dist/orchestrator/TrackerAdapter.js.map +1 -0
  502. package/dist/orchestrator/WorkspaceManager.d.ts +66 -0
  503. package/dist/orchestrator/WorkspaceManager.js +257 -0
  504. package/dist/orchestrator/WorkspaceManager.js.map +1 -0
  505. package/dist/output/BrandThemeLoader.d.ts +54 -0
  506. package/dist/output/BrandThemeLoader.js +340 -0
  507. package/dist/output/BrandThemeLoader.js.map +1 -0
  508. package/dist/output/GovernanceDashboard.d.ts +59 -0
  509. package/dist/output/GovernanceDashboard.js +281 -0
  510. package/dist/output/GovernanceDashboard.js.map +1 -0
  511. package/dist/output/HTMLArtifactLayer.d.ts +97 -0
  512. package/dist/output/HTMLArtifactLayer.js +576 -0
  513. package/dist/output/HTMLArtifactLayer.js.map +1 -0
  514. package/dist/output/HTMLDocumentRenderer.d.ts +83 -0
  515. package/dist/output/HTMLDocumentRenderer.js +718 -0
  516. package/dist/output/HTMLDocumentRenderer.js.map +1 -0
  517. package/dist/output/UIPrototypeRenderer.d.ts +61 -0
  518. package/dist/output/UIPrototypeRenderer.js +500 -0
  519. package/dist/output/UIPrototypeRenderer.js.map +1 -0
  520. package/dist/output/index.d.ts +10 -0
  521. package/dist/output/index.js +8 -0
  522. package/dist/output/index.js.map +1 -0
  523. package/dist/prompts/PhasePromptRegistry.d.ts +53 -0
  524. package/dist/prompts/PhasePromptRegistry.js +517 -0
  525. package/dist/prompts/PhasePromptRegistry.js.map +1 -0
  526. package/dist/prompts/PromptOptimizer.d.ts +42 -0
  527. package/dist/prompts/PromptOptimizer.js +309 -0
  528. package/dist/prompts/PromptOptimizer.js.map +1 -0
  529. package/dist/prompts/VibeTemplateGallery.d.ts +25 -0
  530. package/dist/prompts/VibeTemplateGallery.js +295 -0
  531. package/dist/prompts/VibeTemplateGallery.js.map +1 -0
  532. package/dist/qa/BrowserDaemon.d.ts +23 -0
  533. package/dist/qa/BrowserDaemon.js +79 -0
  534. package/dist/qa/BrowserDaemon.js.map +1 -0
  535. package/dist/qa/E2ETestOrchestrator.d.ts +14 -0
  536. package/dist/qa/E2ETestOrchestrator.js +19 -0
  537. package/dist/qa/E2ETestOrchestrator.js.map +1 -0
  538. package/dist/review/CrossModelReviewer.d.ts +35 -0
  539. package/dist/review/CrossModelReviewer.js +75 -0
  540. package/dist/review/CrossModelReviewer.js.map +1 -0
  541. package/dist/review/ReviewAggregator.d.ts +13 -0
  542. package/dist/review/ReviewAggregator.js +28 -0
  543. package/dist/review/ReviewAggregator.js.map +1 -0
  544. package/dist/review/reviewCommands.d.ts +15 -0
  545. package/dist/review/reviewCommands.js +24 -0
  546. package/dist/review/reviewCommands.js.map +1 -0
  547. package/dist/routing/LocalModelProvider.d.ts +11 -0
  548. package/dist/routing/LocalModelProvider.js +21 -0
  549. package/dist/routing/LocalModelProvider.js.map +1 -0
  550. package/dist/routing/ModelRouter.d.ts +42 -0
  551. package/dist/routing/ModelRouter.js +94 -0
  552. package/dist/routing/ModelRouter.js.map +1 -0
  553. package/dist/routing/PromptCachePolicy.d.ts +37 -0
  554. package/dist/routing/PromptCachePolicy.js +97 -0
  555. package/dist/routing/PromptCachePolicy.js.map +1 -0
  556. package/dist/runtime/AiOsRuntime.d.ts +485 -0
  557. package/dist/runtime/AiOsRuntime.js +1846 -0
  558. package/dist/runtime/AiOsRuntime.js.map +1 -0
  559. package/dist/runtime/CostAnalyzer.d.ts +53 -0
  560. package/dist/runtime/CostAnalyzer.js +160 -0
  561. package/dist/runtime/CostAnalyzer.js.map +1 -0
  562. package/dist/runtime/CostOptimizer.d.ts +11 -0
  563. package/dist/runtime/CostOptimizer.js +21 -0
  564. package/dist/runtime/CostOptimizer.js.map +1 -0
  565. package/dist/runtime/ExecutionLedger.d.ts +46 -0
  566. package/dist/runtime/ExecutionLedger.js +71 -0
  567. package/dist/runtime/ExecutionLedger.js.map +1 -0
  568. package/dist/runtime/FinalReportGuard.d.ts +16 -0
  569. package/dist/runtime/FinalReportGuard.js +14 -0
  570. package/dist/runtime/FinalReportGuard.js.map +1 -0
  571. package/dist/runtime/ModelUsageLedger.d.ts +101 -0
  572. package/dist/runtime/ModelUsageLedger.js +296 -0
  573. package/dist/runtime/ModelUsageLedger.js.map +1 -0
  574. package/dist/runtime/RuntimeDoctor.d.ts +23 -0
  575. package/dist/runtime/RuntimeDoctor.js +151 -0
  576. package/dist/runtime/RuntimeDoctor.js.map +1 -0
  577. package/dist/runtime/RuntimeEvidenceLedger.d.ts +50 -0
  578. package/dist/runtime/RuntimeEvidenceLedger.js +89 -0
  579. package/dist/runtime/RuntimeEvidenceLedger.js.map +1 -0
  580. package/dist/runtime/SessionLedger.d.ts +53 -0
  581. package/dist/runtime/SessionLedger.js +104 -0
  582. package/dist/runtime/SessionLedger.js.map +1 -0
  583. package/dist/runtime/index.d.ts +7 -0
  584. package/dist/runtime/index.js +8 -0
  585. package/dist/runtime/index.js.map +1 -0
  586. package/dist/setup/SetupVerification.d.ts +42 -0
  587. package/dist/setup/SetupVerification.js +180 -0
  588. package/dist/setup/SetupVerification.js.map +1 -0
  589. package/dist/setup/SetupWizard.d.ts +45 -0
  590. package/dist/setup/SetupWizard.js +216 -0
  591. package/dist/setup/SetupWizard.js.map +1 -0
  592. package/dist/shield/PolicyCompiler.d.ts +70 -0
  593. package/dist/shield/PolicyCompiler.js +540 -0
  594. package/dist/shield/PolicyCompiler.js.map +1 -0
  595. package/dist/shield/ProtectedPaths.d.ts +39 -0
  596. package/dist/shield/ProtectedPaths.js +179 -0
  597. package/dist/shield/ProtectedPaths.js.map +1 -0
  598. package/dist/shield/ShieldProtocol.d.ts +50 -0
  599. package/dist/shield/ShieldProtocol.js +103 -0
  600. package/dist/shield/ShieldProtocol.js.map +1 -0
  601. package/dist/skills/ExternalSkills.d.ts +3 -0
  602. package/dist/skills/ExternalSkills.js +27 -0
  603. package/dist/skills/ExternalSkills.js.map +1 -0
  604. package/dist/skills/GrillingSessionSkill.d.ts +65 -0
  605. package/dist/skills/GrillingSessionSkill.js +113 -0
  606. package/dist/skills/GrillingSessionSkill.js.map +1 -0
  607. package/dist/skills/GrillingTemplates.d.ts +7 -0
  608. package/dist/skills/GrillingTemplates.js +38 -0
  609. package/dist/skills/GrillingTemplates.js.map +1 -0
  610. package/dist/skills/RoleSkills.d.ts +20 -0
  611. package/dist/skills/RoleSkills.js +154 -0
  612. package/dist/skills/RoleSkills.js.map +1 -0
  613. package/dist/skills/SkillCatalog.d.ts +13 -0
  614. package/dist/skills/SkillCatalog.js +184 -0
  615. package/dist/skills/SkillCatalog.js.map +1 -0
  616. package/dist/skills/SkillDiscovery.d.ts +84 -0
  617. package/dist/skills/SkillDiscovery.js +402 -0
  618. package/dist/skills/SkillDiscovery.js.map +1 -0
  619. package/dist/skills/SkillDoctor.d.ts +37 -0
  620. package/dist/skills/SkillDoctor.js +267 -0
  621. package/dist/skills/SkillDoctor.js.map +1 -0
  622. package/dist/skills/SkillExecutor.d.ts +38 -0
  623. package/dist/skills/SkillExecutor.js +237 -0
  624. package/dist/skills/SkillExecutor.js.map +1 -0
  625. package/dist/skills/SkillFrontmatter.d.ts +28 -0
  626. package/dist/skills/SkillFrontmatter.js +152 -0
  627. package/dist/skills/SkillFrontmatter.js.map +1 -0
  628. package/dist/skills/SkillInstaller.d.ts +40 -0
  629. package/dist/skills/SkillInstaller.js +117 -0
  630. package/dist/skills/SkillInstaller.js.map +1 -0
  631. package/dist/skills/SkillMdStandard.d.ts +33 -0
  632. package/dist/skills/SkillMdStandard.js +88 -0
  633. package/dist/skills/SkillMdStandard.js.map +1 -0
  634. package/dist/skills/SkillRadar.d.ts +83 -0
  635. package/dist/skills/SkillRadar.js +404 -0
  636. package/dist/skills/SkillRadar.js.map +1 -0
  637. package/dist/skills/SkillRegistry.d.ts +112 -0
  638. package/dist/skills/SkillRegistry.js +161 -0
  639. package/dist/skills/SkillRegistry.js.map +1 -0
  640. package/dist/skills/SkillRepository.d.ts +71 -0
  641. package/dist/skills/SkillRepository.js +435 -0
  642. package/dist/skills/SkillRepository.js.map +1 -0
  643. package/dist/skills/TriggerEngine.d.ts +43 -0
  644. package/dist/skills/TriggerEngine.js +142 -0
  645. package/dist/skills/TriggerEngine.js.map +1 -0
  646. package/dist/skills/coreSkills.d.ts +6 -0
  647. package/dist/skills/coreSkills.js +41 -0
  648. package/dist/skills/coreSkills.js.map +1 -0
  649. package/dist/skills/index.d.ts +10 -0
  650. package/dist/skills/index.js +12 -0
  651. package/dist/skills/index.js.map +1 -0
  652. package/dist/skills/interop/GStackInterop.d.ts +15 -0
  653. package/dist/skills/interop/GStackInterop.js +34 -0
  654. package/dist/skills/interop/GStackInterop.js.map +1 -0
  655. package/dist/skills/interop/OMCInterop.d.ts +15 -0
  656. package/dist/skills/interop/OMCInterop.js +34 -0
  657. package/dist/skills/interop/OMCInterop.js.map +1 -0
  658. package/dist/skills/routing/SkillGate.d.ts +12 -0
  659. package/dist/skills/routing/SkillGate.js +117 -0
  660. package/dist/skills/routing/SkillGate.js.map +1 -0
  661. package/dist/skills/routing/SkillPlanner.d.ts +8 -0
  662. package/dist/skills/routing/SkillPlanner.js +179 -0
  663. package/dist/skills/routing/SkillPlanner.js.map +1 -0
  664. package/dist/skills/routing/SkillPolicy.d.ts +6 -0
  665. package/dist/skills/routing/SkillPolicy.js +336 -0
  666. package/dist/skills/routing/SkillPolicy.js.map +1 -0
  667. package/dist/skills/routing/SkillRoutingTypes.d.ts +89 -0
  668. package/dist/skills/routing/SkillRoutingTypes.js +2 -0
  669. package/dist/skills/routing/SkillRoutingTypes.js.map +1 -0
  670. package/dist/skills/routing/TaskIntentClassifier.d.ts +6 -0
  671. package/dist/skills/routing/TaskIntentClassifier.js +79 -0
  672. package/dist/skills/routing/TaskIntentClassifier.js.map +1 -0
  673. package/dist/skills/routing/index.d.ts +5 -0
  674. package/dist/skills/routing/index.js +6 -0
  675. package/dist/skills/routing/index.js.map +1 -0
  676. package/dist/tasks/IssueTriageFSM.d.ts +26 -0
  677. package/dist/tasks/IssueTriageFSM.js +107 -0
  678. package/dist/tasks/IssueTriageFSM.js.map +1 -0
  679. package/dist/tasks/TaskEngine.d.ts +97 -0
  680. package/dist/tasks/TaskEngine.js +289 -0
  681. package/dist/tasks/TaskEngine.js.map +1 -0
  682. package/dist/testing/DiffTestSelector.d.ts +22 -0
  683. package/dist/testing/DiffTestSelector.js +114 -0
  684. package/dist/testing/DiffTestSelector.js.map +1 -0
  685. package/dist/testing/index.d.ts +1 -0
  686. package/dist/testing/index.js +3 -0
  687. package/dist/testing/index.js.map +1 -0
  688. package/dist/tools/CommandOutputCompressor.d.ts +28 -0
  689. package/dist/tools/CommandOutputCompressor.js +242 -0
  690. package/dist/tools/CommandOutputCompressor.js.map +1 -0
  691. package/dist/tools/CommandRunLedger.d.ts +77 -0
  692. package/dist/tools/CommandRunLedger.js +111 -0
  693. package/dist/tools/CommandRunLedger.js.map +1 -0
  694. package/dist/tools/RtkRuntime.d.ts +9 -0
  695. package/dist/tools/RtkRuntime.js +43 -0
  696. package/dist/tools/RtkRuntime.js.map +1 -0
  697. package/dist/tools/SafeCommandRunner.d.ts +16 -0
  698. package/dist/tools/SafeCommandRunner.js +83 -0
  699. package/dist/tools/SafeCommandRunner.js.map +1 -0
  700. package/dist/tools/ToolCapabilityRegistry.d.ts +51 -0
  701. package/dist/tools/ToolCapabilityRegistry.js +295 -0
  702. package/dist/tools/ToolCapabilityRegistry.js.map +1 -0
  703. package/dist/tools/ToolEvidenceGate.d.ts +39 -0
  704. package/dist/tools/ToolEvidenceGate.js +117 -0
  705. package/dist/tools/ToolEvidenceGate.js.map +1 -0
  706. package/dist/tools/ToolEvidenceStore.d.ts +58 -0
  707. package/dist/tools/ToolEvidenceStore.js +129 -0
  708. package/dist/tools/ToolEvidenceStore.js.map +1 -0
  709. package/dist/tools/ToolOrchestrator.d.ts +67 -0
  710. package/dist/tools/ToolOrchestrator.js +252 -0
  711. package/dist/tools/ToolOrchestrator.js.map +1 -0
  712. package/dist/tools/ToolPolicy.d.ts +33 -0
  713. package/dist/tools/ToolPolicy.js +172 -0
  714. package/dist/tools/ToolPolicy.js.map +1 -0
  715. package/dist/tools/index.d.ts +7 -0
  716. package/dist/tools/index.js +8 -0
  717. package/dist/tools/index.js.map +1 -0
  718. package/dist/tui/TuiDashboard.d.ts +3 -0
  719. package/dist/tui/TuiDashboard.js +120 -0
  720. package/dist/tui/TuiDashboard.js.map +1 -0
  721. package/dist/version.d.ts +3 -0
  722. package/dist/version.js +15 -0
  723. package/dist/version.js.map +1 -0
  724. package/dist/workflow/AdaptiveWorkflowRouter.d.ts +38 -0
  725. package/dist/workflow/AdaptiveWorkflowRouter.js +214 -0
  726. package/dist/workflow/AdaptiveWorkflowRouter.js.map +1 -0
  727. package/dist/workflow/CommitDiscipline.d.ts +68 -0
  728. package/dist/workflow/CommitDiscipline.js +328 -0
  729. package/dist/workflow/CommitDiscipline.js.map +1 -0
  730. package/dist/workflow/ContextGovernance.d.ts +51 -0
  731. package/dist/workflow/ContextGovernance.js +233 -0
  732. package/dist/workflow/ContextGovernance.js.map +1 -0
  733. package/dist/workflow/CrossRepoOrchestrator.d.ts +92 -0
  734. package/dist/workflow/CrossRepoOrchestrator.js +408 -0
  735. package/dist/workflow/CrossRepoOrchestrator.js.map +1 -0
  736. package/dist/workflow/DiagnosticLoop.d.ts +40 -0
  737. package/dist/workflow/DiagnosticLoop.js +105 -0
  738. package/dist/workflow/DiagnosticLoop.js.map +1 -0
  739. package/dist/workflow/EngineeringStandards.d.ts +212 -0
  740. package/dist/workflow/EngineeringStandards.js +1113 -0
  741. package/dist/workflow/EngineeringStandards.js.map +1 -0
  742. package/dist/workflow/EvidenceStore.d.ts +20 -0
  743. package/dist/workflow/EvidenceStore.js +48 -0
  744. package/dist/workflow/EvidenceStore.js.map +1 -0
  745. package/dist/workflow/EvolutionShadowPromoter.d.ts +46 -0
  746. package/dist/workflow/EvolutionShadowPromoter.js +73 -0
  747. package/dist/workflow/EvolutionShadowPromoter.js.map +1 -0
  748. package/dist/workflow/GateCatalog.d.ts +63 -0
  749. package/dist/workflow/GateCatalog.js +268 -0
  750. package/dist/workflow/GateCatalog.js.map +1 -0
  751. package/dist/workflow/GovernanceLock.d.ts +35 -0
  752. package/dist/workflow/GovernanceLock.js +58 -0
  753. package/dist/workflow/GovernanceLock.js.map +1 -0
  754. package/dist/workflow/GovernanceRoi.d.ts +52 -0
  755. package/dist/workflow/GovernanceRoi.js +204 -0
  756. package/dist/workflow/GovernanceRoi.js.map +1 -0
  757. package/dist/workflow/GovernanceTemplatePacks.d.ts +24 -0
  758. package/dist/workflow/GovernanceTemplatePacks.js +2134 -0
  759. package/dist/workflow/GovernanceTemplatePacks.js.map +1 -0
  760. package/dist/workflow/GovernanceTemplates.d.ts +19 -0
  761. package/dist/workflow/GovernanceTemplates.js +1291 -0
  762. package/dist/workflow/GovernanceTemplates.js.map +1 -0
  763. package/dist/workflow/McpGovernance.d.ts +63 -0
  764. package/dist/workflow/McpGovernance.js +198 -0
  765. package/dist/workflow/McpGovernance.js.map +1 -0
  766. package/dist/workflow/OutOfScopeStore.d.ts +37 -0
  767. package/dist/workflow/OutOfScopeStore.js +164 -0
  768. package/dist/workflow/OutOfScopeStore.js.map +1 -0
  769. package/dist/workflow/PhaseMarkerTracker.d.ts +63 -0
  770. package/dist/workflow/PhaseMarkerTracker.js +291 -0
  771. package/dist/workflow/PhaseMarkerTracker.js.map +1 -0
  772. package/dist/workflow/ResourceGovernance.d.ts +120 -0
  773. package/dist/workflow/ResourceGovernance.js +531 -0
  774. package/dist/workflow/ResourceGovernance.js.map +1 -0
  775. package/dist/workflow/ReviewAnalyzer.d.ts +80 -0
  776. package/dist/workflow/ReviewAnalyzer.js +438 -0
  777. package/dist/workflow/ReviewAnalyzer.js.map +1 -0
  778. package/dist/workflow/ReviewStore.d.ts +36 -0
  779. package/dist/workflow/ReviewStore.js +42 -0
  780. package/dist/workflow/ReviewStore.js.map +1 -0
  781. package/dist/workflow/SecurityAudit.d.ts +27 -0
  782. package/dist/workflow/SecurityAudit.js +294 -0
  783. package/dist/workflow/SecurityAudit.js.map +1 -0
  784. package/dist/workflow/SessionCoordinator.d.ts +103 -0
  785. package/dist/workflow/SessionCoordinator.js +401 -0
  786. package/dist/workflow/SessionCoordinator.js.map +1 -0
  787. package/dist/workflow/SessionPreamble.d.ts +19 -0
  788. package/dist/workflow/SessionPreamble.js +130 -0
  789. package/dist/workflow/SessionPreamble.js.map +1 -0
  790. package/dist/workflow/SessionStateTracker.d.ts +74 -0
  791. package/dist/workflow/SessionStateTracker.js +270 -0
  792. package/dist/workflow/SessionStateTracker.js.map +1 -0
  793. package/dist/workflow/ShipPipeline.d.ts +30 -0
  794. package/dist/workflow/ShipPipeline.js +366 -0
  795. package/dist/workflow/ShipPipeline.js.map +1 -0
  796. package/dist/workflow/TaskArtifactScaffolder.d.ts +69 -0
  797. package/dist/workflow/TaskArtifactScaffolder.js +333 -0
  798. package/dist/workflow/TaskArtifactScaffolder.js.map +1 -0
  799. package/dist/workflow/TaskDependencyGraph.d.ts +73 -0
  800. package/dist/workflow/TaskDependencyGraph.js +245 -0
  801. package/dist/workflow/TaskDependencyGraph.js.map +1 -0
  802. package/dist/workflow/TaskLevelDetector.d.ts +41 -0
  803. package/dist/workflow/TaskLevelDetector.js +219 -0
  804. package/dist/workflow/TaskLevelDetector.js.map +1 -0
  805. package/dist/workflow/TaskMetricsStore.d.ts +49 -0
  806. package/dist/workflow/TaskMetricsStore.js +149 -0
  807. package/dist/workflow/TaskMetricsStore.js.map +1 -0
  808. package/dist/workflow/TaskScoreEngine.d.ts +42 -0
  809. package/dist/workflow/TaskScoreEngine.js +181 -0
  810. package/dist/workflow/TaskScoreEngine.js.map +1 -0
  811. package/dist/workflow/TddLoop.d.ts +49 -0
  812. package/dist/workflow/TddLoop.js +78 -0
  813. package/dist/workflow/TddLoop.js.map +1 -0
  814. package/dist/workflow/UpgradeManager.d.ts +178 -0
  815. package/dist/workflow/UpgradeManager.js +665 -0
  816. package/dist/workflow/UpgradeManager.js.map +1 -0
  817. package/dist/workflow/VerificationCommands.d.ts +36 -0
  818. package/dist/workflow/VerificationCommands.js +123 -0
  819. package/dist/workflow/VerificationCommands.js.map +1 -0
  820. package/dist/workflow/VerificationProfile.d.ts +67 -0
  821. package/dist/workflow/VerificationProfile.js +241 -0
  822. package/dist/workflow/VerificationProfile.js.map +1 -0
  823. package/dist/workflow/VerificationSchema.d.ts +46 -0
  824. package/dist/workflow/VerificationSchema.js +97 -0
  825. package/dist/workflow/VerificationSchema.js.map +1 -0
  826. package/dist/workflow/WorkflowArtifactWriter.d.ts +113 -0
  827. package/dist/workflow/WorkflowArtifactWriter.js +242 -0
  828. package/dist/workflow/WorkflowArtifactWriter.js.map +1 -0
  829. package/dist/workflow/WorkflowEngine.d.ts +83 -0
  830. package/dist/workflow/WorkflowEngine.js +183 -0
  831. package/dist/workflow/WorkflowEngine.js.map +1 -0
  832. package/dist/workflow/WorkflowGuidance.d.ts +30 -0
  833. package/dist/workflow/WorkflowGuidance.js +204 -0
  834. package/dist/workflow/WorkflowGuidance.js.map +1 -0
  835. package/dist/workflow/WorkflowOpenTasks.d.ts +16 -0
  836. package/dist/workflow/WorkflowOpenTasks.js +37 -0
  837. package/dist/workflow/WorkflowOpenTasks.js.map +1 -0
  838. package/dist/workflow/WorkflowOrchestrator.d.ts +59 -0
  839. package/dist/workflow/WorkflowOrchestrator.js +326 -0
  840. package/dist/workflow/WorkflowOrchestrator.js.map +1 -0
  841. package/dist/workflow/WorkflowTemplates.d.ts +38 -0
  842. package/dist/workflow/WorkflowTemplates.js +371 -0
  843. package/dist/workflow/WorkflowTemplates.js.map +1 -0
  844. package/dist/workflow/WorkspaceLifecycle.d.ts +71 -0
  845. package/dist/workflow/WorkspaceLifecycle.js +401 -0
  846. package/dist/workflow/WorkspaceLifecycle.js.map +1 -0
  847. package/dist/workflow/WorkspacePolicy.d.ts +46 -0
  848. package/dist/workflow/WorkspacePolicy.js +141 -0
  849. package/dist/workflow/WorkspacePolicy.js.map +1 -0
  850. package/dist/workflow/WorkspaceSafety.d.ts +9 -0
  851. package/dist/workflow/WorkspaceSafety.js +49 -0
  852. package/dist/workflow/WorkspaceSafety.js.map +1 -0
  853. package/dist/workflow/WorkspaceTopology.d.ts +58 -0
  854. package/dist/workflow/WorkspaceTopology.js +176 -0
  855. package/dist/workflow/WorkspaceTopology.js.map +1 -0
  856. package/dist/workflow/autofix/AutoFixEngine.d.ts +37 -0
  857. package/dist/workflow/autofix/AutoFixEngine.js +169 -0
  858. package/dist/workflow/autofix/AutoFixEngine.js.map +1 -0
  859. package/dist/workflow/autonomous/AutonomousDevLoop.d.ts +88 -0
  860. package/dist/workflow/autonomous/AutonomousDevLoop.js +381 -0
  861. package/dist/workflow/autonomous/AutonomousDevLoop.js.map +1 -0
  862. package/dist/workflow/autonomous/BackgroundHunter.d.ts +74 -0
  863. package/dist/workflow/autonomous/BackgroundHunter.js +220 -0
  864. package/dist/workflow/autonomous/BackgroundHunter.js.map +1 -0
  865. package/dist/workflow/autonomous/WorklogManager.d.ts +50 -0
  866. package/dist/workflow/autonomous/WorklogManager.js +264 -0
  867. package/dist/workflow/autonomous/WorklogManager.js.map +1 -0
  868. package/dist/workflow/autonomous/index.d.ts +3 -0
  869. package/dist/workflow/autonomous/index.js +5 -0
  870. package/dist/workflow/autonomous/index.js.map +1 -0
  871. package/dist/workflow/cognitive/AmbiguityScorer.d.ts +17 -0
  872. package/dist/workflow/cognitive/AmbiguityScorer.js +107 -0
  873. package/dist/workflow/cognitive/AmbiguityScorer.js.map +1 -0
  874. package/dist/workflow/cognitive/ConsensusPlanner.d.ts +26 -0
  875. package/dist/workflow/cognitive/ConsensusPlanner.js +141 -0
  876. package/dist/workflow/cognitive/ConsensusPlanner.js.map +1 -0
  877. package/dist/workflow/cognitive/SocraticQuestioner.d.ts +33 -0
  878. package/dist/workflow/cognitive/SocraticQuestioner.js +276 -0
  879. package/dist/workflow/cognitive/SocraticQuestioner.js.map +1 -0
  880. package/dist/workflow/evolution/LessonExtractor.d.ts +90 -0
  881. package/dist/workflow/evolution/LessonExtractor.js +317 -0
  882. package/dist/workflow/evolution/LessonExtractor.js.map +1 -0
  883. package/dist/workflow/evolution/SelfImproveEngine.d.ts +156 -0
  884. package/dist/workflow/evolution/SelfImproveEngine.js +361 -0
  885. package/dist/workflow/evolution/SelfImproveEngine.js.map +1 -0
  886. package/dist/workflow/execution/RalphEngine.d.ts +54 -0
  887. package/dist/workflow/execution/RalphEngine.js +145 -0
  888. package/dist/workflow/execution/RalphEngine.js.map +1 -0
  889. package/dist/workflow/execution/UltraworkEngine.d.ts +43 -0
  890. package/dist/workflow/execution/UltraworkEngine.js +135 -0
  891. package/dist/workflow/execution/UltraworkEngine.js.map +1 -0
  892. package/dist/workflow/gates/EnhancedGates.d.ts +74 -0
  893. package/dist/workflow/gates/EnhancedGates.js +653 -0
  894. package/dist/workflow/gates/EnhancedGates.js.map +1 -0
  895. package/dist/workflow/gates/GateSystem.d.ts +180 -0
  896. package/dist/workflow/gates/GateSystem.js +1279 -0
  897. package/dist/workflow/gates/GateSystem.js.map +1 -0
  898. package/dist/workflow/gates/MetaGovernanceGates.d.ts +70 -0
  899. package/dist/workflow/gates/MetaGovernanceGates.js +617 -0
  900. package/dist/workflow/gates/MetaGovernanceGates.js.map +1 -0
  901. package/dist/workflow/gates/VisualGate.d.ts +41 -0
  902. package/dist/workflow/gates/VisualGate.js +174 -0
  903. package/dist/workflow/gates/VisualGate.js.map +1 -0
  904. package/dist/workflow/index.d.ts +45 -0
  905. package/dist/workflow/index.js +47 -0
  906. package/dist/workflow/index.js.map +1 -0
  907. package/dist/workflow/qa/E2ETestRunner.d.ts +102 -0
  908. package/dist/workflow/qa/E2ETestRunner.js +227 -0
  909. package/dist/workflow/qa/E2ETestRunner.js.map +1 -0
  910. package/dist/workflow/quality/HonestDelivery.d.ts +19 -0
  911. package/dist/workflow/quality/HonestDelivery.js +77 -0
  912. package/dist/workflow/quality/HonestDelivery.js.map +1 -0
  913. package/dist/workflow/quality/KarpathyEvaluator.d.ts +18 -0
  914. package/dist/workflow/quality/KarpathyEvaluator.js +76 -0
  915. package/dist/workflow/quality/KarpathyEvaluator.js.map +1 -0
  916. package/dist/workflow/types.d.ts +151 -0
  917. package/dist/workflow/types.js +4 -0
  918. package/dist/workflow/types.js.map +1 -0
  919. package/dist/workflows/DAGBuilder.d.ts +52 -0
  920. package/dist/workflows/DAGBuilder.js +169 -0
  921. package/dist/workflows/DAGBuilder.js.map +1 -0
  922. package/dist/workflows/GateParser.d.ts +55 -0
  923. package/dist/workflows/GateParser.js +73 -0
  924. package/dist/workflows/GateParser.js.map +1 -0
  925. package/dist/workflows/WorkflowExecutor.d.ts +56 -0
  926. package/dist/workflows/WorkflowExecutor.js +143 -0
  927. package/dist/workflows/WorkflowExecutor.js.map +1 -0
  928. package/dist/workflows/WorkflowOrchestrator.d.ts +81 -0
  929. package/dist/workflows/WorkflowOrchestrator.js +337 -0
  930. package/dist/workflows/WorkflowOrchestrator.js.map +1 -0
  931. package/dist/workflows/index.d.ts +2 -0
  932. package/dist/workflows/index.js +5 -0
  933. package/dist/workflows/index.js.map +1 -0
  934. package/dist/workflows/presets.d.ts +34 -0
  935. package/dist/workflows/presets.js +224 -0
  936. package/dist/workflows/presets.js.map +1 -0
  937. package/docs/README.md +105 -0
  938. package/docs/guides/DEVELOPMENT_WORKFLOW.md +99 -0
  939. package/docs/guides/GETTING_STARTED.md +93 -0
  940. package/docs/guides/MEDICAL_AGENT_OPERATING_GUIDE.md +61 -0
  941. package/docs/guides/MEDICAL_RESEARCH_DELIVERY.md +217 -0
  942. package/docs/guides/MIGRATION.md +119 -0
  943. package/docs/reference/cli.md +2921 -0
  944. package/docs/start/README.md +79 -0
  945. package/docs/start/agent-governance-demo.md +107 -0
  946. package/docs/start/artifact-lifecycle.md +326 -0
  947. package/docs/start/quickstart.md +191 -0
  948. package/docs/start/workflow-upgrade.md +198 -0
  949. package/docs/workflow/GATES_AND_SCORE.md +89 -0
  950. package/docs/workflow/PROMPT_OPTIMIZATION.md +44 -0
  951. package/docs/workflow/README.md +123 -0
  952. package/docs/workflow/node-library.md +52 -0
  953. package/docs/workflow/templates/api-contract.md +29 -0
  954. package/docs/workflow/templates/architecture-review.md +23 -0
  955. package/docs/workflow/templates/db-change-plan.md +20 -0
  956. package/docs/workflow/templates/docs-impact.md +17 -0
  957. package/docs/workflow/templates/e2e-plan.md +20 -0
  958. package/docs/workflow/templates/explore.md +16 -0
  959. package/docs/workflow/templates/github-actions-scale-preflight.yml +32 -0
  960. package/docs/workflow/templates/mini-prd.md +16 -0
  961. package/docs/workflow/templates/plan.md +37 -0
  962. package/docs/workflow/templates/pre-push-scale-preflight.sh +8 -0
  963. package/docs/workflow/templates/product-smoke.md +61 -0
  964. package/docs/workflow/templates/reality-check.md +28 -0
  965. package/docs/workflow/templates/resource-cleanup.md +17 -0
  966. package/docs/workflow/templates/resource-impact.md +25 -0
  967. package/docs/workflow/templates/review.md +12 -0
  968. package/docs/workflow/templates/runtime.md +23 -0
  969. package/docs/workflow/templates/security-review.md +26 -0
  970. package/docs/workflow/templates/skill-evidence.md +33 -0
  971. package/docs/workflow/templates/skill-plan.md +39 -0
  972. package/docs/workflow/templates/spec.md +17 -0
  973. package/docs/workflow/templates/standards-impact.md +28 -0
  974. package/docs/workflow/templates/summary.md +16 -0
  975. package/docs/workflow/templates/tasks.md +8 -0
  976. package/docs/workflow/templates/ui-spec.md +29 -0
  977. package/docs/workflow/templates/verification.md +20 -0
  978. package/docs/workflow/templates/visual-review.md +20 -0
  979. package/docs/zh/quickstart.md +108 -0
  980. package/examples/demo-projects/agent-governance-demo/CONTEXT.md +14 -0
  981. package/examples/demo-projects/agent-governance-demo/README.md +48 -0
  982. package/examples/demo-projects/agent-governance-demo/docs/CONTEXT-MAP.md +14 -0
  983. package/examples/demo-projects/agent-governance-demo/package.json +22 -0
  984. package/examples/demo-projects/agent-governance-demo/src/oauth-state.ts +39 -0
  985. package/examples/demo-projects/agent-governance-demo/tests/oauth-state.test.ts +52 -0
  986. package/mcp-configs/_INDEX.md +55 -0
  987. package/mcp-configs/context7/config.json +9 -0
  988. package/mcp-configs/fetch/config.json +9 -0
  989. package/mcp-configs/filesystem/config.json +9 -0
  990. package/mcp-configs/github/config.json +11 -0
  991. package/mcp-configs/memory/config.json +9 -0
  992. package/mcp-configs/neon/config.json +11 -0
  993. package/mcp-configs/playwright/config.json +9 -0
  994. package/mcp-configs/postgres/config.json +11 -0
  995. package/mcp-configs/puppeteer/config.json +9 -0
  996. package/mcp-configs/sequential-thinking/config.json +9 -0
  997. package/package.json +113 -0
  998. package/scripts/workflow/lib/gbrain-runtime.mjs +185 -0
  999. package/scripts/workflow/lib/report-output.mjs +107 -0
  1000. package/scripts/workflow/medscale-release-smoke.mjs +338 -0
  1001. package/scripts/workflow/provider-rehearsal.mjs +597 -0
  1002. package/scripts/workflow/setup-smoke.mjs +433 -0
  1003. package/target-research-platform/bridge_runner.py +310 -0
  1004. package/target-research-platform/config.yaml +148 -0
  1005. package/target-research-platform/data/immune_infiltration/ACC.csv +201 -0
  1006. package/target-research-platform/data/immune_infiltration/BLCA.csv +201 -0
  1007. package/target-research-platform/data/immune_infiltration/BRCA.csv +201 -0
  1008. package/target-research-platform/data/immune_infiltration/CESC.csv +201 -0
  1009. package/target-research-platform/data/immune_infiltration/CHOL.csv +201 -0
  1010. package/target-research-platform/data/immune_infiltration/COAD.csv +201 -0
  1011. package/target-research-platform/data/immune_infiltration/DLBC.csv +201 -0
  1012. package/target-research-platform/data/immune_infiltration/ESCA.csv +201 -0
  1013. package/target-research-platform/data/immune_infiltration/GBM.csv +201 -0
  1014. package/target-research-platform/data/immune_infiltration/HNSC.csv +201 -0
  1015. package/target-research-platform/data/immune_infiltration/KICH.csv +201 -0
  1016. package/target-research-platform/data/immune_infiltration/KIRC.csv +201 -0
  1017. package/target-research-platform/data/immune_infiltration/KIRP.csv +201 -0
  1018. package/target-research-platform/data/immune_infiltration/LAML.csv +201 -0
  1019. package/target-research-platform/data/immune_infiltration/LGG.csv +201 -0
  1020. package/target-research-platform/data/immune_infiltration/LIHC.csv +201 -0
  1021. package/target-research-platform/data/immune_infiltration/LUAD.csv +201 -0
  1022. package/target-research-platform/data/immune_infiltration/LUSC.csv +201 -0
  1023. package/target-research-platform/data/immune_infiltration/MESO.csv +201 -0
  1024. package/target-research-platform/data/immune_infiltration/OV.csv +201 -0
  1025. package/target-research-platform/data/immune_infiltration/PAAD.csv +201 -0
  1026. package/target-research-platform/data/immune_infiltration/PCPG.csv +201 -0
  1027. package/target-research-platform/data/immune_infiltration/PRAD.csv +201 -0
  1028. package/target-research-platform/data/immune_infiltration/READ.csv +201 -0
  1029. package/target-research-platform/data/immune_infiltration/SARC.csv +201 -0
  1030. package/target-research-platform/data/immune_infiltration/SKCM.csv +201 -0
  1031. package/target-research-platform/data/immune_infiltration/STAD.csv +201 -0
  1032. package/target-research-platform/data/immune_infiltration/TGCT.csv +201 -0
  1033. package/target-research-platform/data/immune_infiltration/THCA.csv +201 -0
  1034. package/target-research-platform/data/immune_infiltration/THYM.csv +201 -0
  1035. package/target-research-platform/data/immune_infiltration/UCEC.csv +201 -0
  1036. package/target-research-platform/data/immune_infiltration/UCS.csv +201 -0
  1037. package/target-research-platform/data/immune_infiltration/UVM.csv +201 -0
  1038. package/target-research-platform/docs/JSON_SCHEMA.md +352 -0
  1039. package/target-research-platform/docs/PROGRESS_2026-06-09.md +140 -0
  1040. package/target-research-platform/main.py +755 -0
  1041. package/target-research-platform/pyproject.toml +54 -0
  1042. package/target-research-platform/requirements.txt +9 -0
  1043. package/target-research-platform/run_dashboard.py +5 -0
  1044. package/target-research-platform/run_real_medical_workflow.py +28 -0
  1045. package/target-research-platform/scripts/demo_report.py +481 -0
  1046. package/target-research-platform/scripts/generate_evidence_package.py +75 -0
  1047. package/target-research-platform/scripts/prepare_immune_data.py +386 -0
  1048. package/target-research-platform/src/__init__.py +4 -0
  1049. package/target-research-platform/src/analysis/__init__.py +3 -0
  1050. package/target-research-platform/src/analysis/stage1_expression/__init__.py +12 -0
  1051. package/target-research-platform/src/analysis/stage1_expression/immune_correlation.py +366 -0
  1052. package/target-research-platform/src/analysis/stage1_expression/pipeline.py +579 -0
  1053. package/target-research-platform/src/analysis/stage1_expression/survival_analysis.py +382 -0
  1054. package/target-research-platform/src/analysis/stage2_screening/__init__.py +12 -0
  1055. package/target-research-platform/src/analysis/stage2_screening/differential_expression.py +451 -0
  1056. package/target-research-platform/src/analysis/stage2_screening/druggability_score.py +477 -0
  1057. package/target-research-platform/src/analysis/stage2_screening/pipeline.py +822 -0
  1058. package/target-research-platform/src/analysis/stage3_deep_research/__init__.py +12 -0
  1059. package/target-research-platform/src/analysis/stage3_deep_research/competitive_landscape.py +479 -0
  1060. package/target-research-platform/src/analysis/stage3_deep_research/pipeline.py +763 -0
  1061. package/target-research-platform/src/analysis/stage3_deep_research/target_function.py +290 -0
  1062. package/target-research-platform/src/analysis/stage4_business/__init__.py +12 -0
  1063. package/target-research-platform/src/analysis/stage4_business/business_plan.py +816 -0
  1064. package/target-research-platform/src/analysis/stage4_business/milestone_planner.py +844 -0
  1065. package/target-research-platform/src/analysis/stage4_business/pipeline.py +284 -0
  1066. package/target-research-platform/src/api_clients/__init__.py +29 -0
  1067. package/target-research-platform/src/api_clients/aminer_client.py +163 -0
  1068. package/target-research-platform/src/api_clients/base_client.py +186 -0
  1069. package/target-research-platform/src/api_clients/clinicaltrials_client.py +411 -0
  1070. package/target-research-platform/src/api_clients/geo_client.py +1420 -0
  1071. package/target-research-platform/src/api_clients/gtex_client.py +209 -0
  1072. package/target-research-platform/src/api_clients/hpa_client.py +170 -0
  1073. package/target-research-platform/src/api_clients/immune_data_manager.py +247 -0
  1074. package/target-research-platform/src/api_clients/openalex_client.py +86 -0
  1075. package/target-research-platform/src/api_clients/opentargets_client.py +558 -0
  1076. package/target-research-platform/src/api_clients/pubmed_client.py +361 -0
  1077. package/target-research-platform/src/api_clients/tcga_client.py +712 -0
  1078. package/target-research-platform/src/api_clients/timer_client.py +169 -0
  1079. package/target-research-platform/src/dashboard/app.py +2283 -0
  1080. package/target-research-platform/src/dashboard/deliverables.py +710 -0
  1081. package/target-research-platform/src/dashboard/static/artifactPreview.js +96 -0
  1082. package/target-research-platform/src/dashboard/static/index.html +1292 -0
  1083. package/target-research-platform/src/dashboard/status_tracker.py +237 -0
  1084. package/target-research-platform/src/output/__init__.py +42 -0
  1085. package/target-research-platform/src/output/agent_llm_provider.py +171 -0
  1086. package/target-research-platform/src/output/chart_generator.py +550 -0
  1087. package/target-research-platform/src/output/data_exporter.py +215 -0
  1088. package/target-research-platform/src/output/delivery_packager.py +791 -0
  1089. package/target-research-platform/src/output/evidence_package.py +230 -0
  1090. package/target-research-platform/src/output/journal_templates.py +193 -0
  1091. package/target-research-platform/src/output/literature_enricher.py +395 -0
  1092. package/target-research-platform/src/output/literature_reviewer.py +420 -0
  1093. package/target-research-platform/src/output/manuscript_fact_checker.py +279 -0
  1094. package/target-research-platform/src/output/manuscript_generator.py +1189 -0
  1095. package/target-research-platform/src/output/manuscript_quality.py +401 -0
  1096. package/target-research-platform/src/output/medical_skills_bridge.py +140 -0
  1097. package/target-research-platform/src/output/report_generator.py +542 -0
  1098. package/target-research-platform/src/output/usage_envelope.py +193 -0
  1099. package/target-research-platform/src/utils/__init__.py +1 -0
  1100. package/target-research-platform/src/utils/config.py +125 -0
  1101. package/target-research-platform/src/utils/logger.py +71 -0
  1102. package/target-research-platform/src/validators/__init__.py +13 -0
  1103. package/target-research-platform/src/validators/cross_validator.py +394 -0
  1104. package/target-research-platform/src/validators/data_provenance.py +298 -0
@@ -0,0 +1,3173 @@
1
+ // MedSCALE Target Research CLI
2
+ // 医学研究者 + Agent 的原生交付入口
3
+ import { defineCommand } from 'citty';
4
+ import { spawn, spawnSync } from 'node:child_process';
5
+ import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
6
+ import { join, relative, resolve } from 'node:path';
7
+ import { PythonBridge } from '../bridge/PythonBridge.js';
8
+ import { STAGE_LABELS } from '../bridge/types.js';
9
+ import { readMedicalWorkflowDashboard } from '../dashboard/MedicalWorkflowData.js';
10
+ import { normalizeLanguage } from '../i18n/Language.js';
11
+ import { importMemoryProviderKnowledge, MemoryBrain, renderMemoryLearningCandidateMarkdown, reviewMemoryLearningCandidate, } from '../memory/index.js';
12
+ import { buildModelUsageInput, ModelUsageLedger, } from '../runtime/ModelUsageLedger.js';
13
+ const PROJECT_DIR = process.env.MEDSCALE_PROJECT_DIR ?? process.env.SCALE_PROJECT_DIR ?? process.cwd();
14
+ const DELIVERY_MEMORY_IMPORT_ROLES = [
15
+ 'manuscript_markdown',
16
+ 'manuscript_zhongliu',
17
+ 'manuscript_meta',
18
+ 'manuscript_quality',
19
+ 'manuscript_fact_check',
20
+ 'literature_evidence_pack',
21
+ 'agent_review_tasks',
22
+ 'agent_reviews',
23
+ 'delivery_manifest',
24
+ ];
25
+ /** 解析 target-research-platform 目录(支持从仓库根或子目录运行) */
26
+ export function resolveTargetPlatform(projectDir = PROJECT_DIR) {
27
+ const candidates = [
28
+ resolve(projectDir, 'target-research-platform'),
29
+ resolve(projectDir, '..', 'target-research-platform'),
30
+ resolve(projectDir, '../..', 'target-research-platform'),
31
+ ];
32
+ for (const platformDir of candidates) {
33
+ const mainPy = join(platformDir, 'main.py');
34
+ if (existsSync(mainPy)) {
35
+ return {
36
+ projectDir: resolve(projectDir),
37
+ platformDir,
38
+ mainPy,
39
+ };
40
+ }
41
+ }
42
+ return null;
43
+ }
44
+ function parseCancerList(raw) {
45
+ if (!raw?.trim())
46
+ return ['BRCA'];
47
+ return raw.split(/[,\s]+/).map(item => item.trim()).filter(Boolean);
48
+ }
49
+ function normalizeTargetToken(value) {
50
+ return value.toLowerCase().replace(/[^a-z0-9]+/g, ' ').trim();
51
+ }
52
+ function resolveTargetOutputDir(platform, output) {
53
+ return resolve(platform.platformDir, String(output ?? './output'));
54
+ }
55
+ function readJsonFile(path) {
56
+ try {
57
+ const parsed = JSON.parse(readFileSync(path, 'utf-8').replace(/^\uFEFF/, ''));
58
+ return parsed && typeof parsed === 'object' && !Array.isArray(parsed)
59
+ ? parsed
60
+ : null;
61
+ }
62
+ catch {
63
+ return null;
64
+ }
65
+ }
66
+ function readWorkspaceJson(root, relativePath) {
67
+ return readJsonFile(join(root, ...relativePath.split('/')));
68
+ }
69
+ function resolveTargetWorkspaceRoot(projectDir) {
70
+ const candidates = [
71
+ resolve(projectDir),
72
+ resolve(projectDir, '..'),
73
+ resolve(projectDir, '../..'),
74
+ ];
75
+ for (const candidate of candidates) {
76
+ if (existsSync(join(candidate, '.scale')))
77
+ return candidate;
78
+ }
79
+ for (const candidate of candidates) {
80
+ if (existsSync(join(candidate, 'package.json')) && existsSync(join(candidate, 'target-research-platform'))) {
81
+ return candidate;
82
+ }
83
+ }
84
+ return resolve(projectDir);
85
+ }
86
+ function pathEntries(env) {
87
+ const value = env.PATH ?? env.Path ?? '';
88
+ return value.split(process.platform === 'win32' ? ';' : ':').filter(Boolean);
89
+ }
90
+ function commandExtensions(command, env) {
91
+ if (command.includes('.'))
92
+ return [''];
93
+ if (process.platform !== 'win32')
94
+ return [''];
95
+ const pathext = String(env.PATHEXT ?? '.COM;.EXE;.BAT;.CMD;.PS1')
96
+ .split(';')
97
+ .map(item => item.trim())
98
+ .filter(Boolean);
99
+ return ['', ...new Set([...pathext, '.PS1'].map(item => item.startsWith('.') ? item : `.${item}`))];
100
+ }
101
+ function findCommandPath(command, env = process.env) {
102
+ const binary = command.split(/\s+/)[0];
103
+ for (const dir of pathEntries(env)) {
104
+ for (const ext of commandExtensions(binary, env)) {
105
+ const candidate = join(dir, `${binary}${ext}`);
106
+ if (existsSync(candidate))
107
+ return candidate;
108
+ }
109
+ }
110
+ return null;
111
+ }
112
+ function runtimeCard(id, title, state, statusLabel, summary, details, nextAction, required) {
113
+ return { id, title, state, statusLabel, summary, details, nextAction, required };
114
+ }
115
+ function targetScaleDir(root) {
116
+ return join(root, '.scale');
117
+ }
118
+ function targetUsagePath(root) {
119
+ return join(targetScaleDir(root), 'model-usage', 'usage.jsonl');
120
+ }
121
+ function normalizeSinceDaysValue(value, fallback = 30) {
122
+ if (value === undefined || value === null || value === '')
123
+ return fallback;
124
+ const raw = String(value).trim().toLowerCase();
125
+ if (raw === 'all' || raw === 'none' || raw === '0')
126
+ return undefined;
127
+ const parsed = Number(raw.replace(/d$/, ''));
128
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
129
+ }
130
+ function medicalUsageLane(record) {
131
+ const metadata = record.metadata ?? {};
132
+ const explicit = typeof metadata.medical_lane === 'string'
133
+ ? metadata.medical_lane
134
+ : typeof metadata.phase === 'string'
135
+ ? metadata.phase
136
+ : typeof metadata.gate === 'string'
137
+ ? metadata.gate
138
+ : '';
139
+ const haystack = [
140
+ explicit,
141
+ record.taskId ?? '',
142
+ record.sessionId ?? '',
143
+ record.model ?? '',
144
+ ].join(' ').toLowerCase();
145
+ if (/literature|pubmed|openalex|文献|检索/.test(haystack))
146
+ return 'literature';
147
+ if (/fact|claim|事实|核查/.test(haystack))
148
+ return 'fact_check';
149
+ if (/package|audit|delivery|zip|交付|审计/.test(haystack))
150
+ return 'package_audit';
151
+ if (/memory|gbrain|learning|candidate|记忆|沉淀/.test(haystack))
152
+ return 'memory';
153
+ if (/agent|review|handoff|peer|评审|协作/.test(haystack))
154
+ return 'agent_review';
155
+ return 'workflow';
156
+ }
157
+ function medicalLaneLabel(lane) {
158
+ const labels = {
159
+ literature: 'Literature review',
160
+ fact_check: 'Medical fact check',
161
+ package_audit: 'Package audit',
162
+ memory: 'Memory settlement',
163
+ agent_review: 'Agent review',
164
+ workflow: 'Workflow',
165
+ };
166
+ return labels[lane] ?? lane;
167
+ }
168
+ function buildMedicalUsageLanes(records) {
169
+ const lanes = new Map();
170
+ for (const record of records) {
171
+ const key = medicalUsageLane(record);
172
+ const lane = lanes.get(key) ?? {
173
+ key,
174
+ label: medicalLaneLabel(key),
175
+ records: 0,
176
+ totalTokens: 0,
177
+ cacheSavingsTokens: 0,
178
+ };
179
+ lane.records += 1;
180
+ lane.totalTokens += record.totalTokens;
181
+ lane.cacheSavingsTokens += record.cacheSavingsTokens;
182
+ if (record.estimatedCostUsd !== undefined) {
183
+ lane.estimatedCostUsd = Math.round(((lane.estimatedCostUsd ?? 0) + record.estimatedCostUsd) * 1_000_000) / 1_000_000;
184
+ }
185
+ lanes.set(key, lane);
186
+ }
187
+ return [...lanes.values()].sort((left, right) => right.totalTokens - left.totalTokens || left.key.localeCompare(right.key));
188
+ }
189
+ export function buildTargetTokenCostReport(options = {}) {
190
+ const root = resolveTargetWorkspaceRoot(options.projectDir ?? PROJECT_DIR);
191
+ const sinceDays = options.day || options.since || options.until
192
+ ? undefined
193
+ : normalizeSinceDaysValue(options.sinceDays, 30);
194
+ const since = options.since
195
+ ?? (sinceDays ? new Date(Date.now() - sinceDays * 24 * 60 * 60 * 1000).toISOString() : undefined);
196
+ const report = new ModelUsageLedger(targetScaleDir(root)).report({
197
+ day: options.day,
198
+ since,
199
+ until: options.until,
200
+ provider: options.provider,
201
+ model: options.model,
202
+ taskId: options.taskId,
203
+ sessionId: options.sessionId,
204
+ limit: options.limit,
205
+ });
206
+ const status = report.summary.totalRecords > 0 ? 'ready' : 'pending';
207
+ return {
208
+ schema: 'medscale.token_cost.v1',
209
+ status,
210
+ generatedAt: report.generatedAt,
211
+ workspaceRoot: root,
212
+ usagePath: targetUsagePath(root),
213
+ window: {
214
+ day: options.day,
215
+ since,
216
+ until: options.until,
217
+ sinceDays,
218
+ },
219
+ summary: report.summary,
220
+ byProvider: report.byProvider,
221
+ byModel: report.byModel,
222
+ byTask: report.byTask,
223
+ byDay: report.byDay,
224
+ byMedicalLane: buildMedicalUsageLanes(report.records),
225
+ records: report.records,
226
+ recommendations: status === 'ready'
227
+ ? ['Review high-token medical lanes before expert handoff and package delivery.']
228
+ : [
229
+ 'Record model usage for literature review, fact check, package audit, agent review, and memory settlement.',
230
+ 'Use `medscale token record --provider <name> --usage-json <json>` after model calls.',
231
+ ],
232
+ };
233
+ }
234
+ const TOKEN_USAGE_FIELD_PATHS = [
235
+ ['input_tokens'],
236
+ ['prompt_tokens'],
237
+ ['output_tokens'],
238
+ ['completion_tokens'],
239
+ ['cache_creation_input_tokens'],
240
+ ['cache_read_input_tokens'],
241
+ ['cached_tokens'],
242
+ ['inputTokens'],
243
+ ['promptTokens'],
244
+ ['outputTokens'],
245
+ ['completionTokens'],
246
+ ['cacheCreationInputTokens'],
247
+ ['cacheReadInputTokens'],
248
+ ['cachedTokens'],
249
+ ['prompt_tokens_details', 'cached_tokens'],
250
+ ['input_tokens_details', 'cached_tokens'],
251
+ ['promptTokensDetails', 'cachedTokens'],
252
+ ['inputTokensDetails', 'cachedTokens'],
253
+ ];
254
+ export function ingestTargetTokenUsage(options = {}) {
255
+ const root = resolveTargetWorkspaceRoot(options.projectDir ?? PROJECT_DIR);
256
+ const resolved = resolveTargetTokenIngestFiles(root, options);
257
+ const ledger = new ModelUsageLedger(targetScaleDir(root));
258
+ const seen = new Set(ledger
259
+ .list({ limit: Number.MAX_SAFE_INTEGER })
260
+ .map(record => typeof record.metadata?.ingest_key === 'string' ? record.metadata.ingest_key : '')
261
+ .filter(Boolean));
262
+ const defaultProvider = stringValue(options.provider);
263
+ const sources = [];
264
+ const records = [];
265
+ const warnings = [...resolved.warnings];
266
+ let duplicates = 0;
267
+ let skipped = 0;
268
+ for (const filePath of resolved.files) {
269
+ const payload = readJsonFile(filePath);
270
+ if (!payload) {
271
+ skipped += 1;
272
+ warnings.push(`Cannot read JSON token usage artifact: ${filePath}`);
273
+ continue;
274
+ }
275
+ const candidates = collectTargetTokenUsageCandidates(filePath, payload);
276
+ if (candidates.length === 0) {
277
+ continue;
278
+ }
279
+ for (const candidate of candidates) {
280
+ const provider = firstString(candidate.payload, ['provider', 'model_provider', 'llm_provider', 'provider_id', 'vendor']) ?? defaultProvider;
281
+ const model = firstString(candidate.payload, ['model', 'model_id', 'model_name', 'llm_model', 'deployment']);
282
+ const usageId = firstString(candidate.payload, ['usage_id', 'usageId']);
283
+ const medicalLane = inferTokenUsageLane(filePath, candidate.pointer, candidate.payload);
284
+ const relativePath = normalizedRelativePath(root, filePath);
285
+ const sourceRole = inferTokenUsageSourceRole(filePath, candidate.payload);
286
+ if (!provider) {
287
+ skipped += 1;
288
+ const warning = `Token usage candidate skipped because provider is missing: ${relativePath}${candidate.pointer || '/'}`;
289
+ warnings.push(warning);
290
+ sources.push({
291
+ file: filePath,
292
+ pointer: candidate.pointer || '/',
293
+ status: 'skipped',
294
+ medicalLane,
295
+ provider: null,
296
+ model,
297
+ totalTokens: 0,
298
+ warning,
299
+ });
300
+ continue;
301
+ }
302
+ const baseInput = buildModelUsageInput({
303
+ provider,
304
+ model,
305
+ taskId: firstString(candidate.payload, ['task_id', 'taskId', 'task', 'phase', 'role']) ?? `medscale-token-ingest-${medicalLane}`,
306
+ sessionId: firstString(candidate.payload, ['session_id', 'sessionId', 'session']),
307
+ estimatedCostUsd: firstNumber(candidate.payload, [
308
+ 'estimatedCostUsd',
309
+ 'estimated_cost_usd',
310
+ 'model_cost_usd',
311
+ 'llm_cost_usd',
312
+ 'cost_usd',
313
+ ]),
314
+ timestamp: firstString(candidate.payload, ['timestamp', 'created_at', 'createdAt', 'generated_at', 'generatedAt']),
315
+ usagePayload: candidate.payload,
316
+ });
317
+ const usageMagnitude = (baseInput.inputTokens ?? 0)
318
+ + (baseInput.outputTokens ?? 0)
319
+ + (baseInput.cacheCreationInputTokens ?? 0)
320
+ + (baseInput.cacheReadInputTokens ?? 0)
321
+ + (baseInput.cachedTokens ?? 0);
322
+ if (usageMagnitude <= 0) {
323
+ skipped += 1;
324
+ const warning = `Token usage candidate did not contain positive token counts: ${relativePath}${candidate.pointer || '/'}`;
325
+ warnings.push(warning);
326
+ sources.push({
327
+ file: filePath,
328
+ pointer: candidate.pointer || '/',
329
+ status: 'skipped',
330
+ medicalLane,
331
+ provider,
332
+ model,
333
+ totalTokens: 0,
334
+ warning,
335
+ });
336
+ continue;
337
+ }
338
+ const ingestKey = usageId
339
+ ? `usage_id:${usageId}`
340
+ : [
341
+ relativePath,
342
+ candidate.pointer || '/',
343
+ provider,
344
+ model ?? '',
345
+ baseInput.inputTokens ?? 0,
346
+ baseInput.outputTokens ?? 0,
347
+ baseInput.cacheCreationInputTokens ?? 0,
348
+ baseInput.cacheReadInputTokens ?? 0,
349
+ baseInput.cachedTokens ?? 0,
350
+ baseInput.estimatedCostUsd ?? '',
351
+ ].join('|');
352
+ if (seen.has(ingestKey)) {
353
+ duplicates += 1;
354
+ sources.push({
355
+ file: filePath,
356
+ pointer: candidate.pointer || '/',
357
+ status: 'duplicate',
358
+ medicalLane,
359
+ provider,
360
+ model,
361
+ totalTokens: (baseInput.inputTokens ?? 0) + (baseInput.outputTokens ?? 0),
362
+ });
363
+ continue;
364
+ }
365
+ const metadata = {
366
+ source_path: relativePath,
367
+ source_pointer: candidate.pointer || '/',
368
+ source_role: sourceRole,
369
+ medical_lane: medicalLane,
370
+ ingest_key: ingestKey,
371
+ };
372
+ if (options.target)
373
+ metadata.target = String(options.target);
374
+ if (options.disease)
375
+ metadata.disease = String(options.disease);
376
+ if (usageId)
377
+ metadata.usage_id = usageId;
378
+ const phase = firstString(candidate.payload, ['phase', 'gate', 'role']);
379
+ if (phase)
380
+ metadata.phase = phase;
381
+ const record = ledger.record({
382
+ ...baseInput,
383
+ metadata,
384
+ });
385
+ seen.add(ingestKey);
386
+ records.push(record);
387
+ sources.push({
388
+ file: filePath,
389
+ pointer: candidate.pointer || '/',
390
+ status: 'recorded',
391
+ medicalLane,
392
+ provider,
393
+ model,
394
+ totalTokens: record.totalTokens,
395
+ recordId: record.id,
396
+ });
397
+ }
398
+ }
399
+ const tokenCost = buildTargetTokenCostReport({
400
+ projectDir: root,
401
+ sinceDays: undefined,
402
+ limit: options.limit ?? 20,
403
+ });
404
+ const recorded = records.length;
405
+ const status = recorded > 0 || duplicates > 0
406
+ ? 'ready'
407
+ : warnings.length > 0
408
+ ? 'warning'
409
+ : 'pending';
410
+ return {
411
+ schema: 'medscale.token_ingest.v1',
412
+ status,
413
+ ok: recorded > 0 || duplicates > 0,
414
+ generatedAt: new Date().toISOString(),
415
+ workspaceRoot: root,
416
+ usagePath: targetUsagePath(root),
417
+ scannedFiles: resolved.files,
418
+ recorded,
419
+ duplicates,
420
+ skipped,
421
+ warnings: uniqueStrings(warnings),
422
+ sources,
423
+ records,
424
+ tokenCost,
425
+ };
426
+ }
427
+ function resolveTargetTokenIngestFiles(root, options) {
428
+ const warnings = [];
429
+ const explicitFiles = splitTokenIngestFiles(options.files ?? []);
430
+ if (explicitFiles.length > 0) {
431
+ const files = explicitFiles.map(file => resolveTokenIngestFilePath(root, file));
432
+ return {
433
+ files: uniqueStrings(files.filter(file => {
434
+ if (existsSync(file))
435
+ return true;
436
+ warnings.push(`Token usage artifact does not exist: ${file}`);
437
+ return false;
438
+ })),
439
+ warnings,
440
+ };
441
+ }
442
+ const target = stringValue(options.target);
443
+ const disease = stringValue(options.disease);
444
+ if (target && disease) {
445
+ const plan = resolveTargetMemorySeedPlan({
446
+ projectDir: root,
447
+ output: options.output,
448
+ target,
449
+ disease,
450
+ });
451
+ return {
452
+ files: uniqueStrings([plan.manifestPath, ...plan.sourceFiles].filter((file) => Boolean(file))),
453
+ warnings: [...plan.warnings],
454
+ };
455
+ }
456
+ const platform = resolveTargetPlatform(root);
457
+ if (!platform) {
458
+ return {
459
+ files: [],
460
+ warnings: ['target-research-platform not found; pass --file or run from a MedSCALE workspace.'],
461
+ };
462
+ }
463
+ const manuscriptsDir = join(resolveTargetOutputDir(platform, options.output), 'manuscripts');
464
+ if (!existsSync(manuscriptsDir)) {
465
+ return {
466
+ files: [],
467
+ warnings: ['Manuscripts output directory does not exist yet; pass --file or run a medical workflow first.'],
468
+ };
469
+ }
470
+ return {
471
+ files: readdirSync(manuscriptsDir)
472
+ .filter(name => name.endsWith('.json'))
473
+ .map(name => join(manuscriptsDir, name)),
474
+ warnings,
475
+ };
476
+ }
477
+ function splitTokenIngestFiles(values) {
478
+ return values
479
+ .flatMap(value => String(value).split(/[;,]/g))
480
+ .map(value => value.trim())
481
+ .filter(Boolean);
482
+ }
483
+ function resolveTokenIngestFilePath(root, file) {
484
+ const cwdPath = resolve(file);
485
+ return existsSync(cwdPath) ? cwdPath : resolve(root, file);
486
+ }
487
+ function collectTargetTokenUsageCandidates(filePath, payload) {
488
+ const candidates = [];
489
+ const visit = (value, pointer) => {
490
+ const record = asRecord(value);
491
+ if (record) {
492
+ if (hasKnownTokenUsagePayload(record)) {
493
+ candidates.push({ filePath, pointer, payload: record });
494
+ return;
495
+ }
496
+ for (const [key, item] of Object.entries(record)) {
497
+ visit(item, jsonPointerChild(pointer, key));
498
+ }
499
+ return;
500
+ }
501
+ if (Array.isArray(value)) {
502
+ value.forEach((item, index) => visit(item, jsonPointerChild(pointer, String(index))));
503
+ }
504
+ };
505
+ visit(payload, '');
506
+ return candidates;
507
+ }
508
+ function hasKnownTokenUsagePayload(value) {
509
+ const response = asRecord(value.response);
510
+ const result = asRecord(value.result);
511
+ const data = asRecord(value.data);
512
+ const candidates = [
513
+ value,
514
+ asRecord(value.usage),
515
+ response ? asRecord(response.usage) : null,
516
+ result ? asRecord(result.usage) : null,
517
+ data ? asRecord(data.usage) : null,
518
+ ].filter((item) => Boolean(item));
519
+ return candidates.some(candidate => TOKEN_USAGE_FIELD_PATHS.some(path => numberAtPath(candidate, path) !== null));
520
+ }
521
+ function numberAtPath(record, path) {
522
+ let current = record;
523
+ for (const key of path) {
524
+ const currentRecord = asRecord(current);
525
+ if (!currentRecord || !(key in currentRecord))
526
+ return null;
527
+ current = currentRecord[key];
528
+ }
529
+ return toNumber(current);
530
+ }
531
+ function firstString(record, keys) {
532
+ for (const key of keys) {
533
+ const value = record[key];
534
+ if (typeof value === 'string' && value.trim())
535
+ return value.trim();
536
+ if (typeof value === 'number' && Number.isFinite(value))
537
+ return String(value);
538
+ }
539
+ return undefined;
540
+ }
541
+ function firstNumber(record, keys) {
542
+ for (const key of keys) {
543
+ const value = toNumber(record[key]);
544
+ if (value !== null && value >= 0)
545
+ return value;
546
+ }
547
+ return undefined;
548
+ }
549
+ function stringValue(value) {
550
+ return typeof value === 'string' && value.trim() ? value.trim() : undefined;
551
+ }
552
+ function jsonPointerChild(pointer, key) {
553
+ const encoded = key.replace(/~/g, '~0').replace(/\//g, '~1');
554
+ return pointer ? `${pointer}/${encoded}` : `/${encoded}`;
555
+ }
556
+ function normalizedRelativePath(root, filePath) {
557
+ return relative(root, filePath).replace(/\\/g, '/');
558
+ }
559
+ function inferTokenUsageLane(filePath, pointer, payload) {
560
+ const haystack = [
561
+ filePath,
562
+ pointer,
563
+ firstString(payload, ['medical_lane', 'medicalLane', 'lane', 'source_role', 'sourceRole', 'phase', 'gate', 'role', 'task_id', 'taskId']) ?? '',
564
+ ].join(' ').toLowerCase();
565
+ if (/literature|pubmed|openalex|evidence/.test(haystack))
566
+ return 'literature';
567
+ if (/fact|claim|check|verification/.test(haystack))
568
+ return 'fact_check';
569
+ if (/package|audit|delivery|manifest|zip/.test(haystack))
570
+ return 'package_audit';
571
+ if (/memory|gbrain|learning|candidate/.test(haystack))
572
+ return 'memory';
573
+ if (/agent|review|handoff|peer/.test(haystack))
574
+ return 'agent_review';
575
+ return 'workflow';
576
+ }
577
+ function inferTokenUsageSourceRole(filePath, payload) {
578
+ const explicit = firstString(payload, ['source_role', 'sourceRole', 'role', 'phase', 'gate']);
579
+ if (explicit)
580
+ return explicit;
581
+ const name = filePath.replace(/\\/g, '/').split('/').pop()?.toLowerCase() ?? '';
582
+ if (name.includes('fact'))
583
+ return 'manuscript_fact_check';
584
+ if (name.includes('quality'))
585
+ return 'manuscript_quality';
586
+ if (name.includes('agent_reviews'))
587
+ return 'agent_reviews';
588
+ if (name.includes('review_tasks'))
589
+ return 'agent_review_tasks';
590
+ if (name.includes('memory_seed'))
591
+ return 'memory_seed';
592
+ if (name.includes('learning_candidate'))
593
+ return 'learning_candidate';
594
+ if (name.includes('delivery_manifest'))
595
+ return 'delivery_manifest';
596
+ return 'token_usage_artifact';
597
+ }
598
+ function enabledProvider(config, id) {
599
+ const providers = Array.isArray(config?.providers) ? config.providers : [];
600
+ const found = providers.find(provider => {
601
+ return provider && typeof provider === 'object' && !Array.isArray(provider) && provider.id === id;
602
+ });
603
+ return found && typeof found === 'object' && !Array.isArray(found) ? found : {};
604
+ }
605
+ function buildRuntimeMemoryCard(root, env) {
606
+ const config = readWorkspaceJson(root, '.scale/memory-providers.json');
607
+ const routing = config?.routing && typeof config.routing === 'object' && !Array.isArray(config.routing)
608
+ ? config.routing
609
+ : {};
610
+ const defaultOrder = Array.isArray(routing.defaultOrder) ? routing.defaultOrder.map(String) : [];
611
+ const gbrain = enabledProvider(config, 'gbrain');
612
+ const scaleLocal = enabledProvider(config, 'scale-local');
613
+ const agentmemory = enabledProvider(config, 'agentmemory');
614
+ const gbrainPath = findCommandPath('gbrain', env);
615
+ const details = [
616
+ `routing=${String(routing.mode ?? 'missing')}; order=${defaultOrder.length ? defaultOrder.join(',') : 'missing'}`,
617
+ `gbrain=${gbrain.enabled ? 'enabled' : 'disabled'}; command=${gbrainPath ? 'found' : 'missing'}; write=${String(gbrain.writeMode ?? 'unknown')}`,
618
+ `scale-local=${scaleLocal.enabled ? 'enabled' : 'disabled'}; write=${String(scaleLocal.writeMode ?? 'unknown')}`,
619
+ `agentmemory=${agentmemory.enabled ? 'enabled' : 'disabled'}`,
620
+ ];
621
+ if (!config) {
622
+ return runtimeCard('third_party_memory', 'Third-party memory', 'warning', 'CONFIG MISSING', 'External memory routing is not configured; the native medical workflow can still run.', details, 'Add a medical memory provider config when recall and memory review are needed.', false);
623
+ }
624
+ if (!gbrain.enabled || !gbrainPath) {
625
+ return runtimeCard('third_party_memory', 'Third-party memory', 'warning', 'GBRAIN OPTIONAL', 'gbrain is unavailable, so recall and memory review will stay local or pending.', details, 'Install or enable gbrain only if this study needs cross-session memory recall.', false);
626
+ }
627
+ return runtimeCard('third_party_memory', 'Third-party memory', 'pass', 'GBRAIN READY', 'External-first memory routing is available for governed research recall.', details, 'Next: expose provider recall and Memory Brain review transitions.', false);
628
+ }
629
+ function buildRuntimeCodeIntelligenceCard(root, env) {
630
+ const config = readWorkspaceJson(root, '.scale/code-intelligence.json');
631
+ const codegraphPath = findCommandPath('codegraph', env);
632
+ const graphifyPath = findCommandPath('graphify', env);
633
+ const codegraphDb = join(root, '.codegraph', 'codegraph.db');
634
+ const graphifyManifest = join(root, 'graphify-out', 'manifest.json');
635
+ const details = [
636
+ `codegraph_command=${codegraphPath ? 'found' : 'missing'}`,
637
+ `codegraph_db=${existsSync(codegraphDb) ? 'present' : 'missing'}`,
638
+ `graphify_command=${graphifyPath ? 'found' : 'missing'}`,
639
+ `graphify_manifest=${existsSync(graphifyManifest) ? 'present' : 'missing'}`,
640
+ `config=${config ? 'present' : 'missing'}`,
641
+ ];
642
+ if (!codegraphPath) {
643
+ return runtimeCard('code_intelligence', 'Code and knowledge graph', 'warning', 'CODEGRAPH OPTIONAL', 'CodeGraph is not available; MedSCALE will use manifest and file-based evidence instead.', details, 'Install CodeGraph only if graph-backed research inspection is needed.', false);
644
+ }
645
+ if (!graphifyPath || !existsSync(graphifyManifest)) {
646
+ return runtimeCard('code_intelligence', 'Code and knowledge graph', 'warning', 'GRAPH DEGRADED', 'Code intelligence is partially available, but Graphify is not fully initialized.', details, 'Run graphify install/status and regenerate the artifact graph.', false);
647
+ }
648
+ return runtimeCard('code_intelligence', 'Code and knowledge graph', 'pass', 'GRAPH READY', 'CodeGraph and Graphify signals are available for research workflow inspection.', details, 'Next: render evidence graph status in the MedSCALE dashboard.', false);
649
+ }
650
+ function buildRuntimeCliCard(env) {
651
+ const probes = {
652
+ python: findCommandPath('python', env),
653
+ uv: findCommandPath('uv', env),
654
+ node: findCommandPath('node', env),
655
+ };
656
+ const details = Object.entries(probes).map(([name, path]) => `${name}=${path ? 'found' : 'missing'}`);
657
+ if (!probes.python) {
658
+ return runtimeCard('cli_runtime', 'Native medical runtime', 'fail', 'RUNTIME MISSING', 'Python is required to run the standalone medical research workflow.', details, 'Restore Python 3.10+ PATH availability before running the medical platform.', true);
659
+ }
660
+ if (!probes.uv) {
661
+ return runtimeCard('cli_runtime', 'Native medical runtime', 'warning', 'PYTHON READY', 'Python is available; uv is optional but recommended for reproducible medical dependencies.', details, 'Use pip or install uv for faster isolated dependency setup.', true);
662
+ }
663
+ return runtimeCard('cli_runtime', 'Native medical runtime', 'pass', 'PYTHON READY', 'Native medical workflow runtime is available without an external governance CLI.', details, 'Next: expose med-research os-plan, mcp doctor, and token report commands.', true);
664
+ }
665
+ function buildRuntimeSkillsCard(root) {
666
+ const config = readWorkspaceJson(root, '.scale/skills.json');
667
+ const policy = config?.policy && typeof config.policy === 'object' && !Array.isArray(config.policy)
668
+ ? config.policy
669
+ : {};
670
+ const domains = config?.domains && typeof config.domains === 'object' && !Array.isArray(config.domains)
671
+ ? config.domains
672
+ : {};
673
+ const requiredMedicalDomains = [
674
+ 'medicalLiteratureReview',
675
+ 'medicalFactCheck',
676
+ 'medicalEvidenceGrading',
677
+ 'medicalStatisticalReview',
678
+ 'medicalPackageAudit',
679
+ 'medicalMemoryCurator',
680
+ ];
681
+ const missingDomains = requiredMedicalDomains.filter(domain => !(domain in domains));
682
+ const details = [
683
+ `policy=${String(policy.mode ?? 'missing')}`,
684
+ `domain_count=${Object.keys(domains).length}`,
685
+ `missing_medical_domains=${missingDomains.length ? missingDomains.join(',') : 'none'}`,
686
+ ];
687
+ if (!config) {
688
+ return runtimeCard('medical_skills', 'Medical skills', 'warning', 'SKILLS MISSING', 'Skill governance is not configured for this workspace.', details, 'Add medical skill domains for literature review, fact check, evidence grading, statistics, package audit, and memory curation.', false);
689
+ }
690
+ if (missingDomains.length > 0) {
691
+ return runtimeCard('medical_skills', 'Medical skills', 'warning', 'MEDICAL DOMAINS MISSING', 'Generic skill governance exists, but medical research roles are not first-class skill domains.', details, 'Add the six MedSCALE medical skill domains and required evidence artifacts.', false);
692
+ }
693
+ return runtimeCard('medical_skills', 'Medical skills', 'pass', 'SKILLS READY', 'Medical research skill domains are configured.', details, 'Next: bind each delivery gate to required skill evidence.', false);
694
+ }
695
+ function buildRuntimeMcpCard(root) {
696
+ const configDir = join(root, 'mcp-configs');
697
+ const entries = existsSync(configDir)
698
+ ? readdirSync(configDir).filter(name => !name.startsWith('_'))
699
+ : [];
700
+ const serverYaml = join(root, '.scale', 'mcp-servers.yaml');
701
+ const serverYamlText = readTextIfPresent(serverYaml);
702
+ const requiredMedicalRoutes = [
703
+ 'medical-literature',
704
+ 'medical-fact-check',
705
+ 'medical-memory-review',
706
+ 'medical-package-audit',
707
+ 'medical-evidence-manifest',
708
+ ];
709
+ const missingMedicalRoutes = requiredMedicalRoutes.filter(route => !serverYamlText.includes(route));
710
+ const details = [
711
+ `mcp_config_count=${entries.length}`,
712
+ `mcp_servers_yaml=${existsSync(serverYaml) ? 'present' : 'missing'}`,
713
+ `missing_medical_routes=${missingMedicalRoutes.length ? missingMedicalRoutes.join(',') : 'none'}`,
714
+ `memory_config=${existsSync(join(configDir, 'memory')) || existsSync(join(configDir, 'memory.json')) ? 'present' : 'missing'}`,
715
+ `playwright_config=${existsSync(join(configDir, 'playwright')) || existsSync(join(configDir, 'playwright.json')) ? 'present' : 'missing'}`,
716
+ ];
717
+ if (entries.length === 0) {
718
+ return runtimeCard('mcp_surface', 'MCP surface', 'warning', 'MCP MISSING', 'No MCP configuration files were found for this workspace.', details, 'Add MCP configs for memory, evidence manifests, browser checks, and medical retrieval.', false);
719
+ }
720
+ if (!existsSync(serverYaml)) {
721
+ return runtimeCard('mcp_surface', 'MCP surface', 'warning', 'MCP PARTIAL', 'MCP configs exist, but the workspace has no MedSCALE server map contract.', details, 'Add a native MedSCALE MCP server map and expose status in the medical doctor.', false);
722
+ }
723
+ if (missingMedicalRoutes.length > 0) {
724
+ return runtimeCard('mcp_surface', 'MCP surface', 'warning', 'MCP MEDICAL ROUTES MISSING', 'MCP server map exists, but it does not yet declare the required MedSCALE medical routes.', details, 'Add literature, fact-check, memory-review, package-audit, and evidence-manifest routes to the MedSCALE MCP server map.', false);
725
+ }
726
+ return runtimeCard('mcp_surface', 'MCP surface', 'pass', 'MCP READY', 'MCP configs and the MedSCALE medical server map are present.', details, 'Next: wire these routes to live MCP tool health checks.', false);
727
+ }
728
+ function buildRuntimeTokenCostCard(root) {
729
+ const report = buildTargetTokenCostReport({ projectDir: root, sinceDays: undefined, limit: 5 });
730
+ const cost = report.summary.estimatedCostUsd;
731
+ const details = [
732
+ `usage_path=${report.usagePath}`,
733
+ `records=${report.summary.totalRecords}`,
734
+ `total_tokens=${report.summary.totalTokens}`,
735
+ `cache_savings_tokens=${report.summary.cacheSavingsTokens}`,
736
+ `estimated_cost_usd=${cost ?? 'unknown'}`,
737
+ `medical_lanes=${report.byMedicalLane.length ? report.byMedicalLane.map(lane => lane.key).join(',') : 'none'}`,
738
+ ];
739
+ if (report.summary.totalRecords === 0) {
740
+ return runtimeCard('token_cost', 'Token and cost ledger', 'warning', 'COST PENDING', 'MedSCALE token/cost reporting is wired, but no medical model usage has been recorded yet.', details, 'Record usage with medscale token record after literature review, fact check, package audit, agent review, and memory settlement.', false);
741
+ }
742
+ return runtimeCard('token_cost', 'Token and cost ledger', 'pass', 'COST TRACKED', 'MedSCALE has recorded model usage for cost and token review.', details, 'Review medscale token report before package delivery and expert handoff.', false);
743
+ }
744
+ function buildRuntimeMedicalRetrievalCard(root, platform) {
745
+ const platformDir = platform?.platformDir ?? join(root, 'target-research-platform');
746
+ const pubmedClient = join(platformDir, 'src', 'api_clients', 'pubmed_client.py');
747
+ const openalexClient = join(platformDir, 'src', 'api_clients', 'openalex_client.py');
748
+ const literatureTests = join(platformDir, 'tests', 'test_literature_enrichment.py');
749
+ const apiClientTests = join(platformDir, 'tests', 'test_api_clients.py');
750
+ const details = [
751
+ `pubmed_client=${existsSync(pubmedClient) ? 'present' : 'missing'}`,
752
+ `openalex_client=${existsSync(openalexClient) ? 'present' : 'missing'}`,
753
+ `literature_tests=${existsSync(literatureTests) ? 'present' : 'missing'}`,
754
+ `api_client_tests=${existsSync(apiClientTests) ? 'present' : 'missing'}`,
755
+ ];
756
+ if (existsSync(pubmedClient) && existsSync(openalexClient) && (existsSync(literatureTests) || existsSync(apiClientTests))) {
757
+ return runtimeCard('medical_retrieval', 'PubMed / OpenAlex retrieval', 'pass', 'RETRIEVAL READY', 'PubMed and OpenAlex clients are present with test coverage for literature enrichment.', details, 'Next: add live availability and rate-limit checks when credentials/network policy allow it.', false);
758
+ }
759
+ return runtimeCard('medical_retrieval', 'PubMed / OpenAlex retrieval', 'warning', 'RETRIEVAL PARTIAL', 'Medical retrieval clients or enrichment tests are missing from the native workflow.', details, 'Add PubMed/OpenAlex clients and literature enrichment tests before external evidence review.', false);
760
+ }
761
+ function buildRuntimePackageAuditCard(root, platform) {
762
+ const platformDir = platform?.platformDir ?? join(root, 'target-research-platform');
763
+ const deliveryPackager = join(platformDir, 'src', 'output', 'delivery_packager.py');
764
+ const deliveryManifestTests = join(platformDir, 'tests', 'test_delivery_manifest.py');
765
+ const source = readTextIfPresent(deliveryPackager);
766
+ const hasAudit = /audit_delivery_package/.test(source) && /hash_mismatches|broken_markdown_refs/.test(source);
767
+ const details = [
768
+ `delivery_packager=${existsSync(deliveryPackager) ? 'present' : 'missing'}`,
769
+ `audit_delivery_package=${hasAudit ? 'present' : 'missing'}`,
770
+ `delivery_manifest_tests=${existsSync(deliveryManifestTests) ? 'present' : 'missing'}`,
771
+ ];
772
+ if (hasAudit && existsSync(deliveryManifestTests)) {
773
+ return runtimeCard('package_audit', 'Package audit', 'pass', 'AUDIT READY', 'Delivery ZIP audit checks archive inventory, hashes, sizes, and markdown references.', details, 'Run medscale package after manuscript generation to refresh audit evidence.', false);
774
+ }
775
+ return runtimeCard('package_audit', 'Package audit', 'warning', 'AUDIT PARTIAL', 'Delivery package audit is not yet a fully test-backed native doctor signal.', details, 'Add package audit tests covering manifest inventory, hashes, and archive references.', false);
776
+ }
777
+ function buildRuntimeFigureRefsCard(root, platform) {
778
+ const platformDir = platform?.platformDir ?? join(root, 'target-research-platform');
779
+ const deliveryPackager = join(platformDir, 'src', 'output', 'delivery_packager.py');
780
+ const qualityGate = join(platformDir, 'src', 'output', 'manuscript_quality.py');
781
+ const packagerSource = readTextIfPresent(deliveryPackager);
782
+ const qualitySource = readTextIfPresent(qualityGate);
783
+ const archiveRefs = /broken_image_refs|image_refs_checked/.test(packagerSource);
784
+ const bodyRefs = /figures\.referenced_in_text/.test(qualitySource);
785
+ const details = [
786
+ `archive_image_refs=${archiveRefs ? 'present' : 'missing'}`,
787
+ `body_figure_refs=${bodyRefs ? 'present' : 'missing'}`,
788
+ `quality_gate=${existsSync(qualityGate) ? 'present' : 'missing'}`,
789
+ ];
790
+ if (archiveRefs && bodyRefs) {
791
+ return runtimeCard('figure_refs', 'Figure reference checks', 'pass', 'FIGURES READY', 'Figure file presence, archive references, and in-text reference checks are native gates.', details, 'Keep figure checks in package audit and manuscript quality tests before handoff.', false);
792
+ }
793
+ return runtimeCard('figure_refs', 'Figure reference checks', 'warning', 'FIGURES PARTIAL', 'Figure reference checks exist only partially across package audit and quality gates.', details, 'Add explicit figure reference coverage for manuscript body and delivery archive paths.', false);
794
+ }
795
+ function buildRuntimeMedicalWorkflowCard(root, platform) {
796
+ const platformDir = platform?.platformDir ?? join(root, 'target-research-platform');
797
+ const details = [
798
+ `platform=${existsSync(platformDir) ? 'present' : 'missing'}`,
799
+ `main_py=${existsSync(join(platformDir, 'main.py')) ? 'present' : 'missing'}`,
800
+ `requirements=${existsSync(join(platformDir, 'requirements.txt')) ? 'present' : 'missing'}`,
801
+ `tests=${existsSync(join(platformDir, 'tests')) ? 'present' : 'missing'}`,
802
+ `dashboard_os=${existsSync(join(platformDir, 'src', 'dashboard', 'app.py')) ? 'present' : 'missing'}`,
803
+ ];
804
+ if (!existsSync(platformDir) || !existsSync(join(platformDir, 'main.py'))) {
805
+ return runtimeCard('medical_workflow', 'Medical workflow', 'fail', 'PLATFORM MISSING', 'target-research-platform is required for MedSCALE Research OS.', details, 'Restore target-research-platform before running the medical workflow.', true);
806
+ }
807
+ if (!existsSync(join(platformDir, 'requirements.txt')) || !existsSync(join(platformDir, 'tests'))) {
808
+ return runtimeCard('medical_workflow', 'Medical workflow', 'warning', 'WORKFLOW PARTIAL', 'The medical platform exists, but dependency or test evidence is incomplete.', details, 'Add medical pytest coverage to the default verification profile.', true);
809
+ }
810
+ return runtimeCard('medical_workflow', 'Medical workflow', 'pass', 'WORKFLOW READY', 'Medical platform files, dependencies, and tests are discoverable.', details, 'Next: include target-research-platform pytest in native medical verification.', true);
811
+ }
812
+ function runtimeReadinessScore(cards) {
813
+ if (cards.length === 0)
814
+ return 0;
815
+ const weights = {
816
+ pass: 100,
817
+ warning: 55,
818
+ pending: 25,
819
+ fail: 0,
820
+ };
821
+ return Math.round(cards.reduce((sum, card) => sum + weights[card.state], 0) / cards.length);
822
+ }
823
+ export function buildTargetRuntimeReadiness(projectDir = PROJECT_DIR, env = process.env) {
824
+ const root = resolveTargetWorkspaceRoot(projectDir);
825
+ const platform = resolveTargetPlatform(root);
826
+ const cards = [
827
+ buildRuntimeMemoryCard(root, env),
828
+ buildRuntimeCodeIntelligenceCard(root, env),
829
+ buildRuntimeCliCard(env),
830
+ buildRuntimeSkillsCard(root),
831
+ buildRuntimeMcpCard(root),
832
+ buildRuntimeTokenCostCard(root),
833
+ buildRuntimeMedicalRetrievalCard(root, platform),
834
+ buildRuntimePackageAuditCard(root, platform),
835
+ buildRuntimeFigureRefsCard(root, platform),
836
+ buildRuntimeMedicalWorkflowCard(root, platform),
837
+ ];
838
+ const requiredMissing = cards
839
+ .filter(card => card.required && card.state === 'fail')
840
+ .flatMap(card => card.details);
841
+ const warningCount = cards.filter(card => card.state === 'warning').length;
842
+ const failCount = cards.filter(card => card.state === 'fail').length;
843
+ const status = requiredMissing.length > 0
844
+ ? 'blocked'
845
+ : (warningCount > 0 || failCount > 0 ? 'degraded' : 'ready');
846
+ const recommendations = cards
847
+ .filter(card => (card.state === 'fail' || card.state === 'warning') && card.nextAction)
848
+ .map(card => card.nextAction);
849
+ return {
850
+ schema: 'medscale.runtime_readiness.v1',
851
+ status,
852
+ score: runtimeReadinessScore(cards),
853
+ workspaceRoot: root,
854
+ requiredMissing,
855
+ warningCount,
856
+ failCount,
857
+ cards,
858
+ recommendations: recommendations.length ? recommendations.slice(0, 6) : ['Run the native MedSCALE doctor before external expert review.'],
859
+ };
860
+ }
861
+ function detectSetupPlatform(value) {
862
+ const raw = String(value ?? '').trim().toLowerCase();
863
+ if (raw === 'windows' || raw === 'win' || raw === 'win32')
864
+ return 'windows';
865
+ if (raw === 'macos' || raw === 'darwin' || raw === 'mac')
866
+ return 'macos';
867
+ if (raw === 'linux')
868
+ return 'linux';
869
+ if (process.platform === 'win32')
870
+ return 'windows';
871
+ if (process.platform === 'darwin')
872
+ return 'macos';
873
+ return 'linux';
874
+ }
875
+ function selectedCommand(platform, windows, unix) {
876
+ const selected = platform === 'windows' ? windows : unix;
877
+ return { windows, unix, selected };
878
+ }
879
+ function targetText(lang, zh, en) {
880
+ return lang === 'zh' ? zh : en;
881
+ }
882
+ function runtimeCardById(readiness, id) {
883
+ return readiness.cards.find(card => card.id === id) ?? null;
884
+ }
885
+ function runtimeDetailValue(card, key) {
886
+ const prefix = `${key}=`;
887
+ const found = card?.details.find(item => item.startsWith(prefix));
888
+ return found ? found.slice(prefix.length) : null;
889
+ }
890
+ function setupStatusFromRuntimeState(card) {
891
+ if (!card)
892
+ return 'missing';
893
+ if (card.state === 'pass')
894
+ return 'ready';
895
+ if (card.state === 'warning' || card.state === 'pending')
896
+ return 'partial';
897
+ return card.required ? 'missing' : 'partial';
898
+ }
899
+ function readTextIfPresent(path) {
900
+ try {
901
+ return existsSync(path) ? readFileSync(path, 'utf-8') : '';
902
+ }
903
+ catch {
904
+ return '';
905
+ }
906
+ }
907
+ function setupCapability(options) {
908
+ return {
909
+ id: options.id,
910
+ title: options.title,
911
+ category: options.category,
912
+ status: options.status,
913
+ required: Boolean(options.required),
914
+ summary: options.summary,
915
+ evidence: options.evidence,
916
+ install: selectedCommand(options.platform, options.installWindows ?? null, options.installUnix ?? null),
917
+ verify: selectedCommand(options.platform, options.verifyWindows ?? null, options.verifyUnix ?? null),
918
+ nextAction: options.nextAction,
919
+ };
920
+ }
921
+ function buildSetupCommands(lang) {
922
+ const packageName = '@hongmaple0820/med-scale-research-os';
923
+ return {
924
+ local: `npm run medscale -- setup --lang ${lang}`,
925
+ localJson: `npm run medscale -- setup --lang ${lang} --json`,
926
+ npx: `npx -y ${packageName} setup --lang ${lang}`,
927
+ npxJson: `npx -y ${packageName} setup --lang ${lang} --json`,
928
+ visual: `npx -y ${packageName} setup --visual --lang ${lang}`,
929
+ };
930
+ }
931
+ function buildTargetSetupCapabilities(options) {
932
+ const { root, platform, lang, env, readiness } = options;
933
+ const memoryCard = runtimeCardById(readiness, 'third_party_memory');
934
+ const codeCard = runtimeCardById(readiness, 'code_intelligence');
935
+ const cliCard = runtimeCardById(readiness, 'cli_runtime');
936
+ const skillsCard = runtimeCardById(readiness, 'medical_skills');
937
+ const mcpCard = runtimeCardById(readiness, 'mcp_surface');
938
+ const workflowCard = runtimeCardById(readiness, 'medical_workflow');
939
+ const retrievalCard = runtimeCardById(readiness, 'medical_retrieval');
940
+ const packageAuditCard = runtimeCardById(readiness, 'package_audit');
941
+ const figureRefsCard = runtimeCardById(readiness, 'figure_refs');
942
+ const codegraphCommand = runtimeDetailValue(codeCard, 'codegraph_command');
943
+ const codegraphDb = runtimeDetailValue(codeCard, 'codegraph_db');
944
+ const graphifyCommand = runtimeDetailValue(codeCard, 'graphify_command');
945
+ const graphifyManifest = runtimeDetailValue(codeCard, 'graphify_manifest');
946
+ const mcpConfigCount = Number(runtimeDetailValue(mcpCard, 'mcp_config_count') ?? 0);
947
+ const mcpServerYaml = runtimeDetailValue(mcpCard, 'mcp_servers_yaml');
948
+ const agentmemory = runtimeDetailValue(memoryCard, 'agentmemory');
949
+ const gbrainCommand = runtimeDetailValue(memoryCard, 'gbrain')?.includes('command=found');
950
+ const platformDir = resolveTargetPlatform(root)?.platformDir ?? join(root, 'target-research-platform');
951
+ const pubmedClient = join(platformDir, 'src', 'api_clients', 'pubmed_client.py');
952
+ const openalexClient = join(platformDir, 'src', 'api_clients', 'openalex_client.py');
953
+ const deliveryPackager = join(platformDir, 'src', 'output', 'delivery_packager.py');
954
+ const rtkPath = findCommandPath('rtk', env);
955
+ const packageJson = readJsonFile(join(root, 'package.json'));
956
+ const packageName = typeof packageJson?.name === 'string' ? packageJson.name : 'missing';
957
+ const medscaleBinReady = existsSync(join(root, 'package.json')) && readTextIfPresent(join(root, 'package.json')).includes('"medscale"');
958
+ const medscalePackageReady = packageName === '@hongmaple0820/med-scale-research-os' && medscaleBinReady;
959
+ const tokenCostReport = buildTargetTokenCostReport({ projectDir: root, sinceDays: undefined, limit: 5 });
960
+ return [
961
+ setupCapability({
962
+ id: 'native-cli',
963
+ title: targetText(lang, 'MedSCALE 原生 CLI', 'MedSCALE native CLI'),
964
+ category: 'runtime',
965
+ status: cliCard?.state === 'fail' ? 'missing' : (medscaleBinReady ? 'ready' : 'partial'),
966
+ required: true,
967
+ summary: targetText(lang, '医学工作流已经有 medscale 入口;基础运行只要求 Python 和医学平台目录。', 'The medical workflow has a medscale entrypoint; the base runtime only requires Python and the medical platform.'),
968
+ evidence: [
969
+ `cli_runtime=${cliCard?.statusLabel ?? 'missing'}`,
970
+ `medscale_bin=${medscaleBinReady ? 'present' : 'missing'}`,
971
+ ],
972
+ installWindows: 'npm install && npm run build',
973
+ installUnix: 'npm install && npm run build',
974
+ verifyWindows: 'npm run medscale -- doctor --json',
975
+ verifyUnix: 'npm run medscale -- doctor --json',
976
+ nextAction: targetText(lang, '继续用 medscale doctor / setup / os-plan 作为医学工作流入口。', 'Use medscale doctor / setup / os-plan as the medical workflow entrypoints.'),
977
+ platform,
978
+ }),
979
+ setupCapability({
980
+ id: 'npx-visual-installer',
981
+ title: targetText(lang, 'npx 可视化安装入口', 'npx visual installer'),
982
+ category: 'runtime',
983
+ status: medscalePackageReady ? 'partial' : 'planned',
984
+ required: false,
985
+ summary: targetText(lang, '本地可视化 setup 入口已经可用;公开 npx 体验仍需要首次发布。', 'The local visual setup entrypoint is available; the public npx experience still needs the first publish.'),
986
+ evidence: [`package_name=${packageName}`, `medscale_bin=${medscaleBinReady ? 'present' : 'missing'}`, 'visual_command=present', 'public_npx_publish=pending'],
987
+ installWindows: 'npm run medscale -- setup --visual --lang zh',
988
+ installUnix: 'npm run medscale -- setup --visual --lang zh',
989
+ verifyWindows: 'npm run medscale -- setup --json',
990
+ verifyUnix: 'npm run medscale -- setup --json',
991
+ nextAction: targetText(lang, '首次发布 npm 包后,用 npx -y 验证跨平台 setup --visual 体验。', 'After the first npm publish, verify the cross-platform setup --visual flow with npx -y.'),
992
+ platform,
993
+ }),
994
+ setupCapability({
995
+ id: 'gbrain',
996
+ title: 'gbrain',
997
+ category: 'memory',
998
+ status: gbrainCommand && memoryCard?.state === 'pass' ? 'ready' : setupStatusFromRuntimeState(memoryCard),
999
+ required: false,
1000
+ summary: targetText(lang, '默认外部记忆供应商,用于跨会话医学证据召回;缺失时不阻断本地医学工作流。', 'Default external memory provider for cross-session medical evidence recall; missing gbrain does not block the local medical workflow.'),
1001
+ evidence: memoryCard?.details ?? ['third_party_memory=missing'],
1002
+ installWindows: 'gbrain init --pglite',
1003
+ installUnix: 'gbrain init --pglite',
1004
+ verifyWindows: 'gbrain doctor --json',
1005
+ verifyUnix: 'gbrain doctor --json',
1006
+ nextAction: targetText(lang, '先保持只读召回和候选写入,后续接 approve/reject/stale/restore 审核流。', 'Keep recall read-only and writes candidate-only, then wire approve/reject/stale/restore review states.'),
1007
+ platform,
1008
+ }),
1009
+ setupCapability({
1010
+ id: 'agentmemory',
1011
+ title: 'agentmemory',
1012
+ category: 'memory',
1013
+ status: agentmemory?.includes('enabled') ? 'partial' : 'missing',
1014
+ required: false,
1015
+ summary: targetText(lang, '第二记忆供应商槽位已在规划内,但当前工作区没有启用为医学记忆路由。', 'A secondary memory provider slot is planned, but this workspace has not enabled it for medical memory routing.'),
1016
+ evidence: [`agentmemory=${agentmemory ?? 'missing'}`],
1017
+ installWindows: 'npx -y @agentmemory/agentmemory --help',
1018
+ installUnix: 'npx -y @agentmemory/agentmemory --help',
1019
+ verifyWindows: 'npm run medscale -- setup --json',
1020
+ verifyUnix: 'npm run medscale -- setup --json',
1021
+ nextAction: targetText(lang, '先以 gbrain 为主,agentmemory 作为团队共享记忆的可选后备。', 'Keep gbrain primary and use agentmemory later as an optional shared-memory fallback.'),
1022
+ platform,
1023
+ }),
1024
+ setupCapability({
1025
+ id: 'memory-brain-review',
1026
+ title: targetText(lang, 'Memory Brain 审核流', 'Memory Brain review flow'),
1027
+ category: 'memory',
1028
+ status: 'ready',
1029
+ required: false,
1030
+ summary: targetText(lang, 'memory seed、learning candidate、approve/reject/stale/restore 已有原生审核状态和审计记录。', 'Memory seed, learning candidates, and approve/reject/stale/restore now have native review states and audit records.'),
1031
+ evidence: ['remember_command=present', 'learn_command=present', 'memory_review_command=present', 'review_transitions=approve,reject,stale,restore'],
1032
+ installWindows: 'npm run medscale -- learn --help',
1033
+ installUnix: 'npm run medscale -- learn --help',
1034
+ verifyWindows: 'npm run medscale -- memory-review --help',
1035
+ verifyUnix: 'npm run medscale -- memory-review --help',
1036
+ nextAction: targetText(lang, '下一阶段把审核状态映射到 18766 医学研究者视图。', 'Next, map review status into the 18766 researcher view.'),
1037
+ platform,
1038
+ }),
1039
+ setupCapability({
1040
+ id: 'rtk',
1041
+ title: 'RTK',
1042
+ category: 'runtime',
1043
+ status: rtkPath ? 'ready' : 'missing',
1044
+ required: false,
1045
+ summary: targetText(lang, 'RTK 可作为命令包装、压缩和外部工具治理层,但不再是 MedSCALE 医学工作流的必需运行时。', 'RTK can serve as a command wrapper, compression, and external tool governance layer, but it is no longer required for MedSCALE runtime.'),
1046
+ evidence: [`rtk=${rtkPath ? 'found' : 'missing'}`],
1047
+ installWindows: 'cargo install --git https://github.com/rtk-ai/rtk',
1048
+ installUnix: 'cargo install --git https://github.com/rtk-ai/rtk',
1049
+ verifyWindows: 'rtk --version',
1050
+ verifyUnix: 'rtk --version',
1051
+ nextAction: targetText(lang, '需要命令证据压缩时再启用;不要把它放回必需依赖。', 'Enable it only for command evidence compression; do not move it back into required dependencies.'),
1052
+ platform,
1053
+ }),
1054
+ setupCapability({
1055
+ id: 'codegraph',
1056
+ title: 'CodeGraph',
1057
+ category: 'code-map',
1058
+ status: codegraphCommand === 'found' && codegraphDb === 'present' ? 'ready' : (codegraphCommand === 'found' || codegraphDb === 'present' ? 'partial' : 'missing'),
1059
+ required: false,
1060
+ summary: targetText(lang, '代码地图能力用于医生/研究者视角的实现追踪;缺失时可退回 manifest 和文件证据。', 'Code-map capability supports researcher-facing implementation traceability; missing CodeGraph falls back to manifests and file evidence.'),
1061
+ evidence: [`codegraph_command=${codegraphCommand ?? 'missing'}`, `codegraph_db=${codegraphDb ?? 'missing'}`],
1062
+ installWindows: 'npm install -g @colbymchenry/codegraph && codegraph init -i',
1063
+ installUnix: 'npm install -g @colbymchenry/codegraph && codegraph init -i',
1064
+ verifyWindows: 'codegraph --help',
1065
+ verifyUnix: 'codegraph --help',
1066
+ nextAction: targetText(lang, '把 CodeGraph 状态纳入 native doctor 深度检查和知识库视图。', 'Fold CodeGraph status into native doctor deep checks and the knowledge-base view.'),
1067
+ platform,
1068
+ }),
1069
+ setupCapability({
1070
+ id: 'graphify',
1071
+ title: 'Graphify',
1072
+ category: 'knowledge',
1073
+ status: graphifyCommand === 'found' && graphifyManifest === 'present' ? 'ready' : (graphifyCommand === 'found' || graphifyManifest === 'present' ? 'partial' : 'missing'),
1074
+ required: false,
1075
+ summary: targetText(lang, '知识图谱能力可增强医学证据、代码和交付物之间的关系追踪。', 'Knowledge graph support can connect medical evidence, code, and delivery artifacts.'),
1076
+ evidence: [`graphify_command=${graphifyCommand ?? 'missing'}`, `graphify_manifest=${graphifyManifest ?? 'missing'}`],
1077
+ installWindows: 'pipx install graphify && graphify install --platform codex',
1078
+ installUnix: 'pipx install graphify && graphify install --platform codex',
1079
+ verifyWindows: 'graphify hook status',
1080
+ verifyUnix: 'graphify hook status',
1081
+ nextAction: targetText(lang, '初始化 graphify-out/manifest.json 后在首页显示知识图谱状态。', 'Initialize graphify-out/manifest.json and surface graph status on the homepage.'),
1082
+ platform,
1083
+ }),
1084
+ setupCapability({
1085
+ id: 'medical-skills',
1086
+ title: targetText(lang, '医学专用 skills', 'Medical skills'),
1087
+ category: 'skills',
1088
+ status: setupStatusFromRuntimeState(skillsCard),
1089
+ required: false,
1090
+ summary: targetText(lang, skillsCard?.state === 'pass'
1091
+ ? '文献评审、事实核查、循证分级、统计审查、package audit、memory curator 已配置为医学 skill 域。'
1092
+ : '文献评审、事实核查、循证分级、统计审查、package audit、memory curator 还没有完整固化为一等 skill 域。', skillsCard?.state === 'pass'
1093
+ ? 'Literature review, fact check, evidence grading, statistical review, package audit, and memory curator are configured as medical skill domains.'
1094
+ : 'Literature review, fact check, evidence grading, statistical review, package audit, and memory curator are not yet fully first-class skill domains.'),
1095
+ evidence: skillsCard?.details ?? ['medical_skills=missing'],
1096
+ installWindows: 'npm run medscale -- setup --json',
1097
+ installUnix: 'npm run medscale -- setup --json',
1098
+ verifyWindows: 'npm run medscale -- doctor --json',
1099
+ verifyUnix: 'npm run medscale -- doctor --json',
1100
+ nextAction: targetText(lang, skillsCard?.state === 'pass'
1101
+ ? '把医学 skill 域绑定到质量、事实核查、循证分级、统计审查、包审计、记忆审核门禁。'
1102
+ : '补齐医学 skill contract,并把每个交付门禁绑定到证据产物。', skillsCard?.state === 'pass'
1103
+ ? 'Bind medical skill domains to quality, fact-check, evidence-grading, statistical-review, package-audit, and memory-review gates.'
1104
+ : 'Add medical skill contracts and bind each delivery gate to evidence artifacts.'),
1105
+ platform,
1106
+ }),
1107
+ setupCapability({
1108
+ id: 'mcp-server-map',
1109
+ title: targetText(lang, 'MedSCALE MCP server map', 'MedSCALE MCP server map'),
1110
+ category: 'mcp',
1111
+ status: setupStatusFromRuntimeState(mcpCard),
1112
+ required: false,
1113
+ summary: targetText(lang, mcpCard?.state === 'pass'
1114
+ ? '医学检索、事实核查、记忆审核、package audit、证据 manifest 已纳入 MedSCALE MCP server map。'
1115
+ : 'MCP 配置目前是 partial;还缺医学检索、事实核查、记忆审核、package audit 的原生 server map。', mcpCard?.state === 'pass'
1116
+ ? 'Literature retrieval, fact checks, memory review, package audit, and evidence manifests are declared in the MedSCALE MCP server map.'
1117
+ : 'MCP is currently partial; native server maps for literature retrieval, fact checks, memory review, and package audit are still missing.'),
1118
+ evidence: mcpCard?.details ?? ['mcp_surface=missing'],
1119
+ installWindows: 'npm run medscale -- setup --json',
1120
+ installUnix: 'npm run medscale -- setup --json',
1121
+ verifyWindows: 'npm run medscale -- doctor --json',
1122
+ verifyUnix: 'npm run medscale -- doctor --json',
1123
+ nextAction: targetText(lang, mcpCard?.state === 'pass'
1124
+ ? '把 MCP route 接入 live health、权限边界和 18766 医学研究者视图。'
1125
+ : '新增 MedSCALE 原生 MCP map,并在 doctor 中做深度检查。', mcpCard?.state === 'pass'
1126
+ ? 'Wire MCP routes into live health checks, permission boundaries, and the 18766 researcher view.'
1127
+ : 'Add the native MedSCALE MCP map and deep-check it from doctor.'),
1128
+ platform,
1129
+ }),
1130
+ setupCapability({
1131
+ id: 'pubmed-openalex',
1132
+ title: 'PubMed / OpenAlex',
1133
+ category: 'medical-evidence',
1134
+ status: setupStatusFromRuntimeState(retrievalCard),
1135
+ required: false,
1136
+ summary: targetText(lang, '医学检索客户端已经存在,但尚未进入 native doctor 深度检查和首页能力图。', 'Medical retrieval clients exist, but they are not yet part of native doctor deep checks or the homepage capability map.'),
1137
+ evidence: retrievalCard?.details ?? [
1138
+ `pubmed_client=${existsSync(pubmedClient) ? 'present' : 'missing'}`,
1139
+ `openalex_client=${existsSync(openalexClient) ? 'present' : 'missing'}`,
1140
+ ],
1141
+ installWindows: 'cd target-research-platform && python -m pip install -r requirements.txt',
1142
+ installUnix: 'cd target-research-platform && python -m pip install -r requirements.txt',
1143
+ verifyWindows: 'cd target-research-platform && python -m pytest tests/test_literature* tests/test_*openalex*',
1144
+ verifyUnix: 'cd target-research-platform && python -m pytest tests/test_literature* tests/test_*openalex*',
1145
+ nextAction: targetText(lang, '把 PubMed/OpenAlex 可用性、速率限制和缓存状态纳入 doctor。', 'Add PubMed/OpenAlex availability, rate-limit, and cache status to doctor.'),
1146
+ platform,
1147
+ }),
1148
+ setupCapability({
1149
+ id: 'package-audit',
1150
+ title: 'Package audit',
1151
+ category: 'audit',
1152
+ status: setupStatusFromRuntimeState(packageAuditCard),
1153
+ required: false,
1154
+ summary: targetText(lang, '交付包审计已有打包器基础;还需要在 native doctor 和首页中显示更细的审计结果。', 'Delivery package audit has a packager foundation; native doctor and homepage need more granular audit status.'),
1155
+ evidence: packageAuditCard?.details ?? [`delivery_packager=${existsSync(deliveryPackager) ? 'present' : 'missing'}`],
1156
+ installWindows: 'cd target-research-platform && python -m pip install -r requirements.txt',
1157
+ installUnix: 'cd target-research-platform && python -m pip install -r requirements.txt',
1158
+ verifyWindows: 'cd target-research-platform && python -m pytest tests/test_deliverables.py tests/test_delivery_manifest.py',
1159
+ verifyUnix: 'cd target-research-platform && python -m pytest tests/test_deliverables.py tests/test_delivery_manifest.py',
1160
+ nextAction: targetText(lang, '把 package audit 从交付物状态升级成 doctor 深度检查项。', 'Promote package audit from delivery status into a doctor deep-check item.'),
1161
+ platform,
1162
+ }),
1163
+ setupCapability({
1164
+ id: 'figure-refs',
1165
+ title: targetText(lang, '图表引用检查', 'Figure reference checks'),
1166
+ category: 'audit',
1167
+ status: setupStatusFromRuntimeState(figureRefsCard),
1168
+ required: false,
1169
+ summary: targetText(lang, '交付包能收集 figures,但图表编号、正文引用、期刊格式检查还没有成为独立门禁。', 'The delivery package can collect figures, but numbering, in-text references, and journal-format checks are not yet an independent gate.'),
1170
+ evidence: figureRefsCard?.details ?? [`delivery_packager=${existsSync(deliveryPackager) ? 'present' : 'missing'}`],
1171
+ installWindows: 'npm run medscale -- package --help',
1172
+ installUnix: 'npm run medscale -- package --help',
1173
+ verifyWindows: 'cd target-research-platform && python -m pytest tests/test_deliverables.py tests/test_delivery_manifest.py',
1174
+ verifyUnix: 'cd target-research-platform && python -m pytest tests/test_deliverables.py tests/test_delivery_manifest.py',
1175
+ nextAction: targetText(lang, '新增 figure refs 审查器,检查正文引用、文件存在性和 submission 清单。', 'Add a figure refs reviewer for in-text references, file presence, and submission manifests.'),
1176
+ platform,
1177
+ }),
1178
+ setupCapability({
1179
+ id: 'token-cost',
1180
+ title: targetText(lang, 'Token / cost 面板', 'Token / cost panel'),
1181
+ category: 'economics',
1182
+ status: tokenCostReport.summary.totalRecords > 0 ? 'ready' : 'partial',
1183
+ required: false,
1184
+ summary: targetText(lang, tokenCostReport.summary.totalRecords > 0
1185
+ ? 'MedSCALE 已写入模型 usage 记录,可用于医学任务 token/cost 复盘。'
1186
+ : 'MedSCALE token/cost 本地账本已接入,等待文献评审、事实核查、包审计、memory settlement 的 usage 记录。', tokenCostReport.summary.totalRecords > 0
1187
+ ? 'MedSCALE has model usage records available for medical task token/cost review.'
1188
+ : 'The MedSCALE token/cost ledger is wired and waiting for usage records from literature review, fact check, package audit, and memory settlement.'),
1189
+ evidence: [
1190
+ 'medscale_token_cli=present',
1191
+ `usage_path=${tokenCostReport.usagePath}`,
1192
+ `records=${tokenCostReport.summary.totalRecords}`,
1193
+ `total_tokens=${tokenCostReport.summary.totalTokens}`,
1194
+ `medical_lanes=${tokenCostReport.byMedicalLane.length ? tokenCostReport.byMedicalLane.map(lane => lane.key).join(',') : 'none'}`,
1195
+ ],
1196
+ installWindows: 'npm run medscale -- token record --help',
1197
+ installUnix: 'npm run medscale -- token record --help',
1198
+ verifyWindows: 'npm run medscale -- token report --json',
1199
+ verifyUnix: 'npm run medscale -- token report --json',
1200
+ nextAction: targetText(lang, '在文献检索、Agent review、fact check、memory settlement 后调用 medscale token record。', 'Call medscale token record after literature review, agent review, fact check, and memory settlement.'),
1201
+ platform,
1202
+ }),
1203
+ setupCapability({
1204
+ id: 'medical-workflow',
1205
+ title: targetText(lang, '医学研究工作流', 'Medical research workflow'),
1206
+ category: 'medical-evidence',
1207
+ status: setupStatusFromRuntimeState(workflowCard),
1208
+ required: true,
1209
+ summary: targetText(lang, 'target-research-platform 是 MedSCALE Research OS 的医学执行内核。', 'target-research-platform is the medical execution kernel of MedSCALE Research OS.'),
1210
+ evidence: workflowCard?.details ?? ['medical_workflow=missing'],
1211
+ installWindows: 'cd target-research-platform && python -m pip install -r requirements.txt',
1212
+ installUnix: 'cd target-research-platform && python -m pip install -r requirements.txt',
1213
+ verifyWindows: 'cd target-research-platform && python -m pytest',
1214
+ verifyUnix: 'cd target-research-platform && python -m pytest',
1215
+ nextAction: targetText(lang, '保持它作为唯一必需运行时,外部能力走增强层。', 'Keep it as the only required runtime and place external capabilities in the enhancement layer.'),
1216
+ platform,
1217
+ }),
1218
+ ];
1219
+ }
1220
+ export function buildTargetSetupPlan(options = {}) {
1221
+ const projectDir = String(options.projectDir ?? PROJECT_DIR);
1222
+ const env = options.env ?? process.env;
1223
+ const root = resolveTargetWorkspaceRoot(projectDir);
1224
+ const lang = normalizeLanguage(options.lang ?? env.MEDSCALE_LANG ?? env.SCALE_LANG ?? 'zh');
1225
+ const platform = detectSetupPlatform(options.platform);
1226
+ const runtimeReadiness = buildTargetRuntimeReadiness(root, env);
1227
+ const capabilities = buildTargetSetupCapabilities({ root, platform, lang, env, readiness: runtimeReadiness });
1228
+ const capabilityById = Object.fromEntries(capabilities.map(capability => [capability.id, capability]));
1229
+ const summary = {
1230
+ ready: capabilities.filter(capability => capability.status === 'ready').length,
1231
+ partial: capabilities.filter(capability => capability.status === 'partial').length,
1232
+ missing: capabilities.filter(capability => capability.status === 'missing').length,
1233
+ planned: capabilities.filter(capability => capability.status === 'planned').length,
1234
+ requiredMissing: capabilities
1235
+ .filter(capability => capability.required && capability.status === 'missing')
1236
+ .map(capability => capability.id),
1237
+ };
1238
+ const status = summary.requiredMissing.length > 0
1239
+ ? 'blocked'
1240
+ : (summary.partial > 0 || summary.missing > 0 || summary.planned > 0 ? 'degraded' : 'ready');
1241
+ const nextSteps = [
1242
+ targetText(lang, '先运行 medscale doctor --json 确认必需运行时。', 'Run medscale doctor --json to confirm required runtime health.'),
1243
+ capabilityById['medical-skills']?.status === 'ready' && capabilityById['mcp-server-map']?.status === 'ready'
1244
+ ? targetText(lang, '将医学 skills 和 MCP route 绑定到质量、事实核查、包审计、记忆审核门禁。', 'Bind medical skills and MCP routes to quality, fact-check, package-audit, and memory-review gates.')
1245
+ : targetText(lang, '补医学 skills、MCP server map、Memory Brain 审核流。', 'Add medical skills, MCP server maps, and Memory Brain review transitions.'),
1246
+ targetText(lang, '把 PubMed/OpenAlex、package audit、figure refs、token/cost 纳入 native doctor 深度检查。', 'Fold PubMed/OpenAlex, package audit, figure refs, and token/cost into native doctor deep checks.'),
1247
+ targetText(lang, '整理 npm 包名和 README 后发布 npx 可视化安装入口。', 'Package the npm name and README, then publish the npx visual installer.'),
1248
+ ];
1249
+ const notes = targetText(lang, [
1250
+ 'setup 当前是 plan-only,不会自动安装或修改系统环境。',
1251
+ 'RTK、CodeGraph、Graphify、gbrain、agentmemory 都是增强能力,不阻断基础医学工作流。',
1252
+ 'MedSCALE Research OS 运行入口使用 medscale,不再要求 scale CLI。',
1253
+ ], [
1254
+ 'setup is currently plan-only and does not install or modify the system environment.',
1255
+ 'RTK, CodeGraph, Graphify, gbrain, and agentmemory are enhanced capabilities, not blockers for the base medical workflow.',
1256
+ 'MedSCALE Research OS uses medscale as the runtime entrypoint and does not require the scale CLI.',
1257
+ ]);
1258
+ return {
1259
+ schema: 'medscale.setup_plan.v1',
1260
+ product: 'MedSCALE Research OS',
1261
+ lang,
1262
+ platform,
1263
+ status,
1264
+ mode: 'plan-only',
1265
+ workspaceRoot: root,
1266
+ runtimeReadiness,
1267
+ commands: buildSetupCommands(lang),
1268
+ summary,
1269
+ capabilities,
1270
+ nextSteps,
1271
+ notes,
1272
+ };
1273
+ }
1274
+ function renderTargetSetupPlan(plan) {
1275
+ const label = (status) => {
1276
+ if (status === 'ready')
1277
+ return 'PASS';
1278
+ if (status === 'partial')
1279
+ return 'WARN';
1280
+ if (status === 'missing')
1281
+ return 'TODO';
1282
+ return 'PLAN';
1283
+ };
1284
+ const title = targetText(plan.lang, 'MedSCALE Research OS 安装与能力计划', 'MedSCALE Research OS Setup and Capability Plan');
1285
+ const lines = [
1286
+ '',
1287
+ title,
1288
+ '='.repeat(50),
1289
+ `Product: ${plan.product}`,
1290
+ `Platform: ${plan.platform}`,
1291
+ `Status: ${plan.status} (${plan.runtimeReadiness.score})`,
1292
+ `Mode: ${plan.mode}`,
1293
+ `Workspace: ${plan.workspaceRoot}`,
1294
+ '',
1295
+ targetText(plan.lang, '入口命令:', 'Entry commands:'),
1296
+ ` Local: ${plan.commands.local}`,
1297
+ ` Local JSON: ${plan.commands.localJson}`,
1298
+ ` npx: ${plan.commands.npx}`,
1299
+ ` Visual: ${plan.commands.visual}`,
1300
+ '',
1301
+ targetText(plan.lang, '能力矩阵:', 'Capability matrix:'),
1302
+ ...plan.capabilities.map(capability => {
1303
+ const command = capability.verify.selected ?? capability.install.selected ?? 'n/a';
1304
+ return ` [${label(capability.status)}] ${capability.title} (${capability.category}) - ${capability.summary}\n verify: ${command}\n next: ${capability.nextAction}`;
1305
+ }),
1306
+ '',
1307
+ targetText(plan.lang, '下一步:', 'Next steps:'),
1308
+ ...plan.nextSteps.map(item => ` - ${item}`),
1309
+ '',
1310
+ targetText(plan.lang, '说明:', 'Notes:'),
1311
+ ...plan.notes.map(item => ` - ${item}`),
1312
+ ];
1313
+ return lines.join('\n');
1314
+ }
1315
+ export function renderTargetSetupVisualPlan(plan) {
1316
+ const statusLabel = (status) => {
1317
+ if (status === 'ready')
1318
+ return 'PASS';
1319
+ if (status === 'partial')
1320
+ return 'WARN';
1321
+ if (status === 'missing')
1322
+ return 'TODO';
1323
+ return 'PLAN';
1324
+ };
1325
+ const categoryLabel = (category) => {
1326
+ const labels = {
1327
+ runtime: targetText(plan.lang, '运行时', 'Runtime'),
1328
+ memory: targetText(plan.lang, '记忆', 'Memory'),
1329
+ knowledge: targetText(plan.lang, '知识图谱', 'Knowledge'),
1330
+ mcp: 'MCP',
1331
+ skills: 'Skills',
1332
+ 'code-map': targetText(plan.lang, '代码地图', 'Code map'),
1333
+ 'medical-evidence': targetText(plan.lang, '医学证据', 'Medical evidence'),
1334
+ audit: targetText(plan.lang, '审计', 'Audit'),
1335
+ economics: targetText(plan.lang, '成本', 'Economics'),
1336
+ };
1337
+ return labels[category];
1338
+ };
1339
+ const grouped = plan.capabilities.reduce((acc, capability) => {
1340
+ const list = acc.get(capability.category) ?? [];
1341
+ list.push(capability);
1342
+ acc.set(capability.category, list);
1343
+ return acc;
1344
+ }, new Map());
1345
+ const categories = [
1346
+ 'runtime',
1347
+ 'medical-evidence',
1348
+ 'memory',
1349
+ 'skills',
1350
+ 'mcp',
1351
+ 'knowledge',
1352
+ 'code-map',
1353
+ 'audit',
1354
+ 'economics',
1355
+ ];
1356
+ const commandRows = [
1357
+ ['local', plan.commands.local],
1358
+ ['local-json', plan.commands.localJson],
1359
+ ['visual', plan.commands.visual],
1360
+ ['npx-json', plan.commands.npxJson],
1361
+ ];
1362
+ const installQueue = plan.capabilities
1363
+ .filter(capability => capability.status !== 'ready')
1364
+ .map(capability => ({ capability, command: capability.install.selected }))
1365
+ .filter(item => item.command);
1366
+ const verifyQueue = plan.capabilities
1367
+ .filter(capability => capability.verify.selected)
1368
+ .map(capability => ({ capability, command: capability.verify.selected }));
1369
+ const lines = [
1370
+ '',
1371
+ targetText(plan.lang, 'MedSCALE Research OS 可视化安装向导', 'MedSCALE Research OS Visual Setup Guide'),
1372
+ '='.repeat(56),
1373
+ `${targetText(plan.lang, '工作区', 'Workspace')}: ${plan.workspaceRoot}`,
1374
+ `${targetText(plan.lang, '平台', 'Platform')}: ${plan.platform}`,
1375
+ `${targetText(plan.lang, '状态', 'Status')}: ${plan.status} | ready=${plan.summary.ready} partial=${plan.summary.partial} missing=${plan.summary.missing} planned=${plan.summary.planned}`,
1376
+ '',
1377
+ targetText(plan.lang, '复制命令', 'Copy commands'),
1378
+ '-'.repeat(56),
1379
+ ...commandRows.map(([name, command]) => ` ${name.padEnd(10)} ${command}`),
1380
+ '',
1381
+ targetText(plan.lang, '能力分组', 'Capability lanes'),
1382
+ '-'.repeat(56),
1383
+ ];
1384
+ for (const category of categories) {
1385
+ const capabilities = grouped.get(category);
1386
+ if (!capabilities?.length)
1387
+ continue;
1388
+ lines.push(` ${categoryLabel(category)}`);
1389
+ for (const capability of capabilities) {
1390
+ const marker = capability.required ? 'required' : 'optional';
1391
+ lines.push(` [${statusLabel(capability.status)}] ${capability.title} (${marker})`);
1392
+ lines.push(` ${capability.summary}`);
1393
+ lines.push(` next: ${capability.nextAction}`);
1394
+ }
1395
+ }
1396
+ lines.push('', targetText(plan.lang, '安装队列', 'Install queue'), '-'.repeat(56));
1397
+ if (installQueue.length) {
1398
+ for (const item of installQueue)
1399
+ lines.push(` [${statusLabel(item.capability.status)}] ${item.capability.id}: ${item.command}`);
1400
+ }
1401
+ else {
1402
+ lines.push(targetText(plan.lang, ' 没有待安装能力。', ' No install actions needed.'));
1403
+ }
1404
+ lines.push('', targetText(plan.lang, '验证队列', 'Verify queue'), '-'.repeat(56));
1405
+ for (const item of verifyQueue)
1406
+ lines.push(` [${statusLabel(item.capability.status)}] ${item.capability.id}: ${item.command}`);
1407
+ lines.push('', targetText(plan.lang, '安全边界', 'Safety boundary'), '-'.repeat(56));
1408
+ lines.push(...plan.notes.map(item => ` - ${item}`));
1409
+ lines.push('');
1410
+ lines.push(targetText(plan.lang, '提示:setup --visual 只展示和分组命令,不会自动安装第三方工具。', 'Tip: setup --visual only displays grouped commands; it does not auto-install third-party tools.'));
1411
+ return lines.join('\n');
1412
+ }
1413
+ function toNumber(value) {
1414
+ const parsed = Number(value);
1415
+ return Number.isFinite(parsed) ? parsed : null;
1416
+ }
1417
+ function toStringList(value) {
1418
+ return Array.isArray(value)
1419
+ ? value.map(item => typeof item === 'string' ? item.trim() : '').filter(Boolean)
1420
+ : [];
1421
+ }
1422
+ function quoteMaybe(value) {
1423
+ return value && value.trim() ? value : 'N/A';
1424
+ }
1425
+ function uniqueStrings(values) {
1426
+ return [...new Set(values.map(value => value?.trim()).filter(Boolean))];
1427
+ }
1428
+ function deriveMemorySlugFromManifest(manifestPath) {
1429
+ return manifestPath.replace(/\\/g, '/').split('/').pop()?.replace(/_delivery_manifest\.json$/i, '') ?? 'medical_delivery';
1430
+ }
1431
+ function buildTargetMemorySummaryMarkdown(plan) {
1432
+ const manifest = plan.manifestPath ? readJsonFile(plan.manifestPath) : null;
1433
+ const files = Array.isArray(manifest?.files) ? manifest.files : [];
1434
+ const qualityPath = filePathForRole(files, 'manuscript_quality');
1435
+ const factPath = filePathForRole(files, 'manuscript_fact_check');
1436
+ const metaPath = filePathForRole(files, 'manuscript_meta');
1437
+ const quality = qualityPath ? readJsonFile(qualityPath) : null;
1438
+ const fact = factPath ? readJsonFile(factPath) : null;
1439
+ const meta = metaPath ? readJsonFile(metaPath) : null;
1440
+ const manifestQuality = asRecord(manifest?.quality_gate);
1441
+ const manifestFact = asRecord(manifest?.fact_check);
1442
+ const literature = asRecord(manifest?.literature);
1443
+ const enrichment = asRecord(literature?.enrichment);
1444
+ const sourceCounts = asRecord(literature?.source_counts);
1445
+ const dataSources = toStringList(manifest?.data_sources);
1446
+ const reviewTodo = toStringList(manifest?.human_review_todo);
1447
+ const hints = uniqueStrings([
1448
+ plan.target,
1449
+ plan.disease,
1450
+ `${plan.target} ${plan.disease}`,
1451
+ `${plan.target} manuscript`,
1452
+ `${plan.target} zhongliu`,
1453
+ `${plan.target} quality gate`,
1454
+ `${plan.target} fact check`,
1455
+ `${plan.target} delivery manifest`,
1456
+ `${plan.target} literature evidence`,
1457
+ 'medical research delivery',
1458
+ 'manuscript quality gate',
1459
+ 'manuscript fact check',
1460
+ ]);
1461
+ const figureNames = Array.isArray(manifest?.figures)
1462
+ ? manifest.figures
1463
+ .map(item => {
1464
+ if (!item || typeof item !== 'object' || Array.isArray(item))
1465
+ return null;
1466
+ return String(item.relative ?? item.path ?? '').trim() || null;
1467
+ })
1468
+ .filter(Boolean)
1469
+ : [];
1470
+ return [
1471
+ `# Medical Delivery Summary`,
1472
+ '',
1473
+ `Target: ${quoteMaybe(plan.target)}`,
1474
+ `Disease: ${quoteMaybe(plan.disease)}`,
1475
+ `Slug: ${quoteMaybe(plan.slug)}`,
1476
+ `Manifest path: ${quoteMaybe(plan.manifestPath)}`,
1477
+ '',
1478
+ `Search hints: ${hints.join(' | ')}`,
1479
+ '',
1480
+ '## Quality Gate',
1481
+ `Passed: ${String(quality?.passed ?? manifestQuality?.passed ?? 'unknown')}`,
1482
+ `Grade: ${quoteMaybe(String(quality?.grade ?? manifestQuality?.grade ?? ''))}`,
1483
+ `Score: ${quoteMaybe(String(quality?.score ?? manifestQuality?.score ?? ''))}`,
1484
+ `Errors: ${quoteMaybe(String(quality?.errors ?? manifestQuality?.errors ?? ''))}`,
1485
+ `Warnings: ${quoteMaybe(String(quality?.warnings ?? manifestQuality?.warnings ?? ''))}`,
1486
+ '',
1487
+ '## Fact Check',
1488
+ `Passed: ${String(fact?.passed ?? manifestFact?.passed ?? 'unknown')}`,
1489
+ `Score: ${quoteMaybe(String(fact?.score ?? manifestFact?.score ?? ''))}`,
1490
+ `Claims checked: ${quoteMaybe(String(fact?.claims_checked ?? manifestFact?.claims_checked ?? ''))}`,
1491
+ `Unverified claims: ${Array.isArray(fact?.unverified_claims) ? fact?.unverified_claims.length : quoteMaybe(String(fact?.unverified_claims ?? '0'))}`,
1492
+ '',
1493
+ '## Literature Evidence',
1494
+ `Review count: ${quoteMaybe(String(literature?.count ?? ''))}`,
1495
+ `Agent cache reviews: ${quoteMaybe(String(literature?.agent_cache_count ?? sourceCounts?.agent_cache ?? '0'))}`,
1496
+ `LLM reviews: ${quoteMaybe(String(literature?.llm_count ?? '0'))}`,
1497
+ `Rule-based reviews: ${quoteMaybe(String(literature?.rule_based_count ?? '0'))}`,
1498
+ `Enrichment sources: ${toStringList(enrichment?.sources).join(', ') || 'none'}`,
1499
+ `MeSH count: ${quoteMaybe(String(enrichment?.mesh_count ?? ''))}`,
1500
+ `Citation count available: ${quoteMaybe(String(enrichment?.citation_count_available ?? ''))}`,
1501
+ '',
1502
+ '## Data Sources',
1503
+ ...(dataSources.length > 0 ? dataSources.map(item => `- ${item}`) : ['- none']),
1504
+ '',
1505
+ '## Figures',
1506
+ ...(figureNames.length > 0 ? figureNames.map(item => `- ${item}`) : ['- none']),
1507
+ '',
1508
+ '## Human Review Todo',
1509
+ ...(reviewTodo.length > 0 ? reviewTodo.map(item => `- ${item}`) : ['- none']),
1510
+ '',
1511
+ '## Importable Medical Artifacts',
1512
+ ...plan.sourceFiles.map(item => `- ${item}`),
1513
+ '',
1514
+ '## Delivery Boundary',
1515
+ String(manifest?.disclaimer ?? 'This is a generated medical research delivery draft and requires human review before submission or clinical interpretation.'),
1516
+ '',
1517
+ ...(meta ? [
1518
+ '## Metadata Keys',
1519
+ ...Object.keys(meta).slice(0, 16).map(key => `- ${key}`),
1520
+ '',
1521
+ ] : []),
1522
+ ].join('\n');
1523
+ }
1524
+ function buildTargetMemorySummaryArtifact(plan) {
1525
+ const summaryPath = join(plan.manuscriptsDir, `${plan.slug ?? 'medical_delivery'}_memory_summary.md`);
1526
+ const content = buildTargetMemorySummaryMarkdown(plan);
1527
+ mkdirSync(plan.manuscriptsDir, { recursive: true });
1528
+ writeFileSync(summaryPath, content, 'utf-8');
1529
+ return { summaryPath, content };
1530
+ }
1531
+ function writeTargetMemorySeedRecord(plan, provider, summaryPath, importReport) {
1532
+ const recordPath = join(plan.manuscriptsDir, `${plan.slug ?? 'medical_delivery'}_memory_seed.json`);
1533
+ const payload = {
1534
+ generated_at: new Date().toISOString(),
1535
+ target: plan.target,
1536
+ disease: plan.disease,
1537
+ slug: plan.slug,
1538
+ provider,
1539
+ manifest_path: plan.manifestPath,
1540
+ summary_path: summaryPath,
1541
+ source_files: summaryPath ? [summaryPath, ...plan.sourceFiles] : [...plan.sourceFiles],
1542
+ missing_roles: plan.missingRoles,
1543
+ import_ok: importReport?.ok ?? false,
1544
+ import_exit_code: importReport?.exitCode ?? null,
1545
+ staged_files: importReport?.stagedFiles ?? [],
1546
+ warnings: uniqueStrings([...(plan.warnings ?? []), ...(importReport?.warnings ?? [])]),
1547
+ };
1548
+ writeFileSync(recordPath, JSON.stringify(payload, null, 2), 'utf-8');
1549
+ return recordPath;
1550
+ }
1551
+ function filePathForRole(files, role) {
1552
+ const entry = files.find(item => item && typeof item === 'object' && !Array.isArray(item) && String(item.role ?? '') === role);
1553
+ const path = entry?.path;
1554
+ return typeof path === 'string' && path.trim() ? path : null;
1555
+ }
1556
+ function asRecord(value) {
1557
+ return value && typeof value === 'object' && !Array.isArray(value)
1558
+ ? value
1559
+ : null;
1560
+ }
1561
+ export function resolveTargetMemorySeedPlan(options) {
1562
+ const projectDir = resolve(String(options.projectDir ?? PROJECT_DIR));
1563
+ const platform = resolveTargetPlatform(projectDir);
1564
+ if (!platform) {
1565
+ return {
1566
+ ok: false,
1567
+ projectDir,
1568
+ workflowRoot: resolve(projectDir, 'target-research-platform'),
1569
+ outputDir: resolve(projectDir, 'target-research-platform', String(options.output ?? './output')),
1570
+ manuscriptsDir: resolve(projectDir, 'target-research-platform', String(options.output ?? './output'), 'manuscripts'),
1571
+ target: options.target,
1572
+ disease: options.disease,
1573
+ slug: null,
1574
+ manifestPath: null,
1575
+ sourceFiles: [],
1576
+ missingRoles: [...DELIVERY_MEMORY_IMPORT_ROLES],
1577
+ warnings: ['target-research-platform not found; cannot resolve medical delivery artifacts for memory seeding.'],
1578
+ };
1579
+ }
1580
+ const outputDir = resolveTargetOutputDir(platform, options.output);
1581
+ const manuscriptsDir = join(outputDir, 'manuscripts');
1582
+ if (!existsSync(manuscriptsDir)) {
1583
+ return {
1584
+ ok: false,
1585
+ projectDir,
1586
+ workflowRoot: platform.platformDir,
1587
+ outputDir,
1588
+ manuscriptsDir,
1589
+ target: options.target,
1590
+ disease: options.disease,
1591
+ slug: null,
1592
+ manifestPath: null,
1593
+ sourceFiles: [],
1594
+ missingRoles: [...DELIVERY_MEMORY_IMPORT_ROLES],
1595
+ warnings: ['Manuscripts output directory does not exist yet. Run the native manuscript/package command from target-research-platform first.'],
1596
+ };
1597
+ }
1598
+ const targetKey = normalizeTargetToken(options.target);
1599
+ const diseaseKey = normalizeTargetToken(options.disease);
1600
+ const manifestFiles = readdirSync(manuscriptsDir)
1601
+ .filter(name => name.endsWith('_delivery_manifest.json'))
1602
+ .map(name => join(manuscriptsDir, name));
1603
+ const matchedManifest = manifestFiles.find(filePath => {
1604
+ const payload = readJsonFile(filePath);
1605
+ return normalizeTargetToken(String(payload?.target ?? '')) === targetKey
1606
+ && normalizeTargetToken(String(payload?.disease ?? '')) === diseaseKey;
1607
+ }) ?? null;
1608
+ if (!matchedManifest) {
1609
+ return {
1610
+ ok: false,
1611
+ projectDir,
1612
+ workflowRoot: platform.platformDir,
1613
+ outputDir,
1614
+ manuscriptsDir,
1615
+ target: options.target,
1616
+ disease: options.disease,
1617
+ slug: null,
1618
+ manifestPath: null,
1619
+ sourceFiles: [],
1620
+ missingRoles: [...DELIVERY_MEMORY_IMPORT_ROLES],
1621
+ warnings: ['Delivery manifest for the requested target/disease was not found. Run the native package command for this study first.'],
1622
+ };
1623
+ }
1624
+ const manifest = readJsonFile(matchedManifest);
1625
+ const files = Array.isArray(manifest?.files) ? manifest.files : [];
1626
+ const selectedFiles = [];
1627
+ const missingRoles = [];
1628
+ const warnings = [];
1629
+ for (const role of DELIVERY_MEMORY_IMPORT_ROLES) {
1630
+ const item = files.find(entry => {
1631
+ if (!entry || typeof entry !== 'object' || Array.isArray(entry))
1632
+ return false;
1633
+ return String(entry.role ?? '') === role;
1634
+ });
1635
+ const filePath = item?.path ? String(item.path) : null;
1636
+ if (!filePath || !existsSync(filePath)) {
1637
+ missingRoles.push(role);
1638
+ continue;
1639
+ }
1640
+ selectedFiles.push(filePath);
1641
+ }
1642
+ if (selectedFiles.length === 0) {
1643
+ warnings.push('The delivery manifest exists, but none of the memory-importable medical artifacts were found on disk.');
1644
+ }
1645
+ return {
1646
+ ok: selectedFiles.length > 0,
1647
+ projectDir,
1648
+ workflowRoot: platform.platformDir,
1649
+ outputDir,
1650
+ manuscriptsDir,
1651
+ target: options.target,
1652
+ disease: options.disease,
1653
+ slug: deriveMemorySlugFromManifest(matchedManifest),
1654
+ manifestPath: matchedManifest,
1655
+ sourceFiles: selectedFiles,
1656
+ missingRoles,
1657
+ warnings,
1658
+ };
1659
+ }
1660
+ export function seedTargetDeliveryMemory(options) {
1661
+ const plan = resolveTargetMemorySeedPlan(options);
1662
+ if (!plan.ok) {
1663
+ return {
1664
+ ok: false,
1665
+ target: options.target,
1666
+ disease: options.disease,
1667
+ provider: String(options.provider ?? 'gbrain'),
1668
+ manifestPath: plan.manifestPath,
1669
+ summaryPath: null,
1670
+ recordPath: null,
1671
+ sourceFiles: plan.sourceFiles,
1672
+ missingRoles: plan.missingRoles,
1673
+ importReport: null,
1674
+ warnings: plan.warnings,
1675
+ };
1676
+ }
1677
+ const summary = buildTargetMemorySummaryArtifact(plan);
1678
+ const importReport = importMemoryProviderKnowledge({
1679
+ projectDir: plan.projectDir,
1680
+ provider: String(options.provider ?? 'gbrain'),
1681
+ files: [summary.summaryPath, ...plan.sourceFiles],
1682
+ noEmbed: true,
1683
+ });
1684
+ const recordPath = writeTargetMemorySeedRecord(plan, String(options.provider ?? 'gbrain'), summary.summaryPath, importReport);
1685
+ return {
1686
+ ok: importReport.ok,
1687
+ target: options.target,
1688
+ disease: options.disease,
1689
+ provider: String(options.provider ?? 'gbrain'),
1690
+ manifestPath: plan.manifestPath,
1691
+ summaryPath: summary.summaryPath,
1692
+ recordPath,
1693
+ sourceFiles: [summary.summaryPath, ...plan.sourceFiles],
1694
+ missingRoles: plan.missingRoles,
1695
+ importReport,
1696
+ warnings: [...plan.warnings, ...importReport.warnings],
1697
+ };
1698
+ }
1699
+ function safeTargetLearningSegment(value) {
1700
+ return value
1701
+ .toLowerCase()
1702
+ .replace(/[^a-z0-9]+/g, '-')
1703
+ .replace(/^-+|-+$/g, '')
1704
+ || 'medical-delivery';
1705
+ }
1706
+ function toProjectPath(projectDir, filePath) {
1707
+ const normalized = relative(projectDir, filePath).replace(/\\/g, '/');
1708
+ return normalized && !normalized.startsWith('..') ? normalized : filePath.replace(/\\/g, '/');
1709
+ }
1710
+ function buildTargetDeliveryLearningSummary(options) {
1711
+ const parts = [
1712
+ `Medical delivery "${options.taskLabel}"`,
1713
+ options.qualityPassed === true
1714
+ ? `passed the manuscript quality gate${options.qualityGrade ? ` (${options.qualityGrade})` : ''}${options.qualityScore != null ? ` with score ${options.qualityScore}` : ''}`
1715
+ : options.qualityPassed === false
1716
+ ? 'did not pass the manuscript quality gate'
1717
+ : 'is still missing a definitive manuscript quality result',
1718
+ options.factPassed === true
1719
+ ? `${options.claimsChecked ?? 'multiple'} claims passed fact check${options.factScore != null ? ` (score ${options.factScore})` : ''}`
1720
+ : options.factPassed === false
1721
+ ? 'still has unresolved fact-check issues'
1722
+ : 'still needs more fact-check evidence',
1723
+ `literature review coverage=${options.reviewCount ?? 0} (agent=${options.agentCount}, llm=${options.llmCount}, rule=${options.ruleBasedCount})`,
1724
+ options.seedProvider
1725
+ ? `memory seed ${options.seedProvider}=${options.seedOk === true ? 'ready' : options.seedOk === false ? 'failed' : 'pending'}`
1726
+ : 'memory seed not requested',
1727
+ ];
1728
+ return `${parts.join('; ')}. Review this candidate before promoting it into durable project memory or knowledge-base rules.`;
1729
+ }
1730
+ export function settleTargetDeliveryLearning(options) {
1731
+ const plan = resolveTargetMemorySeedPlan(options);
1732
+ if (!plan.ok || !plan.manifestPath) {
1733
+ return {
1734
+ ok: false,
1735
+ target: options.target,
1736
+ disease: options.disease,
1737
+ candidateId: null,
1738
+ candidatePath: null,
1739
+ candidateMarkdownPath: null,
1740
+ mirrorRecordPath: null,
1741
+ mirrorSummaryPath: null,
1742
+ recommendedAction: null,
1743
+ promotable: false,
1744
+ brainNodeId: null,
1745
+ brainIngestOk: null,
1746
+ sourceFiles: plan.sourceFiles,
1747
+ warnings: plan.warnings,
1748
+ };
1749
+ }
1750
+ const manifest = readJsonFile(plan.manifestPath);
1751
+ if (!manifest) {
1752
+ return {
1753
+ ok: false,
1754
+ target: options.target,
1755
+ disease: options.disease,
1756
+ candidateId: null,
1757
+ candidatePath: null,
1758
+ candidateMarkdownPath: null,
1759
+ mirrorRecordPath: null,
1760
+ mirrorSummaryPath: null,
1761
+ recommendedAction: null,
1762
+ promotable: false,
1763
+ brainNodeId: null,
1764
+ brainIngestOk: null,
1765
+ sourceFiles: plan.sourceFiles,
1766
+ warnings: ['The delivery manifest exists but could not be parsed.'],
1767
+ };
1768
+ }
1769
+ const files = Array.isArray(manifest.files) ? manifest.files : [];
1770
+ const qualityPath = filePathForRole(files, 'manuscript_quality');
1771
+ const factPath = filePathForRole(files, 'manuscript_fact_check');
1772
+ const metaPath = filePathForRole(files, 'manuscript_meta');
1773
+ const packagePath = filePathForRole(files, 'delivery_package');
1774
+ const quality = qualityPath ? readJsonFile(qualityPath) : null;
1775
+ const fact = factPath ? readJsonFile(factPath) : null;
1776
+ const literature = asRecord(manifest.literature);
1777
+ const manifestQuality = asRecord(manifest.quality_gate);
1778
+ const manifestFact = asRecord(manifest.fact_check);
1779
+ const reviewTodo = toStringList(manifest.human_review_todo);
1780
+ const qualityPassed = typeof quality?.passed === 'boolean'
1781
+ ? quality.passed
1782
+ : typeof manifestQuality?.passed === 'boolean'
1783
+ ? manifestQuality.passed
1784
+ : null;
1785
+ const factPassed = typeof fact?.passed === 'boolean'
1786
+ ? fact.passed
1787
+ : typeof manifestFact?.passed === 'boolean'
1788
+ ? manifestFact.passed
1789
+ : null;
1790
+ const qualityGrade = String(quality?.grade ?? manifestQuality?.grade ?? '').trim() || null;
1791
+ const qualityScore = toNumber(quality?.score ?? manifestQuality?.score);
1792
+ const factScore = toNumber(fact?.score ?? manifestFact?.score);
1793
+ const claimsChecked = toNumber(fact?.claims_checked ?? manifestFact?.claims_checked);
1794
+ const reviewCount = toNumber(literature?.count);
1795
+ const agentCount = toNumber(literature?.agent_cache_count) ?? 0;
1796
+ const llmCount = toNumber(literature?.llm_count) ?? 0;
1797
+ const ruleBasedCount = toNumber(literature?.rule_based_count) ?? 0;
1798
+ const slug = plan.slug ?? safeTargetLearningSegment(`${plan.target}-${plan.disease}`);
1799
+ const recommendedAction = qualityPassed === false || factPassed === false
1800
+ ? 'resolve-failures-first'
1801
+ : qualityPassed === true && factPassed === true
1802
+ ? 'review-for-knowledge-base'
1803
+ : 'record-more-evidence';
1804
+ const promotable = recommendedAction === 'review-for-knowledge-base';
1805
+ const warnings = uniqueStrings([
1806
+ ...plan.warnings,
1807
+ ...(plan.missingRoles.length > 0
1808
+ ? [`Memory-seeding source roles are incomplete: ${plan.missingRoles.join(', ')}`]
1809
+ : []),
1810
+ ...(qualityPassed === false ? ['Manuscript quality gate did not pass for this delivery.'] : []),
1811
+ ...(factPassed === false ? ['Manuscript fact check did not pass for this delivery.'] : []),
1812
+ ...(qualityPassed !== true ? ['Quality evidence is incomplete; keep this learning candidate under review.'] : []),
1813
+ ...(factPassed !== true ? ['Fact-check evidence is incomplete; keep this learning candidate under review.'] : []),
1814
+ ...(ruleBasedCount > 0 && agentCount + llmCount === 0
1815
+ ? ['Literature interpretation still depends on rule-based fallback; upgrade Agent/LLM review before promotion.']
1816
+ : []),
1817
+ ...reviewTodo.map(item => `Human review todo: ${item}`),
1818
+ ...(options.memorySeed && !options.memorySeed.ok
1819
+ ? [`Memory seed via ${options.memorySeed.provider} is incomplete; cross-session recall may miss this delivery.`]
1820
+ : []),
1821
+ ]);
1822
+ const scaleRoot = resolve(plan.projectDir, '.scale');
1823
+ const learningDir = join(scaleRoot, 'memory', 'learning-candidates');
1824
+ const candidateId = `MLC-medical-${safeTargetLearningSegment(slug)}`;
1825
+ const candidatePath = join(learningDir, `${candidateId}.json`);
1826
+ const candidateMarkdownPath = join(learningDir, `${candidateId}.md`);
1827
+ const mirrorRecordPath = join(plan.manuscriptsDir, `${slug}_memory_learning_candidate.json`);
1828
+ const mirrorSummaryPath = join(plan.manuscriptsDir, `${slug}_memory_learning_candidate.md`);
1829
+ const artifactPaths = uniqueStrings([
1830
+ plan.manifestPath,
1831
+ qualityPath,
1832
+ factPath,
1833
+ metaPath,
1834
+ packagePath,
1835
+ options.memorySeed?.recordPath,
1836
+ options.memorySeed?.summaryPath,
1837
+ ...plan.sourceFiles,
1838
+ ]);
1839
+ const candidate = {
1840
+ version: '1.0',
1841
+ id: candidateId,
1842
+ status: 'candidate',
1843
+ generatedAt: new Date().toISOString(),
1844
+ title: `Medical learning candidate: ${plan.target} / ${plan.disease}`,
1845
+ task: `Review medical delivery for ${plan.target} in ${plan.disease}`,
1846
+ taskId: `medical-delivery-${safeTargetLearningSegment(slug)}`,
1847
+ sessionId: options.memorySeed?.provider ? `medical-memory-${safeTargetLearningSegment(options.memorySeed.provider)}` : undefined,
1848
+ level: 'M',
1849
+ summary: buildTargetDeliveryLearningSummary({
1850
+ taskLabel: `${plan.target} / ${plan.disease}`,
1851
+ qualityPassed,
1852
+ qualityGrade,
1853
+ qualityScore,
1854
+ factPassed,
1855
+ factScore,
1856
+ claimsChecked,
1857
+ reviewCount,
1858
+ agentCount,
1859
+ llmCount,
1860
+ ruleBasedCount,
1861
+ seedProvider: options.memorySeed?.provider ?? null,
1862
+ seedOk: options.memorySeed?.ok ?? null,
1863
+ }),
1864
+ recommendedAction,
1865
+ promotable,
1866
+ tags: uniqueStrings([
1867
+ 'medical-delivery',
1868
+ 'medical-learning',
1869
+ `target-${safeTargetLearningSegment(plan.target)}`,
1870
+ `disease-${safeTargetLearningSegment(plan.disease)}`,
1871
+ promotable ? 'verified-evidence' : 'review-required',
1872
+ qualityPassed === false || factPassed === false ? 'failed-evidence' : null,
1873
+ ]),
1874
+ evidenceIds: [],
1875
+ sessionEventIds: [],
1876
+ knowledgeIds: [],
1877
+ graphRefs: [],
1878
+ artifactPaths: artifactPaths.map(filePath => toProjectPath(plan.projectDir, filePath)),
1879
+ evidenceSummaries: [
1880
+ {
1881
+ id: 'delivery-manifest',
1882
+ status: 'passed',
1883
+ title: 'Delivery manifest',
1884
+ summary: `Resolved at ${toProjectPath(plan.projectDir, plan.manifestPath)} with ${artifactPaths.length} linked artifact(s).`,
1885
+ },
1886
+ {
1887
+ id: 'quality-gate',
1888
+ status: qualityPassed === true ? 'passed' : qualityPassed === false ? 'failed' : 'pending',
1889
+ title: 'Manuscript quality gate',
1890
+ summary: `grade=${qualityGrade ?? 'n/a'}; score=${qualityScore ?? 'n/a'}; passed=${qualityPassed == null ? 'unknown' : String(qualityPassed)}`,
1891
+ },
1892
+ {
1893
+ id: 'fact-check',
1894
+ status: factPassed === true ? 'passed' : factPassed === false ? 'failed' : 'pending',
1895
+ title: 'Manuscript fact check',
1896
+ summary: `score=${factScore ?? 'n/a'}; claims_checked=${claimsChecked ?? 'n/a'}; passed=${factPassed == null ? 'unknown' : String(factPassed)}`,
1897
+ },
1898
+ {
1899
+ id: 'literature-evidence',
1900
+ status: ruleBasedCount > 0 && agentCount + llmCount === 0 ? 'warning' : 'passed',
1901
+ title: 'Literature evidence mix',
1902
+ summary: `reviews=${reviewCount ?? 0}; agent=${agentCount}; llm=${llmCount}; rule=${ruleBasedCount}`,
1903
+ },
1904
+ ...(options.memorySeed ? [{
1905
+ id: 'memory-seed',
1906
+ status: options.memorySeed.ok ? 'passed' : 'failed',
1907
+ title: `Memory seed (${options.memorySeed.provider})`,
1908
+ summary: `summary=${options.memorySeed.summaryPath ? 'ready' : 'missing'}; record=${options.memorySeed.recordPath ? 'ready' : 'missing'}`,
1909
+ }] : []),
1910
+ ],
1911
+ sessionSummaries: [
1912
+ {
1913
+ id: 'medical-delivery',
1914
+ eventType: 'medical.delivery.ready',
1915
+ phase: 'package',
1916
+ message: `Delivery package available for ${plan.target} / ${plan.disease}.`,
1917
+ },
1918
+ ...(options.memorySeed ? [{
1919
+ id: 'medical-memory-seed',
1920
+ eventType: 'medical.memory.seed',
1921
+ phase: 'remember',
1922
+ message: `Seeded to ${options.memorySeed.provider}: ${options.memorySeed.ok ? 'ok' : 'failed'}.`,
1923
+ }] : []),
1924
+ ],
1925
+ warnings,
1926
+ contextBudget: {
1927
+ used: artifactPaths.length,
1928
+ limit: artifactPaths.length,
1929
+ remaining: 0,
1930
+ overBudget: false,
1931
+ },
1932
+ contentRef: toProjectPath(plan.projectDir, candidateMarkdownPath),
1933
+ };
1934
+ mkdirSync(learningDir, { recursive: true });
1935
+ writeFileSync(candidatePath, JSON.stringify(candidate, null, 2), 'utf-8');
1936
+ writeFileSync(candidateMarkdownPath, renderMemoryLearningCandidateMarkdown(candidate), 'utf-8');
1937
+ let brainNodeId = null;
1938
+ let brainIngestOk = null;
1939
+ let brainWarnings = [];
1940
+ if (options.ingestToBrain) {
1941
+ const brain = new MemoryBrain({ projectDir: plan.projectDir });
1942
+ try {
1943
+ const ingest = brain.ingest({ from: 'candidate', candidateId, type: 'decision' });
1944
+ brainIngestOk = ingest.ok;
1945
+ brainNodeId = ingest.nodes[0]?.id ?? null;
1946
+ brainWarnings = ingest.warnings;
1947
+ }
1948
+ finally {
1949
+ brain.close();
1950
+ }
1951
+ }
1952
+ const finalWarnings = uniqueStrings([...warnings, ...brainWarnings]);
1953
+ const finalCandidate = {
1954
+ ...candidate,
1955
+ warnings: finalWarnings,
1956
+ };
1957
+ const summaryMarkdown = renderMemoryLearningCandidateMarkdown(finalCandidate);
1958
+ writeFileSync(candidatePath, JSON.stringify(finalCandidate, null, 2), 'utf-8');
1959
+ writeFileSync(candidateMarkdownPath, summaryMarkdown, 'utf-8');
1960
+ writeFileSync(mirrorSummaryPath, summaryMarkdown, 'utf-8');
1961
+ writeFileSync(mirrorRecordPath, JSON.stringify({
1962
+ generated_at: finalCandidate.generatedAt,
1963
+ target: plan.target,
1964
+ disease: plan.disease,
1965
+ slug,
1966
+ candidate_id: candidateId,
1967
+ candidate_path: candidatePath,
1968
+ candidate_markdown_path: candidateMarkdownPath,
1969
+ summary_path: mirrorSummaryPath,
1970
+ recommended_action: recommendedAction,
1971
+ promotable,
1972
+ brain_ingest_ok: brainIngestOk,
1973
+ brain_node_id: brainNodeId,
1974
+ source_files: artifactPaths,
1975
+ warnings: finalWarnings,
1976
+ candidate: finalCandidate,
1977
+ }, null, 2), 'utf-8');
1978
+ return {
1979
+ ok: !options.ingestToBrain || brainIngestOk !== false,
1980
+ target: plan.target,
1981
+ disease: plan.disease,
1982
+ candidateId,
1983
+ candidatePath,
1984
+ candidateMarkdownPath,
1985
+ mirrorRecordPath,
1986
+ mirrorSummaryPath,
1987
+ recommendedAction,
1988
+ promotable,
1989
+ brainNodeId,
1990
+ brainIngestOk,
1991
+ sourceFiles: artifactPaths,
1992
+ warnings: finalWarnings,
1993
+ };
1994
+ }
1995
+ function normalizeMemoryReviewAction(value) {
1996
+ const normalized = String(value ?? '').trim().toLowerCase();
1997
+ if (normalized === 'approve' || normalized === 'reject' || normalized === 'stale' || normalized === 'restore') {
1998
+ return normalized;
1999
+ }
2000
+ throw new Error('memory-review action must be approve, reject, stale, or restore.');
2001
+ }
2002
+ function normalizeTargetMemoryScope(value) {
2003
+ if (value === undefined || value === null || value === '')
2004
+ return undefined;
2005
+ const normalized = String(value).trim().toLowerCase();
2006
+ if (normalized === 'project' || normalized === 'workspace' || normalized === 'global-candidate')
2007
+ return normalized;
2008
+ throw new Error('--scope must be project, workspace, or global-candidate.');
2009
+ }
2010
+ function extractLastJson(stdout) {
2011
+ const trimmed = stdout.replace(/^\uFEFF/, '').trim();
2012
+ if (!trimmed)
2013
+ return null;
2014
+ const firstBrace = trimmed.indexOf('{');
2015
+ if (firstBrace >= 0) {
2016
+ try {
2017
+ return JSON.parse(trimmed.slice(firstBrace));
2018
+ }
2019
+ catch {
2020
+ // fall through
2021
+ }
2022
+ }
2023
+ const lines = trimmed.split('\n').filter(Boolean);
2024
+ for (let i = lines.length - 1; i >= 0; i -= 1) {
2025
+ const line = lines[i].trim();
2026
+ if (!line.startsWith('{') && !line.startsWith('['))
2027
+ continue;
2028
+ try {
2029
+ return JSON.parse(line);
2030
+ }
2031
+ catch {
2032
+ // continue scanning
2033
+ }
2034
+ }
2035
+ return null;
2036
+ }
2037
+ function runPythonCommand(platform, args, options) {
2038
+ const spawnOptions = {
2039
+ cwd: platform.platformDir,
2040
+ env: {
2041
+ ...process.env,
2042
+ PYTHONIOENCODING: 'utf-8',
2043
+ PYTHONUTF8: '1',
2044
+ },
2045
+ encoding: 'utf-8',
2046
+ };
2047
+ const commandArgs = [platform.mainPy, ...args];
2048
+ const useInherit = options?.inherit ?? !options?.json;
2049
+ if (useInherit) {
2050
+ const result = spawnSync('python', commandArgs, {
2051
+ ...spawnOptions,
2052
+ stdio: 'inherit',
2053
+ });
2054
+ return {
2055
+ code: result.status ?? 1,
2056
+ stdout: '',
2057
+ stderr: '',
2058
+ parsed: null,
2059
+ };
2060
+ }
2061
+ const result = spawnSync('python', commandArgs, {
2062
+ ...spawnOptions,
2063
+ stdio: ['ignore', 'pipe', 'pipe'],
2064
+ });
2065
+ const stdout = String(result.stdout ?? '');
2066
+ const stderr = String(result.stderr ?? '');
2067
+ const parsedRaw = extractLastJson(stdout);
2068
+ const parsed = parsedRaw && typeof parsedRaw === 'object' && !Array.isArray(parsedRaw)
2069
+ ? parsedRaw
2070
+ : null;
2071
+ return {
2072
+ code: result.status ?? 1,
2073
+ stdout,
2074
+ stderr,
2075
+ parsed,
2076
+ };
2077
+ }
2078
+ function readMedicalResearchOsPlan(platform) {
2079
+ const script = [
2080
+ 'import json',
2081
+ 'from pathlib import Path',
2082
+ 'from src.dashboard.app import DashboardState',
2083
+ 'payload = DashboardState(Path.cwd()).build_medical_research_os_plan()',
2084
+ 'print(json.dumps(payload, ensure_ascii=False))',
2085
+ ].join('; ');
2086
+ const result = spawnSync('python', ['-c', script], {
2087
+ cwd: platform.platformDir,
2088
+ env: {
2089
+ ...process.env,
2090
+ PYTHONIOENCODING: 'utf-8',
2091
+ PYTHONUTF8: '1',
2092
+ },
2093
+ encoding: 'utf-8',
2094
+ stdio: ['ignore', 'pipe', 'pipe'],
2095
+ });
2096
+ const stdout = String(result.stdout ?? '');
2097
+ const stderr = String(result.stderr ?? '');
2098
+ const parsedRaw = extractLastJson(stdout);
2099
+ const parsed = parsedRaw && typeof parsedRaw === 'object' && !Array.isArray(parsedRaw)
2100
+ ? parsedRaw
2101
+ : null;
2102
+ return {
2103
+ code: result.status ?? 1,
2104
+ stdout,
2105
+ stderr,
2106
+ parsed,
2107
+ };
2108
+ }
2109
+ function buildTargetPackageCommandArgs(args, jsonMode) {
2110
+ const commandArgs = [
2111
+ 'package',
2112
+ '--target',
2113
+ String(args.target),
2114
+ '--disease',
2115
+ String(args.disease),
2116
+ '--output',
2117
+ String(args.output ?? './output'),
2118
+ ];
2119
+ if (jsonMode)
2120
+ commandArgs.push('--json');
2121
+ return commandArgs;
2122
+ }
2123
+ export const targetAnalyzeCommand = defineCommand({
2124
+ meta: {
2125
+ name: 'analyze',
2126
+ description: 'Run full 4-stage target research pipeline (expression → screening → deep research → business)',
2127
+ },
2128
+ args: {
2129
+ target: { type: 'positional', required: true, description: 'Target gene symbol, e.g. CDK4' },
2130
+ disease: { type: 'string', required: true, description: 'Disease name, e.g. "breast cancer"' },
2131
+ cancers: { type: 'string', default: 'BRCA', description: 'Comma-separated cancer codes, e.g. BRCA,LUAD' },
2132
+ ensg: { type: 'string', description: 'Optional Ensembl gene ID' },
2133
+ modality: {
2134
+ type: 'string',
2135
+ default: 'small_molecule',
2136
+ description: 'Drug modality: small_molecule | antibody | cell_therapy | gene_therapy',
2137
+ },
2138
+ 'risk-level': { type: 'string', default: 'medium', description: 'Risk level: low | medium | high' },
2139
+ output: { type: 'string', default: './output', description: 'Output directory under target-research-platform' },
2140
+ dir: { type: 'string', default: PROJECT_DIR, description: 'Project root directory' },
2141
+ json: { type: 'boolean', default: false, description: 'Output machine-readable JSON' },
2142
+ },
2143
+ async run({ args }) {
2144
+ const platform = resolveTargetPlatform(String(args.dir ?? PROJECT_DIR));
2145
+ if (!platform) {
2146
+ console.error('未找到 target-research-platform/main.py,请在 yixue-scale-engine 仓库根目录运行。');
2147
+ process.exit(1);
2148
+ }
2149
+ const cancers = parseCancerList(String(args.cancers ?? 'BRCA'));
2150
+ const cmdArgs = [
2151
+ 'full',
2152
+ '--target', String(args.target),
2153
+ '--disease', String(args.disease),
2154
+ '--cancers', ...cancers,
2155
+ '--modality', String(args.modality ?? 'small_molecule'),
2156
+ '--risk-level', String(args['risk-level'] ?? 'medium'),
2157
+ '--output', String(args.output ?? './output'),
2158
+ '--cache', './cache',
2159
+ ];
2160
+ if (args.ensg)
2161
+ cmdArgs.push('--ensg', String(args.ensg));
2162
+ if (args.json)
2163
+ cmdArgs.push('--json');
2164
+ if (!args.json) {
2165
+ console.log(`\n开始分析: ${args.target} / ${args.disease} (${cancers.join(', ')})`);
2166
+ console.log('预计耗时 5-15 分钟,请保持网络畅通。\n');
2167
+ }
2168
+ const result = runPythonCommand(platform, cmdArgs, { json: Boolean(args.json), inherit: !args.json });
2169
+ if (args.json) {
2170
+ if (result.parsed) {
2171
+ console.log(JSON.stringify(result.parsed, null, 2));
2172
+ }
2173
+ else {
2174
+ console.log(JSON.stringify({
2175
+ success: false,
2176
+ error: 'Pipeline finished without JSON output',
2177
+ stderr: result.stderr.slice(-1000),
2178
+ }, null, 2));
2179
+ }
2180
+ process.exit(result.code);
2181
+ }
2182
+ if (result.code !== 0) {
2183
+ console.error('\n分析失败,请运行 target-research-platform 的原生 doctor/测试检查环境。');
2184
+ process.exit(result.code);
2185
+ }
2186
+ console.log('\n 下一步:');
2187
+ console.log(' medscale status # 查看运行状态与报告链接');
2188
+ console.log(' medscale dashboard # 打开医学研究工作台 http://127.0.0.1:18766');
2189
+ },
2190
+ });
2191
+ function printDeliveryReadiness(snapshot) {
2192
+ const delivery = snapshot.deliveryPackage;
2193
+ if (!delivery)
2194
+ return;
2195
+ const packageAudit = delivery.packageAudit;
2196
+ const findings = delivery.qualityFindings ?? [];
2197
+ const evidence = delivery.literatureEvidence;
2198
+ const todo = delivery.humanReviewTodo ?? [];
2199
+ if (!packageAudit && !findings.length && !evidence && !todo.length)
2200
+ return;
2201
+ console.log('\n Delivery readiness:');
2202
+ if (packageAudit) {
2203
+ const verdict = packageAudit.passed === true ? 'PASS' : packageAudit.passed === false ? 'FAIL' : 'UNKNOWN';
2204
+ console.log(` ZIP audit: ${verdict}; entries=${packageAudit.entryCount ?? '-'}; files=${packageAudit.filesChecked ?? '-'}`);
2205
+ console.log(` Archive refs: images=${packageAudit.imageRefsChecked ?? '-'}; links=${packageAudit.markdownRefsChecked ?? '-'}; README=${packageAudit.readmePresent === true ? 'ready' : packageAudit.readmePresent === false ? 'missing' : 'unknown'}`);
2206
+ if ((packageAudit.brokenImageRefs ?? 0) > 0 || (packageAudit.brokenMarkdownRefs ?? 0) > 0) {
2207
+ console.log(` Broken refs: images=${packageAudit.brokenImageRefs ?? 0}; links=${packageAudit.brokenMarkdownRefs ?? 0}`);
2208
+ }
2209
+ }
2210
+ if (findings.length > 0) {
2211
+ console.log(' Quality findings:');
2212
+ for (const finding of findings.slice(0, 5)) {
2213
+ const severity = finding.severity ?? 'unknown';
2214
+ const id = finding.id ?? 'quality';
2215
+ const message = finding.message ?? '';
2216
+ console.log(` - [${severity}] ${id}: ${message}`);
2217
+ }
2218
+ }
2219
+ if (evidence) {
2220
+ const sources = evidence.sources.length > 0 ? evidence.sources.join(', ') : 'none';
2221
+ console.log(` Literature reviews: ${evidence.count ?? '-'} papers; Agent=${evidence.agentCacheCount ?? 0}; LLM=${evidence.llmCount ?? 0}; rule=${evidence.ruleBasedCount ?? 0}`);
2222
+ console.log(` Enrichment: sources=${sources}; MeSH=${evidence.meshCount ?? 0}; citations=${evidence.citationCountAvailable ?? 0}; cache=${evidence.cacheUsed ? 'used' : 'not used'}`);
2223
+ }
2224
+ if (todo.length > 0) {
2225
+ console.log(' Human review todo:');
2226
+ for (const item of todo.slice(0, 8)) {
2227
+ console.log(` - ${item}`);
2228
+ }
2229
+ }
2230
+ }
2231
+ function printMemorySeedSummary(snapshot) {
2232
+ const seed = snapshot.memorySeed;
2233
+ if (!seed)
2234
+ return;
2235
+ const status = seed.importOk === true
2236
+ ? 'ready'
2237
+ : seed.importOk === false
2238
+ ? 'failed'
2239
+ : (seed.recordReady || seed.summaryReady ? 'partial' : 'pending');
2240
+ console.log('\n Memory seed:');
2241
+ console.log(` Status: ${status}`);
2242
+ console.log(` Provider: ${seed.provider ?? 'unknown'}`);
2243
+ if (seed.generatedAt)
2244
+ console.log(` Generated: ${seed.generatedAt}`);
2245
+ console.log(` Record: ${seed.recordReady ? 'ready' : 'missing'}`);
2246
+ console.log(` Summary: ${seed.summaryReady ? 'ready' : 'missing'}`);
2247
+ if (seed.sourceFileCount != null || seed.stagedFileCount != null) {
2248
+ console.log(` Files: source=${seed.sourceFileCount ?? 0}; staged=${seed.stagedFileCount ?? 0}`);
2249
+ }
2250
+ if (seed.recordPath)
2251
+ console.log(` Record path: ${seed.recordPath}`);
2252
+ if (seed.summaryPath)
2253
+ console.log(` Summary path: ${seed.summaryPath}`);
2254
+ if (seed.missingRoles.length > 0) {
2255
+ console.log(` Missing roles: ${seed.missingRoles.join(', ')}`);
2256
+ }
2257
+ if (seed.warnings.length > 0) {
2258
+ console.log(' Warnings:');
2259
+ for (const warning of seed.warnings.slice(0, 5)) {
2260
+ console.log(` - ${warning}`);
2261
+ }
2262
+ }
2263
+ }
2264
+ function printLearningCandidateSummary(snapshot) {
2265
+ const learning = snapshot.learningCandidate;
2266
+ if (!learning)
2267
+ return;
2268
+ const status = learning.brainIngestOk === false
2269
+ ? 'brain-ingest-failed'
2270
+ : learning.promotable
2271
+ ? 'ready-for-review'
2272
+ : learning.recommendedAction === 'resolve-failures-first'
2273
+ ? 'blocked'
2274
+ : 'collect-more-evidence';
2275
+ console.log('\n Learning candidate:');
2276
+ console.log(` Status: ${status}`);
2277
+ console.log(` Candidate ID: ${learning.candidateId ?? 'unknown'}`);
2278
+ console.log(` Recommended action: ${learning.recommendedAction ?? 'unknown'}`);
2279
+ console.log(` Promotable: ${learning.promotable ? 'yes' : 'no'}`);
2280
+ if (learning.generatedAt)
2281
+ console.log(` Generated: ${learning.generatedAt}`);
2282
+ console.log(` Record: ${learning.recordReady ? 'ready' : 'missing'}`);
2283
+ console.log(` Summary: ${learning.summaryReady ? 'ready' : 'missing'}`);
2284
+ if (learning.brainNodeId)
2285
+ console.log(` Brain node: ${learning.brainNodeId}`);
2286
+ if (learning.recordPath)
2287
+ console.log(` Record path: ${learning.recordPath}`);
2288
+ if (learning.summaryPath)
2289
+ console.log(` Summary path: ${learning.summaryPath}`);
2290
+ if (learning.warnings.length > 0) {
2291
+ console.log(' Warnings:');
2292
+ for (const warning of learning.warnings.slice(0, 5)) {
2293
+ console.log(` - ${warning}`);
2294
+ }
2295
+ }
2296
+ }
2297
+ export const targetStatusCommand = defineCommand({
2298
+ meta: {
2299
+ name: 'status',
2300
+ description: 'Show latest target research pipeline status and artifact links',
2301
+ },
2302
+ args: {
2303
+ dir: { type: 'string', default: PROJECT_DIR, description: 'Project root directory' },
2304
+ json: { type: 'boolean', default: false, description: 'Output as JSON' },
2305
+ },
2306
+ async run({ args }) {
2307
+ const projectDir = resolve(String(args.dir ?? PROJECT_DIR));
2308
+ const snapshot = readMedicalWorkflowDashboard(projectDir);
2309
+ if (args.json) {
2310
+ console.log(JSON.stringify(snapshot, null, 2));
2311
+ return;
2312
+ }
2313
+ console.log('\n靶点研究管线状态');
2314
+ console.log('='.repeat(50));
2315
+ if (!snapshot.available || !snapshot.liveStatus) {
2316
+ console.log(' 状态: 暂无运行记录');
2317
+ for (const error of snapshot.errors)
2318
+ console.log(` 提示: ${error}`);
2319
+ console.log('\n 请先运行: medscale analyze <GENE> --disease "<disease>"');
2320
+ return;
2321
+ }
2322
+ const live = snapshot.liveStatus;
2323
+ console.log(` 运行 ID: ${live.run_id ?? '—'}`);
2324
+ console.log(` 状态: ${live.status}`);
2325
+ console.log(` 靶点: ${live.target}`);
2326
+ console.log(` 疾病: ${live.disease}`);
2327
+ console.log(` 进度: ${live.progress_percent}%`);
2328
+ console.log(` 当前阶段: ${live.current_stage_label ?? live.current_stage ?? '—'}`);
2329
+ if (snapshot.manuscriptQuality) {
2330
+ const quality = snapshot.manuscriptQuality;
2331
+ const verdict = quality.passed === true ? 'PASS' : quality.passed === false ? 'FAIL' : 'UNKNOWN';
2332
+ const score = quality.score == null ? '—' : quality.score;
2333
+ console.log('\n 论文质量门禁:');
2334
+ console.log(` 结果: ${verdict}`);
2335
+ if (quality.grade)
2336
+ console.log(` 等级: ${quality.grade}`);
2337
+ console.log(` 分数: ${score}`);
2338
+ if (quality.errors != null || quality.warnings != null) {
2339
+ console.log(` 问题: ${quality.errors ?? 0} errors / ${quality.warnings ?? 0} warnings`);
2340
+ }
2341
+ }
2342
+ if (snapshot.manuscriptFactCheck) {
2343
+ const fact = snapshot.manuscriptFactCheck;
2344
+ const verdict = fact.passed === true ? 'PASS' : fact.passed === false ? 'FAIL' : 'UNKNOWN';
2345
+ console.log('\n 医学事实核查:');
2346
+ console.log(` 结果: ${verdict}`);
2347
+ console.log(` 分数: ${fact.score ?? '—'}`);
2348
+ console.log(` 核查项: ${fact.claimsChecked ?? '—'}`);
2349
+ console.log(` 问题: ${fact.errors ?? 0} errors / ${fact.warnings ?? 0} warnings`);
2350
+ }
2351
+ if (snapshot.deliveryPackage) {
2352
+ console.log('\n Delivery package:');
2353
+ console.log(` ZIP: ${snapshot.deliveryPackage.exists ? 'ready' : 'missing'}`);
2354
+ if (snapshot.deliveryPackage.packagePath) {
2355
+ console.log(` Path: ${snapshot.deliveryPackage.packagePath}`);
2356
+ }
2357
+ if (snapshot.deliveryPackage.size != null) {
2358
+ console.log(` Size: ${Math.round(snapshot.deliveryPackage.size / 1024)} KB`);
2359
+ }
2360
+ if (snapshot.deliveryPackage.packageAudit) {
2361
+ const audit = snapshot.deliveryPackage.packageAudit;
2362
+ const verdict = audit.passed === true ? 'PASS' : audit.passed === false ? 'FAIL' : 'UNKNOWN';
2363
+ console.log(` Package audit: ${verdict}`);
2364
+ console.log(` Entries: ${audit.entryCount ?? '-'}; checked files: ${audit.filesChecked ?? '-'}; image refs: ${audit.imageRefsChecked ?? '-'}`);
2365
+ if (audit.errors != null || audit.warnings != null) {
2366
+ console.log(` Issues: ${audit.errors ?? 0} errors / ${audit.warnings ?? 0} warnings`);
2367
+ }
2368
+ }
2369
+ }
2370
+ printMemorySeedSummary(snapshot);
2371
+ printLearningCandidateSummary(snapshot);
2372
+ printDeliveryReadiness(snapshot);
2373
+ if (snapshot.business) {
2374
+ console.log('\n 商业规划摘要:');
2375
+ if (snapshot.business.totalDurationMonths != null) {
2376
+ console.log(` 周期: ${snapshot.business.totalDurationMonths} 个月`);
2377
+ }
2378
+ if (snapshot.business.totalCostEstimate != null) {
2379
+ console.log(` 成本估算: $${snapshot.business.totalCostEstimate}M`);
2380
+ }
2381
+ }
2382
+ if (snapshot.reports.length > 0) {
2383
+ console.log('\n 可下载报告:');
2384
+ for (const report of snapshot.reports.slice(0, 8)) {
2385
+ const mark = report.exists ? '✓' : '✗';
2386
+ console.log(` [${mark}] ${report.label}: ${report.relativePath}`);
2387
+ }
2388
+ }
2389
+ },
2390
+ });
2391
+ export const targetDoctorCommand = defineCommand({
2392
+ meta: {
2393
+ name: 'doctor',
2394
+ description: 'Check Python runtime and target-research-platform health',
2395
+ },
2396
+ args: {
2397
+ dir: { type: 'string', default: PROJECT_DIR, description: 'Project root directory' },
2398
+ json: { type: 'boolean', default: false, description: 'Output as JSON' },
2399
+ },
2400
+ async run({ args }) {
2401
+ const projectDir = resolve(String(args.dir ?? PROJECT_DIR));
2402
+ const platform = resolveTargetPlatform(projectDir);
2403
+ const bridge = new PythonBridge({
2404
+ platformDir: platform?.platformDir ?? './target-research-platform',
2405
+ });
2406
+ const health = await bridge.healthCheck();
2407
+ const requirementsExists = platform
2408
+ ? existsSync(join(platform.platformDir, 'requirements.txt'))
2409
+ : false;
2410
+ const runtimeReadiness = buildTargetRuntimeReadiness(projectDir);
2411
+ const platformOk = Boolean(platform && health.pythonAvailable && health.platformExists);
2412
+ const report = {
2413
+ ok: platformOk && runtimeReadiness.status !== 'blocked',
2414
+ platformFound: Boolean(platform),
2415
+ platformDir: platform?.platformDir ?? null,
2416
+ pythonAvailable: health.pythonAvailable,
2417
+ pythonVersion: health.pythonVersion ?? null,
2418
+ platformExists: health.platformExists,
2419
+ requirementsExists,
2420
+ runtimeReadiness,
2421
+ recommendations: [],
2422
+ };
2423
+ if (!platform) {
2424
+ report.recommendations.push('在 yixue-scale-engine 仓库根目录运行,或设置 --dir 指向仓库根。');
2425
+ }
2426
+ if (!health.pythonAvailable) {
2427
+ report.recommendations.push('安装 Python 3.10+ 并确保 python 在 PATH 中。');
2428
+ }
2429
+ if (platform && !requirementsExists) {
2430
+ report.recommendations.push('缺少 requirements.txt,请检查 target-research-platform 目录完整性。');
2431
+ }
2432
+ if (platform && health.pythonAvailable) {
2433
+ report.recommendations.push(`安装依赖: cd target-research-platform && pip install -r requirements.txt`);
2434
+ }
2435
+ report.recommendations.push(...runtimeReadiness.recommendations);
2436
+ if (args.json) {
2437
+ console.log(JSON.stringify(report, null, 2));
2438
+ process.exit(report.ok ? 0 : 1);
2439
+ }
2440
+ console.log('\n靶点研究环境诊断');
2441
+ console.log('='.repeat(50));
2442
+ console.log(` 平台目录: ${report.platformDir ?? '未找到'}`);
2443
+ console.log(` Python: ${report.pythonAvailable ? report.pythonVersion : '不可用'}`);
2444
+ console.log(` main.py: ${report.platformExists ? '存在' : '缺失'}`);
2445
+ console.log(` requirements.txt: ${report.requirementsExists ? '存在' : '缺失'}`);
2446
+ console.log(` MedSCALE runtime: ${runtimeReadiness.status} (${runtimeReadiness.score})`);
2447
+ console.log('\n Runtime Doctor:');
2448
+ for (const card of runtimeReadiness.cards) {
2449
+ const mark = card.state === 'pass' ? 'PASS' : card.state === 'warning' ? 'WARN' : card.state === 'fail' ? 'FAIL' : 'PENDING';
2450
+ console.log(` [${mark}] ${card.title}: ${card.statusLabel}`);
2451
+ console.log(` ${card.summary}`);
2452
+ }
2453
+ if (report.recommendations.length > 0) {
2454
+ console.log('\n 建议:');
2455
+ for (const item of report.recommendations)
2456
+ console.log(` - ${item}`);
2457
+ }
2458
+ console.log(`\n 总体: ${report.ok ? '可运行' : '需要修复'}`);
2459
+ process.exit(report.ok ? 0 : 1);
2460
+ },
2461
+ });
2462
+ export const targetOsPlanCommand = defineCommand({
2463
+ meta: {
2464
+ name: 'os-plan',
2465
+ description: 'Export the MedSCALE Research OS collaboration plan as read-only JSON',
2466
+ },
2467
+ args: {
2468
+ dir: { type: 'string', default: PROJECT_DIR, description: 'Project root directory' },
2469
+ json: { type: 'boolean', default: false, description: 'Output as JSON' },
2470
+ },
2471
+ async run({ args }) {
2472
+ const platform = resolveTargetPlatform(String(args.dir ?? PROJECT_DIR));
2473
+ if (!platform) {
2474
+ const payload = {
2475
+ success: false,
2476
+ error: 'target-research-platform not found; cannot build MedSCALE Research OS plan.',
2477
+ };
2478
+ if (args.json) {
2479
+ console.log(JSON.stringify(payload, null, 2));
2480
+ }
2481
+ else {
2482
+ console.error(payload.error);
2483
+ }
2484
+ process.exit(1);
2485
+ }
2486
+ const result = readMedicalResearchOsPlan(platform);
2487
+ if (args.json) {
2488
+ console.log(JSON.stringify(result.parsed ?? {
2489
+ success: false,
2490
+ error: 'MedSCALE Research OS plan did not return JSON.',
2491
+ stderr: result.stderr.slice(-1000),
2492
+ }, null, 2));
2493
+ process.exit(result.code === 0 && result.parsed ? 0 : 1);
2494
+ }
2495
+ if (result.code !== 0 || !result.parsed) {
2496
+ console.error('MedSCALE Research OS plan generation failed.');
2497
+ if (result.stderr.trim())
2498
+ console.error(result.stderr.trim());
2499
+ process.exit(1);
2500
+ }
2501
+ const plan = result.parsed;
2502
+ const product = plan.product && typeof plan.product === 'object' && !Array.isArray(plan.product)
2503
+ ? plan.product
2504
+ : {};
2505
+ const loop = plan.agent_loop_readiness && typeof plan.agent_loop_readiness === 'object' && !Array.isArray(plan.agent_loop_readiness)
2506
+ ? plan.agent_loop_readiness
2507
+ : {};
2508
+ const runtime = plan.runtime_readiness && typeof plan.runtime_readiness === 'object' && !Array.isArray(plan.runtime_readiness)
2509
+ ? plan.runtime_readiness
2510
+ : {};
2511
+ const promptStudio = plan.prompt_studio && typeof plan.prompt_studio === 'object' && !Array.isArray(plan.prompt_studio)
2512
+ ? plan.prompt_studio
2513
+ : {};
2514
+ const templates = Array.isArray(promptStudio.templates) ? promptStudio.templates : [];
2515
+ console.log('\nMedSCALE Research OS Plan');
2516
+ console.log('='.repeat(50));
2517
+ console.log(` Product: ${String(product.name ?? 'MedSCALE Research OS')}`);
2518
+ console.log(` Status: ${String(loop.status ?? 'unknown')} (${String(loop.score ?? '-')})`);
2519
+ console.log(` Runtime: ${String(runtime.status ?? 'unknown')} (${String(runtime.score ?? '-')})`);
2520
+ console.log(` Prompt templates: ${templates.length}`);
2521
+ console.log('\n JSON:');
2522
+ console.log(' medscale os-plan --json');
2523
+ },
2524
+ });
2525
+ function parseTargetJsonArg(value, name) {
2526
+ try {
2527
+ return JSON.parse(String(value ?? 'null').replace(/^\uFEFF/, ''));
2528
+ }
2529
+ catch {
2530
+ throw new Error(`${name} must be valid JSON.`);
2531
+ }
2532
+ }
2533
+ function parseTargetMetadata(value) {
2534
+ const parsed = parseTargetJsonArg(value ?? '{}', '--metadata-json');
2535
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
2536
+ throw new Error('--metadata-json must be a JSON object.');
2537
+ }
2538
+ const metadata = {};
2539
+ for (const [key, item] of Object.entries(parsed)) {
2540
+ if (typeof item === 'string' || typeof item === 'number' || typeof item === 'boolean')
2541
+ metadata[key] = item;
2542
+ }
2543
+ return metadata;
2544
+ }
2545
+ function parseTargetNonNegative(value, name) {
2546
+ if (value === undefined || value === null || value === '')
2547
+ return undefined;
2548
+ const parsed = Number(value);
2549
+ if (!Number.isFinite(parsed) || parsed < 0)
2550
+ throw new Error(`${name} must be a non-negative number.`);
2551
+ return parsed;
2552
+ }
2553
+ function parseTargetPositiveInt(value, name) {
2554
+ if (value === undefined || value === null || value === '')
2555
+ return undefined;
2556
+ const parsed = Number(value);
2557
+ if (!Number.isInteger(parsed) || parsed <= 0)
2558
+ throw new Error(`${name} must be a positive integer.`);
2559
+ return parsed;
2560
+ }
2561
+ function targetUsagePayload(args, root) {
2562
+ if (args['usage-file'])
2563
+ return parseTargetJsonArg(readFileSync(resolve(root, String(args['usage-file'])), 'utf-8'), '--usage-file');
2564
+ if (args['usage-json'])
2565
+ return parseTargetJsonArg(args['usage-json'], '--usage-json');
2566
+ return undefined;
2567
+ }
2568
+ function buildTargetModelUsageInput(args, root) {
2569
+ const provider = String(args.provider ?? '').trim();
2570
+ if (!provider)
2571
+ throw new Error('MedSCALE token record requires --provider.');
2572
+ const metadata = parseTargetMetadata(args['metadata-json']);
2573
+ for (const key of ['medical-lane', 'phase', 'gate', 'target', 'disease']) {
2574
+ if (args[key] !== undefined && args[key] !== '')
2575
+ metadata[key.replace('-', '_')] = String(args[key]);
2576
+ }
2577
+ return buildModelUsageInput({
2578
+ provider,
2579
+ model: args.model ? String(args.model) : undefined,
2580
+ taskId: args['task-id'] ? String(args['task-id']) : undefined,
2581
+ sessionId: args['session-id'] ? String(args['session-id']) : undefined,
2582
+ inputTokens: parseTargetNonNegative(args['input-tokens'], '--input-tokens'),
2583
+ outputTokens: parseTargetNonNegative(args['output-tokens'], '--output-tokens'),
2584
+ cacheEligibleTokens: parseTargetNonNegative(args['cache-eligible-tokens'], '--cache-eligible-tokens'),
2585
+ cacheCreationInputTokens: parseTargetNonNegative(args['cache-creation-input-tokens'], '--cache-creation-input-tokens'),
2586
+ cacheReadInputTokens: parseTargetNonNegative(args['cache-read-input-tokens'], '--cache-read-input-tokens'),
2587
+ cachedTokens: parseTargetNonNegative(args['cached-tokens'], '--cached-tokens'),
2588
+ estimatedCostUsd: parseTargetNonNegative(args['estimated-cost-usd'], '--estimated-cost-usd'),
2589
+ metadata,
2590
+ timestamp: args.timestamp ? String(args.timestamp) : undefined,
2591
+ usagePayload: targetUsagePayload(args, root),
2592
+ });
2593
+ }
2594
+ export const targetTokenCommand = defineCommand({
2595
+ meta: {
2596
+ name: 'token',
2597
+ description: 'Record and report MedSCALE medical workflow token/cost usage',
2598
+ },
2599
+ subCommands: {
2600
+ record: defineCommand({
2601
+ meta: { name: 'record', description: 'Record real model usage for a medical research task' },
2602
+ args: {
2603
+ dir: { type: 'string', default: PROJECT_DIR, description: 'Project root directory' },
2604
+ provider: { type: 'string', required: true, description: 'Model provider: anthropic, openai, codex, etc.' },
2605
+ model: { type: 'string', description: 'Optional model id' },
2606
+ 'task-id': { type: 'string', description: 'Task id linked to this model usage' },
2607
+ 'session-id': { type: 'string', description: 'Session id linked to this model usage' },
2608
+ 'medical-lane': { type: 'string', description: 'Medical lane: literature, fact_check, package_audit, memory, agent_review, workflow' },
2609
+ phase: { type: 'string', description: 'Medical workflow phase' },
2610
+ gate: { type: 'string', description: 'Review gate linked to this usage' },
2611
+ target: { type: 'string', description: 'Target gene/symbol linked to this usage' },
2612
+ disease: { type: 'string', description: 'Disease context linked to this usage' },
2613
+ 'usage-json': { type: 'string', description: 'Raw provider response or usage JSON' },
2614
+ 'usage-file': { type: 'string', description: 'Path to a JSON file containing provider usage' },
2615
+ 'input-tokens': { type: 'string', description: 'Explicit input token count; overrides usage JSON' },
2616
+ 'output-tokens': { type: 'string', description: 'Explicit output token count; overrides usage JSON' },
2617
+ 'cache-eligible-tokens': { type: 'string', description: 'Explicit cache-eligible token count' },
2618
+ 'cache-creation-input-tokens': { type: 'string', description: 'Explicit Anthropic cache creation token count' },
2619
+ 'cache-read-input-tokens': { type: 'string', description: 'Explicit Anthropic cache read token count' },
2620
+ 'cached-tokens': { type: 'string', description: 'Explicit OpenAI cached token count' },
2621
+ 'estimated-cost-usd': { type: 'string', description: 'Optional estimated cost in USD' },
2622
+ timestamp: { type: 'string', description: 'Optional ISO timestamp' },
2623
+ 'metadata-json': { type: 'string', default: '{}', description: 'Additional JSON metadata' },
2624
+ json: { type: 'boolean', default: false, description: 'Output machine-readable JSON' },
2625
+ },
2626
+ run({ args }) {
2627
+ const root = resolveTargetWorkspaceRoot(String(args.dir ?? PROJECT_DIR));
2628
+ const record = new ModelUsageLedger(targetScaleDir(root)).record(buildTargetModelUsageInput(args, root));
2629
+ if (args.json) {
2630
+ console.log(JSON.stringify(record, null, 2));
2631
+ return;
2632
+ }
2633
+ console.log(`MedSCALE token usage recorded: ${record.id}`);
2634
+ console.log(` Provider: ${record.provider}`);
2635
+ console.log(` Model: ${record.model ?? 'unknown'}`);
2636
+ console.log(` Tokens: input ${record.inputTokens}, output ${record.outputTokens}, total ${record.totalTokens}`);
2637
+ if (record.cacheSavingsTokens > 0)
2638
+ console.log(` Cache savings: ${record.cacheSavingsTokens} tokens`);
2639
+ if (record.estimatedCostUsd !== undefined)
2640
+ console.log(` Estimated cost: $${record.estimatedCostUsd.toFixed(6)}`);
2641
+ },
2642
+ }),
2643
+ ingest: defineCommand({
2644
+ meta: { name: 'ingest', description: 'Scan medical workflow JSON artifacts and ingest real model usage fields' },
2645
+ args: {
2646
+ dir: { type: 'string', default: PROJECT_DIR, description: 'Project root directory' },
2647
+ target: { type: 'string', description: 'Target gene/symbol used to resolve delivery artifacts' },
2648
+ disease: { type: 'string', description: 'Disease context used to resolve delivery artifacts' },
2649
+ output: { type: 'string', default: './output', description: 'Output root under target-research-platform' },
2650
+ file: { type: 'string', description: 'JSON artifact path(s); comma or semicolon separated' },
2651
+ provider: { type: 'string', description: 'Default provider when artifact usage omits provider' },
2652
+ limit: { type: 'string', description: 'Maximum recent records to include in the embedded report' },
2653
+ json: { type: 'boolean', default: false, description: 'Output machine-readable JSON' },
2654
+ },
2655
+ run({ args }) {
2656
+ const files = args.file ? [String(args.file)] : [];
2657
+ const report = ingestTargetTokenUsage({
2658
+ projectDir: String(args.dir ?? PROJECT_DIR),
2659
+ output: args.output ? String(args.output) : undefined,
2660
+ target: args.target ? String(args.target) : undefined,
2661
+ disease: args.disease ? String(args.disease) : undefined,
2662
+ files,
2663
+ provider: args.provider ? String(args.provider) : undefined,
2664
+ limit: parseTargetPositiveInt(args.limit, '--limit'),
2665
+ });
2666
+ if (args.json) {
2667
+ console.log(JSON.stringify(report, null, 2));
2668
+ return;
2669
+ }
2670
+ console.log('MedSCALE Token Usage Ingest');
2671
+ console.log(` Status: ${report.status}`);
2672
+ console.log(` Files scanned: ${report.scannedFiles.length}`);
2673
+ console.log(` Recorded: ${report.recorded}`);
2674
+ console.log(` Duplicates: ${report.duplicates}`);
2675
+ console.log(` Skipped: ${report.skipped}`);
2676
+ console.log(` Ledger records: ${report.tokenCost.summary.totalRecords}`);
2677
+ for (const source of report.sources.slice(0, 8)) {
2678
+ const provider = source.provider ?? 'provider-missing';
2679
+ console.log(` ${source.status}: ${source.medicalLane} ${provider} ${source.totalTokens} tokens (${source.pointer})`);
2680
+ }
2681
+ for (const warning of report.warnings.slice(0, 8))
2682
+ console.log(` [WARN] ${warning}`);
2683
+ },
2684
+ }),
2685
+ report: defineCommand({
2686
+ meta: { name: 'report', description: 'Summarize MedSCALE token/cost usage by provider, task, day, and medical lane' },
2687
+ args: {
2688
+ dir: { type: 'string', default: PROJECT_DIR, description: 'Project root directory' },
2689
+ day: { type: 'string', description: 'Exact UTC day in YYYY-MM-DD format' },
2690
+ since: { type: 'string', description: 'ISO timestamp lower bound' },
2691
+ until: { type: 'string', description: 'ISO timestamp upper bound' },
2692
+ 'since-days': { type: 'string', default: '30', description: 'Relative time window when day/since/until are omitted; use all to disable' },
2693
+ provider: { type: 'string', description: 'Filter by provider' },
2694
+ model: { type: 'string', description: 'Filter by model id' },
2695
+ 'task-id': { type: 'string', description: 'Filter by task id' },
2696
+ 'session-id': { type: 'string', description: 'Filter by session id' },
2697
+ limit: { type: 'string', description: 'Maximum recent records to include; defaults to 20' },
2698
+ json: { type: 'boolean', default: false, description: 'Output machine-readable JSON' },
2699
+ },
2700
+ run({ args }) {
2701
+ const report = buildTargetTokenCostReport({
2702
+ projectDir: String(args.dir ?? PROJECT_DIR),
2703
+ day: args.day ? String(args.day) : undefined,
2704
+ since: args.since ? String(args.since) : undefined,
2705
+ until: args.until ? String(args.until) : undefined,
2706
+ sinceDays: normalizeSinceDaysValue(args['since-days'], 30),
2707
+ provider: args.provider ? String(args.provider) : undefined,
2708
+ model: args.model ? String(args.model) : undefined,
2709
+ taskId: args['task-id'] ? String(args['task-id']) : undefined,
2710
+ sessionId: args['session-id'] ? String(args['session-id']) : undefined,
2711
+ limit: parseTargetPositiveInt(args.limit, '--limit'),
2712
+ });
2713
+ if (args.json) {
2714
+ console.log(JSON.stringify(report, null, 2));
2715
+ return;
2716
+ }
2717
+ console.log('MedSCALE Token/Cost Report');
2718
+ console.log(` Status: ${report.status}`);
2719
+ console.log(` Records: ${report.summary.totalRecords}`);
2720
+ console.log(` Tokens: input ${report.summary.totalInputTokens}, output ${report.summary.totalOutputTokens}, total ${report.summary.totalTokens}`);
2721
+ console.log(` Cache savings: ${report.summary.cacheSavingsTokens} tokens`);
2722
+ if (report.summary.estimatedCostUsd !== undefined)
2723
+ console.log(` Estimated cost: $${report.summary.estimatedCostUsd.toFixed(6)}`);
2724
+ for (const lane of report.byMedicalLane.slice(0, 6)) {
2725
+ const cost = lane.estimatedCostUsd !== undefined ? `, $${lane.estimatedCostUsd.toFixed(6)}` : '';
2726
+ console.log(` ${lane.label}: ${lane.records} record(s), ${lane.totalTokens} tokens${cost}`);
2727
+ }
2728
+ for (const item of report.recommendations)
2729
+ console.log(` Next: ${item}`);
2730
+ },
2731
+ }),
2732
+ },
2733
+ });
2734
+ export const targetSetupCommand = defineCommand({
2735
+ meta: {
2736
+ name: 'setup',
2737
+ description: 'Plan MedSCALE Research OS third-party capabilities and install checks',
2738
+ },
2739
+ args: {
2740
+ dir: { type: 'string', default: PROJECT_DIR, description: 'Project root directory' },
2741
+ lang: { type: 'string', default: undefined, description: 'Output language: zh or en' },
2742
+ platform: { type: 'string', default: undefined, description: 'Target platform: windows, macos, or linux' },
2743
+ json: { type: 'boolean', default: false, description: 'Output machine-readable JSON' },
2744
+ visual: { type: 'boolean', default: false, description: 'Show the researcher-facing visual setup plan' },
2745
+ apply: { type: 'boolean', default: false, description: 'Reserved for future guided installation; currently plan-only' },
2746
+ },
2747
+ async run({ args }) {
2748
+ const plan = buildTargetSetupPlan({
2749
+ projectDir: String(args.dir ?? PROJECT_DIR),
2750
+ lang: args.lang,
2751
+ platform: args.platform,
2752
+ });
2753
+ const payload = {
2754
+ ...plan,
2755
+ requestedApply: Boolean(args.apply),
2756
+ requestedVisual: Boolean(args.visual),
2757
+ applyAvailable: false,
2758
+ applyMessage: plan.lang === 'zh'
2759
+ ? 'setup 当前是 plan-only;请按 install/verify 命令逐项执行。'
2760
+ : 'setup is currently plan-only; run each install/verify command explicitly.',
2761
+ };
2762
+ if (args.json) {
2763
+ console.log(JSON.stringify(payload, null, 2));
2764
+ process.exit(plan.status === 'blocked' ? 1 : 0);
2765
+ }
2766
+ console.log(args.visual ? renderTargetSetupVisualPlan(plan) : renderTargetSetupPlan(plan));
2767
+ if (args.apply) {
2768
+ console.log('');
2769
+ console.log(payload.applyMessage);
2770
+ }
2771
+ process.exit(plan.status === 'blocked' ? 1 : 0);
2772
+ },
2773
+ });
2774
+ export const targetDashboardCommand = defineCommand({
2775
+ meta: {
2776
+ name: 'dashboard',
2777
+ description: 'Start local web dashboard for target research results',
2778
+ },
2779
+ args: {
2780
+ dir: { type: 'string', default: PROJECT_DIR, description: 'Project root directory' },
2781
+ host: { type: 'string', default: '127.0.0.1', description: 'Bind host' },
2782
+ port: { type: 'string', default: '18766', description: 'Bind port' },
2783
+ },
2784
+ async run({ args }) {
2785
+ const platform = resolveTargetPlatform(String(args.dir ?? PROJECT_DIR));
2786
+ if (!platform) {
2787
+ console.error('未找到 target-research-platform,无法启动 Dashboard。');
2788
+ process.exit(1);
2789
+ }
2790
+ const dashboardModule = join(platform.platformDir, 'src', 'dashboard', 'app.py');
2791
+ if (!existsSync(dashboardModule)) {
2792
+ console.error(`Dashboard 模块不存在: ${dashboardModule}`);
2793
+ process.exit(1);
2794
+ }
2795
+ console.log(`启动医学研究工作台: http://${args.host}:${args.port}`);
2796
+ console.log('按 Ctrl+C 停止服务\n');
2797
+ const child = spawn('python', ['-m', 'src.dashboard.app', '--host', String(args.host), '--port', String(args.port)], { cwd: platform.platformDir, stdio: 'inherit', env: process.env });
2798
+ child.on('exit', (code) => process.exit(code ?? 0));
2799
+ },
2800
+ });
2801
+ export const targetManuscriptCommand = defineCommand({
2802
+ meta: {
2803
+ name: 'manuscript',
2804
+ description: 'Generate a journal manuscript draft from existing target research outputs',
2805
+ },
2806
+ args: {
2807
+ target: { type: 'string', required: true, description: 'Target gene symbol, e.g. CDK4' },
2808
+ disease: { type: 'string', required: true, description: 'Disease name, e.g. "breast cancer"' },
2809
+ output: { type: 'string', default: './output', description: 'Output root under target-research-platform' },
2810
+ dir: { type: 'string', default: PROJECT_DIR, description: 'Project root directory' },
2811
+ 'fail-on-quality': { type: 'boolean', default: false, description: 'Exit non-zero when manuscript quality gate fails' },
2812
+ json: { type: 'boolean', default: false, description: 'Output machine-readable JSON' },
2813
+ },
2814
+ async run({ args }) {
2815
+ const platform = resolveTargetPlatform(String(args.dir ?? PROJECT_DIR));
2816
+ if (!platform) {
2817
+ console.error('target-research-platform not found; cannot generate manuscript.');
2818
+ process.exit(1);
2819
+ }
2820
+ const commandArgs = [
2821
+ 'manuscript',
2822
+ '--target',
2823
+ String(args.target),
2824
+ '--disease',
2825
+ String(args.disease),
2826
+ '--output',
2827
+ String(args.output ?? './output'),
2828
+ ];
2829
+ if (args['fail-on-quality'])
2830
+ commandArgs.push('--fail-on-quality');
2831
+ if (args.json)
2832
+ commandArgs.push('--json');
2833
+ if (!args.json) {
2834
+ console.log(`\nGenerating manuscript draft: ${args.target} / ${args.disease}`);
2835
+ }
2836
+ const result = runPythonCommand(platform, commandArgs, {
2837
+ json: Boolean(args.json),
2838
+ inherit: !args.json,
2839
+ });
2840
+ if (args.json) {
2841
+ if (result.parsed) {
2842
+ console.log(JSON.stringify(result.parsed, null, 2));
2843
+ }
2844
+ else {
2845
+ console.log(JSON.stringify({
2846
+ success: false,
2847
+ error: 'Manuscript command finished without JSON output',
2848
+ stderr: result.stderr.slice(-1000),
2849
+ }, null, 2));
2850
+ }
2851
+ }
2852
+ process.exit(result.code);
2853
+ },
2854
+ });
2855
+ export const targetRememberCommand = defineCommand({
2856
+ meta: {
2857
+ name: 'remember',
2858
+ description: 'Seed the latest medical delivery artifacts into the configured memory provider',
2859
+ },
2860
+ args: {
2861
+ target: { type: 'string', required: true, description: 'Target gene symbol, e.g. CDK4' },
2862
+ disease: { type: 'string', required: true, description: 'Disease name, e.g. "breast cancer"' },
2863
+ output: { type: 'string', default: './output', description: 'Output root under target-research-platform' },
2864
+ provider: { type: 'string', default: 'gbrain', description: 'Memory provider id, default gbrain' },
2865
+ dir: { type: 'string', default: PROJECT_DIR, description: 'Project root directory' },
2866
+ json: { type: 'boolean', default: false, description: 'Output machine-readable JSON' },
2867
+ },
2868
+ async run({ args }) {
2869
+ const report = seedTargetDeliveryMemory({
2870
+ projectDir: String(args.dir ?? PROJECT_DIR),
2871
+ output: String(args.output ?? './output'),
2872
+ target: String(args.target),
2873
+ disease: String(args.disease),
2874
+ provider: String(args.provider ?? 'gbrain'),
2875
+ });
2876
+ if (args.json) {
2877
+ console.log(JSON.stringify(report, null, 2));
2878
+ process.exit(report.ok ? 0 : 1);
2879
+ }
2880
+ console.log(`\nSeeding medical delivery memory: ${args.target} / ${args.disease}`);
2881
+ console.log(` Provider: ${report.provider}`);
2882
+ if (report.manifestPath)
2883
+ console.log(` Manifest: ${report.manifestPath}`);
2884
+ if (report.summaryPath)
2885
+ console.log(` Summary: ${report.summaryPath}`);
2886
+ if (report.recordPath)
2887
+ console.log(` Record: ${report.recordPath}`);
2888
+ console.log(` Files: ${report.sourceFiles.length}`);
2889
+ if (report.missingRoles.length > 0) {
2890
+ console.log(` Missing roles: ${report.missingRoles.join(', ')}`);
2891
+ }
2892
+ for (const warning of report.warnings)
2893
+ console.log(` [WARN] ${warning}`);
2894
+ process.exit(report.ok ? 0 : 1);
2895
+ },
2896
+ });
2897
+ export const targetLearnCommand = defineCommand({
2898
+ meta: {
2899
+ name: 'learn',
2900
+ description: 'Settle the latest medical delivery into a reviewable learning candidate for Memory Brain',
2901
+ },
2902
+ args: {
2903
+ target: { type: 'string', required: true, description: 'Target gene symbol, e.g. CDK4' },
2904
+ disease: { type: 'string', required: true, description: 'Disease name, e.g. "breast cancer"' },
2905
+ output: { type: 'string', default: './output', description: 'Output root under target-research-platform' },
2906
+ dir: { type: 'string', default: PROJECT_DIR, description: 'Project root directory' },
2907
+ 'seed-memory': { type: 'boolean', default: false, description: 'Seed delivery memory before settling the learning candidate' },
2908
+ provider: { type: 'string', default: 'gbrain', description: 'Memory provider id used with --seed-memory' },
2909
+ 'ingest-memory-brain': { type: 'boolean', default: false, description: 'Also ingest the learning candidate into Memory Brain as a candidate node' },
2910
+ json: { type: 'boolean', default: false, description: 'Output machine-readable JSON' },
2911
+ },
2912
+ async run({ args }) {
2913
+ const memorySeed = args['seed-memory']
2914
+ ? seedTargetDeliveryMemory({
2915
+ projectDir: String(args.dir ?? PROJECT_DIR),
2916
+ output: String(args.output ?? './output'),
2917
+ target: String(args.target),
2918
+ disease: String(args.disease),
2919
+ provider: String(args.provider ?? 'gbrain'),
2920
+ })
2921
+ : null;
2922
+ const report = settleTargetDeliveryLearning({
2923
+ projectDir: String(args.dir ?? PROJECT_DIR),
2924
+ output: String(args.output ?? './output'),
2925
+ target: String(args.target),
2926
+ disease: String(args.disease),
2927
+ memorySeed,
2928
+ ingestToBrain: Boolean(args['ingest-memory-brain']),
2929
+ });
2930
+ if (args.json) {
2931
+ console.log(JSON.stringify({
2932
+ ...report,
2933
+ ...(memorySeed ? { memory_seed: memorySeed } : {}),
2934
+ }, null, 2));
2935
+ process.exit(report.ok ? 0 : 1);
2936
+ }
2937
+ console.log(`\nSettling medical learning candidate: ${args.target} / ${args.disease}`);
2938
+ console.log(` Candidate: ${report.candidateId ?? 'n/a'}`);
2939
+ console.log(` Recommended action: ${report.recommendedAction ?? 'n/a'}`);
2940
+ console.log(` Promotable: ${report.promotable ? 'yes' : 'no'}`);
2941
+ if (report.candidatePath)
2942
+ console.log(` Candidate path: ${report.candidatePath}`);
2943
+ if (report.candidateMarkdownPath)
2944
+ console.log(` Candidate markdown: ${report.candidateMarkdownPath}`);
2945
+ if (report.mirrorRecordPath)
2946
+ console.log(` Delivery record: ${report.mirrorRecordPath}`);
2947
+ if (report.mirrorSummaryPath)
2948
+ console.log(` Delivery summary: ${report.mirrorSummaryPath}`);
2949
+ if (report.brainNodeId)
2950
+ console.log(` Brain node: ${report.brainNodeId}`);
2951
+ for (const warning of report.warnings.slice(0, 8))
2952
+ console.log(` [WARN] ${warning}`);
2953
+ process.exit(report.ok ? 0 : 1);
2954
+ },
2955
+ });
2956
+ export const targetMemoryReviewCommand = defineCommand({
2957
+ meta: {
2958
+ name: 'memory-review',
2959
+ description: 'Review a Memory Brain learning candidate: approve, reject, stale, or restore',
2960
+ },
2961
+ args: {
2962
+ action: { type: 'positional', required: true, description: 'Review action: approve, reject, stale, or restore' },
2963
+ 'candidate-id': { type: 'string', description: 'Learning candidate id; defaults to the latest candidate' },
2964
+ reviewer: { type: 'string', default: 'medscale', description: 'Reviewer id/name for the audit record' },
2965
+ reason: { type: 'string', description: 'Short review reason' },
2966
+ scope: { type: 'string', description: 'Memory scope: project, workspace, or global-candidate' },
2967
+ dir: { type: 'string', default: PROJECT_DIR, description: 'Project root directory' },
2968
+ json: { type: 'boolean', default: false, description: 'Output machine-readable JSON' },
2969
+ },
2970
+ run({ args }) {
2971
+ let action;
2972
+ let scope;
2973
+ try {
2974
+ action = normalizeMemoryReviewAction(args.action);
2975
+ scope = normalizeTargetMemoryScope(args.scope);
2976
+ }
2977
+ catch (error) {
2978
+ console.error(error.message);
2979
+ process.exit(1);
2980
+ return;
2981
+ }
2982
+ const report = reviewMemoryLearningCandidate({
2983
+ projectDir: String(args.dir ?? PROJECT_DIR),
2984
+ candidateId: args['candidate-id'] ? String(args['candidate-id']) : undefined,
2985
+ action,
2986
+ reviewer: String(args.reviewer ?? 'medscale'),
2987
+ reason: args.reason ? String(args.reason) : undefined,
2988
+ scope,
2989
+ });
2990
+ if (args.json) {
2991
+ console.log(JSON.stringify(report, null, 2));
2992
+ process.exit(report.ok ? 0 : 1);
2993
+ }
2994
+ console.log(`\nMemory Brain review: ${action}`);
2995
+ console.log(` Candidate: ${report.candidateId ?? 'n/a'}`);
2996
+ console.log(` Status: ${report.status}`);
2997
+ console.log(` Node: ${report.nodeId ?? 'n/a'} (${report.nodeStatus ?? 'n/a'})`);
2998
+ if (report.reviewPath)
2999
+ console.log(` Review record: ${report.reviewPath}`);
3000
+ if (report.reviewMarkdownPath)
3001
+ console.log(` Review markdown: ${report.reviewMarkdownPath}`);
3002
+ for (const warning of report.warnings)
3003
+ console.log(` [WARN] ${warning}`);
3004
+ process.exit(report.ok ? 0 : 1);
3005
+ },
3006
+ });
3007
+ export const targetPackageCommand = defineCommand({
3008
+ meta: {
3009
+ name: 'package',
3010
+ description: 'Create a researcher-facing ZIP delivery package from generated manuscript artifacts',
3011
+ },
3012
+ args: {
3013
+ target: { type: 'string', required: true, description: 'Target gene symbol, e.g. CDK4' },
3014
+ disease: { type: 'string', required: true, description: 'Disease name, e.g. "breast cancer"' },
3015
+ output: { type: 'string', default: './output', description: 'Output root under target-research-platform' },
3016
+ dir: { type: 'string', default: PROJECT_DIR, description: 'Project root directory' },
3017
+ 'seed-memory': { type: 'boolean', default: false, description: 'After packaging, seed the resulting delivery artifacts into the memory provider' },
3018
+ 'memory-provider': { type: 'string', default: 'gbrain', description: 'Memory provider id used with --seed-memory' },
3019
+ 'settle-learning': { type: 'boolean', default: false, description: 'After packaging, settle the delivery into a reviewable learning candidate' },
3020
+ 'ingest-memory-brain': { type: 'boolean', default: false, description: 'When settling learning, also ingest the candidate into Memory Brain' },
3021
+ json: { type: 'boolean', default: false, description: 'Output machine-readable JSON' },
3022
+ },
3023
+ async run({ args }) {
3024
+ const platform = resolveTargetPlatform(String(args.dir ?? PROJECT_DIR));
3025
+ if (!platform) {
3026
+ console.error('target-research-platform not found; cannot package manuscript delivery.');
3027
+ process.exit(1);
3028
+ }
3029
+ const commandArgs = buildTargetPackageCommandArgs(args, Boolean(args.json));
3030
+ if (!args.json) {
3031
+ console.log(`\nPackaging manuscript delivery: ${args.target} / ${args.disease}`);
3032
+ }
3033
+ let packageResult = runPythonCommand(platform, commandArgs, {
3034
+ json: Boolean(args.json),
3035
+ inherit: !args.json,
3036
+ });
3037
+ let memorySeed = null;
3038
+ if (packageResult.code === 0 && args['seed-memory']) {
3039
+ memorySeed = seedTargetDeliveryMemory({
3040
+ projectDir: String(args.dir ?? PROJECT_DIR),
3041
+ output: String(args.output ?? './output'),
3042
+ target: String(args.target),
3043
+ disease: String(args.disease),
3044
+ provider: String(args['memory-provider'] ?? 'gbrain'),
3045
+ });
3046
+ }
3047
+ let learningCandidate = null;
3048
+ if (packageResult.code === 0 && args['settle-learning']) {
3049
+ learningCandidate = settleTargetDeliveryLearning({
3050
+ projectDir: String(args.dir ?? PROJECT_DIR),
3051
+ output: String(args.output ?? './output'),
3052
+ target: String(args.target),
3053
+ disease: String(args.disease),
3054
+ memorySeed,
3055
+ ingestToBrain: Boolean(args['ingest-memory-brain']),
3056
+ });
3057
+ }
3058
+ let refreshPackageError = null;
3059
+ if (packageResult.code === 0
3060
+ && (memorySeed || learningCandidate)) {
3061
+ const refreshed = runPythonCommand(platform, buildTargetPackageCommandArgs(args, true), { json: true, inherit: false });
3062
+ if (refreshed.code === 0 && refreshed.parsed) {
3063
+ packageResult = refreshed;
3064
+ }
3065
+ else {
3066
+ refreshPackageError = refreshed.stderr.trim() || refreshed.stdout.trim() || 'Package refresh finished without JSON output';
3067
+ }
3068
+ }
3069
+ const tokenUsageIngest = packageResult.code === 0
3070
+ ? ingestTargetTokenUsage({
3071
+ projectDir: String(args.dir ?? PROJECT_DIR),
3072
+ output: String(args.output ?? './output'),
3073
+ target: String(args.target),
3074
+ disease: String(args.disease),
3075
+ })
3076
+ : null;
3077
+ if (args.json) {
3078
+ if (packageResult.parsed) {
3079
+ console.log(JSON.stringify({
3080
+ ...packageResult.parsed,
3081
+ ...(memorySeed ? { memory_seed: memorySeed } : {}),
3082
+ ...(learningCandidate ? { learning_candidate: learningCandidate } : {}),
3083
+ ...(tokenUsageIngest ? { token_usage_ingest: tokenUsageIngest } : {}),
3084
+ ...(refreshPackageError ? { refresh_package_error: refreshPackageError } : {}),
3085
+ }, null, 2));
3086
+ }
3087
+ else {
3088
+ console.log(JSON.stringify({
3089
+ success: false,
3090
+ error: 'Package command finished without JSON output',
3091
+ stderr: packageResult.stderr.slice(-1000),
3092
+ ...(memorySeed ? { memory_seed: memorySeed } : {}),
3093
+ ...(learningCandidate ? { learning_candidate: learningCandidate } : {}),
3094
+ ...(tokenUsageIngest ? { token_usage_ingest: tokenUsageIngest } : {}),
3095
+ ...(refreshPackageError ? { refresh_package_error: refreshPackageError } : {}),
3096
+ }, null, 2));
3097
+ }
3098
+ }
3099
+ else {
3100
+ if (memorySeed) {
3101
+ console.log(` Memory seed: ${memorySeed.ok ? 'completed' : 'failed'} (${memorySeed.provider})`);
3102
+ if (memorySeed.summaryPath)
3103
+ console.log(` Memory summary: ${memorySeed.summaryPath}`);
3104
+ if (memorySeed.recordPath)
3105
+ console.log(` Memory record: ${memorySeed.recordPath}`);
3106
+ console.log(` Seeded files: ${memorySeed.sourceFiles.length}`);
3107
+ if (memorySeed.missingRoles.length > 0) {
3108
+ console.log(` Missing roles: ${memorySeed.missingRoles.join(', ')}`);
3109
+ }
3110
+ for (const warning of memorySeed.warnings.slice(0, 8))
3111
+ console.log(` [WARN] ${warning}`);
3112
+ }
3113
+ if (learningCandidate) {
3114
+ console.log(` Learning candidate: ${learningCandidate.promotable ? 'ready-for-review' : learningCandidate.recommendedAction}`);
3115
+ if (learningCandidate.mirrorRecordPath)
3116
+ console.log(` Learning record: ${learningCandidate.mirrorRecordPath}`);
3117
+ if (learningCandidate.mirrorSummaryPath)
3118
+ console.log(` Learning summary: ${learningCandidate.mirrorSummaryPath}`);
3119
+ if (learningCandidate.brainNodeId)
3120
+ console.log(` Brain node: ${learningCandidate.brainNodeId}`);
3121
+ for (const warning of learningCandidate.warnings.slice(0, 8))
3122
+ console.log(` [WARN] ${warning}`);
3123
+ }
3124
+ if (memorySeed || learningCandidate) {
3125
+ if (refreshPackageError) {
3126
+ console.log(` [WARN] Delivery ZIP refresh failed: ${refreshPackageError}`);
3127
+ }
3128
+ else {
3129
+ console.log(' Delivery ZIP refreshed with memory-seed and learning-candidate artifacts.');
3130
+ }
3131
+ }
3132
+ if (tokenUsageIngest) {
3133
+ console.log(` Token usage ingest: ${tokenUsageIngest.recorded} recorded, ${tokenUsageIngest.duplicates} duplicate, ${tokenUsageIngest.skipped} skipped`);
3134
+ for (const warning of tokenUsageIngest.warnings.slice(0, 4))
3135
+ console.log(` [WARN] ${warning}`);
3136
+ }
3137
+ }
3138
+ const exitCode = packageResult.code !== 0
3139
+ ? packageResult.code
3140
+ : (Boolean(refreshPackageError)
3141
+ ||
3142
+ (args['seed-memory'] && memorySeed && !memorySeed.ok)
3143
+ || (args['settle-learning'] && learningCandidate && !learningCandidate.ok))
3144
+ ? 1
3145
+ : 0;
3146
+ process.exit(exitCode);
3147
+ },
3148
+ });
3149
+ export const targetCommand = defineCommand({
3150
+ meta: {
3151
+ name: 'target',
3152
+ description: 'Medical target research pipeline - analyze, manuscript, package, status, dashboard, doctor',
3153
+ },
3154
+ subCommands: {
3155
+ analyze: targetAnalyzeCommand,
3156
+ manuscript: targetManuscriptCommand,
3157
+ remember: targetRememberCommand,
3158
+ learn: targetLearnCommand,
3159
+ 'memory-review': targetMemoryReviewCommand,
3160
+ token: targetTokenCommand,
3161
+ package: targetPackageCommand,
3162
+ status: targetStatusCommand,
3163
+ doctor: targetDoctorCommand,
3164
+ 'os-plan': targetOsPlanCommand,
3165
+ setup: targetSetupCommand,
3166
+ dashboard: targetDashboardCommand,
3167
+ },
3168
+ });
3169
+ /** 阶段标签映射(供测试和文档引用) */
3170
+ export function formatStageLabel(stage) {
3171
+ return STAGE_LABELS[stage];
3172
+ }
3173
+ //# sourceMappingURL=targetCommands.js.map