@inflexa-ai/harness 0.1.1 → 0.2.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 (268) hide show
  1. package/dist/agents/conversation-agent.d.ts +12 -11
  2. package/dist/agents/conversation-agent.js +30 -33
  3. package/dist/agents/report-builder.js +2 -1
  4. package/dist/agents/sandbox/bulk-transcriptomics-agent.js +1 -1
  5. package/dist/agents/sandbox/cheminformatics-agent.js +1 -19
  6. package/dist/agents/sandbox/chromatin-agent.js +1 -10
  7. package/dist/agents/sandbox/dna-methylation-agent.js +1 -10
  8. package/dist/agents/sandbox/drug-repurposing-agent.js +4 -14
  9. package/dist/agents/sandbox/enrichment-agent.js +1 -10
  10. package/dist/agents/sandbox/ephemeral-executor.js +1 -10
  11. package/dist/agents/sandbox/genomic-variant-agent.js +1 -3
  12. package/dist/agents/sandbox/immune-profiling-agent.js +1 -13
  13. package/dist/agents/sandbox/metabolomics-agent.js +1 -1
  14. package/dist/agents/sandbox/microbiome-agent.js +1 -1
  15. package/dist/agents/sandbox/multi-omics-integration-agent.js +1 -12
  16. package/dist/agents/sandbox/multimodal-sc-agent.js +1 -1
  17. package/dist/agents/sandbox/network-agent.js +1 -10
  18. package/dist/agents/sandbox/pkpd-clinical-response-agent.js +2 -8
  19. package/dist/agents/sandbox/proteomics-agent.js +1 -1
  20. package/dist/agents/sandbox/scientific-executor.js +1 -10
  21. package/dist/agents/sandbox/shared.d.ts +17 -6
  22. package/dist/agents/sandbox/shared.js +49 -38
  23. package/dist/agents/sandbox/single-cell-agent.js +1 -1
  24. package/dist/agents/sandbox/spatial-omics-agent.js +1 -1
  25. package/dist/agents/sandbox/statistical-modeling-agent.js +1 -1
  26. package/dist/agents/sandbox/translational-safety-agent.js +3 -9
  27. package/dist/agents/sandbox/types.d.ts +1 -1
  28. package/dist/agents/system-prompt.d.ts +37 -11
  29. package/dist/agents/system-prompt.js +35 -12
  30. package/dist/app/data-profile-orientation.d.ts +34 -0
  31. package/dist/app/data-profile-orientation.js +117 -0
  32. package/dist/contracts/schemas/chat-parts.d.ts +9 -9
  33. package/dist/execution/artifact-metadata.js +2 -1
  34. package/dist/execution/ephemeral-runner.d.ts +13 -0
  35. package/dist/execution/ephemeral-runner.js +23 -1
  36. package/dist/execution/run-synthesis.js +20 -19
  37. package/dist/execution/step-summary.js +2 -1
  38. package/dist/index.d.ts +6 -2
  39. package/dist/index.js +19 -5
  40. package/dist/loop/__fixtures__/scripted-provider.d.ts +2 -2
  41. package/dist/loop/__fixtures__/scripted-provider.js +2 -1
  42. package/dist/loop/metrics.d.ts +33 -1
  43. package/dist/loop/metrics.js +56 -2
  44. package/dist/loop/run-agent.d.ts +13 -1
  45. package/dist/loop/run-agent.js +19 -4
  46. package/dist/memory/card-builders.d.ts +8 -1
  47. package/dist/memory/card-builders.js +20 -3
  48. package/dist/memory/reconstruct-cards.js +4 -3
  49. package/dist/memory/thread-history.d.ts +27 -2
  50. package/dist/memory/thread-history.js +45 -5
  51. package/dist/memory/working-memory.d.ts +93 -10
  52. package/dist/memory/working-memory.js +220 -84
  53. package/dist/prompts/SOUL.d.ts +22 -9
  54. package/dist/prompts/SOUL.js +56 -37
  55. package/dist/prompts/analogical-reasoner.d.ts +1 -1
  56. package/dist/prompts/analogical-reasoner.js +2 -2
  57. package/dist/prompts/briefing.d.ts +100 -0
  58. package/dist/prompts/briefing.js +166 -0
  59. package/dist/prompts/conversation.d.ts +1 -1
  60. package/dist/prompts/conversation.js +94 -440
  61. package/dist/prompts/literature-reviewer.d.ts +1 -1
  62. package/dist/prompts/literature-reviewer.js +10 -10
  63. package/dist/prompts/planner.js +28 -59
  64. package/dist/prompts/report-builder.d.ts +1 -1
  65. package/dist/prompts/report-builder.js +71 -24
  66. package/dist/prompts/sandbox/bulk-transcriptomics-agent.d.ts +1 -1
  67. package/dist/prompts/sandbox/bulk-transcriptomics-agent.js +2 -7
  68. package/dist/prompts/sandbox/cheminformatics-agent.d.ts +1 -1
  69. package/dist/prompts/sandbox/cheminformatics-agent.js +11 -15
  70. package/dist/prompts/sandbox/chromatin-agent.d.ts +1 -1
  71. package/dist/prompts/sandbox/chromatin-agent.js +3 -7
  72. package/dist/prompts/sandbox/data-profiler.d.ts +1 -1
  73. package/dist/prompts/sandbox/data-profiler.js +13 -8
  74. package/dist/prompts/sandbox/dna-methylation-agent.d.ts +1 -1
  75. package/dist/prompts/sandbox/dna-methylation-agent.js +2 -7
  76. package/dist/prompts/sandbox/drug-repurposing-agent.d.ts +1 -1
  77. package/dist/prompts/sandbox/drug-repurposing-agent.js +15 -16
  78. package/dist/prompts/sandbox/enrichment-agent.d.ts +1 -1
  79. package/dist/prompts/sandbox/enrichment-agent.js +2 -9
  80. package/dist/prompts/sandbox/genomic-variant-agent.d.ts +1 -1
  81. package/dist/prompts/sandbox/genomic-variant-agent.js +2 -6
  82. package/dist/prompts/sandbox/immune-profiling-agent.d.ts +1 -1
  83. package/dist/prompts/sandbox/immune-profiling-agent.js +3 -8
  84. package/dist/prompts/sandbox/metabolomics-agent.d.ts +1 -1
  85. package/dist/prompts/sandbox/metabolomics-agent.js +1 -7
  86. package/dist/prompts/sandbox/microbiome-agent.d.ts +1 -1
  87. package/dist/prompts/sandbox/microbiome-agent.js +2 -7
  88. package/dist/prompts/sandbox/multi-omics-integration-agent.d.ts +1 -1
  89. package/dist/prompts/sandbox/multi-omics-integration-agent.js +2 -8
  90. package/dist/prompts/sandbox/multimodal-sc-agent.d.ts +1 -1
  91. package/dist/prompts/sandbox/multimodal-sc-agent.js +2 -7
  92. package/dist/prompts/sandbox/network-agent.d.ts +1 -1
  93. package/dist/prompts/sandbox/network-agent.js +2 -7
  94. package/dist/prompts/sandbox/proteomics-agent.d.ts +1 -1
  95. package/dist/prompts/sandbox/proteomics-agent.js +2 -9
  96. package/dist/prompts/sandbox/single-cell-agent.d.ts +1 -1
  97. package/dist/prompts/sandbox/single-cell-agent.js +2 -9
  98. package/dist/prompts/sandbox/spatial-omics-agent.d.ts +1 -1
  99. package/dist/prompts/sandbox/spatial-omics-agent.js +3 -6
  100. package/dist/prompts/sandbox/statistical-modeling-agent.d.ts +1 -1
  101. package/dist/prompts/sandbox/statistical-modeling-agent.js +2 -7
  102. package/dist/prompts/sandbox/translational-safety-agent.d.ts +1 -1
  103. package/dist/prompts/sandbox/translational-safety-agent.js +13 -14
  104. package/dist/prompts/sandbox-standards.d.ts +22 -14
  105. package/dist/prompts/sandbox-standards.js +91 -71
  106. package/dist/prompts/synthesis-agent.d.ts +1 -1
  107. package/dist/prompts/synthesis-agent.js +33 -131
  108. package/dist/provenance/collector.js +1 -1
  109. package/dist/providers/ai-sdk.js +31 -4
  110. package/dist/providers/prompt-cache.d.ts +74 -0
  111. package/dist/providers/prompt-cache.js +77 -0
  112. package/dist/providers/types.d.ts +33 -0
  113. package/dist/reference-data/catalog.d.ts +131 -0
  114. package/dist/reference-data/catalog.js +348 -0
  115. package/dist/reference-data/receipt.d.ts +41 -0
  116. package/dist/reference-data/receipt.js +40 -0
  117. package/dist/schemas/data-profile-schemas.js +5 -3
  118. package/dist/schemas/plan-schemas.d.ts +21 -21
  119. package/dist/schemas/plan-schemas.js +9 -3
  120. package/dist/schemas/run-synthesis.d.ts +8 -4
  121. package/dist/schemas/run-synthesis.js +92 -56
  122. package/dist/schemas/validate-plan.js +1 -1
  123. package/dist/schemas/workflow-state.d.ts +7 -1
  124. package/dist/schemas/workflow-state.js +33 -19
  125. package/dist/state/artifacts.d.ts +13 -0
  126. package/dist/state/artifacts.js +27 -0
  127. package/dist/state/data-profile.d.ts +64 -5
  128. package/dist/state/index.d.ts +3 -3
  129. package/dist/state/index.js +1 -1
  130. package/dist/tasks/data-profile.d.ts +20 -2
  131. package/dist/tasks/data-profile.js +71 -22
  132. package/dist/tools/bio/chembl.d.ts +38 -0
  133. package/dist/tools/bio/chembl.js +138 -0
  134. package/dist/tools/bio/comptox.d.ts +50 -0
  135. package/dist/tools/bio/comptox.js +149 -0
  136. package/dist/tools/bio/get-impc-ko-profile.js +9 -6
  137. package/dist/tools/bio/index.d.ts +5 -17
  138. package/dist/tools/bio/index.js +5 -17
  139. package/dist/tools/bio/keys.d.ts +14 -9
  140. package/dist/tools/bio/keys.js +16 -16
  141. package/dist/tools/bio/opentargets.d.ts +38 -0
  142. package/dist/tools/bio/opentargets.js +89 -0
  143. package/dist/tools/bio/pubchem.d.ts +29 -0
  144. package/dist/tools/bio/pubchem.js +92 -0
  145. package/dist/tools/bio/pubmed.d.ts +51 -0
  146. package/dist/tools/bio/pubmed.js +100 -0
  147. package/dist/tools/bio/search-bgee-expression.js +12 -6
  148. package/dist/tools/bio/search-clinical-trials.js +16 -5
  149. package/dist/tools/bio/search-faers.js +8 -4
  150. package/dist/tools/bio/search-geo-datasets.js +20 -6
  151. package/dist/tools/bio/search-gwas-catalog.d.ts +1 -1
  152. package/dist/tools/bio/search-pharmgkb.js +10 -4
  153. package/dist/tools/display/index.d.ts +1 -0
  154. package/dist/tools/display/index.js +1 -0
  155. package/dist/tools/display/normalize-echart-spec.d.ts +61 -0
  156. package/dist/tools/display/normalize-echart-spec.js +211 -0
  157. package/dist/tools/display/show-user.d.ts +6 -1
  158. package/dist/tools/display/show-user.js +25 -12
  159. package/dist/tools/execute-plan.js +5 -2
  160. package/dist/tools/iterate-report.d.ts +168 -118
  161. package/dist/tools/iterate-report.js +334 -96
  162. package/dist/tools/lib/chembl-client.d.ts +12 -0
  163. package/dist/tools/lib/chembl-client.js +127 -0
  164. package/dist/tools/lib/ctx-ops.d.ts +224 -0
  165. package/dist/tools/lib/ctx-ops.js +450 -0
  166. package/dist/tools/lib/iuphar-client.js +10 -1
  167. package/dist/tools/lib/openfda-client.js +11 -3
  168. package/dist/tools/lib/pathway-client.js +10 -4
  169. package/dist/tools/lib/pubchem-ops.d.ts +74 -0
  170. package/dist/tools/lib/pubchem-ops.js +224 -0
  171. package/dist/tools/memory/update-working-memory.d.ts +45 -7
  172. package/dist/tools/memory/update-working-memory.js +111 -41
  173. package/dist/tools/report/index.d.ts +3 -2
  174. package/dist/tools/report/index.js +3 -2
  175. package/dist/tools/research/generate-analogy-report.js +25 -12
  176. package/dist/tools/research/generate-plan.d.ts +12 -5
  177. package/dist/tools/research/generate-plan.js +168 -37
  178. package/dist/tools/research/index.d.ts +1 -0
  179. package/dist/tools/research/index.js +1 -0
  180. package/dist/tools/research/inspect-data-profile.d.ts +85 -0
  181. package/dist/tools/research/inspect-data-profile.js +161 -0
  182. package/dist/tools/research/literature-reviewer.js +3 -4
  183. package/dist/tools/sandbox/list-available-packages.d.ts +79 -5
  184. package/dist/tools/sandbox/list-available-packages.js +152 -10
  185. package/dist/tools/sandbox/list-available-refs.d.ts +141 -5
  186. package/dist/tools/sandbox/list-available-refs.js +647 -134
  187. package/dist/tools/sandbox/report-blocker.d.ts +39 -9
  188. package/dist/tools/sandbox/report-blocker.js +43 -20
  189. package/dist/tools/workspace/read-file.js +4 -5
  190. package/dist/tools/workspace/run-exec.d.ts +4 -4
  191. package/dist/tools/workspace/run-exec.js +4 -4
  192. package/dist/tools/workspace/show-file.js +10 -6
  193. package/dist/tools/workspace/show-plan.js +12 -6
  194. package/dist/tools/workspace/workspace-search.d.ts +1 -1
  195. package/dist/tools/workspace/workspace-search.js +11 -5
  196. package/dist/workflows/execute-analysis.d.ts +43 -4
  197. package/dist/workflows/execute-analysis.js +107 -6
  198. package/dist/workflows/target-assessment/lib/citation-validator.js +2 -2
  199. package/dist/workflows/target-assessment/lib/clinical-consequence-annotator.js +2 -1
  200. package/dist/workspace/paths.d.ts +2 -2
  201. package/dist/workspace/paths.js +2 -2
  202. package/package.json +33 -33
  203. package/dist/execution/filesystem-artifact-registry.d.ts +0 -57
  204. package/dist/execution/filesystem-artifact-registry.js +0 -92
  205. package/dist/lib/identifiers.d.ts +0 -8
  206. package/dist/lib/identifiers.js +0 -10
  207. package/dist/lib/mime-detect.d.ts +0 -17
  208. package/dist/lib/mime-detect.js +0 -29
  209. package/dist/lib/streamed-download.d.ts +0 -28
  210. package/dist/lib/streamed-download.js +0 -111
  211. package/dist/lib/trace-context.d.ts +0 -11
  212. package/dist/lib/trace-context.js +0 -49
  213. package/dist/providers/llm-capabilities.d.ts +0 -33
  214. package/dist/providers/llm-capabilities.js +0 -58
  215. package/dist/schemas/render-step-prompt.d.ts +0 -32
  216. package/dist/schemas/render-step-prompt.js +0 -76
  217. package/dist/tools/bio/find-approval-precedent.d.ts +0 -32
  218. package/dist/tools/bio/find-approval-precedent.js +0 -72
  219. package/dist/tools/bio/get-article-details.d.ts +0 -11
  220. package/dist/tools/bio/get-article-details.js +0 -20
  221. package/dist/tools/bio/get-article-full-text.d.ts +0 -19
  222. package/dist/tools/bio/get-article-full-text.js +0 -32
  223. package/dist/tools/bio/get-bioactivity.d.ts +0 -11
  224. package/dist/tools/bio/get-bioactivity.js +0 -23
  225. package/dist/tools/bio/get-drug-info.d.ts +0 -9
  226. package/dist/tools/bio/get-drug-info.js +0 -22
  227. package/dist/tools/bio/get-mechanism.d.ts +0 -8
  228. package/dist/tools/bio/get-mechanism.js +0 -18
  229. package/dist/tools/bio/get-pubchem-assays.d.ts +0 -22
  230. package/dist/tools/bio/get-pubchem-assays.js +0 -107
  231. package/dist/tools/bio/get-pubchem-cross-refs.d.ts +0 -15
  232. package/dist/tools/bio/get-pubchem-cross-refs.js +0 -68
  233. package/dist/tools/bio/get-target-safety.d.ts +0 -18
  234. package/dist/tools/bio/get-target-safety.js +0 -26
  235. package/dist/tools/bio/search-compounds.d.ts +0 -22
  236. package/dist/tools/bio/search-compounds.js +0 -160
  237. package/dist/tools/bio/search-ctx-chemical.d.ts +0 -50
  238. package/dist/tools/bio/search-ctx-chemical.js +0 -130
  239. package/dist/tools/bio/search-ctx-exposure.d.ts +0 -55
  240. package/dist/tools/bio/search-ctx-exposure.js +0 -176
  241. package/dist/tools/bio/search-ctx-hazard.d.ts +0 -111
  242. package/dist/tools/bio/search-ctx-hazard.js +0 -178
  243. package/dist/tools/bio/search-opentargets.d.ts +0 -11
  244. package/dist/tools/bio/search-opentargets.js +0 -25
  245. package/dist/tools/bio/search-pubchem-compound.d.ts +0 -26
  246. package/dist/tools/bio/search-pubchem-compound.js +0 -110
  247. package/dist/tools/bio/search-pubmed.d.ts +0 -17
  248. package/dist/tools/bio/search-pubmed.js +0 -31
  249. package/dist/tools/bio/search-targets.d.ts +0 -9
  250. package/dist/tools/bio/search-targets.js +0 -20
  251. package/dist/tools/bio/search-toxcast.d.ts +0 -36
  252. package/dist/tools/bio/search-toxcast.js +0 -141
  253. package/dist/workflows/register-workflows.d.ts +0 -51
  254. package/dist/workflows/register-workflows.js +0 -48
  255. package/dist/workflows/resume-execute-analysis.d.ts +0 -70
  256. package/dist/workflows/resume-execute-analysis.js +0 -80
  257. package/dist/workflows/target-assessment/correction-loop.d.ts +0 -45
  258. package/dist/workflows/target-assessment/correction-loop.js +0 -62
  259. package/dist/workflows/target-assessment/steps/phase0-resolve.d.ts +0 -71
  260. package/dist/workflows/target-assessment/steps/phase0-resolve.js +0 -21
  261. package/dist/workflows/target-assessment/steps/phase1-aggregate.d.ts +0 -1018
  262. package/dist/workflows/target-assessment/steps/phase1-aggregate.js +0 -25
  263. package/dist/workspace/mount-strategy.d.ts +0 -50
  264. package/dist/workspace/mount-strategy.js +0 -67
  265. package/dist/workspace/provenance-collector.d.ts +0 -34
  266. package/dist/workspace/provenance-collector.js +0 -16
  267. package/dist/workspace/workspace-paths.d.ts +0 -26
  268. package/dist/workspace/workspace-paths.js +0 -31
@@ -0,0 +1,40 @@
1
+ import { z } from "zod";
2
+ import { ReferenceArtifactPathSchema, ReferenceDatasetSchema, ReferenceSha256Schema } from "./catalog.js";
3
+ /** Schema version for installation receipts shared by all embedders. */
4
+ export const REFERENCE_INSTALL_RECEIPT_VERSION = 1;
5
+ /**
6
+ * What was actually written to disk for one artifact. The size and digest are
7
+ * *observed at install*, never copied from the catalog — for a `pinned`
8
+ * artifact they equal the catalog's (the install would have failed otherwise),
9
+ * and for an `unpinned` one they are the only record of what the mutable
10
+ * upstream served, which is what `verify` later checks the files against.
11
+ */
12
+ const ReferenceReceiptArtifactSchema = z.object({
13
+ path: ReferenceArtifactPathSchema,
14
+ bytes: z.number().int().nonnegative(),
15
+ sha256: ReferenceSha256Schema,
16
+ integrity: z.enum(["pinned", "unpinned"]),
17
+ });
18
+ /** Optional metadata describing one activated reference dataset version. */
19
+ export const ReferenceInstallReceiptSchema = z
20
+ .object({
21
+ version: z.literal(REFERENCE_INSTALL_RECEIPT_VERSION),
22
+ datasetId: ReferenceDatasetSchema.shape.id,
23
+ datasetVersion: ReferenceDatasetSchema.shape.version,
24
+ activatedAt: z.iso.datetime({ offset: true }),
25
+ artifacts: z.array(ReferenceReceiptArtifactSchema).min(1),
26
+ })
27
+ .superRefine((receipt, ctx) => {
28
+ const paths = new Set();
29
+ for (const [index, artifact] of receipt.artifacts.entries()) {
30
+ if (paths.has(artifact.path)) {
31
+ ctx.addIssue({ code: "custom", message: `Duplicate receipt artifact path: ${artifact.path}`, path: ["artifacts", index, "path"] });
32
+ }
33
+ paths.add(artifact.path);
34
+ }
35
+ });
36
+ /** Parse optional/untrusted receipt metadata; invalid receipts are ignored. */
37
+ export function parseReferenceInstallReceipt(input) {
38
+ const result = ReferenceInstallReceiptSchema.safeParse(input);
39
+ return result.success ? result.data : undefined;
40
+ }
@@ -15,7 +15,7 @@ export const ProfilerFileSchema = z.object({
15
15
  .describe("Semantic data type: count-matrix, normalized-expression, variants, alignments, " +
16
16
  "clinical-metadata, clinical-sdtm, clinical-adam, clinical-response, " +
17
17
  "pharmacokinetic-data, adverse-events, safety-labs, " +
18
- "molecular-structures, annotations"),
18
+ "molecular-structures, annotations, document (paper PDF, README, methods doc)"),
19
19
  format: z.string().describe("File format (e.g. CSV, TSV, h5ad, MTX, VCF, BAM, SDF, FASTQ)"),
20
20
  rows: z.number().nullish(),
21
21
  cols: z.number().nullish(),
@@ -43,7 +43,7 @@ export const OrganismSchema = z.object({
43
43
  source: SubjectSourceEnum,
44
44
  confidence: z
45
45
  .enum(["high", "medium", "low"])
46
- .describe("high: explicit organism column or paper/README statement. " +
46
+ .describe("high: explicit user-context statement, an organism column, or a paper/README statement. " +
47
47
  "medium: filename convention or accession lookup. " +
48
48
  "low: inferred from gene IDs or other indirect signals, OR sources disagree (in which case also record the conflict in qualityAssessment.concerns)."),
49
49
  notes: z.string().optional().describe("Brief note when source is 'inferred' or confidence is 'low' (one sentence)."),
@@ -51,7 +51,9 @@ export const OrganismSchema = z.object({
51
51
  export const ProfilerOutputSchema = z.object({
52
52
  files: z.array(ProfilerFileSchema),
53
53
  analysisSummary: z.string().describe("Narrative overview of the dataset — structure, content, analytical potential, and limitations"),
54
- domain: z.string().describe("Scientific domain (e.g. transcriptomics, proteomics, genomics, chemistry, clinical, imaging, metabolomics, multi-omics)"),
54
+ domain: z
55
+ .string()
56
+ .describe("Scientific domain (e.g. transcriptomics, proteomics, genomics, cheminformatics, clinical, imaging, metabolomics, multi-omics)"),
55
57
  subtype: z.string().optional().describe("Specific subtype within domain (e.g. bulk-rna-seq, single-cell, LC-MS/MS, whole-genome-sequencing)"),
56
58
  organism: OrganismSchema.nullable().describe("Subject organism, identified from any input (metadata files, paper PDFs, READMEs, filenames, accession patterns). " +
57
59
  "Set to null ONLY when no input identifies the organism — never guess. " +
@@ -11,6 +11,13 @@ export declare const PlanStepSchema: z.ZodObject<{
11
11
  id: z.ZodString;
12
12
  context: z.ZodOptional<z.ZodString>;
13
13
  description: z.ZodOptional<z.ZodString>;
14
+ track: z.ZodString;
15
+ step_type: z.ZodString;
16
+ question: z.ZodString;
17
+ constraints: z.ZodOptional<z.ZodArray<z.ZodString>>;
18
+ acceptance_criteria: z.ZodArray<z.ZodString>;
19
+ caveats: z.ZodOptional<z.ZodArray<z.ZodString>>;
20
+ depends_on: z.ZodArray<z.ZodString>;
14
21
  resources: z.ZodNonOptional<z.ZodOptional<z.ZodObject<{
15
22
  cpu: z.ZodNumber;
16
23
  memoryGb: z.ZodNumber;
@@ -18,13 +25,6 @@ export declare const PlanStepSchema: z.ZodObject<{
18
25
  count: z.ZodNumber;
19
26
  }, z.core.$strip>>;
20
27
  }, z.core.$strip>>>;
21
- constraints: z.ZodOptional<z.ZodArray<z.ZodString>>;
22
- track: z.ZodString;
23
- step_type: z.ZodString;
24
- question: z.ZodString;
25
- acceptance_criteria: z.ZodArray<z.ZodString>;
26
- caveats: z.ZodOptional<z.ZodArray<z.ZodString>>;
27
- depends_on: z.ZodArray<z.ZodString>;
28
28
  agent: z.ZodEnum<{
29
29
  [x: string]: string;
30
30
  }>;
@@ -43,6 +43,13 @@ export declare const PlannerPlanSchema: z.ZodObject<{
43
43
  id: z.ZodString;
44
44
  context: z.ZodOptional<z.ZodString>;
45
45
  description: z.ZodOptional<z.ZodString>;
46
+ track: z.ZodString;
47
+ step_type: z.ZodString;
48
+ question: z.ZodString;
49
+ constraints: z.ZodOptional<z.ZodArray<z.ZodString>>;
50
+ acceptance_criteria: z.ZodArray<z.ZodString>;
51
+ caveats: z.ZodOptional<z.ZodArray<z.ZodString>>;
52
+ depends_on: z.ZodArray<z.ZodString>;
46
53
  resources: z.ZodNonOptional<z.ZodOptional<z.ZodObject<{
47
54
  cpu: z.ZodNumber;
48
55
  memoryGb: z.ZodNumber;
@@ -50,13 +57,6 @@ export declare const PlannerPlanSchema: z.ZodObject<{
50
57
  count: z.ZodNumber;
51
58
  }, z.core.$strip>>;
52
59
  }, z.core.$strip>>>;
53
- constraints: z.ZodOptional<z.ZodArray<z.ZodString>>;
54
- track: z.ZodString;
55
- step_type: z.ZodString;
56
- question: z.ZodString;
57
- acceptance_criteria: z.ZodArray<z.ZodString>;
58
- caveats: z.ZodOptional<z.ZodArray<z.ZodString>>;
59
- depends_on: z.ZodArray<z.ZodString>;
60
60
  agent: z.ZodEnum<{
61
61
  [x: string]: string;
62
62
  }>;
@@ -84,6 +84,13 @@ export declare const PlanningAgentOutputSchema: z.ZodObject<{
84
84
  id: z.ZodString;
85
85
  context: z.ZodOptional<z.ZodString>;
86
86
  description: z.ZodOptional<z.ZodString>;
87
+ track: z.ZodString;
88
+ step_type: z.ZodString;
89
+ question: z.ZodString;
90
+ constraints: z.ZodOptional<z.ZodArray<z.ZodString>>;
91
+ acceptance_criteria: z.ZodArray<z.ZodString>;
92
+ caveats: z.ZodOptional<z.ZodArray<z.ZodString>>;
93
+ depends_on: z.ZodArray<z.ZodString>;
87
94
  resources: z.ZodNonOptional<z.ZodOptional<z.ZodObject<{
88
95
  cpu: z.ZodNumber;
89
96
  memoryGb: z.ZodNumber;
@@ -91,13 +98,6 @@ export declare const PlanningAgentOutputSchema: z.ZodObject<{
91
98
  count: z.ZodNumber;
92
99
  }, z.core.$strip>>;
93
100
  }, z.core.$strip>>>;
94
- constraints: z.ZodOptional<z.ZodArray<z.ZodString>>;
95
- track: z.ZodString;
96
- step_type: z.ZodString;
97
- question: z.ZodString;
98
- acceptance_criteria: z.ZodArray<z.ZodString>;
99
- caveats: z.ZodOptional<z.ZodArray<z.ZodString>>;
100
- depends_on: z.ZodArray<z.ZodString>;
101
101
  agent: z.ZodEnum<{
102
102
  [x: string]: string;
103
103
  }>;
@@ -19,13 +19,19 @@ export const PlanStepSchema = AnalysisStepSchema.omit({
19
19
  })
20
20
  .required({ agent: true, resources: true })
21
21
  .extend({
22
- agent: z.enum(plannableAgentIds).describe("Sandbox agent ID from the available agents list"),
22
+ agent: z.enum(plannableAgentIds).describe("Sandbox agent ID, routed by the step's primary data object. Must be one of the available agents."),
23
23
  });
24
24
  /** Plan schema for planner output — uses PlanStepSchema for steps and requires
25
25
  * a concise title (optional on the persistence schema for historical plans). */
26
26
  export const PlannerPlanSchema = AnalysisPlanSchema.extend({
27
- title: z.string().min(1).max(80).describe("Concise human-readable plan name (3–8 words)"),
28
- steps: z.array(PlanStepSchema),
27
+ title: z
28
+ .string()
29
+ .min(1)
30
+ .max(80)
31
+ .describe('Concise plan name (3–8 words) naming the analysis by what it does — e.g. "AD lesional vs control DE + pathways", ' +
32
+ '"scRNA immune deconvolution". Ground it in the actual research question and conditions; it is shown as the run\'s heading in chat. ' +
33
+ 'Not a generic name like "Transcriptomics analysis".'),
34
+ steps: z.array(PlanStepSchema).describe("The steps of the plan, as a DAG wired by depends_on."),
29
35
  });
30
36
  /** Hydrate slim planner output into a full AnalysisPlan with execution-time defaults. */
31
37
  export function hydratePlanSteps(plannerPlan) {
@@ -4,6 +4,10 @@
4
4
  * Produced by the synthesis step after all sandbox steps complete.
5
5
  * Combines computational findings from step summaries with literature
6
6
  * evidence from the literature-reviewer agent.
7
+ *
8
+ * This schema is the synthesizer's output contract: it is emitted as the
9
+ * `submit_synthesis` tool's arg schema, so every field's meaning must live in
10
+ * `.describe()` — a JSDoc comment here reaches no model.
7
11
  */
8
12
  import { z } from "zod";
9
13
  export declare const LiteratureReferenceSchema: z.ZodObject<{
@@ -27,11 +31,11 @@ export declare const SynthesizedFindingSchema: z.ZodObject<{
27
31
  low: "low";
28
32
  }>;
29
33
  noveltyStatus: z.ZodEnum<{
30
- expected: "expected";
31
34
  novel: "novel";
32
35
  confirmed: "confirmed";
33
36
  partially_confirmed: "partially_confirmed";
34
37
  contradicted: "contradicted";
38
+ expected: "expected";
35
39
  }>;
36
40
  literatureInterpretation: z.ZodString;
37
41
  references: z.ZodArray<z.ZodObject<{
@@ -53,7 +57,6 @@ export declare const SynthesizedFindingSchema: z.ZodObject<{
53
57
  "clinical-evidence": "clinical-evidence";
54
58
  }>;
55
59
  actionType: z.ZodOptional<z.ZodEnum<{
56
- none: "none";
57
60
  "therapeutic-target": "therapeutic-target";
58
61
  "predictive-biomarker": "predictive-biomarker";
59
62
  "prognostic-biomarker": "prognostic-biomarker";
@@ -62,6 +65,7 @@ export declare const SynthesizedFindingSchema: z.ZodObject<{
62
65
  "resistance-mechanism": "resistance-mechanism";
63
66
  "patient-stratification": "patient-stratification";
64
67
  "mechanism-of-action": "mechanism-of-action";
68
+ none: "none";
65
69
  }>>;
66
70
  rationale: z.ZodString;
67
71
  }, z.core.$strip>>;
@@ -88,11 +92,11 @@ export declare const RunSynthesisSchema: z.ZodObject<{
88
92
  low: "low";
89
93
  }>;
90
94
  noveltyStatus: z.ZodEnum<{
91
- expected: "expected";
92
95
  novel: "novel";
93
96
  confirmed: "confirmed";
94
97
  partially_confirmed: "partially_confirmed";
95
98
  contradicted: "contradicted";
99
+ expected: "expected";
96
100
  }>;
97
101
  literatureInterpretation: z.ZodString;
98
102
  references: z.ZodArray<z.ZodObject<{
@@ -114,7 +118,6 @@ export declare const RunSynthesisSchema: z.ZodObject<{
114
118
  "clinical-evidence": "clinical-evidence";
115
119
  }>;
116
120
  actionType: z.ZodOptional<z.ZodEnum<{
117
- none: "none";
118
121
  "therapeutic-target": "therapeutic-target";
119
122
  "predictive-biomarker": "predictive-biomarker";
120
123
  "prognostic-biomarker": "prognostic-biomarker";
@@ -123,6 +126,7 @@ export declare const RunSynthesisSchema: z.ZodObject<{
123
126
  "resistance-mechanism": "resistance-mechanism";
124
127
  "patient-stratification": "patient-stratification";
125
128
  "mechanism-of-action": "mechanism-of-action";
129
+ none: "none";
126
130
  }>>;
127
131
  rationale: z.ZodString;
128
132
  }, z.core.$strip>>;
@@ -4,35 +4,51 @@
4
4
  * Produced by the synthesis step after all sandbox steps complete.
5
5
  * Combines computational findings from step summaries with literature
6
6
  * evidence from the literature-reviewer agent.
7
+ *
8
+ * This schema is the synthesizer's output contract: it is emitted as the
9
+ * `submit_synthesis` tool's arg schema, so every field's meaning must live in
10
+ * `.describe()` — a JSDoc comment here reaches no model.
7
11
  */
8
12
  import { z } from "zod";
9
13
  export const LiteratureReferenceSchema = z.object({
10
- pmid: z.string(),
11
- citation: z.string(),
12
- relevance: z.string(),
13
- concordance: z.enum(["supports", "contradicts", "extends", "contextualizes"]),
14
+ pmid: z.string().describe("Numeric PubMed ID. Must come from a literature_reviewer response — never invented."),
15
+ citation: z.string().describe('Short citation for the paper, e.g. "Smith 2020".'),
16
+ relevance: z.string().describe("Why this paper matters to the finding — what it establishes, challenges, or contextualizes."),
17
+ concordance: z
18
+ .enum(["supports", "contradicts", "extends", "contextualizes"])
19
+ .describe("How the paper relates to the finding. " +
20
+ "supports: the paper directly supports the finding. " +
21
+ "contradicts: the paper reports a conflicting result. " +
22
+ "extends: the paper builds on the finding in another context. " +
23
+ "contextualizes: the paper provides background but does not directly address the finding."),
14
24
  });
15
25
  export const SynthesizedFindingSchema = z.object({
16
- /** Which step produced this finding. */
17
- stepId: z.string(),
18
- /** Finding title from the step summary. */
19
- title: z.string(),
20
- /** Finding description from the step summary. */
21
- description: z.string(),
22
- /** Confidence from the step summary. */
23
- confidence: z.enum(["high", "medium", "low"]),
24
- /** Novelty assessment based on literature review. */
25
- noveltyStatus: z.enum(["novel", "confirmed", "partially_confirmed", "contradicted", "expected"]),
26
- /** How this finding relates to existing literature. */
27
- literatureInterpretation: z.string(),
28
- /** Supporting or contradicting references. */
29
- references: z.array(LiteratureReferenceSchema),
30
- /** Translational proximity and actionability assessment. */
26
+ stepId: z.string().describe("Which step produced this finding. Must be a stepId present in the input summaries."),
27
+ title: z.string().describe("Finding title from the step summary."),
28
+ description: z.string().describe("Finding description from the step summary."),
29
+ confidence: z
30
+ .enum(["high", "medium", "low"])
31
+ .describe("Confidence from the step summary — reflect the summary's own stated confidence, not a re-assessment. " +
32
+ "If the summary states none, use medium; use high only for findings the summary treats as robust."),
33
+ noveltyStatus: z
34
+ .enum(["novel", "confirmed", "partially_confirmed", "contradicted", "expected"])
35
+ .describe("Novelty assessment based on literature review. " +
36
+ "novel: the literature does not describe this result in this context. " +
37
+ "confirmed: the literature independently establishes this result. " +
38
+ "partially_confirmed: the literature supports related but not identical claims (e.g. same gene, different tissue). " +
39
+ "contradicted: the literature reports the opposite direction or effect. " +
40
+ "expected: a standard, well-known result (housekeeping genes, canonical QC outcomes) — not a discovery."),
41
+ literatureInterpretation: z.string().describe("How this finding relates to existing literature."),
42
+ references: z.array(LiteratureReferenceSchema).describe("Supporting or contradicting references."),
31
43
  translationalRelevance: z
32
44
  .object({
33
- /** How close this finding is to clinical application. */
34
- stage: z.enum(["discovery", "preclinical-validation", "biomarker-candidate", "clinical-evidence"]),
35
- /** What type of translational action this finding supports. */
45
+ stage: z
46
+ .enum(["discovery", "preclinical-validation", "biomarker-candidate", "clinical-evidence"])
47
+ .describe("How close this finding is to clinical application. " +
48
+ "discovery: novel biology with no direct clinical path yet. " +
49
+ "preclinical-validation: known target/pathway with existing preclinical evidence but no clinical data in this context. " +
50
+ "biomarker-candidate: measurable, differential, with a biologically plausible mechanism linking it to outcome. " +
51
+ "clinical-evidence: supported by or directly relevant to clinical trial data or approved therapeutics."),
36
52
  actionType: z
37
53
  .enum([
38
54
  "therapeutic-target",
@@ -45,43 +61,63 @@ export const SynthesizedFindingSchema = z.object({
45
61
  "mechanism-of-action",
46
62
  "none",
47
63
  ])
48
- .optional(),
49
- /** Brief rationale for the stage and action type. */
50
- rationale: z.string(),
64
+ .optional()
65
+ .describe("What type of translational action this finding supports. " +
66
+ "therapeutic-target: gene/protein/pathway suitable for drug intervention. " +
67
+ "predictive-biomarker: differentiates treatment responders from non-responders (requires treatment x marker interaction evidence). " +
68
+ "prognostic-biomarker: predicts outcome regardless of treatment. " +
69
+ "pharmacodynamic-biomarker: measures target engagement or drug effect over time. " +
70
+ "safety-signal: suggests potential toxicity, adverse effect, or off-target liability. " +
71
+ "resistance-mechanism: explains non-response or acquired resistance. " +
72
+ "patient-stratification: enables subgroup identification for enrichment strategies. " +
73
+ "mechanism-of-action: illuminates how a drug or intervention works. " +
74
+ "none: biological value but no direct translational path."),
75
+ rationale: z
76
+ .string()
77
+ .describe("ONE sentence on why this stage and action type were assigned. " +
78
+ "Must reference specific evidence (existing drugs, clinical trials, biomarker properties, literature)."),
51
79
  })
52
- .optional(),
80
+ .optional()
81
+ .describe("Translational proximity and actionability. Populate only for findings with genuine translational implications — " +
82
+ "omit for purely technical or methodological findings."),
53
83
  });
54
84
  export const BiologicalThemeSchema = z.object({
55
- /** Theme name, e.g. "Immune dysregulation", "Metabolic reprogramming". */
56
- name: z.string(),
57
- /** Findings that contribute to this theme (by stepId + title). */
58
- findings: z.array(z.object({ stepId: z.string(), title: z.string() })),
59
- /** How these findings connect into a coherent biological story. */
60
- narrative: z.string(),
85
+ name: z
86
+ .string()
87
+ .describe('Theme name — a conclusion, not a topic label. "ECM remodeling drives the NAFLD-to-NASH transition" is a theme; ' +
88
+ '"Differential expression results" is not.'),
89
+ findings: z
90
+ .array(z.object({ stepId: z.string(), title: z.string() }))
91
+ .describe("Findings that contribute to this theme. Each entry must match an entry in findings[] by stepId + title."),
92
+ narrative: z.string().describe("How these findings connect into a coherent biological story — 3-5 sentences connecting them, not restating them."),
61
93
  });
62
94
  export const RunSynthesisSchema = z.object({
63
- runId: z.string(),
64
- /** Brief (2-4 sentence) summary of the run's scope and top-line result. */
65
- overview: z.string(),
66
- /**
67
- * Integrated interpretation: what the run establishes, what is novel,
68
- * what is actionable from a translational perspective. This is the
69
- * primary interpretive section — the "so what" of the analysis.
70
- */
71
- conclusions: z.string(),
72
- /**
73
- * Selective findings — only novel, contradicted, or high-impact results
74
- * that warrant individual attention. NOT a per-step catalog.
75
- */
76
- findings: z.array(SynthesizedFindingSchema),
77
- /** Cross-step biological themes. */
78
- themes: z.array(BiologicalThemeSchema),
79
- /** Methodological and translational caveats. */
80
- limitations: z.array(z.string()),
81
- /** Key references across all findings. */
82
- keyReferences: z.array(z.object({
83
- pmid: z.string(),
84
- citation: z.string(),
85
- description: z.string(),
86
- })),
95
+ runId: z.string().describe("The run being synthesized. Must equal the runId given in the prompt."),
96
+ overview: z
97
+ .string()
98
+ .describe("2-4 sentences: the run's scope, the top-line result, and the most important takeaway. " +
99
+ "An abstract's conclusion, not its body — do NOT enumerate counts, gene lists, or per-step results."),
100
+ conclusions: z
101
+ .string()
102
+ .describe("The PRIMARY interpretive section — the 'so what' — as connected prose (3-5 paragraphs). " +
103
+ "What the run establishes and what is novel vs confirmatory; what is actionable translationally (therapeutic-target candidates, " +
104
+ "biomarker candidates, safety signals, resistance mechanisms); how findings connect into a biological story; where computational " +
105
+ "predictions agree or disagree with clinical evidence; and an honest assessment of the translational distance."),
106
+ findings: z
107
+ .array(SynthesizedFindingSchema)
108
+ .describe("SELECTIVE — only novel, contradicted, high-impact, or unexpected results that warrant individual attention. " +
109
+ "NOT a per-step catalog. Target 3-7 for a typical run."),
110
+ themes: z
111
+ .array(BiologicalThemeSchema)
112
+ .describe("Cross-step biological themes. Target 2-4. Return fewer (or zero) rather than forcing findings that do not converge."),
113
+ limitations: z
114
+ .array(z.string())
115
+ .describe("Concrete methodological and translational caveats — not generic disclaimers. " + "Each names what it affects and why it matters. Target 3-6."),
116
+ keyReferences: z
117
+ .array(z.object({
118
+ pmid: z.string().describe("Numeric PubMed ID. Must already appear in at least one finding's references[]."),
119
+ citation: z.string().describe('Short citation for the paper, e.g. "Smith 2020".'),
120
+ description: z.string().describe("What the paper establishes and why it is key to this run."),
121
+ }))
122
+ .describe("The 5-10 most important papers across all findings. Prioritize those that directly validate, contradict, or extend the findings — do not pad with background citations."),
87
123
  });
@@ -26,7 +26,7 @@ export function deriveOutputPrefix(stepId) {
26
26
  return stepId
27
27
  .toLowerCase()
28
28
  .replace(/[^a-z0-9]+/g, "-")
29
- .replace(/^-+|-+$/g, "");
29
+ .replace(/^-|-$/g, "");
30
30
  }
31
31
  /**
32
32
  * Validate an analysis plan for structural correctness.
@@ -5,6 +5,12 @@
5
5
  * and the completion schemas that validate LLM structured output.
6
6
  */
7
7
  import { z } from "zod";
8
+ /**
9
+ * A step of an analysis plan. `PlanStepSchema` (schemas/plan-schemas.ts) narrows
10
+ * this into the planner's output contract and emits it as the `validate_plan` /
11
+ * `submit_plan` arg schema — so each field's meaning belongs in `.describe()`,
12
+ * not in a comment the model never sees.
13
+ */
8
14
  export declare const AnalysisStepSchema: z.ZodObject<{
9
15
  id: z.ZodString;
10
16
  name: z.ZodString;
@@ -220,8 +226,8 @@ export declare const SuspensionPayloadSchema: z.ZodObject<{
220
226
  message: z.ZodOptional<z.ZodString>;
221
227
  severity: z.ZodOptional<z.ZodEnum<{
222
228
  error: "error";
223
- warning: "warning";
224
229
  info: "info";
230
+ warning: "warning";
225
231
  }>>;
226
232
  content: z.ZodOptional<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
227
233
  type: z.ZodLiteral<"markdown">;
@@ -6,17 +6,27 @@
6
6
  */
7
7
  import { z } from "zod";
8
8
  // ── Plan structures ─────────────────────────────────────────────────
9
+ /**
10
+ * A step of an analysis plan. `PlanStepSchema` (schemas/plan-schemas.ts) narrows
11
+ * this into the planner's output contract and emits it as the `validate_plan` /
12
+ * `submit_plan` arg schema — so each field's meaning belongs in `.describe()`,
13
+ * not in a comment the model never sees.
14
+ */
9
15
  export const AnalysisStepSchema = z.object({
10
- id: z.string().describe("Step ID in format T{track}S{step}"),
11
- name: z.string(),
12
- track: z.string(),
13
- step_type: z.string(),
14
- question: z.string(),
15
- context: z.string().optional(),
16
- constraints: z.array(z.string()).optional(),
17
- acceptance_criteria: z.array(z.string()),
18
- caveats: z.array(z.string()).optional(),
19
- depends_on: z.array(z.string()),
16
+ id: z.string().describe("Step ID in format T{track}S{step} (e.g. T1S1, T1S2, T2S1). Unique within the plan and usable as a directory-name segment."),
17
+ name: z.string().describe("Short human-readable step name."),
18
+ track: z.string().describe("The track this step belongs to. Steps in the same track share a logical theme; steps in different tracks are independent."),
19
+ step_type: z.string().describe('Short label for the kind of work the step does (e.g. "analysis").'),
20
+ question: z
21
+ .string()
22
+ .describe("The specific question this step answers, framed with the actual condition names and comparisons from the experimental design."),
23
+ context: z.string().optional().describe("Background the sandbox agent needs to do the work."),
24
+ constraints: z.array(z.string()).optional().describe("Requirements the sandbox agent must follow exactly — not suggestions."),
25
+ acceptance_criteria: z.array(z.string()).describe("What the result must satisfy for the step to count as successful."),
26
+ caveats: z.array(z.string()).optional().describe("Pitfalls the sandbox agent should watch for."),
27
+ depends_on: z
28
+ .array(z.string())
29
+ .describe("IDs of steps in this plan that must complete before this one runs. Empty when the step has no prerequisites. The graph must be acyclic."),
20
30
  status: z.enum(["pending", "running", "completed", "failed", "skipped"]).default("pending"),
21
31
  // Optional on the persistence schema so historical plans (pre-resources)
22
32
  // still parse on the read side. `PlanStepSchema` re-requires it for planner
@@ -24,16 +34,17 @@ export const AnalysisStepSchema = z.object({
24
34
  // resources (no silent default) and clamps to cluster limits before use.
25
35
  resources: z
26
36
  .object({
27
- cpu: z.number(),
28
- memoryGb: z.number(),
29
- gpu: z.object({ count: z.number() }).optional(),
37
+ cpu: z.number().describe("CPU cores the step needs."),
38
+ memoryGb: z.number().describe("Memory in GB the step needs."),
39
+ gpu: z.object({ count: z.number() }).optional().describe("GPUs the step needs. Omit unless the step genuinely requires one."),
30
40
  })
31
- .optional(),
41
+ .optional()
42
+ .describe("Resources the step needs. Ground the estimate in the actual data size — see the resource-estimation rules."),
32
43
  // Execution fields
33
44
  agent: z.string().optional().describe("Assigned sandbox agent name from registry"),
34
45
  timeout: z.number().optional().describe("Execution timeout in seconds (falls back to image default)"),
35
46
  maxSteps: z.number().describe("Max LLM agentic steps for sandbox agent"),
36
- description: z.string().optional().describe("Human-readable description of what the step does"),
47
+ description: z.string().optional().describe("Human-readable description of what the step produces."),
37
48
  // Step result fields (populated during execution)
38
49
  summary: z.string().optional().describe("Execution result summary"),
39
50
  artifactIds: z.array(z.string()).optional().describe("Artifact IDs produced by this step"),
@@ -43,11 +54,14 @@ export const AnalysisPlanSchema = z.object({
43
54
  // Optional on the persistence schema so historical plans (pre-title) still
44
55
  // parse on the read side. `PlannerPlanSchema` re-requires it for new plans.
45
56
  title: z.string().optional().describe("Concise human-readable plan name"),
46
- analytical_narrative: z.string(),
57
+ analytical_narrative: z
58
+ .string()
59
+ .describe("Brief narrative of the logical flow: why these steps, in this order, address the research question. " +
60
+ "Reference the data characteristics that informed the choices."),
47
61
  steps: z.array(AnalysisStepSchema),
48
- created_at: z.string(),
49
- omicsType: z.string().optional().describe("Detected omics data type (e.g., transcriptomics, proteomics)"),
50
- omicsSubtype: z.string().optional().describe("Detected subtype (e.g., bulk-rna-seq, single-cell)"),
62
+ created_at: z.string().describe("ISO-8601 timestamp for when the plan was created."),
63
+ omicsType: z.string().optional().describe("Omics data type detected from the data context (e.g. transcriptomics, proteomics, metabolomics)."),
64
+ omicsSubtype: z.string().optional().describe("Subtype detected from the data context (e.g. bulk-rna-seq, single-cell, microarray)."),
51
65
  });
52
66
  // ── Suspension Payload ──────────────────────────────────────────────
53
67
  /**
@@ -44,6 +44,19 @@ export interface InputArtifactMeta {
44
44
  */
45
45
  export declare function queryInputArtifacts(pool: Querier, analysisId: string, paths: string[]): Promise<InputArtifactMeta[]>;
46
46
  export declare function queryUnsyncedStepArtifacts(pool: Querier, resourceId: string, runId: string, stepId: string): Promise<ArtifactRow[]>;
47
+ /** One registered step output, as a downstream consumer needs to name it. */
48
+ export interface StepArtifactRef {
49
+ /** Workspace-root-relative path (`runs/{runId}/{stepId}/output/de.csv`). */
50
+ path: string;
51
+ fileType: string | null;
52
+ }
53
+ /**
54
+ * The artifacts a completed step registered, most consequential first. Ordered
55
+ * by artifact kind (outputs, then figures, notebooks, scripts, logs) and then by
56
+ * path, so a `limit` truncates the tail of the list rather than an arbitrary
57
+ * slice of it — and so the same call replays to the same rows.
58
+ */
59
+ export declare function queryStepArtifactPaths(pool: Querier, resourceId: string, runId: string, stepId: string, limit: number): Promise<StepArtifactRef[]>;
47
60
  /** Count step-output artifacts produced by a run — for the run-completed card. */
48
61
  export declare function countArtifactsForRun(pool: Querier, analysisId: string, runId: string): Promise<number>;
49
62
  export declare function updateArtifactId(pool: Querier, resourceId: string, path: string, artifactId: string, fileType?: string | null): Promise<void>;
@@ -121,6 +121,33 @@ export async function queryUnsyncedStepArtifacts(pool, resourceId, runId, stepId
121
121
  });
122
122
  return result.rows.map(mapArtifactRow);
123
123
  }
124
+ /**
125
+ * The artifacts a completed step registered, most consequential first. Ordered
126
+ * by artifact kind (outputs, then figures, notebooks, scripts, logs) and then by
127
+ * path, so a `limit` truncates the tail of the list rather than an arbitrary
128
+ * slice of it — and so the same call replays to the same rows.
129
+ */
130
+ export async function queryStepArtifactPaths(pool, resourceId, runId, stepId, limit) {
131
+ if (limit <= 0)
132
+ return [];
133
+ const result = await pool.query({
134
+ text: `SELECT path, file_type
135
+ FROM cortex_artifacts
136
+ WHERE analysis_id = $1 AND source_run = $2 AND source_step = $3
137
+ AND role = 'step_output'
138
+ ORDER BY CASE file_type
139
+ WHEN 'output' THEN 0
140
+ WHEN 'figure' THEN 1
141
+ WHEN 'notebook' THEN 2
142
+ WHEN 'script' THEN 3
143
+ ELSE 4
144
+ END,
145
+ path
146
+ LIMIT $4`,
147
+ values: [resourceId, runId, stepId, limit],
148
+ });
149
+ return result.rows.map((r) => ({ path: r.path, fileType: r.file_type ?? null }));
150
+ }
124
151
  /** Count step-output artifacts produced by a run — for the run-completed card. */
125
152
  export async function countArtifactsForRun(pool, analysisId, runId) {
126
153
  const result = await pool.query({