@inflexa-ai/harness 0.46.2 → 0.48.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 (279) hide show
  1. package/README.md +2 -2
  2. package/dist/agents/conversation-agent.d.ts +7 -6
  3. package/dist/agents/conversation-agent.js +26 -4
  4. package/dist/agents/report-session-agent.d.ts +14 -14
  5. package/dist/agents/report-session-agent.js +40 -26
  6. package/dist/agents/sandbox/shared.d.ts +18 -13
  7. package/dist/agents/sandbox/shared.js +42 -27
  8. package/dist/agents/sandbox/types.d.ts +1 -1
  9. package/dist/agents/sandbox-catalog.d.ts +2 -0
  10. package/dist/agents/sandbox-catalog.js +30 -1
  11. package/dist/app/synthesize-run.d.ts +10 -6
  12. package/dist/app/synthesize-run.js +4 -2
  13. package/dist/contracts/analogy-report.d.ts +46 -2
  14. package/dist/contracts/analogy-report.js +31 -25
  15. package/dist/contracts/chat-parts.d.ts +3 -14
  16. package/dist/contracts/report-reference.d.ts +2 -1
  17. package/dist/contracts/report-reference.js +2 -1
  18. package/dist/contracts/schemas/chat-parts.d.ts +0 -27
  19. package/dist/contracts/schemas/chat-parts.js +1 -3
  20. package/dist/execution/run-canceler.d.ts +2 -0
  21. package/dist/execution/run-canceler.js +9 -0
  22. package/dist/execution/run-synthesis.d.ts +36 -8
  23. package/dist/execution/run-synthesis.js +114 -32
  24. package/dist/index.d.ts +5 -6
  25. package/dist/index.js +5 -7
  26. package/dist/input-scan/enrich.d.ts +5 -10
  27. package/dist/input-scan/enrich.js +12 -8
  28. package/dist/lib/hooks.d.ts +1 -1
  29. package/dist/lib/markdown-pdf.d.ts +27 -0
  30. package/dist/lib/markdown-pdf.js +236 -0
  31. package/dist/lib/metrics.d.ts +31 -0
  32. package/dist/lib/metrics.js +64 -0
  33. package/dist/lib/pdf-text.d.ts +23 -0
  34. package/dist/lib/pdf-text.js +34 -0
  35. package/dist/lib/regulatory-corpus/fetch-fda-guidance.js +3 -5
  36. package/dist/lib/regulatory-corpus/fetch-ich.js +3 -5
  37. package/dist/loop/chat-stream.js +2 -1
  38. package/dist/loop/run-loop.d.ts +5 -0
  39. package/dist/loop/run-loop.js +30 -2
  40. package/dist/loop/tool-name-repair.d.ts +11 -0
  41. package/dist/loop/tool-name-repair.js +23 -0
  42. package/dist/loop/types.d.ts +19 -0
  43. package/dist/memory/card-builders.d.ts +1 -1
  44. package/dist/prompts/SOUL.d.ts +6 -6
  45. package/dist/prompts/SOUL.js +22 -121
  46. package/dist/prompts/analogical-reasoner.d.ts +1 -1
  47. package/dist/prompts/analogical-reasoner.js +35 -101
  48. package/dist/prompts/briefing.d.ts +20 -11
  49. package/dist/prompts/briefing.js +36 -19
  50. package/dist/prompts/conversation.d.ts +1 -1
  51. package/dist/prompts/conversation.js +103 -383
  52. package/dist/prompts/planner.d.ts +1 -5
  53. package/dist/prompts/planner.js +45 -128
  54. package/dist/prompts/report-session.d.ts +1 -1
  55. package/dist/prompts/report-session.js +29 -58
  56. package/dist/prompts/sandbox/bulk-transcriptomics-agent.d.ts +1 -1
  57. package/dist/prompts/sandbox/bulk-transcriptomics-agent.js +3 -3
  58. package/dist/prompts/sandbox/cheminformatics-agent.d.ts +1 -1
  59. package/dist/prompts/sandbox/cheminformatics-agent.js +12 -47
  60. package/dist/prompts/sandbox/chromatin-agent.d.ts +1 -1
  61. package/dist/prompts/sandbox/chromatin-agent.js +4 -5
  62. package/dist/prompts/sandbox/data-profiler.js +11 -34
  63. package/dist/prompts/sandbox/dna-methylation-agent.d.ts +1 -1
  64. package/dist/prompts/sandbox/dna-methylation-agent.js +3 -1
  65. package/dist/prompts/sandbox/drug-repurposing-agent.d.ts +1 -1
  66. package/dist/prompts/sandbox/drug-repurposing-agent.js +23 -73
  67. package/dist/prompts/sandbox/enrichment-agent.d.ts +1 -1
  68. package/dist/prompts/sandbox/enrichment-agent.js +3 -1
  69. package/dist/prompts/sandbox/genomic-variant-agent.d.ts +1 -1
  70. package/dist/prompts/sandbox/genomic-variant-agent.js +3 -4
  71. package/dist/prompts/sandbox/immune-profiling-agent.d.ts +1 -1
  72. package/dist/prompts/sandbox/immune-profiling-agent.js +5 -4
  73. package/dist/prompts/sandbox/metabolomics-agent.d.ts +1 -1
  74. package/dist/prompts/sandbox/metabolomics-agent.js +3 -1
  75. package/dist/prompts/sandbox/microbiome-agent.d.ts +1 -1
  76. package/dist/prompts/sandbox/microbiome-agent.js +3 -1
  77. package/dist/prompts/sandbox/multi-omics-integration-agent.d.ts +1 -1
  78. package/dist/prompts/sandbox/multi-omics-integration-agent.js +3 -1
  79. package/dist/prompts/sandbox/multimodal-sc-agent.d.ts +1 -1
  80. package/dist/prompts/sandbox/multimodal-sc-agent.js +3 -1
  81. package/dist/prompts/sandbox/network-agent.d.ts +1 -1
  82. package/dist/prompts/sandbox/network-agent.js +3 -1
  83. package/dist/prompts/sandbox/pkpd-clinical-response-agent.d.ts +1 -1
  84. package/dist/prompts/sandbox/pkpd-clinical-response-agent.js +4 -7
  85. package/dist/prompts/sandbox/proteomics-agent.d.ts +1 -1
  86. package/dist/prompts/sandbox/proteomics-agent.js +3 -1
  87. package/dist/prompts/sandbox/scientific-executor.d.ts +1 -1
  88. package/dist/prompts/sandbox/scientific-executor.js +0 -12
  89. package/dist/prompts/sandbox/single-cell-agent.d.ts +1 -1
  90. package/dist/prompts/sandbox/single-cell-agent.js +3 -1
  91. package/dist/prompts/sandbox/spatial-omics-agent.d.ts +1 -1
  92. package/dist/prompts/sandbox/spatial-omics-agent.js +3 -1
  93. package/dist/prompts/sandbox/statistical-modeling-agent.d.ts +1 -1
  94. package/dist/prompts/sandbox/statistical-modeling-agent.js +4 -4
  95. package/dist/prompts/sandbox/translational-safety-agent.d.ts +1 -1
  96. package/dist/prompts/sandbox/translational-safety-agent.js +10 -29
  97. package/dist/prompts/sandbox-standards.d.ts +15 -18
  98. package/dist/prompts/sandbox-standards.js +96 -305
  99. package/dist/prompts/synthesis-agent.d.ts +1 -1
  100. package/dist/prompts/synthesis-agent.js +24 -90
  101. package/dist/provenance/collector.d.ts +2 -5
  102. package/dist/provenance/collector.js +2 -5
  103. package/dist/provenance/seam.d.ts +36 -1
  104. package/dist/provenance/workspace-reads.d.ts +36 -0
  105. package/dist/provenance/workspace-reads.js +33 -0
  106. package/dist/report-model/production-resolver.d.ts +22 -52
  107. package/dist/report-model/production-resolver.js +43 -112
  108. package/dist/report-render/chart-export.d.ts +9 -0
  109. package/dist/report-render/chart-export.js +1 -1
  110. package/dist/report-render/views/chart-view.d.ts +1 -0
  111. package/dist/report-render/views/chart-view.js +1 -0
  112. package/dist/report-render/views/lineage.d.ts +1 -0
  113. package/dist/report-render/views/page-view.d.ts +1 -0
  114. package/dist/report-render/views/page-view.js +1 -0
  115. package/dist/report-render/views/prose.d.ts +1 -0
  116. package/dist/report-render/views/prose.js +1 -0
  117. package/dist/report-render/views/references-view.d.ts +1 -0
  118. package/dist/report-render/views/values.d.ts +1 -0
  119. package/dist/report-render/views/values.js +1 -0
  120. package/dist/runtime/assemble.d.ts +32 -12
  121. package/dist/runtime/assemble.js +49 -38
  122. package/dist/sandbox/client.d.ts +5 -3
  123. package/dist/sandbox/create-sandbox.d.ts +7 -12
  124. package/dist/sandbox/create-sandbox.js +15 -37
  125. package/dist/sandbox/docker-client.d.ts +1 -3
  126. package/dist/sandbox/docker-client.js +3 -5
  127. package/dist/sandbox/exec-outcome.d.ts +11 -11
  128. package/dist/sandbox/exec-outcome.js +22 -22
  129. package/dist/sandbox/exec.d.ts +5 -0
  130. package/dist/sandbox/exec.js +9 -1
  131. package/dist/sandbox/identity.d.ts +4 -16
  132. package/dist/sandbox/identity.js +5 -21
  133. package/dist/sandbox/k8s-client.d.ts +0 -1
  134. package/dist/sandbox/k8s-client.js +8 -13
  135. package/dist/sandbox/lease-names.d.ts +6 -0
  136. package/dist/sandbox/lease-names.js +12 -0
  137. package/dist/sandbox/leases.d.ts +105 -0
  138. package/dist/sandbox/leases.js +519 -0
  139. package/dist/sandbox/liveness.d.ts +5 -2
  140. package/dist/sandbox/mount-plan.d.ts +10 -1
  141. package/dist/sandbox/mount-plan.js +7 -1
  142. package/dist/sandbox/reconciler.d.ts +58 -0
  143. package/dist/sandbox/reconciler.js +153 -0
  144. package/dist/sandbox/sandbox-step-translate.d.ts +1 -1
  145. package/dist/sandbox/types.d.ts +25 -18
  146. package/dist/sandbox/types.js +10 -4
  147. package/dist/schemas/plan-schemas.d.ts +0 -21
  148. package/dist/schemas/plan-schemas.js +2 -3
  149. package/dist/schemas/run-synthesis.d.ts +2 -2
  150. package/dist/schemas/run-synthesis.js +3 -3
  151. package/dist/schemas/validate-plan.d.ts +1 -14
  152. package/dist/schemas/validate-plan.js +5 -24
  153. package/dist/schemas/workflow-state.d.ts +3 -32
  154. package/dist/schemas/workflow-state.js +4 -13
  155. package/dist/state/index.d.ts +2 -3
  156. package/dist/state/index.js +1 -2
  157. package/dist/state/migrations/20261030120000_lease_the_sandboxes.d.ts +7 -0
  158. package/dist/state/migrations/20261030120000_lease_the_sandboxes.js +34 -0
  159. package/dist/state/migrations/20261030120100_drop_the_report_derivations.d.ts +5 -0
  160. package/dist/state/migrations/20261030120100_drop_the_report_derivations.js +9 -0
  161. package/dist/state/migrations/20261030120200_keep_the_report_derivations.d.ts +6 -0
  162. package/dist/state/migrations/20261030120200_keep_the_report_derivations.js +10 -0
  163. package/dist/state/migrations/index.js +6 -0
  164. package/dist/state/purge-analysis.d.ts +4 -2
  165. package/dist/state/purge-analysis.js +22 -11
  166. package/dist/state/sandbox-leases.d.ts +81 -0
  167. package/dist/state/sandbox-leases.js +247 -0
  168. package/dist/state/schema.d.ts +1 -13
  169. package/dist/state/schema.js +1 -6
  170. package/dist/state/step-executions.d.ts +13 -2
  171. package/dist/state/step-executions.js +23 -4
  172. package/dist/tasks/data-profile.d.ts +40 -2
  173. package/dist/tasks/data-profile.js +89 -87
  174. package/dist/tools/ad-hoc-router.d.ts +1 -6
  175. package/dist/tools/ad-hoc-router.js +5 -48
  176. package/dist/tools/bio/comptox.js +1 -1
  177. package/dist/tools/bio/drug-gene-interactions.js +1 -1
  178. package/dist/tools/bio/gene-disease-evidence.js +1 -1
  179. package/dist/tools/bio/keys.d.ts +1 -1
  180. package/dist/tools/bio/pubmed.js +31 -0
  181. package/dist/tools/bio/search-gene.js +17 -0
  182. package/dist/tools/bio/search-geo-datasets.js +13 -0
  183. package/dist/tools/bio/search-regulatory-approvals.js +1 -1
  184. package/dist/tools/define-tool.d.ts +25 -2
  185. package/dist/tools/define-tool.js +11 -1
  186. package/dist/tools/display/show-user.js +1 -1
  187. package/dist/tools/execute-analysis.d.ts +1 -3
  188. package/dist/tools/execute-analysis.js +5 -33
  189. package/dist/tools/report-authoring/authoring-tools.d.ts +2 -2
  190. package/dist/tools/report-authoring/authoring-tools.js +31 -6
  191. package/dist/tools/report-session/index.d.ts +0 -1
  192. package/dist/tools/report-session/index.js +0 -1
  193. package/dist/tools/report-session/script-tools.d.ts +33 -0
  194. package/dist/tools/report-session/script-tools.js +186 -0
  195. package/dist/tools/research/generate-analogy-report.d.ts +16 -9
  196. package/dist/tools/research/generate-analogy-report.js +111 -49
  197. package/dist/tools/research/generate-plan.d.ts +102 -7
  198. package/dist/tools/research/generate-plan.js +74 -43
  199. package/dist/tools/research/index.d.ts +4 -3
  200. package/dist/tools/research/index.js +4 -3
  201. package/dist/tools/research/inspect-run.d.ts +0 -1
  202. package/dist/tools/research/inspect-run.js +5 -10
  203. package/dist/tools/research/search-arxiv.js +15 -0
  204. package/dist/tools/research/search-github-repos.js +13 -0
  205. package/dist/tools/research/search-semantic-scholar.js +16 -0
  206. package/dist/tools/research/synthesis-lookups.d.ts +21 -0
  207. package/dist/tools/research/synthesis-lookups.js +29 -0
  208. package/dist/tools/research/web-fetch.d.ts +1 -1
  209. package/dist/tools/research/web-fetch.js +14 -12
  210. package/dist/tools/sandbox/lease-tools.d.ts +32 -0
  211. package/dist/tools/sandbox/lease-tools.js +60 -0
  212. package/dist/tools/script/archive.d.ts +34 -0
  213. package/dist/tools/script/archive.js +182 -0
  214. package/dist/tools/script/codemode-worker.d.ts +5 -0
  215. package/dist/tools/script/codemode-worker.js +5 -0
  216. package/dist/tools/script/file-tools.d.ts +106 -0
  217. package/dist/tools/script/file-tools.js +491 -0
  218. package/dist/tools/script/metrics.d.ts +30 -0
  219. package/dist/tools/script/metrics.js +53 -0
  220. package/dist/tools/script/quickjs.wasm +0 -0
  221. package/dist/tools/script/run-script.d.ts +76 -0
  222. package/dist/tools/script/run-script.js +413 -0
  223. package/dist/tools/script/scratch.d.ts +84 -0
  224. package/dist/tools/script/scratch.js +145 -0
  225. package/dist/tools/start-report-session.js +1 -1
  226. package/dist/tools/workspace/edit-file.js +2 -1
  227. package/dist/tools/workspace/execute-command.d.ts +9 -13
  228. package/dist/tools/workspace/execute-command.js +23 -19
  229. package/dist/tools/workspace/file-stat.js +1 -1
  230. package/dist/tools/workspace/grep.d.ts +5 -2
  231. package/dist/tools/workspace/grep.js +19 -10
  232. package/dist/tools/workspace/mutator.d.ts +51 -4
  233. package/dist/tools/workspace/mutator.js +54 -13
  234. package/dist/tools/workspace/read-file.d.ts +5 -2
  235. package/dist/tools/workspace/read-file.js +15 -11
  236. package/dist/tools/workspace/read-surface.d.ts +17 -0
  237. package/dist/tools/workspace/read-surface.js +17 -0
  238. package/dist/tools/workspace/result-bounds.d.ts +1 -0
  239. package/dist/tools/workspace/run-exec.d.ts +12 -13
  240. package/dist/tools/workspace/run-exec.js +13 -13
  241. package/dist/tools/workspace/scan-inputs.d.ts +2 -5
  242. package/dist/tools/workspace/scan-inputs.js +2 -3
  243. package/dist/tools/workspace/show-file.js +1 -1
  244. package/dist/tools/workspace/show-plan.js +4 -3
  245. package/dist/tools/workspace/write-file.js +2 -1
  246. package/dist/workflows/execute-analysis-scheduler.d.ts +0 -26
  247. package/dist/workflows/execute-analysis-scheduler.js +12 -32
  248. package/dist/workflows/execute-analysis.d.ts +17 -35
  249. package/dist/workflows/execute-analysis.js +13 -107
  250. package/dist/workflows/pause.js +29 -22
  251. package/dist/workflows/sandbox-step.d.ts +16 -31
  252. package/dist/workflows/sandbox-step.js +36 -71
  253. package/dist/workflows/test/sql-writes.d.ts +0 -1
  254. package/dist/workflows/test/sql-writes.js +0 -2
  255. package/dist/workspace/filesystem.d.ts +2 -2
  256. package/dist/workspace/filesystem.js +10 -5
  257. package/dist/workspace/paths.d.ts +19 -1
  258. package/dist/workspace/paths.js +22 -1
  259. package/dist/workspace/session-files.d.ts +35 -0
  260. package/dist/workspace/session-files.js +16 -0
  261. package/package.json +7 -3
  262. package/dist/prompts/literature-reviewer.d.ts +0 -1
  263. package/dist/prompts/literature-reviewer.js +0 -114
  264. package/dist/sandbox/reaper.d.ts +0 -81
  265. package/dist/sandbox/reaper.js +0 -161
  266. package/dist/sandbox/step-sandbox.d.ts +0 -47
  267. package/dist/sandbox/step-sandbox.js +0 -53
  268. package/dist/state/active-sandboxes.d.ts +0 -33
  269. package/dist/state/active-sandboxes.js +0 -65
  270. package/dist/tasks/extract-values-script.d.ts +0 -64
  271. package/dist/tasks/extract-values-script.js +0 -180
  272. package/dist/tasks/extract-values.d.ts +0 -77
  273. package/dist/tasks/extract-values.js +0 -146
  274. package/dist/tools/report-session/derive-table.d.ts +0 -164
  275. package/dist/tools/report-session/derive-table.js +0 -419
  276. package/dist/tools/research/literature-reviewer.d.ts +0 -42
  277. package/dist/tools/research/literature-reviewer.js +0 -107
  278. package/dist/workflows/metrics.d.ts +0 -23
  279. package/dist/workflows/metrics.js +0 -38
@@ -7,8 +7,8 @@ literature-grounded **interpretation** — not a catalog of what each step
7
7
  produced.
8
8
 
9
9
  You are task-oriented — you do not interact with the user. You receive
10
- the run's context, investigate what you need via your research sub-agent,
11
- and return a structured synthesis.
10
+ the run's context, look up the evidence that you need, and return a
11
+ structured synthesis.
12
12
 
13
13
  ## How Your Work Reaches the User
14
14
 
@@ -34,45 +34,27 @@ can read that themselves. What they need from you is:
34
34
  Think like a senior reviewer writing the Discussion section of a paper,
35
35
  not like a scribe summarizing the Results section.
36
36
 
37
- ## Your Tools
38
-
39
- ### literature_reviewer (research sub-agent — delegate focused research)
40
- A task-oriented sub-agent that holds the bio-lookup and literature tools.
41
- Delegate to it when you need evidence — you have no bio-lookup tools of
42
- your own.
43
-
44
- Delegations must be **focused**:
45
- - One well-scoped research brief per call (e.g., "Investigate FOXM1 and
46
- MKI67 in the context of proliferation signatures in bulk RNA-seq of
47
- breast tumor vs normal. Assess novelty and find supporting PMIDs.")
48
- - Include the experimental context the sub-agent needs (conditions, modality,
49
- what the computational finding showed).
50
- - Do NOT send the whole summary block and ask for "a literature review".
51
- The sub-agent will produce shallow results on diffuse briefs.
52
-
53
- You may delegate again after an initial pass if a
54
- theme becomes apparent and needs its own evidence sweep.
55
-
56
- ### submit_synthesis (success path)
57
- Submit the synthesis. Checks the payload; returns either
58
- \`{accepted: true}\` (DONE — stop) or \`{accepted: false, issues}\` (fix
59
- specific fields per issue path and call again, OR switch to
60
- \`report_blocker\` if the synthesis cannot be made valid). The last accepted
61
- submission is the synthesis.
62
-
63
- ### report_blocker (terminal — cannot produce a synthesis)
64
- Call ONLY when the run produced no synthesizable content — every summary is
65
- empty, or the summaries are contradictory to the point of incoherence.
66
- "No findings worth surfacing" is NOT a blocker: with non-empty summaries you
67
- can always submit a synthesis (overview + conclusions) with an empty
68
- \`findings[]\`. Pass a short reason, then stop.
69
-
70
- ## Canonical Flow
71
-
72
- Ground the novel findings, the contradictions, and the cross-step themes
73
- in literature before you draft. Then call \`submit_synthesis\`. If it is
74
- rejected, fix the cited issue paths and call again. If it cannot be made
75
- valid, call \`report_blocker\`.
37
+ ## The Files of the Run
38
+
39
+ The step summaries come first. Read a file of the run only where a summary is
40
+ thin: a number that a summary names and does not give, a table that it points
41
+ to, or a paper that the analysis holds. Each file that you read fills your
42
+ context, thus read the part that you need.
43
+
44
+ ## Evidence
45
+
46
+ Your lookup tools (genes, proteins, annotations, interactions, PubMed,
47
+ citations, drug-gene interactions, preclinical profiles) are cheap API calls,
48
+ and they run in \`run_script\`: put the independent lookups in one script, and
49
+ print what you keep. Ground the novel findings, the contradictions, and the
50
+ cross-step themes in literature before you draft. Look up what
51
+ a finding needs: a high-confidence finding that can be novel, a finding that
52
+ maps to a known disease or pathway, a theme across two or more steps. A QC
53
+ result or a technical finding with no biological claim needs no lookup.
54
+
55
+ Each \`pmid\` that you cite must be in a lookup result of this run, also a
56
+ result that a script read and did not print.
57
+ \`submit_synthesis\` refuses each other PMID.
76
58
 
77
59
  ## Writing the Synthesis
78
60
 
@@ -95,9 +77,7 @@ a known drug?
95
77
 
96
78
  **Assigning \`preclinical-validation\`** — cite IMPC mouse-KO phenotypes for
97
79
  loss-of-function consequences and cross-species baseline expression for
98
- tissue-of-action context (both come back from
99
- \`gene_preclinical_profile\`), when the literature reviewer's report
100
- includes them.
80
+ tissue-of-action context, both from \`gene_preclinical_profile\`.
101
81
 
102
82
  **What a good \`limitation\` looks like** — it names what it affects and
103
83
  why it matters:
@@ -111,49 +91,6 @@ why it matters:
111
91
  - "Target druggability not assessed — pathway importance does not imply
112
92
  tractability."
113
93
 
114
- ## Cross-Field Invariants (enforced at submit_synthesis)
115
-
116
- - \`finding.stepId\` must match a stepId present in the input summaries.
117
- - Every \`theme.findings[]\` entry must reference a finding that exists
118
- in \`findings[]\` (same stepId + title).
119
- - Every \`keyReferences[].pmid\` must appear in at least one
120
- \`finding.references[]\` entry — the cross-run list summarizes what's
121
- already cited per finding.
122
-
123
- Every \`pmid\` you write comes from a \`literature_reviewer\` response.
124
- \`submit_synthesis\` cannot check this, and nothing after you re-checks a
125
- PMID, so an invented one reaches the reader as a real citation.
126
-
127
- ## Investigation Strategy
128
-
129
- **Which findings need delegation?**
130
- - Findings labeled high-confidence in the summary but potentially novel —
131
- needs literature check to confirm or challenge novelty.
132
- - Findings that could map to a known disease or pathway context — needs
133
- a PubMed sweep for the gene+condition combination.
134
- - Candidate themes spanning 2+ steps — delegate a theme-level brief to
135
- get references that tie the findings together.
136
-
137
- **Which findings do NOT need delegation?**
138
- - Trivial / expected results (QC passed, dimensions as expected).
139
- - Technical findings with no biological claim (batch effect detected,
140
- normalization applied).
141
-
142
- **Composing a delegation brief** — include:
143
- 1. The specific genes/pathways/features to investigate (from the summary).
144
- 2. The experimental context (conditions, modality, organism if known).
145
- 3. What the computational finding showed (one sentence).
146
- 4. What you want back (novelty assessment? supporting PMIDs? pathway
147
- context? interaction partners?).
148
-
149
- Example:
150
- > "Investigate SPP1, TREM2, and APOE in the context of microglia
151
- > activation in Alzheimer's disease single-cell RNA-seq. Finding:
152
- > these three genes form a co-expression module enriched in
153
- > disease-associated microglia. Return: novelty assessment, 3-5 key
154
- > PMIDs supporting or challenging the DAM signature, and any known
155
- > interactions among the three."
156
-
157
94
  ## Do NOT
158
95
 
159
96
  - **Reiterate step results.** The reader has the step summaries. Do not
@@ -176,9 +113,6 @@ Example:
176
113
  predictive requires evidence of treatment x marker interaction,
177
114
  prognostic only requires association with outcome.
178
115
  - Force findings into themes. If findings don't converge, return fewer (or zero) themes.
179
- - Call \`submit_synthesis\` before delegating at least once when findings need
180
- literature grounding. (A run with only technical/QC findings may skip delegation
181
- and submit directly, but state that clearly in the overview.)
182
116
  - Submit a placeholder or stub payload to "see what happens". A degenerate
183
117
  payload that passes the schema is recorded as the run's result.
184
118
  `;
@@ -5,11 +5,8 @@
5
5
  * Integrates with:
6
6
  * - K8sSandbox executeCommand provenance (script reads + writes via inotify)
7
7
  * - Data-mount filesystem write tracking (agent file-tool outputs)
8
- *
9
- * Input attribution comes exclusively from sandbox exec inotify (the
10
- * authoritative record of what computation actually consumed). Agent
11
- * tool reads are not tracked here — they're exploratory and would
12
- * pollute the lineage graph.
8
+ * - The workspace read tools of the agent (`provenance/workspace-reads.ts`),
9
+ * whose host-side reads no exec frame names
13
10
  */
14
11
  import type { ArtifactRecord } from "../execution/artifact-record.js";
15
12
  import type { ProvenanceRecord, InputRef, InputSource } from "./types.js";
@@ -5,11 +5,8 @@
5
5
  * Integrates with:
6
6
  * - K8sSandbox executeCommand provenance (script reads + writes via inotify)
7
7
  * - Data-mount filesystem write tracking (agent file-tool outputs)
8
- *
9
- * Input attribution comes exclusively from sandbox exec inotify (the
10
- * authoritative record of what computation actually consumed). Agent
11
- * tool reads are not tracked here — they're exploratory and would
12
- * pollute the lineage graph.
8
+ * - The workspace read tools of the agent (`provenance/workspace-reads.ts`),
9
+ * whose host-side reads no exec frame names
13
10
  */
14
11
  import { presentFirst } from "../lib/present.js";
15
12
  import { collapseWhitespace, hasWhitespace } from "../lib/text.js";
@@ -97,7 +97,8 @@ type BlockAct = {
97
97
  * One observation of a session.
98
98
  *
99
99
  * The union names one event for each act: the start of a session, the four block operations, the title,
100
- * the derivation, the preview, the record, the file write of a conversation turn, and the approval of a plan. Each event carries
100
+ * the derivation, the preview, the record, the file write of a conversation turn, a script that read or wrote a
101
+ * file, and the approval of a plan. Each event carries
101
102
  * the analysis and the thread, thus a consumer places it with no lookup. The title sits on the document,
102
103
  * thus the title event names no block.
103
104
  *
@@ -186,6 +187,40 @@ export type SessionProvenanceEvent = {
186
187
  tool: string;
187
188
  /** The loop's tool-call id of the write — the replay-stable identity of the invocation. */
188
189
  invocationId: string;
190
+ } | {
191
+ /**
192
+ * One script of `run_script` that read or wrote a file. The script, each file that it read, and each
193
+ * file that it derived carry the hash of their exact bytes, thus a derived file chains to the files
194
+ * that made it. The harness emits it from the fold of the call record, thus a replay emits it again
195
+ * with the same values.
196
+ */
197
+ type: "run-script";
198
+ analysisId: string;
199
+ /** The thread whose turn ran the script. Absent when the scope carries none. */
200
+ threadId?: string;
201
+ /** The loop's tool-call id of the `run_script` call. */
202
+ invocationId: string;
203
+ /** The saved script. Absent when the session has no scratch directory. */
204
+ script?: {
205
+ path: string;
206
+ hash: string;
207
+ size: number;
208
+ };
209
+ /** Each table that the script read, analysis-root-relative. */
210
+ reads: ReadonlyArray<{
211
+ path: string;
212
+ hash: string;
213
+ }>;
214
+ /** Each file that the script derived, analysis-root-relative. */
215
+ writes: ReadonlyArray<{
216
+ path: string;
217
+ hash: string;
218
+ size: number;
219
+ }>;
220
+ /** Each tool that the script called, in call order. */
221
+ tools: readonly string[];
222
+ /** The script ran to its end. A failed script keeps the files that it wrote before the failure. */
223
+ ok: boolean;
189
224
  };
190
225
  /**
191
226
  * The provenance seam of the harness. An embedder realizes the members that it records, and the harness
@@ -0,0 +1,36 @@
1
+ /**
2
+ * The lineage of the workspace reads of a step agent.
3
+ *
4
+ * `read_file`, `grep`, and `read_pdf` read on the host, outside each sandbox exec, thus no exec frame names their
5
+ * reads. A tool puts its reads into its call record, and its `foldCallRecord` gives them to the collector of the step.
6
+ * Thus a replay, which runs no `execute`, rebuilds the same inputs.
7
+ */
8
+ import type { Logger } from "../lib/logger.js";
9
+ import type { ProvenanceCollector } from "./collector.js";
10
+ /**
11
+ * One file whose content a read tool gave to the agent. `path` is analysis-relative. `hash` is the SHA-256 of the
12
+ * whole file, or `null` when the tool held only a part of it.
13
+ */
14
+ export type WorkspaceRead = {
15
+ readonly path: string;
16
+ readonly hash: string | null;
17
+ };
18
+ /** The call record of a read tool. */
19
+ export type WorkspaceReadRecord = {
20
+ readonly reads: readonly WorkspaceRead[];
21
+ };
22
+ export type WorkspaceReadLineage = {
23
+ /** The read of `path`, as the tool gave it to the read seam. `wholeFile` is the bytes of the whole file, or `null` for a part. */
24
+ readOf(path: string, wholeFile: Buffer | null): WorkspaceRead | undefined;
25
+ /** Track the reads of one call in the collector of the step. */
26
+ track(reads: readonly WorkspaceRead[]): void;
27
+ };
28
+ export type WorkspaceReadLineageDeps = {
29
+ readonly collector: ProvenanceCollector;
30
+ readonly workspaceRoot: string;
31
+ readonly analysisId: string;
32
+ /** The host base of a relative path, the same that the read tools give to the read seam. */
33
+ readonly workingDir: string;
34
+ readonly logger?: Logger;
35
+ };
36
+ export declare function createWorkspaceReadLineage(deps: WorkspaceReadLineageDeps): WorkspaceReadLineage;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * The lineage of the workspace reads of a step agent.
3
+ *
4
+ * `read_file`, `grep`, and `read_pdf` read on the host, outside each sandbox exec, thus no exec frame names their
5
+ * reads. A tool puts its reads into its call record, and its `foldCallRecord` gives them to the collector of the step.
6
+ * Thus a replay, which runs no `execute`, rebuilds the same inputs.
7
+ */
8
+ import { createNoopLogger } from "../lib/console-logger.js";
9
+ import { computeSha256 } from "../lib/fs-helpers.js";
10
+ import { resolveWorkspacePath } from "../workspace/paths.js";
11
+ export function createWorkspaceReadLineage(deps) {
12
+ const { collector, workspaceRoot, analysisId, workingDir } = deps;
13
+ // The mount root of `execute_command`, thus a file that an exec and a read tool read is one input.
14
+ const mountRoot = `/${analysisId}`;
15
+ const logger = (deps.logger ?? createNoopLogger()).named("workspace-reads");
16
+ return {
17
+ readOf(path, wholeFile) {
18
+ const resolved = resolveWorkspacePath({ workspaceRoot, analysisId, path, workingDir });
19
+ if (resolved.kind !== "ok")
20
+ return undefined;
21
+ // A hash of a part names no version of the file. Reconcile hashes the file from disk instead.
22
+ return { path: resolved.relative.split("\\").join("/"), hash: wholeFile === null ? null : computeSha256(wholeFile) };
23
+ },
24
+ track(reads) {
25
+ for (const read of reads) {
26
+ if (collector.trackInputAccess(mountRoot, read.path, read.hash) !== null)
27
+ continue;
28
+ if (collector.claimRefusalNarration(read.path))
29
+ logger.warn("refusing lineage edge to an undeclared same-run path", { path: read.path });
30
+ }
31
+ },
32
+ };
33
+ }
@@ -5,51 +5,21 @@
5
5
  * The realization holds three layers. Layer one is identity: membership through `snapshotEntry`, and a
6
6
  * streamed hash compare with `computeSha256File`. A hash mismatch fails before any parse. Layer two is
7
7
  * the host fast path: an in-process parse of a CSV, a TSV, a JSON, or a parquet file at or under the cap.
8
- * Layer three is the fall-through: an over-cap file or a host parse fault goes to the extraction arm. On any
9
- * doubt the read falls through, thus correctness never depends on the host parser. An extension that names
10
- * no tabular format refuses here, because the host decides the format for both arms.
8
+ * Layer three is the fall-through: an over-cap file or a host parse fault fails as `extraction-unavailable`.
9
+ * On any doubt the read falls through, thus the host parser never gives a partial or guessed answer. An
10
+ * extension that names no tabular format refuses the same way.
11
11
  *
12
12
  * A read of the bytes is the expensive part, thus an optional `ArtifactReadCache` outlives one resolver. It
13
- * holds the streamed hash and the extracted rows against a stat signature. Two tool calls of one analysis
14
- * share one cache, and each call still binds its own extraction arm with its own auth.
13
+ * holds the streamed hash and the parsed rows against a stat signature. Two tool calls of one analysis
14
+ * share one cache.
15
15
  *
16
16
  * The realization calls the shared assert functions in `assert-rules.ts`, and it mirrors the locator walk
17
17
  * and the reason choices of `fixture-resolver.ts`. Thus one semantics exists, and the fixture stays the
18
18
  * executable specification of the value tier. The two realizations are substitutable behind the seam.
19
19
  */
20
- import { type Result } from "neverthrow";
21
- import type { SuspendingRefusal } from "../sandbox/sandbox-error.js";
22
20
  import { type ReferenceResolver } from "./reference-resolver.js";
23
21
  /** One artifact row, as plain cells. A text-backed format holds a numeric column as a string. */
24
- type Row = Record<string, string | number>;
25
- /**
26
- * One artifact that the host fast path could not read, addressed for the extraction arm. The `hash` pins
27
- * the exact bytes, thus the arm reads the same artifact that the identity layer verified.
28
- *
29
- * `format` carries the reader that the host decided. The arm never derives a reader from the extension,
30
- * thus the host arm and the sandbox arm can never read one file two ways.
31
- */
32
- export type ExtractionRequest = {
33
- readonly path: string;
34
- readonly hash: string;
35
- readonly format: TabularFormat;
36
- };
37
- /** The rows that the extraction arm read for one artifact. Downstream the rows share the host path logic. */
38
- export type ExtractionArtifact = {
39
- readonly rows: Array<Record<string, string | number>>;
40
- };
41
- /**
42
- * The out-of-process read arm. One `extract` call covers every fall-through artifact of one document
43
- * pass. The result maps each requested path to its rows. A path that the arm could not read is absent
44
- * from the map, and the reference at that path fails as `unreadable-artifact`. A refusal of the sandbox of the
45
- * pass with the suspend flag is the `err`, and each reference of the batch reports its reason.
46
- *
47
- * The arm is a seam, thus a test stubs it. While no realization is wired, a fall-through reference fails
48
- * with `extraction-unavailable`, and the detail names the absent arm.
49
- */
50
- export type ExtractionArm = {
51
- extract(requests: readonly ExtractionRequest[]): Promise<Result<ReadonlyMap<string, ExtractionArtifact>, SuspendingRefusal>>;
52
- };
22
+ export type Row = Record<string, string | number>;
53
23
  /**
54
24
  * The disk facts of one artifact that outlive one resolver.
55
25
  *
@@ -64,12 +34,11 @@ export type ArtifactRead = {
64
34
  readonly rows?: Array<Record<string, string | number>>;
65
35
  };
66
36
  /**
67
- * The read cache of one analysis. It holds what a read of the bytes costs: the streamed hash, and the rows
68
- * of a file that the host could not parse in process. Two resolvers of one analysis share one cache, thus a
69
- * preview and the record that follows it hash one unchanged file one time and start one container.
37
+ * The read cache of one analysis. It holds what a read of the bytes costs: the streamed hash, and the parsed
38
+ * rows. Two resolvers of one analysis share one cache, thus a preview and the record that follows it hash and
39
+ * parse one unchanged file one time.
70
40
  *
71
- * The cache holds no authorization and no session value. Each resolver still binds its own extraction arm
72
- * over the auth of its own call.
41
+ * The cache holds no authorization and no session value.
73
42
  */
74
43
  export type ArtifactReadCache = {
75
44
  get(absolutePath: string): ArtifactRead | undefined;
@@ -89,22 +58,23 @@ export declare function createArtifactReadStore(): ArtifactReadStore;
89
58
  * The construction deps of the production resolver.
90
59
  *
91
60
  * `workspaceRoot` and `analysisId` contain the untrusted snapshot path through `resolveWorkspacePath`,
92
- * the same containment as the preview tool. `cap` gates the cell extraction, and it defaults to 16 MiB.
93
- * `extractionArm` is optional, because no sandbox realization is wired yet. `readCache` is optional, thus a
94
- * resolver with no cache reads every artifact itself and its reads die with it.
61
+ * the same containment as the preview tool. `cap` gates the cell read, and it defaults to 16 MiB.
62
+ * `readCache` is optional, thus a resolver with no cache reads every artifact itself and its reads die with it.
95
63
  */
96
64
  export type ProductionResolverDeps = {
97
65
  readonly workspaceRoot: string;
98
66
  readonly analysisId: string;
99
67
  readonly cap?: number;
100
- readonly extractionArm?: ExtractionArm;
101
68
  readonly readCache?: ArtifactReadCache;
102
69
  };
70
+ /** The tabular formats that the host fast path reads. Another extension names no format at all. */
71
+ export type TabularFormat = "csv" | "tsv" | "json" | "parquet";
103
72
  /**
104
- * The tabular formats that the host fast path reads. The host decides which one a file is, one time, and it
105
- * carries the decision to the extraction arm. Another extension names no format at all.
73
+ * Map a file extension to the format that the host arm reads. An unknown extension gives back `undefined`.
74
+ *
75
+ * This is the one format decision of the report path.
106
76
  */
107
- export type TabularFormat = "csv" | "tsv" | "json" | "parquet";
77
+ export declare function detectFormat(path: string): TabularFormat | undefined;
108
78
  /**
109
79
  * Read one value as a cell, or drop it.
110
80
  *
@@ -114,8 +84,7 @@ export type TabularFormat = "csv" | "tsv" | "json" | "parquet";
114
84
  * where the caller detects the loss.
115
85
  *
116
86
  * A non-finite number is not a cell either. A parquet float column holds a `NaN` or an `Infinity`, thus the
117
- * coercion drops it and the row omits the key. The extraction script (`tasks/extract-values-script.ts`)
118
- * drops the same value to `None`, thus the host arm and the sandbox arm read the same bytes the same way.
87
+ * coercion drops it and the row omits the key.
119
88
  */
120
89
  export declare function coerceCell(value: unknown): string | number | undefined;
121
90
  /**
@@ -123,8 +92,10 @@ export declare function coerceCell(value: unknown): string | number | undefined;
123
92
  * name are structural doubt, thus each gives back `undefined` and the file falls through.
124
93
  */
125
94
  export declare function parseDelimited(text: string, delimiter: string): Row[] | undefined;
95
+ /** Parse the bytes of one table in a decided format. A parse fault gives back `undefined`. */
96
+ export declare function parseTable(format: TabularFormat, bytes: Buffer): Promise<Row[] | undefined>;
126
97
  /**
127
- * Make the production resolver over the workspace root and the optional extraction arm.
98
+ * Make the production resolver over the workspace root.
128
99
  *
129
100
  * The resolver holds a per-pass cache. `prepare` groups the references by artifact, reads each file one
130
101
  * time, and fills the cache. `resolve` then answers from the cache. A `resolve` with no prior `prepare`
@@ -132,4 +103,3 @@ export declare function parseDelimited(text: string, delimiter: string): Row[] |
132
103
  * artifact on both paths, and never one read for each reference.
133
104
  */
134
105
  export declare function createProductionResolver(deps: ProductionResolverDeps): ReferenceResolver;
135
- export {};