@inflexa-ai/harness 0.1.1 → 0.3.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 (330) hide show
  1. package/README.md +48 -0
  2. package/dist/agents/conversation-agent.d.ts +15 -11
  3. package/dist/agents/conversation-agent.js +31 -34
  4. package/dist/agents/report-builder.js +2 -1
  5. package/dist/agents/sandbox/bulk-transcriptomics-agent.js +1 -1
  6. package/dist/agents/sandbox/cheminformatics-agent.js +1 -19
  7. package/dist/agents/sandbox/chromatin-agent.js +1 -10
  8. package/dist/agents/sandbox/dna-methylation-agent.js +1 -10
  9. package/dist/agents/sandbox/drug-repurposing-agent.js +4 -14
  10. package/dist/agents/sandbox/enrichment-agent.js +1 -10
  11. package/dist/agents/sandbox/ephemeral-executor.js +1 -10
  12. package/dist/agents/sandbox/genomic-variant-agent.js +1 -3
  13. package/dist/agents/sandbox/immune-profiling-agent.js +1 -13
  14. package/dist/agents/sandbox/metabolomics-agent.js +1 -1
  15. package/dist/agents/sandbox/microbiome-agent.js +1 -1
  16. package/dist/agents/sandbox/multi-omics-integration-agent.js +1 -12
  17. package/dist/agents/sandbox/multimodal-sc-agent.js +1 -1
  18. package/dist/agents/sandbox/network-agent.js +1 -10
  19. package/dist/agents/sandbox/pkpd-clinical-response-agent.js +2 -8
  20. package/dist/agents/sandbox/proteomics-agent.js +1 -1
  21. package/dist/agents/sandbox/scientific-executor.js +1 -10
  22. package/dist/agents/sandbox/shared.d.ts +20 -6
  23. package/dist/agents/sandbox/shared.js +50 -39
  24. package/dist/agents/sandbox/single-cell-agent.js +1 -1
  25. package/dist/agents/sandbox/spatial-omics-agent.js +1 -1
  26. package/dist/agents/sandbox/statistical-modeling-agent.js +1 -1
  27. package/dist/agents/sandbox/translational-safety-agent.js +3 -9
  28. package/dist/agents/sandbox/types.d.ts +1 -1
  29. package/dist/agents/system-prompt.d.ts +37 -11
  30. package/dist/agents/system-prompt.js +35 -12
  31. package/dist/app/chat-turn.d.ts +3 -0
  32. package/dist/app/chat-turn.js +3 -1
  33. package/dist/app/data-profile-orientation.d.ts +34 -0
  34. package/dist/app/data-profile-orientation.js +117 -0
  35. package/dist/app/synthesize-run.d.ts +3 -0
  36. package/dist/app/synthesize-run.js +3 -1
  37. package/dist/contracts/schemas/chat-parts.d.ts +9 -9
  38. package/dist/execution/artifact-metadata.d.ts +3 -0
  39. package/dist/execution/artifact-metadata.js +10 -3
  40. package/dist/execution/artifact-registration.d.ts +2 -1
  41. package/dist/execution/artifact-registration.js +8 -2
  42. package/dist/execution/ephemeral-runner.d.ts +16 -0
  43. package/dist/execution/ephemeral-runner.js +31 -5
  44. package/dist/execution/post-step-pipeline.d.ts +3 -0
  45. package/dist/execution/post-step-pipeline.js +24 -4
  46. package/dist/execution/reconcile-manifest.d.ts +7 -0
  47. package/dist/execution/reconcile-manifest.js +19 -5
  48. package/dist/execution/report-runner.d.ts +3 -0
  49. package/dist/execution/report-runner.js +4 -4
  50. package/dist/execution/run-synthesis.js +20 -19
  51. package/dist/execution/step-summary.d.ts +3 -0
  52. package/dist/execution/step-summary.js +6 -3
  53. package/dist/index.d.ts +9 -2
  54. package/dist/index.js +24 -5
  55. package/dist/lib/chrome.d.ts +4 -1
  56. package/dist/lib/chrome.js +10 -7
  57. package/dist/lib/console-logger.d.ts +19 -0
  58. package/dist/lib/console-logger.js +62 -0
  59. package/dist/lib/logger.d.ts +88 -0
  60. package/dist/lib/logger.js +37 -0
  61. package/dist/lib/otel.d.ts +2 -1
  62. package/dist/lib/otel.js +8 -3
  63. package/dist/loop/__fixtures__/scripted-provider.d.ts +2 -2
  64. package/dist/loop/__fixtures__/scripted-provider.js +2 -1
  65. package/dist/loop/metrics.d.ts +33 -1
  66. package/dist/loop/metrics.js +56 -2
  67. package/dist/loop/run-agent.d.ts +13 -1
  68. package/dist/loop/run-agent.js +19 -4
  69. package/dist/memory/card-builders.d.ts +8 -1
  70. package/dist/memory/card-builders.js +20 -3
  71. package/dist/memory/reconstruct-cards.js +4 -3
  72. package/dist/memory/thread-history.d.ts +27 -2
  73. package/dist/memory/thread-history.js +45 -5
  74. package/dist/memory/working-memory.d.ts +93 -10
  75. package/dist/memory/working-memory.js +220 -84
  76. package/dist/prompts/SOUL.d.ts +22 -9
  77. package/dist/prompts/SOUL.js +56 -37
  78. package/dist/prompts/analogical-reasoner.d.ts +1 -1
  79. package/dist/prompts/analogical-reasoner.js +2 -2
  80. package/dist/prompts/briefing.d.ts +100 -0
  81. package/dist/prompts/briefing.js +166 -0
  82. package/dist/prompts/conversation.d.ts +1 -1
  83. package/dist/prompts/conversation.js +94 -440
  84. package/dist/prompts/literature-reviewer.d.ts +1 -1
  85. package/dist/prompts/literature-reviewer.js +10 -10
  86. package/dist/prompts/planner.js +28 -59
  87. package/dist/prompts/report-builder.d.ts +1 -1
  88. package/dist/prompts/report-builder.js +71 -24
  89. package/dist/prompts/sandbox/bulk-transcriptomics-agent.d.ts +1 -1
  90. package/dist/prompts/sandbox/bulk-transcriptomics-agent.js +2 -7
  91. package/dist/prompts/sandbox/cheminformatics-agent.d.ts +1 -1
  92. package/dist/prompts/sandbox/cheminformatics-agent.js +11 -15
  93. package/dist/prompts/sandbox/chromatin-agent.d.ts +1 -1
  94. package/dist/prompts/sandbox/chromatin-agent.js +3 -7
  95. package/dist/prompts/sandbox/data-profiler.d.ts +1 -1
  96. package/dist/prompts/sandbox/data-profiler.js +13 -8
  97. package/dist/prompts/sandbox/dna-methylation-agent.d.ts +1 -1
  98. package/dist/prompts/sandbox/dna-methylation-agent.js +2 -7
  99. package/dist/prompts/sandbox/drug-repurposing-agent.d.ts +1 -1
  100. package/dist/prompts/sandbox/drug-repurposing-agent.js +15 -16
  101. package/dist/prompts/sandbox/enrichment-agent.d.ts +1 -1
  102. package/dist/prompts/sandbox/enrichment-agent.js +2 -9
  103. package/dist/prompts/sandbox/genomic-variant-agent.d.ts +1 -1
  104. package/dist/prompts/sandbox/genomic-variant-agent.js +2 -6
  105. package/dist/prompts/sandbox/immune-profiling-agent.d.ts +1 -1
  106. package/dist/prompts/sandbox/immune-profiling-agent.js +3 -8
  107. package/dist/prompts/sandbox/metabolomics-agent.d.ts +1 -1
  108. package/dist/prompts/sandbox/metabolomics-agent.js +1 -7
  109. package/dist/prompts/sandbox/microbiome-agent.d.ts +1 -1
  110. package/dist/prompts/sandbox/microbiome-agent.js +2 -7
  111. package/dist/prompts/sandbox/multi-omics-integration-agent.d.ts +1 -1
  112. package/dist/prompts/sandbox/multi-omics-integration-agent.js +2 -8
  113. package/dist/prompts/sandbox/multimodal-sc-agent.d.ts +1 -1
  114. package/dist/prompts/sandbox/multimodal-sc-agent.js +2 -7
  115. package/dist/prompts/sandbox/network-agent.d.ts +1 -1
  116. package/dist/prompts/sandbox/network-agent.js +2 -7
  117. package/dist/prompts/sandbox/proteomics-agent.d.ts +1 -1
  118. package/dist/prompts/sandbox/proteomics-agent.js +2 -9
  119. package/dist/prompts/sandbox/single-cell-agent.d.ts +1 -1
  120. package/dist/prompts/sandbox/single-cell-agent.js +2 -9
  121. package/dist/prompts/sandbox/spatial-omics-agent.d.ts +1 -1
  122. package/dist/prompts/sandbox/spatial-omics-agent.js +3 -6
  123. package/dist/prompts/sandbox/statistical-modeling-agent.d.ts +1 -1
  124. package/dist/prompts/sandbox/statistical-modeling-agent.js +2 -7
  125. package/dist/prompts/sandbox/translational-safety-agent.d.ts +1 -1
  126. package/dist/prompts/sandbox/translational-safety-agent.js +13 -14
  127. package/dist/prompts/sandbox-standards.d.ts +22 -14
  128. package/dist/prompts/sandbox-standards.js +91 -71
  129. package/dist/prompts/synthesis-agent.d.ts +1 -1
  130. package/dist/prompts/synthesis-agent.js +33 -131
  131. package/dist/provenance/collector.js +1 -1
  132. package/dist/providers/ai-sdk.js +31 -4
  133. package/dist/providers/prompt-cache.d.ts +74 -0
  134. package/dist/providers/prompt-cache.js +77 -0
  135. package/dist/providers/types.d.ts +33 -0
  136. package/dist/reference-data/catalog.d.ts +131 -0
  137. package/dist/reference-data/catalog.js +348 -0
  138. package/dist/reference-data/receipt.d.ts +41 -0
  139. package/dist/reference-data/receipt.js +40 -0
  140. package/dist/runtime/boot.d.ts +2 -2
  141. package/dist/runtime/boot.js +1 -1
  142. package/dist/runtime/connection-budget.d.ts +2 -2
  143. package/dist/runtime/connection-budget.js +5 -3
  144. package/dist/runtime/dbos.d.ts +7 -7
  145. package/dist/runtime/dbos.js +14 -11
  146. package/dist/runtime/shutdown.d.ts +2 -2
  147. package/dist/runtime/shutdown.js +4 -3
  148. package/dist/sandbox/create-sandbox.d.ts +2 -2
  149. package/dist/sandbox/docker-client.d.ts +2 -2
  150. package/dist/sandbox/docker-client.js +4 -1
  151. package/dist/sandbox/k8s-client.d.ts +3 -0
  152. package/dist/sandbox/k8s-client.js +5 -4
  153. package/dist/sandbox/notification-sweep.d.ts +3 -3
  154. package/dist/sandbox/notification-sweep.js +4 -2
  155. package/dist/sandbox/reaper.d.ts +3 -3
  156. package/dist/sandbox/reaper.js +7 -4
  157. package/dist/sandbox/watchdog.d.ts +3 -3
  158. package/dist/sandbox/watchdog.js +8 -2
  159. package/dist/schemas/data-profile-schemas.js +5 -3
  160. package/dist/schemas/plan-schemas.d.ts +21 -21
  161. package/dist/schemas/plan-schemas.js +9 -3
  162. package/dist/schemas/run-synthesis.d.ts +8 -4
  163. package/dist/schemas/run-synthesis.js +92 -56
  164. package/dist/schemas/validate-plan.js +1 -1
  165. package/dist/schemas/workflow-state.d.ts +7 -1
  166. package/dist/schemas/workflow-state.js +33 -19
  167. package/dist/state/artifacts.d.ts +13 -0
  168. package/dist/state/artifacts.js +27 -0
  169. package/dist/state/data-profile.d.ts +64 -5
  170. package/dist/state/index.d.ts +3 -3
  171. package/dist/state/index.js +1 -1
  172. package/dist/state/init.d.ts +2 -1
  173. package/dist/state/init.js +5 -6
  174. package/dist/tasks/data-profile.d.ts +25 -2
  175. package/dist/tasks/data-profile.js +95 -39
  176. package/dist/tools/bio/chembl.d.ts +38 -0
  177. package/dist/tools/bio/chembl.js +138 -0
  178. package/dist/tools/bio/comptox.d.ts +50 -0
  179. package/dist/tools/bio/comptox.js +149 -0
  180. package/dist/tools/bio/get-impc-ko-profile.js +9 -6
  181. package/dist/tools/bio/index.d.ts +5 -17
  182. package/dist/tools/bio/index.js +5 -17
  183. package/dist/tools/bio/keys.d.ts +14 -9
  184. package/dist/tools/bio/keys.js +16 -16
  185. package/dist/tools/bio/opentargets.d.ts +38 -0
  186. package/dist/tools/bio/opentargets.js +89 -0
  187. package/dist/tools/bio/pubchem.d.ts +29 -0
  188. package/dist/tools/bio/pubchem.js +92 -0
  189. package/dist/tools/bio/pubmed.d.ts +51 -0
  190. package/dist/tools/bio/pubmed.js +100 -0
  191. package/dist/tools/bio/search-bgee-expression.js +12 -6
  192. package/dist/tools/bio/search-clinical-trials.js +16 -5
  193. package/dist/tools/bio/search-dgidb.d.ts +11 -1
  194. package/dist/tools/bio/search-dgidb.js +92 -78
  195. package/dist/tools/bio/search-faers.js +8 -4
  196. package/dist/tools/bio/search-geo-datasets.js +20 -6
  197. package/dist/tools/bio/search-gwas-catalog.d.ts +1 -1
  198. package/dist/tools/bio/search-pharmgkb.js +10 -4
  199. package/dist/tools/display/index.d.ts +1 -0
  200. package/dist/tools/display/index.js +1 -0
  201. package/dist/tools/display/normalize-echart-spec.d.ts +61 -0
  202. package/dist/tools/display/normalize-echart-spec.js +211 -0
  203. package/dist/tools/display/show-user.d.ts +6 -1
  204. package/dist/tools/display/show-user.js +25 -12
  205. package/dist/tools/execute-plan.js +5 -2
  206. package/dist/tools/iterate-report.d.ts +171 -118
  207. package/dist/tools/iterate-report.js +336 -96
  208. package/dist/tools/lib/chembl-client.d.ts +12 -0
  209. package/dist/tools/lib/chembl-client.js +127 -0
  210. package/dist/tools/lib/ctx-ops.d.ts +224 -0
  211. package/dist/tools/lib/ctx-ops.js +450 -0
  212. package/dist/tools/lib/iuphar-client.js +10 -1
  213. package/dist/tools/lib/openfda-client.js +11 -3
  214. package/dist/tools/lib/pathway-client.js +10 -4
  215. package/dist/tools/lib/pubchem-ops.d.ts +74 -0
  216. package/dist/tools/lib/pubchem-ops.js +224 -0
  217. package/dist/tools/memory/update-working-memory.d.ts +45 -7
  218. package/dist/tools/memory/update-working-memory.js +111 -41
  219. package/dist/tools/report/index.d.ts +3 -2
  220. package/dist/tools/report/index.js +3 -2
  221. package/dist/tools/research/generate-analogy-report.js +25 -12
  222. package/dist/tools/research/generate-plan.d.ts +12 -5
  223. package/dist/tools/research/generate-plan.js +168 -37
  224. package/dist/tools/research/index.d.ts +1 -0
  225. package/dist/tools/research/index.js +1 -0
  226. package/dist/tools/research/inspect-data-profile.d.ts +85 -0
  227. package/dist/tools/research/inspect-data-profile.js +161 -0
  228. package/dist/tools/research/literature-reviewer.d.ts +3 -0
  229. package/dist/tools/research/literature-reviewer.js +5 -6
  230. package/dist/tools/sandbox/list-available-packages.d.ts +79 -5
  231. package/dist/tools/sandbox/list-available-packages.js +152 -10
  232. package/dist/tools/sandbox/list-available-refs.d.ts +141 -5
  233. package/dist/tools/sandbox/list-available-refs.js +647 -134
  234. package/dist/tools/sandbox/report-blocker.d.ts +39 -9
  235. package/dist/tools/sandbox/report-blocker.js +43 -20
  236. package/dist/tools/workspace/execute-command.d.ts +3 -0
  237. package/dist/tools/workspace/execute-command.js +3 -1
  238. package/dist/tools/workspace/read-file.js +4 -5
  239. package/dist/tools/workspace/run-exec.d.ts +4 -4
  240. package/dist/tools/workspace/run-exec.js +4 -4
  241. package/dist/tools/workspace/show-file.js +10 -6
  242. package/dist/tools/workspace/show-plan.js +12 -6
  243. package/dist/tools/workspace/workspace-search.d.ts +1 -1
  244. package/dist/tools/workspace/workspace-search.js +11 -5
  245. package/dist/workflows/execute-analysis.d.ts +46 -4
  246. package/dist/workflows/execute-analysis.js +118 -13
  247. package/dist/workflows/execute-target-assessment.d.ts +3 -0
  248. package/dist/workflows/execute-target-assessment.js +19 -15
  249. package/dist/workflows/sandbox-step.d.ts +9 -0
  250. package/dist/workflows/sandbox-step.js +39 -17
  251. package/dist/workflows/target-assessment/lib/citation-validator.js +2 -2
  252. package/dist/workflows/target-assessment/lib/clinical-consequence-annotator.js +2 -1
  253. package/dist/workflows/target-assessment/lib/llm-step.d.ts +3 -0
  254. package/dist/workflows/target-assessment/lib/llm-step.js +3 -1
  255. package/dist/workflows/target-assessment/lib/structured-llm.d.ts +3 -0
  256. package/dist/workflows/target-assessment/lib/structured-llm.js +1 -0
  257. package/dist/workflows/target-assessment/phase5-persist.d.ts +3 -0
  258. package/dist/workflows/target-assessment/phase5-persist.js +8 -3
  259. package/dist/workflows/target-assessment/progress.d.ts +2 -1
  260. package/dist/workflows/target-assessment/progress.js +4 -3
  261. package/dist/workspace/filesystem.js +163 -74
  262. package/dist/workspace/paths.d.ts +2 -2
  263. package/dist/workspace/paths.js +2 -2
  264. package/package.json +95 -96
  265. package/dist/execution/filesystem-artifact-registry.d.ts +0 -57
  266. package/dist/execution/filesystem-artifact-registry.js +0 -92
  267. package/dist/lib/identifiers.d.ts +0 -8
  268. package/dist/lib/identifiers.js +0 -10
  269. package/dist/lib/mime-detect.d.ts +0 -17
  270. package/dist/lib/mime-detect.js +0 -29
  271. package/dist/lib/streamed-download.d.ts +0 -28
  272. package/dist/lib/streamed-download.js +0 -111
  273. package/dist/lib/trace-context.d.ts +0 -11
  274. package/dist/lib/trace-context.js +0 -49
  275. package/dist/providers/llm-capabilities.d.ts +0 -33
  276. package/dist/providers/llm-capabilities.js +0 -58
  277. package/dist/schemas/render-step-prompt.d.ts +0 -32
  278. package/dist/schemas/render-step-prompt.js +0 -76
  279. package/dist/tools/bio/find-approval-precedent.d.ts +0 -32
  280. package/dist/tools/bio/find-approval-precedent.js +0 -72
  281. package/dist/tools/bio/get-article-details.d.ts +0 -11
  282. package/dist/tools/bio/get-article-details.js +0 -20
  283. package/dist/tools/bio/get-article-full-text.d.ts +0 -19
  284. package/dist/tools/bio/get-article-full-text.js +0 -32
  285. package/dist/tools/bio/get-bioactivity.d.ts +0 -11
  286. package/dist/tools/bio/get-bioactivity.js +0 -23
  287. package/dist/tools/bio/get-drug-info.d.ts +0 -9
  288. package/dist/tools/bio/get-drug-info.js +0 -22
  289. package/dist/tools/bio/get-mechanism.d.ts +0 -8
  290. package/dist/tools/bio/get-mechanism.js +0 -18
  291. package/dist/tools/bio/get-pubchem-assays.d.ts +0 -22
  292. package/dist/tools/bio/get-pubchem-assays.js +0 -107
  293. package/dist/tools/bio/get-pubchem-cross-refs.d.ts +0 -15
  294. package/dist/tools/bio/get-pubchem-cross-refs.js +0 -68
  295. package/dist/tools/bio/get-target-safety.d.ts +0 -18
  296. package/dist/tools/bio/get-target-safety.js +0 -26
  297. package/dist/tools/bio/search-compounds.d.ts +0 -22
  298. package/dist/tools/bio/search-compounds.js +0 -160
  299. package/dist/tools/bio/search-ctx-chemical.d.ts +0 -50
  300. package/dist/tools/bio/search-ctx-chemical.js +0 -130
  301. package/dist/tools/bio/search-ctx-exposure.d.ts +0 -55
  302. package/dist/tools/bio/search-ctx-exposure.js +0 -176
  303. package/dist/tools/bio/search-ctx-hazard.d.ts +0 -111
  304. package/dist/tools/bio/search-ctx-hazard.js +0 -178
  305. package/dist/tools/bio/search-opentargets.d.ts +0 -11
  306. package/dist/tools/bio/search-opentargets.js +0 -25
  307. package/dist/tools/bio/search-pubchem-compound.d.ts +0 -26
  308. package/dist/tools/bio/search-pubchem-compound.js +0 -110
  309. package/dist/tools/bio/search-pubmed.d.ts +0 -17
  310. package/dist/tools/bio/search-pubmed.js +0 -31
  311. package/dist/tools/bio/search-targets.d.ts +0 -9
  312. package/dist/tools/bio/search-targets.js +0 -20
  313. package/dist/tools/bio/search-toxcast.d.ts +0 -36
  314. package/dist/tools/bio/search-toxcast.js +0 -141
  315. package/dist/workflows/register-workflows.d.ts +0 -51
  316. package/dist/workflows/register-workflows.js +0 -48
  317. package/dist/workflows/resume-execute-analysis.d.ts +0 -70
  318. package/dist/workflows/resume-execute-analysis.js +0 -80
  319. package/dist/workflows/target-assessment/correction-loop.d.ts +0 -45
  320. package/dist/workflows/target-assessment/correction-loop.js +0 -62
  321. package/dist/workflows/target-assessment/steps/phase0-resolve.d.ts +0 -71
  322. package/dist/workflows/target-assessment/steps/phase0-resolve.js +0 -21
  323. package/dist/workflows/target-assessment/steps/phase1-aggregate.d.ts +0 -1018
  324. package/dist/workflows/target-assessment/steps/phase1-aggregate.js +0 -25
  325. package/dist/workspace/mount-strategy.d.ts +0 -50
  326. package/dist/workspace/mount-strategy.js +0 -67
  327. package/dist/workspace/provenance-collector.d.ts +0 -34
  328. package/dist/workspace/provenance-collector.js +0 -16
  329. package/dist/workspace/workspace-paths.d.ts +0 -26
  330. package/dist/workspace/workspace-paths.js +0 -31
@@ -1,14 +1,19 @@
1
1
  /**
2
- * `report_blocker` — a step agent's honest exit when it cannot fulfil its
3
- * step (see the harness-sandbox-agents spec). There is no `submit`/`done` tool: a step's deliverable is
4
- * its persisted files, so a clean end-of-turn after writing them is the
5
- * implicit success. Calling `report_blocker` is the alternative to
6
- * improvising an inline result the harness would launder into a green run.
2
+ * `report_blocker` — an agent's honest exit when it cannot fulfil the loop it
3
+ * is driving (see the harness-sandbox-agents spec). There is no `submit`/`done`
4
+ * tool on a sandbox step: a step's deliverable is its persisted files, so a
5
+ * clean end-of-turn after writing them is the implicit success. Calling
6
+ * `report_blocker` is the alternative to improvising an inline result the
7
+ * harness would launder into a green run.
7
8
  *
8
- * Mirrors the synthesizer's blocker (`execution/run-synthesis.ts`): the
9
- * workflow body owns a per-run `BlockerHolder` and reads `holder.outcome`
10
- * after `runAgent`. The tool only records the reason and tells the agent to
11
- * stop — the body decides the terminal status.
9
+ * This module is the canonical home of the tool. Three loops offer it — the
10
+ * sandbox step agent, the planner (`tools/research/generate-plan.ts`) and the
11
+ * run synthesizer (`execution/run-synthesis.ts`) — and all three share one id,
12
+ * one input schema and one terminal contract via `createReportBlockerToolFor`.
13
+ * What differs per loop is only what a blocker *means* there, so each call site
14
+ * injects its own `blockedWhen` prose and its own capture closure. The tool
15
+ * records the reason and tells the agent to stop; the driving body reads its
16
+ * own outcome cell after the loop and decides the terminal status.
12
17
  */
13
18
  import { type Tool } from "../define-tool.js";
14
19
  export interface BlockerOutcome {
@@ -20,4 +25,29 @@ export interface BlockerHolder {
20
25
  outcome: BlockerOutcome | null;
21
26
  }
22
27
  export declare function createBlockerHolder(): BlockerHolder;
28
+ export interface ReportBlockerDeps {
29
+ /**
30
+ * The calling loop's blocker-capture side effect — writes the outcome into
31
+ * whatever cell that body reads after its loop. Invoked on every call; the
32
+ * closure owns the first-call-wins guard, because only the call site knows
33
+ * what else may already have terminated its loop.
34
+ */
35
+ readonly record: (outcome: BlockerOutcome) => void;
36
+ /**
37
+ * What a blocker means in THIS loop: which loop the call ends and the
38
+ * conditions that warrant it. Composed into the shared terminal contract,
39
+ * so a description can never promise a loop this instance does not end.
40
+ */
41
+ readonly blockedWhen: string;
42
+ }
43
+ /**
44
+ * Build the `report_blocker` tool for one loop. The id, the input schema and
45
+ * the terminal contract ("pass a reason, then stop") are fixed here; the call
46
+ * site supplies only the per-loop meaning and the capture closure.
47
+ */
48
+ export declare function createReportBlockerToolFor(deps: ReportBlockerDeps): Tool;
49
+ /**
50
+ * The sandbox step agent's `report_blocker`, bound to the step body's holder.
51
+ * A blocker here ends the step with no deliverables and a blocked reason.
52
+ */
23
53
  export declare function createReportBlockerTool(holder: BlockerHolder): Tool;
@@ -1,14 +1,19 @@
1
1
  /**
2
- * `report_blocker` — a step agent's honest exit when it cannot fulfil its
3
- * step (see the harness-sandbox-agents spec). There is no `submit`/`done` tool: a step's deliverable is
4
- * its persisted files, so a clean end-of-turn after writing them is the
5
- * implicit success. Calling `report_blocker` is the alternative to
6
- * improvising an inline result the harness would launder into a green run.
2
+ * `report_blocker` — an agent's honest exit when it cannot fulfil the loop it
3
+ * is driving (see the harness-sandbox-agents spec). There is no `submit`/`done`
4
+ * tool on a sandbox step: a step's deliverable is its persisted files, so a
5
+ * clean end-of-turn after writing them is the implicit success. Calling
6
+ * `report_blocker` is the alternative to improvising an inline result the
7
+ * harness would launder into a green run.
7
8
  *
8
- * Mirrors the synthesizer's blocker (`execution/run-synthesis.ts`): the
9
- * workflow body owns a per-run `BlockerHolder` and reads `holder.outcome`
10
- * after `runAgent`. The tool only records the reason and tells the agent to
11
- * stop — the body decides the terminal status.
9
+ * This module is the canonical home of the tool. Three loops offer it — the
10
+ * sandbox step agent, the planner (`tools/research/generate-plan.ts`) and the
11
+ * run synthesizer (`execution/run-synthesis.ts`) — and all three share one id,
12
+ * one input schema and one terminal contract via `createReportBlockerToolFor`.
13
+ * What differs per loop is only what a blocker *means* there, so each call site
14
+ * injects its own `blockedWhen` prose and its own capture closure. The tool
15
+ * records the reason and tells the agent to stop; the driving body reads its
16
+ * own outcome cell after the loop and decides the terminal status.
12
17
  */
13
18
  import { ok } from "neverthrow";
14
19
  import { z } from "zod";
@@ -16,20 +21,20 @@ import { defineTool } from "../define-tool.js";
16
21
  export function createBlockerHolder() {
17
22
  return { outcome: null };
18
23
  }
19
- export function createReportBlockerTool(holder) {
24
+ /** The one input every `report_blocker` takes, wherever it is offered. */
25
+ const ReportBlockerInputSchema = z.object({ reason: z.string().min(1) });
26
+ /**
27
+ * Build the `report_blocker` tool for one loop. The id, the input schema and
28
+ * the terminal contract ("pass a reason, then stop") are fixed here; the call
29
+ * site supplies only the per-loop meaning and the capture closure.
30
+ */
31
+ export function createReportBlockerToolFor(deps) {
20
32
  return defineTool({
21
33
  id: "report_blocker",
22
- description: "Terminal. Call this when you cannot fulfil the step — required inputs " +
23
- "are missing or unreadable, the requested analysis is infeasible with " +
24
- "the available data/packages, or you cannot produce the persisted " +
25
- "deliverables (scripts, output files, figures). Pass a clear reason. Do " +
26
- "NOT improvise an inline result and narrate it; if you cannot persist " +
27
- "real output files, report a blocker. Stop after calling.",
28
- inputSchema: z.object({ reason: z.string().min(1) }),
34
+ description: `Terminal. ${deps.blockedWhen} Pass a clear reason. Stop immediately after calling — take no further actions.`,
35
+ inputSchema: ReportBlockerInputSchema,
29
36
  execute: async (input) => {
30
- if (holder.outcome === null) {
31
- holder.outcome = { kind: "blocker", reason: input.reason };
32
- }
37
+ deps.record({ kind: "blocker", reason: input.reason });
33
38
  return ok({
34
39
  recorded: true,
35
40
  message: "Blocker recorded. You are done — stop now and do not take further actions.",
@@ -37,3 +42,21 @@ export function createReportBlockerTool(holder) {
37
42
  },
38
43
  });
39
44
  }
45
+ /**
46
+ * The sandbox step agent's `report_blocker`, bound to the step body's holder.
47
+ * A blocker here ends the step with no deliverables and a blocked reason.
48
+ */
49
+ export function createReportBlockerTool(holder) {
50
+ return createReportBlockerToolFor({
51
+ record: (outcome) => {
52
+ if (holder.outcome === null)
53
+ holder.outcome = outcome;
54
+ },
55
+ blockedWhen: "Ends this analysis step with no deliverables. Call it when you cannot " +
56
+ "fulfil the step — required inputs are missing or unreadable, the " +
57
+ "requested analysis is infeasible with the available data/packages, or " +
58
+ "you cannot produce the persisted deliverables (scripts, output files, " +
59
+ "figures). Do NOT improvise an inline result and narrate it: if you " +
60
+ "cannot persist real output files, report a blocker.",
61
+ });
62
+ }
@@ -22,7 +22,10 @@
22
22
  import type { SandboxClient } from "../../sandbox/client.js";
23
23
  import type { SandboxRef } from "../../sandbox/types.js";
24
24
  import type { ProvenanceCollector } from "../../provenance/collector.js";
25
+ import type { Logger } from "../../lib/logger.js";
25
26
  export interface ExecuteCommandDeps {
27
+ /** Operational logging seam; omitted falls back to no-op. */
28
+ readonly logger?: Logger;
26
29
  readonly sandboxClient: SandboxClient;
27
30
  /** Live sandbox handle for the step. Created once per step at composition root. */
28
31
  readonly sandbox: SandboxRef;
@@ -26,6 +26,7 @@ import { defineTool } from "../define-tool.js";
26
26
  import { feedExecFrame } from "../../provenance/exec-frame.js";
27
27
  import { boundExecResult } from "./result-bounds.js";
28
28
  import { runSandboxExec } from "./run-exec.js";
29
+ import { createNoopLogger } from "../../lib/console-logger.js";
29
30
  const ExecuteCommandInputSchema = z.object({
30
31
  command: z
31
32
  .array(z.string().min(1))
@@ -86,7 +87,8 @@ export function createExecuteCommandTool(deps) {
86
87
  });
87
88
  }
88
89
  catch (err) {
89
- console.warn(`[execute_command] provenance frame handling failed (non-fatal) for ${execId}: ${err instanceof Error ? err.message : err}`);
90
+ const logger = (deps.logger ?? createNoopLogger()).named("execute_command");
91
+ logger.warn("provenance frame handling failed (non-fatal)", { execId, ...logger.errorFields(err) });
90
92
  }
91
93
  }
92
94
  return ok({ status: "ok", ...boundExecResult(result) });
@@ -19,8 +19,7 @@ const ReadFileInputSchema = z.object({
19
19
  .min(1)
20
20
  .describe("Workspace path. Relative paths resolve against your working directory; " +
21
21
  "an absolute '/<analysisId>/...' path is resolved against the analysis " +
22
- "root (use absolute to read input data, the data profile, or other " +
23
- "steps' outputs)."),
22
+ "root (use absolute to read input data or other steps' outputs)."),
24
23
  headLines: z
25
24
  .number()
26
25
  .int()
@@ -28,7 +27,7 @@ const ReadFileInputSchema = z.object({
28
27
  .max(10_000)
29
28
  .optional()
30
29
  .describe("Read only the first N lines (head). Use for inspecting CSV/TSV " +
31
- "headers, profile summaries, or the top of any large file. Mutually " +
30
+ "headers, step summaries, or the top of any large file. Mutually " +
32
31
  "exclusive with tailLines."),
33
32
  tailLines: z
34
33
  .number()
@@ -42,8 +41,8 @@ export function createReadFileTool(fs, workingDir) {
42
41
  return defineTool({
43
42
  id: "read_file",
44
43
  description: "Read a workspace file: input data, prior-run outputs, current-run " +
45
- "outputs, step summaries, run syntheses, or the data profile. Returns " +
46
- "the file content as UTF-8 text. Output is capped at " +
44
+ "outputs, step summaries, or run syntheses. Returns the file content " +
45
+ "as UTF-8 text. Output is capped at " +
47
46
  `${DEFAULT_MAX_BYTES} bytes; pass headLines or tailLines to read a ` +
48
47
  "specific window of a large file (typical for bio CSV/TSV/log files). " +
49
48
  "Oversize reads come back truncated with a marker. Missing paths and " +
@@ -1,10 +1,10 @@
1
1
  /**
2
- * Internal helper used by the three mutate tools to drive one sandbox exec
2
+ * Internal helper used by dependency-bearing tools to drive one sandbox exec
3
3
  * through the `SandboxClient`. Centralises the submit/await pair, exec-id
4
4
  * derivation, and intermediate-event forwarding so all three tools share
5
- * one chokepoint — the contract `execute_command` makes structural is that
6
- * `write_file` / `edit_file` are layered on top of it, not parallel side
7
- * paths into sandbox-server.
5
+ * one chokepoint. `write_file` / `edit_file` are layered on the workspace
6
+ * mutator and environment introspection tools such as `list_available_refs`
7
+ * use this same replay-safe submit/await path rather than a parallel protocol.
8
8
  *
9
9
  * Not a registered tool — `defineTool` is called by the user-facing tools
10
10
  * (`execute-command.ts`, `write-file.ts`, `edit-file.ts`) which wrap this.
@@ -1,10 +1,10 @@
1
1
  /**
2
- * Internal helper used by the three mutate tools to drive one sandbox exec
2
+ * Internal helper used by dependency-bearing tools to drive one sandbox exec
3
3
  * through the `SandboxClient`. Centralises the submit/await pair, exec-id
4
4
  * derivation, and intermediate-event forwarding so all three tools share
5
- * one chokepoint — the contract `execute_command` makes structural is that
6
- * `write_file` / `edit_file` are layered on top of it, not parallel side
7
- * paths into sandbox-server.
5
+ * one chokepoint. `write_file` / `edit_file` are layered on the workspace
6
+ * mutator and environment introspection tools such as `list_available_refs`
7
+ * use this same replay-safe submit/await path rather than a parallel protocol.
8
8
  *
9
9
  * Not a registered tool — `defineTool` is called by the user-facing tools
10
10
  * (`execute-command.ts`, `write-file.ts`, `edit-file.ts`) which wrap this.
@@ -20,19 +20,23 @@ const ShowFileInputSchema = z.object({
20
20
  title: z.string().optional().describe("Group heading shown above the card or gallery"),
21
21
  files: z
22
22
  .array(z.object({
23
- path: z.string().describe("Analysis-rooted file path (e.g., 'runs/run-abc/step-1/figures/volcano.png')"),
23
+ path: z.string().describe("Analysis-rooted file path — no leading slash, no `..` (e.g., 'runs/run-abc/step-1/figures/volcano.png')"),
24
24
  caption: z.string().optional().describe("One-sentence context rendered beside this file"),
25
25
  }))
26
26
  .min(1)
27
27
  .max(MAX_FILES)
28
- .describe(`1 to ${MAX_FILES} files; multiple files render as a gallery`),
28
+ .describe(`The related set of files to show together, 1 to ${MAX_FILES} per call; multiple render as ONE gallery card. Pass a related set in a single call — do not make one call per figure.`),
29
29
  });
30
30
  export const showFileTool = defineTool({
31
31
  id: "show_file",
32
- description: "Display one or more existing analysis artifacts (images, CSVs, PDFs, notebooks, logs) in chat by path. " +
33
- "Paths must be analysis-rooted (no leading slash, no `..`). Up to 10 files per call — multiple render as a gallery. " +
34
- "Do NOT read a file and paste its bytes elsewhere; this tool references the file directly. " +
35
- "File content is fetched when the user views the card — you do not need to provide it.",
32
+ description: "Display EXISTING analysis artifacts in chat by path — images, CSVs, PDFs, notebooks, logs. " +
33
+ "The card references the file directly and its content is fetched when the user views it: you never read, " +
34
+ "inline, or paste the bytes. Pick this tool by what you are referencing, not by how the output looks: " +
35
+ "NOT for content you synthesized (a chart, a table, a snippet you invented — use `show_user`), NOT for a stored plan (`show_plan`). " +
36
+ "Paths are analysis-rooted (no leading slash, no `..`); discover them with `workspace_search` or `list_files`. " +
37
+ "Up to 10 files per call — pass a related set in ONE call and they render as a gallery, rather than one call per figure. " +
38
+ "Cards render in call order, so to interleave figures with prose alternate `show_user(markdown)` and `show_file` calls " +
39
+ "(markdown image syntax pointing at a workspace file does NOT render — this tool is the only way to show one).",
36
40
  inputSchema: ShowFileInputSchema,
37
41
  execute: async (input, ctx) => {
38
42
  const card = buildFileReferenceCardData(input);
@@ -18,13 +18,19 @@ const PLAN_ID_REGEX = /^pln-[a-f0-9]{8}$/;
18
18
  export function createShowPlanTool(pool) {
19
19
  return defineTool({
20
20
  id: "show_plan",
21
- description: "Display a previously generated plan in chat by its planId. " +
22
- "Use when the user asks to see a plan again, or to reference a historical plan. " +
23
- "Get planIds from `inspect-run` (each run carries its planId) or `generatePlan` (newly created). " +
24
- "The plan content is embedded in the chat part so the UI renders it directly.",
21
+ description: "Display a STORED plan in chat by its planId. The plan is loaded from storage and embedded in the card, " +
22
+ "so the UI renders it directly. Use it to present the plan `generate_plan` just produced, and when the user " +
23
+ "asks to see an earlier plan again. " +
24
+ "Pick this tool by what you are referencing, not by how the output looks: " +
25
+ "NOT for a plan you are drafting in conversation (that is `generate_plan`), NOT for other synthesized content " +
26
+ "(`show_user`), NOT for analysis files (`show_file`). Never re-type a plan's steps into a `show_user` markdown " +
27
+ "card — that renders a second, divergent copy of the same plan.",
25
28
  inputSchema: z.object({
26
- planId: z.string().regex(PLAN_ID_REGEX, "planId must match pln-<8hex>").describe("Plan ID from generatePlan or inspect-run"),
27
- title: z.string().optional().describe("Optional display heading"),
29
+ planId: z
30
+ .string()
31
+ .regex(PLAN_ID_REGEX, "planId must match pln-<8hex>")
32
+ .describe("Plan ID (`pln-<8hex>`) from `generate_plan` (newly created) or `inspect_run` (each run carries the planId it ran)"),
33
+ title: z.string().optional().describe("Optional card heading; defaults to the plan's own title"),
28
34
  }),
29
35
  execute: async ({ planId, title }, ctx) => {
30
36
  const resourceId = scopeResource(ctx.session.scope).resourceId;
@@ -15,7 +15,7 @@ import type { EmbeddingProvider } from "../../providers/types.js";
15
15
  export declare function createWorkspaceSearchTool(pool: Pool, embedding: EmbeddingProvider): import("../define-tool.js").Tool<{
16
16
  query: string;
17
17
  limit: number;
18
- type?: "output" | "input" | "summary" | "synthesis" | undefined;
18
+ type?: "output" | "input" | "synthesis" | "summary" | undefined;
19
19
  }, {
20
20
  results: {
21
21
  id: string;
@@ -32,13 +32,19 @@ function indexName(analysisId) {
32
32
  export function createWorkspaceSearchTool(pool, embedding) {
33
33
  return defineTool({
34
34
  id: "workspace_search",
35
- description: "Semantic search over the analysis workspace — input data, analysis " +
36
- "outputs, step summaries, run syntheses, and the data profile. Returns " +
37
- "ranked file paths with descriptions and metadata; read a file " +
38
- "separately to see its contents. Optionally filter by entry type.",
35
+ description: "Semantic search over the analysis workspace. Returns ranked file paths " +
36
+ "with descriptions and metadata; read a file separately to see its " +
37
+ "contents. Indexed entries are exactly four types, and `type` restricts " +
38
+ 'results to one of them: "input" (staged input data files — their ' +
39
+ 'descriptions come from the data profiler), "output" (files a step ' +
40
+ 'produced), "summary" (a step\'s summary), "synthesis" (a run\'s ' +
41
+ "literature-grounded synthesis).",
39
42
  inputSchema: z.object({
40
43
  query: z.string().min(1).describe("What to search for, in natural language"),
41
- type: z.enum(["input", "output", "summary", "synthesis"]).optional().describe("Restrict results to one workspace entry type"),
44
+ type: z
45
+ .enum(["input", "output", "summary", "synthesis"])
46
+ .optional()
47
+ .describe('Restrict results to one entry type: "input", "output", "summary", or "synthesis"'),
42
48
  limit: z.number().int().min(1).max(50).default(8).describe("Maximum number of results to return"),
43
49
  }),
44
50
  execute: async ({ query, type, limit }, ctx) => {
@@ -20,6 +20,10 @@
20
20
  * - dispatch every `scheduleReady(plan, completedSet, startedSet)` via
21
21
  * `DBOS.startWorkflow` with deterministic child id
22
22
  * `"${parent.workflowID}-${N}"` (N is the step's stable index)
23
+ * - compose each child's seed prompt HERE, at dispatch (`composeStepSeed`,
24
+ * inside a durable step): the moment a step is dispatched is the first
25
+ * moment its dependencies' results exist, so this is the only place the
26
+ * seed can name them
23
27
  * - each child input is `forStep(input.runSession, stepId)` for the
24
28
  * session field
25
29
  * - emit `data-dag-state` (reconciling by id) on every dispatch +
@@ -53,6 +57,8 @@ import type { Pool } from "pg";
53
57
  import type { MachineBudget, ResourceSpec } from "../config/resource-limits.js";
54
58
  import type { RunSession } from "../auth/types.js";
55
59
  import type { RunAuthorizer } from "../execution/run-authorizer.js";
60
+ import type { Logger } from "../lib/logger.js";
61
+ import type { AnalysisStep } from "../schemas/workflow-state.js";
56
62
  import type { ChatProvider, EmbeddingProvider } from "../providers/types.js";
57
63
  import type { BioToolKeys } from "../tools/bio/keys.js";
58
64
  import type { RunCharge } from "../billing/run-charge.js";
@@ -76,8 +82,15 @@ export interface ExecuteAnalysisInput {
76
82
  readonly steps: readonly PlanStep[];
77
83
  /** Optional thread id for cortex_runs.thread_id (UI breadcrumb only). */
78
84
  readonly threadId?: string | null;
79
- /** Per-step prompt body the child workflow forwards to its agent. */
80
- readonly promptByStepId: Readonly<Record<string, string>>;
85
+ /**
86
+ * The plan's steps, keyed by id — the instruction DATA each step's seed is
87
+ * composed FROM, not a pre-rendered prompt string. The seed itself is
88
+ * composed per step at dispatch (`composeStepSeed`), because that is the
89
+ * first moment a step's dependencies have produced anything to tell it
90
+ * about. Snapshotted here at the async edge so the body never re-reads the
91
+ * plan row (a mid-run plan edit cannot change a running run's instructions).
92
+ */
93
+ readonly planStepById: Readonly<Record<string, AnalysisStep>>;
81
94
  /** Per-step agent id (sandbox catalog entry). */
82
95
  readonly agentByStepId: Readonly<Record<string, string>>;
83
96
  /** Per-step planner-estimated sandbox resource request. */
@@ -194,6 +207,8 @@ export type RunProvenanceEvent = {
194
207
  * embedder, model, keys, roots) the in-body synthesis needs.
195
208
  */
196
209
  export interface ExecuteAnalysisDeps {
210
+ /** Operational logging seam; omitted falls back to no-op. */
211
+ readonly logger?: Logger;
197
212
  readonly pool: Pool;
198
213
  /** Chat provider for the in-body literature-grounded synthesis. */
199
214
  readonly provider: ChatProvider;
@@ -229,8 +244,9 @@ export interface ExecuteAnalysisDeps {
229
244
  }
230
245
  /**
231
246
  * Project the sandbox-step input handed to each child. The parent owns the
232
- * level computation; the rest comes from `ExecuteAnalysisInput`. The body
233
- * fills in `runSession` via `forStep` after this returns. Exported for the
247
+ * level computation and the seed (`prompt`, composed by `composeStepSeed` at
248
+ * dispatch); the rest comes from `ExecuteAnalysisInput`. The body fills in
249
+ * `runSession` via `forStep` after this returns. Exported for the
234
250
  * projection/timeout-propagation tests.
235
251
  */
236
252
  export declare function buildChildInput(args: {
@@ -239,7 +255,33 @@ export declare function buildChildInput(args: {
239
255
  level: number;
240
256
  runId: string;
241
257
  workflowId: string;
258
+ prompt: string;
242
259
  }): Omit<SandboxStepInput, "runSession">;
260
+ /**
261
+ * Compose one step's seed — the user-content message its agent opens on.
262
+ *
263
+ * The composition point is the design: the scheduler calls this at the instant
264
+ * it dispatches a step, which is the first instant at which every one of that
265
+ * step's dependencies has *finished* and written its results down. A seed
266
+ * rendered any earlier (at plan submission, say) cannot mention them, and the
267
+ * agent is left to rediscover its own upstream.
268
+ *
269
+ * Everything read here is durable state written by an already-settled child
270
+ * (`output/summary.md`, `cortex_artifacts`) or by the profiler
271
+ * (`cortex_analysis_state`) — never live in-flight state, which would not
272
+ * reproduce.
273
+ *
274
+ * REPLAY: the caller wraps this in a `DBOS.runStep`, so the composed string is
275
+ * checkpointed and a replay returns it verbatim — the DB and disk are not read
276
+ * again and cannot drift the seed under a recovered run. Never call it
277
+ * unwrapped from the workflow body.
278
+ */
279
+ export declare function composeStepSeed(args: {
280
+ input: ExecuteAnalysisInput;
281
+ stepId: string;
282
+ runId: string;
283
+ deps: ExecuteAnalysisDeps;
284
+ }): Promise<string>;
243
285
  /**
244
286
  * Run-level literature-grounded synthesis (no sandbox). Returns the
245
287
  * quick-display findings for the run-completed card; empty when synthesis is