@inflexa-ai/harness 0.44.0 → 0.45.1

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 (187) hide show
  1. package/dist/agents/conversation-agent.d.ts +10 -0
  2. package/dist/agents/conversation-agent.js +19 -1
  3. package/dist/agents/sandbox/shared.d.ts +23 -2
  4. package/dist/agents/sandbox/shared.js +51 -18
  5. package/dist/agents/sandbox/translational-safety-agent.js +26 -0
  6. package/dist/agents/sandbox/types.d.ts +24 -1
  7. package/dist/agents/sandbox-catalog.d.ts +14 -0
  8. package/dist/agents/sandbox-catalog.js +19 -0
  9. package/dist/app/approve-plan.d.ts +51 -0
  10. package/dist/app/approve-plan.js +84 -0
  11. package/dist/app/chat-turn.js +6 -3
  12. package/dist/app/data-profile-view.d.ts +1 -1
  13. package/dist/app/run-activity.js +4 -6
  14. package/dist/config/environment-stores.d.ts +4 -2
  15. package/dist/contracts/chat-events.d.ts +14 -2
  16. package/dist/contracts/chat-events.js +1 -1
  17. package/dist/contracts/chat-frame.d.ts +7 -0
  18. package/dist/contracts/chat-frame.js +24 -6
  19. package/dist/contracts/chat-parts.d.ts +73 -2
  20. package/dist/contracts/chat-parts.js +3 -1
  21. package/dist/contracts/index.d.ts +4 -2
  22. package/dist/contracts/index.js +1 -0
  23. package/dist/contracts/part-registry.js +3 -0
  24. package/dist/contracts/schemas/chat-events.d.ts +38 -0
  25. package/dist/contracts/schemas/chat-events.js +8 -0
  26. package/dist/contracts/schemas/chat-parts.d.ts +239 -15
  27. package/dist/contracts/schemas/chat-parts.js +80 -12
  28. package/dist/contracts/schemas/index.d.ts +2 -2
  29. package/dist/contracts/schemas/index.js +2 -2
  30. package/dist/contracts/subagent-activity.d.ts +12 -0
  31. package/dist/contracts/subagent-activity.js +76 -0
  32. package/dist/execution/artifact-metadata.js +1 -3
  33. package/dist/execution/dbos-workflow-purger.d.ts +2 -0
  34. package/dist/execution/dbos-workflow-purger.js +21 -14
  35. package/dist/execution/run-canceler.d.ts +33 -11
  36. package/dist/execution/run-canceler.js +130 -28
  37. package/dist/execution/run-end-record.d.ts +30 -0
  38. package/dist/execution/run-end-record.js +27 -0
  39. package/dist/execution/run-event-parts.d.ts +6 -5
  40. package/dist/execution/run-event-parts.js +6 -5
  41. package/dist/execution/run-event-stream.d.ts +18 -6
  42. package/dist/execution/run-event-stream.js +67 -17
  43. package/dist/execution/run-synthesis.d.ts +21 -0
  44. package/dist/execution/run-synthesis.js +77 -3
  45. package/dist/index.d.ts +28 -10
  46. package/dist/index.js +26 -2
  47. package/dist/lib/hooks.d.ts +1 -1
  48. package/dist/lib/metrics.d.ts +2 -2
  49. package/dist/loop/call-guard.d.ts +50 -0
  50. package/dist/loop/call-guard.js +90 -0
  51. package/dist/loop/compaction.d.ts +5 -0
  52. package/dist/loop/compaction.js +17 -0
  53. package/dist/loop/run-agent.d.ts +9 -0
  54. package/dist/loop/run-agent.js +16 -1
  55. package/dist/loop/run-to-terminal.js +4 -1
  56. package/dist/loop/types.d.ts +8 -0
  57. package/dist/memory/card-builders.d.ts +11 -0
  58. package/dist/memory/card-builders.js +35 -21
  59. package/dist/memory/conversation-display-recorder.d.ts +2 -2
  60. package/dist/memory/conversation-display-recorder.js +38 -4
  61. package/dist/memory/conversation-display-storage.d.ts +9 -2
  62. package/dist/memory/conversation-display-storage.js +18 -3
  63. package/dist/memory/thread-history.d.ts +42 -8
  64. package/dist/memory/thread-history.js +164 -45
  65. package/dist/memory/thread-store.d.ts +13 -0
  66. package/dist/memory/thread-store.js +15 -1
  67. package/dist/prompts/briefing.d.ts +57 -3
  68. package/dist/prompts/briefing.js +129 -2
  69. package/dist/prompts/conversation.d.ts +1 -1
  70. package/dist/prompts/conversation.js +3 -1
  71. package/dist/prompts/planner.js +13 -2
  72. package/dist/provenance/seam.d.ts +39 -20
  73. package/dist/provenance/seam.js +7 -5
  74. package/dist/providers/ai-sdk.js +93 -11
  75. package/dist/providers/types.d.ts +6 -0
  76. package/dist/reference-data/catalog.js +141 -2
  77. package/dist/report-model/authoring-grammar.d.ts +26 -26
  78. package/dist/report-model/pin-snapshot.d.ts +1 -1
  79. package/dist/report-model/pin-snapshot.js +2 -50
  80. package/dist/runtime/assemble.d.ts +8 -1
  81. package/dist/runtime/assemble.js +11 -0
  82. package/dist/runtime/boot.d.ts +3 -0
  83. package/dist/runtime/boot.js +10 -1
  84. package/dist/sandbox/image-packages.d.ts +26 -4
  85. package/dist/sandbox/image-packages.js +18 -4
  86. package/dist/sandbox/sandbox-step-translate.d.ts +23 -0
  87. package/dist/sandbox/sandbox-step-translate.js +24 -0
  88. package/dist/schemas/artifact-manifest.d.ts +1 -1
  89. package/dist/schemas/artifact-manifest.js +11 -9
  90. package/dist/schemas/data-profile-schemas.d.ts +12 -12
  91. package/dist/schemas/plan-schemas.d.ts +75 -21
  92. package/dist/schemas/plan-schemas.js +1 -1
  93. package/dist/schemas/run-synthesis.d.ts +2 -2
  94. package/dist/schemas/workflow-state.d.ts +113 -0
  95. package/dist/schemas/workflow-state.js +54 -0
  96. package/dist/state/analyses-metrics.d.ts +79 -7
  97. package/dist/state/analyses-metrics.js +141 -6
  98. package/dist/state/artifacts.d.ts +66 -3
  99. package/dist/state/artifacts.js +85 -7
  100. package/dist/state/data-profile.d.ts +4 -2
  101. package/dist/state/data-profile.js +7 -5
  102. package/dist/state/index.d.ts +9 -8
  103. package/dist/state/index.js +5 -5
  104. package/dist/state/migrations/20261012120000_index_the_runs_by_start.d.ts +8 -0
  105. package/dist/state/migrations/20261012120000_index_the_runs_by_start.js +12 -0
  106. package/dist/state/migrations/20261013120000_index_the_ended_runs_and_the_recent_threads.d.ts +8 -0
  107. package/dist/state/migrations/20261013120000_index_the_ended_runs_and_the_recent_threads.js +13 -0
  108. package/dist/state/migrations/20261013180000_narrow_the_active_run_index.d.ts +8 -0
  109. package/dist/state/migrations/20261013180000_narrow_the_active_run_index.js +13 -0
  110. package/dist/state/migrations/20261014120000_index_the_plans_by_parent_and_the_runs_by_plan.d.ts +8 -0
  111. package/dist/state/migrations/20261014120000_index_the_plans_by_parent_and_the_runs_by_plan.js +13 -0
  112. package/dist/state/migrations/index.js +8 -0
  113. package/dist/state/plans.d.ts +21 -0
  114. package/dist/state/plans.js +25 -0
  115. package/dist/state/runs.d.ts +79 -14
  116. package/dist/state/runs.js +150 -33
  117. package/dist/state/schema.d.ts +2 -0
  118. package/dist/state/step-executions.d.ts +9 -0
  119. package/dist/state/step-executions.js +22 -0
  120. package/dist/tasks/data-profile-activity.d.ts +7 -1
  121. package/dist/tasks/data-profile-activity.js +18 -9
  122. package/dist/tasks/data-profile.d.ts +15 -1
  123. package/dist/tasks/data-profile.js +16 -11
  124. package/dist/tools/ad-hoc-router.d.ts +2 -0
  125. package/dist/tools/ad-hoc-router.js +18 -2
  126. package/dist/tools/approval/gateway.js +28 -5
  127. package/dist/tools/capability-data.d.ts +36 -0
  128. package/dist/tools/capability-data.js +73 -0
  129. package/dist/tools/display/show-user.d.ts +1 -1
  130. package/dist/tools/execute-analysis.d.ts +80 -1
  131. package/dist/tools/execute-analysis.js +352 -110
  132. package/dist/tools/knowledge/check.d.ts +60 -0
  133. package/dist/tools/knowledge/check.js +92 -0
  134. package/dist/tools/knowledge/client.d.ts +382 -0
  135. package/dist/tools/knowledge/client.js +302 -0
  136. package/dist/tools/knowledge/environment.d.ts +78 -0
  137. package/dist/tools/knowledge/environment.js +105 -0
  138. package/dist/tools/knowledge/index.d.ts +49 -0
  139. package/dist/tools/knowledge/index.js +70 -0
  140. package/dist/tools/knowledge/local-slots.d.ts +62 -0
  141. package/dist/tools/knowledge/local-slots.js +177 -0
  142. package/dist/tools/knowledge/pin.d.ts +14 -0
  143. package/dist/tools/knowledge/pin.js +17 -0
  144. package/dist/tools/knowledge/recommend.d.ts +92 -0
  145. package/dist/tools/knowledge/recommend.js +98 -0
  146. package/dist/tools/knowledge/situation.d.ts +143 -0
  147. package/dist/tools/knowledge/situation.js +164 -0
  148. package/dist/tools/knowledge/skeleton.d.ts +69 -0
  149. package/dist/tools/knowledge/skeleton.js +202 -0
  150. package/dist/tools/knowledge/template.d.ts +137 -0
  151. package/dist/tools/knowledge/template.js +267 -0
  152. package/dist/tools/research/generate-plan.d.ts +23 -0
  153. package/dist/tools/research/generate-plan.js +203 -12
  154. package/dist/tools/research/guarded-address.d.ts +20 -0
  155. package/dist/tools/research/guarded-address.js +148 -0
  156. package/dist/tools/research/inspect-data-profile.d.ts +1 -1
  157. package/dist/tools/research/inspect-run.d.ts +1 -1
  158. package/dist/tools/research/inspect-run.js +7 -7
  159. package/dist/tools/research/searxng-engine.d.ts +40 -0
  160. package/dist/tools/research/searxng-engine.js +120 -0
  161. package/dist/tools/research/web-fetch.d.ts +124 -0
  162. package/dist/tools/research/web-fetch.js +627 -0
  163. package/dist/tools/research/web-search.d.ts +75 -0
  164. package/dist/tools/research/web-search.js +112 -0
  165. package/dist/tools/sandbox/list-available-packages.d.ts +7 -4
  166. package/dist/tools/sandbox/list-available-packages.js +12 -4
  167. package/dist/tools/sandbox/list-available-refs.d.ts +21 -0
  168. package/dist/tools/sandbox/list-available-refs.js +60 -3
  169. package/dist/tools/sandbox/report-blocker.js +5 -1
  170. package/dist/tools/terminal-text.d.ts +11 -0
  171. package/dist/tools/terminal-text.js +19 -0
  172. package/dist/tools/workspace/decision-record.d.ts +81 -0
  173. package/dist/tools/workspace/decision-record.js +117 -0
  174. package/dist/tools/workspace/edit-file.d.ts +3 -1
  175. package/dist/tools/workspace/edit-file.js +20 -2
  176. package/dist/tools/workspace/execute-command.d.ts +17 -0
  177. package/dist/tools/workspace/execute-command.js +28 -1
  178. package/dist/tools/workspace/index.d.ts +1 -0
  179. package/dist/tools/workspace/index.js +1 -0
  180. package/dist/tools/workspace/mutator.d.ts +1 -1
  181. package/dist/workflows/execute-analysis.d.ts +62 -21
  182. package/dist/workflows/execute-analysis.js +307 -79
  183. package/dist/workflows/plan/graph.d.ts +16 -0
  184. package/dist/workflows/plan/graph.js +36 -0
  185. package/dist/workflows/sandbox-step.d.ts +12 -0
  186. package/dist/workflows/sandbox-step.js +14 -12
  187. package/package.json +5 -1
@@ -294,6 +294,30 @@ export const REFERENCE_DATA_CATALOG = deepFreeze(ReferenceDataCatalogSchema.pars
294
294
  },
295
295
  ],
296
296
  },
297
+ {
298
+ // Two species in one table: no organism field, like omnipath-interactions.
299
+ id: "mgi-mouse-human-homology",
300
+ version: "current",
301
+ title: "MGI mouse-human homology classes",
302
+ description: "The Mouse Genome Informatics homology reports: the one-to-one mouse-to-human orthologs of the protein-coding genes, and the full homology classes with the sequence identifiers. MGI rebuilds the reports weekly, so they are verified against what you downloaded rather than a checked-in digest.",
303
+ sourceUrl: "https://www.informatics.jax.org/downloads/reports/index.html",
304
+ license: { identifier: "CC-BY-4.0", url: "https://www.informatics.jax.org/mgihome/other/copyright.shtml" },
305
+ recommendation: { group: "gene-identifiers", recommended: false },
306
+ artifacts: [
307
+ {
308
+ path: "HOM_ProteinCoding.rpt",
309
+ url: "https://www.informatics.jax.org/downloads/reports/HOM_ProteinCoding.rpt",
310
+ format: "tsv",
311
+ contents: "Tab-separated, NO header, about 780 KB, one row per mouse protein-coding gene with a one-to-one human ortholog. Positional columns: 1 MGI accession id, 2 mouse symbol, 3 mouse NCBI gene id, 4 HGNC id, 5 human symbol, 6 human NCBI gene id. The first choice for a mouse-to-human map.",
312
+ },
313
+ {
314
+ path: "HOM_MouseHumanSequence.rpt",
315
+ url: "https://www.informatics.jax.org/downloads/reports/HOM_MouseHumanSequence.rpt",
316
+ format: "tsv",
317
+ contents: "Tab-separated with a header, about 15 MB, one row per gene. The rows that share a 'DB Class Key' are one homology class across the two species, and a class can hold more than one gene of one species. Key columns: 'Common Organism Name' (mouse, laboratory or human), 'NCBI Taxon ID', Symbol, 'EntrezGene ID', 'Mouse MGI ID', 'HGNC ID'. Use it for a gene absent from the one-to-one file, and report the class size.",
318
+ },
319
+ ],
320
+ },
297
321
  {
298
322
  id: "reactome-pathways",
299
323
  version: "current",
@@ -802,7 +826,7 @@ export const REFERENCE_DATA_CATALOG = deepFreeze(ReferenceDataCatalogSchema.pars
802
826
  id: "string-ppi-human",
803
827
  version: "12.0",
804
828
  title: "STRING human protein-protein interaction network",
805
- description: "STRING v12.0 functional protein association network for Homo sapiens: every protein pair with a combined confidence score, the genome-scale graph network-proximity methods measure distances over. Roughly 85 MB across two files — the network itself and the identifier mapping it cannot be read without. Immutable v12.0 release.",
829
+ description: "STRING v12.0 functional protein association network for Homo sapiens: every protein pair with a combined confidence score, the genome-scale graph network-proximity methods measure distances over. Roughly 85 MB across two files — the network itself and the identifier mapping it cannot be read without. For an exact join to an Ensembl-keyed table, add `string-aliases-human`. Immutable v12.0 release.",
806
830
  organism: "human",
807
831
  sourceUrl: "https://string-db.org/cgi/access",
808
832
  license: { identifier: "CC-BY-4.0", url: "https://creativecommons.org/licenses/by/4.0/" },
@@ -818,7 +842,28 @@ export const REFERENCE_DATA_CATALOG = deepFreeze(ReferenceDataCatalogSchema.pars
818
842
  path: "9606.protein.info.v12.0.txt.gz",
819
843
  url: "https://stringdb-downloads.org/download/protein.info.v12.0/9606.protein.info.v12.0.txt.gz",
820
844
  format: "tsv",
821
- contents: "Gzipped TSV, ~19,700 rows, header '#string_protein_id preferred_name protein_size annotation'. Mandatory rather than supplementary: preferred_name is the gene symbol for each STRING id in the links file, and without this join the network cannot be connected to a gene list, a drug-target set, or any other dataset here.",
845
+ contents: "Gzipped TSV, ~19,700 rows, header '#string_protein_id preferred_name protein_size annotation'. Mandatory rather than supplementary: preferred_name is the only name this dataset gives each STRING id of the links file, so without this join the network carries no gene names at all. preferred_name is a symbol, and a symbol join silently drops a renamed gene: for an exact identifier join, add `string-aliases-human` and key on its Ensembl gene id rows instead.",
846
+ },
847
+ ],
848
+ },
849
+ {
850
+ // The companion of string-ppi-human. It is its own dataset because a new
851
+ // artifact on an installed dataset at the same version invalidates the
852
+ // receipt of every existing install and forces a full re-download.
853
+ id: "string-aliases-human",
854
+ version: "12.0",
855
+ title: "STRING human protein aliases",
856
+ description: "The STRING v12.0 alias table for Homo sapiens: every external identifier of each STRING protein, with its source. The companion of `string-ppi-human`: its Ensembl gene id rows give the exact join from the STRING network to a GTEx or a GENCODE table, which the symbol of the info file does not give for a renamed gene. About 20 MB. Immutable v12.0 release.",
857
+ organism: "human",
858
+ sourceUrl: "https://string-db.org/cgi/access",
859
+ license: { identifier: "CC-BY-4.0", url: "https://creativecommons.org/licenses/by/4.0/" },
860
+ recommendation: { group: "interaction-networks", recommended: false },
861
+ artifacts: [
862
+ {
863
+ path: "9606.protein.aliases.v12.0.txt.gz",
864
+ url: "https://stringdb-downloads.org/download/protein.aliases.v12.0/9606.protein.aliases.v12.0.txt.gz",
865
+ format: "tsv",
866
+ contents: "Gzipped TSV, about 20 MB, header '#string_protein_id alias source', many rows per protein. Filter source == 'Ensembl_gene' to get one Ensembl gene id (ENSG) per STRING protein id: the exact join key to a GTEx or a GENCODE table, which the symbol of the info file does not give for a renamed gene.",
822
867
  },
823
868
  ],
824
869
  },
@@ -864,6 +909,100 @@ export const REFERENCE_DATA_CATALOG = deepFreeze(ReferenceDataCatalogSchema.pars
864
909
  },
865
910
  ],
866
911
  },
912
+ {
913
+ id: "impc-phenotyping",
914
+ version: "release-24.0",
915
+ title: "IMPC mouse knockout phenotyping, data release 24.0",
916
+ description: "The International Mouse Phenotyping Consortium data release 24.0 reports: the significant genotype-to-phenotype assertions, the viability calls, and the procedure completeness of each phenotyped colony. Immutable release directory.",
917
+ organism: "mouse",
918
+ sourceUrl: "https://ftp.ebi.ac.uk/pub/databases/impc/all-data-releases/release-24.0/results/",
919
+ license: { identifier: "CC-BY-4.0", url: "https://www.mousephenotype.org/help/faqs/is-impc-data-freely-available/" },
920
+ recommendation: { group: "phenotype-annotations", recommended: false },
921
+ artifacts: [
922
+ {
923
+ path: "genotype-phenotype-assertions-ALL.csv.gz",
924
+ url: "https://ftp.ebi.ac.uk/pub/databases/impc/all-data-releases/release-24.0/results/genotype-phenotype-assertions-ALL.csv.gz",
925
+ format: "csv",
926
+ contents: "Gzipped CSV with a header, about 4.8 MB, one row per significant genotype-phenotype association. Key columns: marker_accession_id (MGI id), marker_symbol, zygosity, top_level_mp_term_id, top_level_mp_term_name, mp_term_id, mp_term_name, p_value, effect_size, resource_name (IMPC, EuroPhenome, MGP, 3i, pwg — matched case-sensitively). zygosity is hemizygote, heterozygote, or homozygote. top_level_mp_term_id holds a comma-separated list on 13,643 of its 67,350 rows, so split it and test membership: equality against MP:0005370 (liver and biliary system) returns 509 rows over 322 genes, membership returns 612 over 351. A gene absent here was either clean or never tested: the completeness file tells which.",
927
+ },
928
+ {
929
+ path: "procedureCompletenessAndPhenotypeHits.csv.gz",
930
+ url: "https://ftp.ebi.ac.uk/pub/databases/impc/all-data-releases/release-24.0/results/procedureCompletenessAndPhenotypeHits.csv.gz",
931
+ format: "csv",
932
+ contents: "Gzipped CSV with a quoted header, about 24 MB, one row per gene, colony, zygosity, and life stage. The '|'-separated columns 'Procedure Stable Id: Successful' and 'Parameter Name: Successful' say what was tested (the clinical chemistry procedure ids share the prefix IMPC_CBC_, with versions such as IMPC_CBC_001, and parameter names written out in full — 'Alanine aminotransferase', 'Aspartate aminotransferase', 'Alkaline phosphatase', 'Total bilirubin' — never abbreviated to ALT or AST); 'Top-level MP Accession Id: Significant' and 'MP Accession Id: Significant' say what was found. 'Life Stage' is one of seven values, 'Early adult' among them, and 'Zygosity' includes hemizygote beside homozygote and heterozygote. The only file that separates a gene tested with no hit from a gene never tested.",
933
+ },
934
+ {
935
+ path: "viability.csv.gz",
936
+ url: "https://ftp.ebi.ac.uk/pub/databases/impc/all-data-releases/release-24.0/results/viability.csv.gz",
937
+ format: "csv",
938
+ contents: "Gzipped CSV with a quoted header, about 470 KB, one row per colony and zygosity. Key columns: 'Gene Accession Id' (MGI id), 'Gene Symbol', 'Zygosity', 'Viability Phenotype HOMs/HEMIs' (lowercase: lethal, subviable, viable), 'Supporting Data' (the long form, for example 'Homozygous - Viable'), 'Viability Call Method' (curated or computed). 'Zygosity' is homozygote or hemizygote, so an X-linked knockout carries a hemizygous call and no homozygous one. One gene can hold different calls on different colonies — 14 genes hold both a lethal and a viable call — so lethal takes precedence over subviable and over viable within one gene.",
939
+ },
940
+ ],
941
+ },
942
+ {
943
+ id: "hpo-annotations",
944
+ version: "2026-09-01",
945
+ title: "Human Phenotype Ontology gene-to-phenotype annotations",
946
+ description: "The HPO release 2026-09-01: the gene-to-phenotype annotation table derived from OMIM and Orphanet, with the ontology file that gives the term hierarchy. Immutable GitHub release assets.",
947
+ organism: "human",
948
+ sourceUrl: "https://github.com/obophenotype/human-phenotype-ontology/releases/tag/v2026-09-01",
949
+ // The HPO license has no SPDX identifier. Its page gives three conditions: cite the
950
+ // HPO Consortium, show the version of each HPO file in a public display, and do not
951
+ // change the files. The installer fetches the files from the upstream and changes
952
+ // nothing; the acknowledgement in a product is the concern of the product.
953
+ license: { identifier: "LicenseRef-HPO", url: "https://hpo.jax.org/app/license" },
954
+ recommendation: { group: "phenotype-annotations", recommended: false },
955
+ artifacts: [
956
+ {
957
+ path: "genes_to_phenotype.txt",
958
+ url: "https://github.com/obophenotype/human-phenotype-ontology/releases/download/v2026-09-01/genes_to_phenotype.txt",
959
+ format: "tsv",
960
+ contents: "Tab-separated with a header, about 20 MB. Columns: ncbi_gene_id (Entrez), gene_symbol, hpo_id, hpo_name, frequency, disease_id (OMIM or ORPHA). One row per gene, term, and disease, thus a gene repeats. The rows carry the annotated terms only, not their ancestors: take the descendant closure of a root term from hp.obo before a filter.",
961
+ },
962
+ {
963
+ path: "hp.obo",
964
+ url: "https://github.com/obophenotype/human-phenotype-ontology/releases/download/v2026-09-01/hp.obo",
965
+ format: "obo",
966
+ contents: "The ontology in OBO format, about 11 MB: one [Term] stanza per HP term with id, name, and is_a parents. Walk the is_a edges to take the descendants of a root term, for example HP:0001392 (Abnormality of the liver) or HP:0004297 (Abnormality of the biliary system).",
967
+ },
968
+ ],
969
+ },
970
+ {
971
+ // Mouse phenotypes keyed on human Ensembl ids: no single organism, like omnipath-interactions.
972
+ id: "opentargets-mouse-phenotype",
973
+ version: "26.09",
974
+ title: "Open Targets mouse model phenotypes mapped to human targets",
975
+ description: "The mouse_phenotype dataset of Open Targets Platform 26.09: the IMPC and the MGI literature phenotypes of mouse models, with the human target that Open Targets mapped each mouse gene to. One zstd parquet part. Immutable release.",
976
+ sourceUrl: "https://ftp.ebi.ac.uk/pub/databases/opentargets/platform/26.09/output/mouse_phenotype/",
977
+ license: { identifier: "CC0-1.0", url: "https://platform-docs.opentargets.org/licence" },
978
+ recommendation: { group: "phenotype-annotations", recommended: false },
979
+ artifacts: [
980
+ {
981
+ path: "mouse_phenotype.parquet",
982
+ url: "https://ftp.ebi.ac.uk/pub/databases/opentargets/platform/26.09/output/mouse_phenotype/part-00000-5e904527-9bf6-4fd5-9fc4-5f272954b1f8-c000.zstd.parquet",
983
+ format: "parquet",
984
+ contents: "Zstd parquet, about 6.5 MB, 203,583 rows, one row per human target, mouse gene, and phenotype term. Columns: targetFromSourceId (human Ensembl gene id), targetInModel (mouse symbol), targetInModelMgiId, targetInModelEnsemblId, modelPhenotypeId (MP id), modelPhenotypeLabel, modelPhenotypeClasses (list of top-level MP id and label), biologicalModels (allele, background, literature). Read with pandas and pyarrow. The mouse-to-human map is the one of Open Targets, which can differ from the MGI homology tables.",
985
+ },
986
+ ],
987
+ },
988
+ {
989
+ id: "opentargets-target-safety-event",
990
+ version: "26.09",
991
+ title: "Open Targets target safety events",
992
+ description: "The target_safety_event dataset of Open Targets Platform 26.09: curated safety liabilities per target from the published panels, ToxCast, AOP-Wiki, and ClinPGx, each with the organ or tissue of the event. One zstd parquet part. Immutable release.",
993
+ organism: "human",
994
+ sourceUrl: "https://ftp.ebi.ac.uk/pub/databases/opentargets/platform/26.09/output/target_safety_event/",
995
+ license: { identifier: "CC0-1.0", url: "https://platform-docs.opentargets.org/licence" },
996
+ recommendation: { group: "phenotype-annotations", recommended: false },
997
+ artifacts: [
998
+ {
999
+ path: "target_safety_event.parquet",
1000
+ url: "https://ftp.ebi.ac.uk/pub/databases/opentargets/platform/26.09/output/target_safety_event/part-00000-e457d966-d50e-4afc-841d-547765a1e4d7-c000.zstd.parquet",
1001
+ format: "parquet",
1002
+ contents: "Zstd parquet, about 120 KB, 4,387 rows, one row per target and safety event. Columns: targetId (Ensembl gene id), event, eventId (EFO), effects (direction, dosing), biosamples (tissueLabel, tissueId as UBERON, cell fields), datasource, literature (PMID), studies. biosamples is null on 1,786 rows, so guard the test. tissueId carries one term in two spellings — UBERON_0002107 on 74 rows, UBERON:0002107 on 6 — and event is free text in mixed case ('Hepatotoxicity', 'Increased, Liver Steatosis'), so match both spellings and ignore case: a liver filter then flags 88 targets rather than 57. The sources are curated panels, not an exhaustive list: absence is not safety.",
1003
+ },
1004
+ ],
1005
+ },
867
1006
  {
868
1007
  id: "celltypist-immune",
869
1008
  version: "2",
@@ -38,9 +38,10 @@ declare const AUTHORING_ATOM_SCHEMAS: readonly [z.ZodObject<{
38
38
  }, z.core.$strict>;
39
39
  bindings: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
40
40
  format: z.ZodOptional<z.ZodString>;
41
- kind: z.ZodLiteral<"artifact-value">;
42
41
  path: z.ZodString;
42
+ kind: z.ZodLiteral<"artifact-value">;
43
43
  unit: z.ZodOptional<z.ZodString>;
44
+ snapshot: z.ZodOptional<z.ZodString>;
44
45
  locator: z.ZodObject<{
45
46
  column: z.ZodString;
46
47
  rowFilter: z.ZodOptional<z.ZodObject<{
@@ -55,12 +56,12 @@ declare const AUTHORING_ATOM_SCHEMAS: readonly [z.ZodObject<{
55
56
  tolerance: z.ZodOptional<z.ZodNumber>;
56
57
  }, z.core.$strict>>;
57
58
  run: z.ZodOptional<z.ZodString>;
58
- snapshot: z.ZodOptional<z.ZodString>;
59
59
  }, z.core.$strict>, z.ZodObject<{
60
60
  format: z.ZodOptional<z.ZodString>;
61
- kind: z.ZodLiteral<"artifact-table">;
62
61
  path: z.ZodString;
62
+ kind: z.ZodLiteral<"artifact-table">;
63
63
  unit: z.ZodOptional<z.ZodString>;
64
+ snapshot: z.ZodOptional<z.ZodString>;
64
65
  rowBound: z.ZodOptional<z.ZodObject<{
65
66
  column: z.ZodString;
66
67
  count: z.ZodNumber;
@@ -79,14 +80,13 @@ declare const AUTHORING_ATOM_SCHEMAS: readonly [z.ZodObject<{
79
80
  }>>>;
80
81
  columnLabels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
81
82
  run: z.ZodOptional<z.ZodString>;
82
- snapshot: z.ZodOptional<z.ZodString>;
83
83
  }, z.core.$strict>, z.ZodObject<{
84
84
  format: z.ZodOptional<z.ZodString>;
85
- kind: z.ZodLiteral<"artifact-file">;
86
85
  path: z.ZodString;
86
+ kind: z.ZodLiteral<"artifact-file">;
87
87
  unit: z.ZodOptional<z.ZodString>;
88
- run: z.ZodOptional<z.ZodString>;
89
88
  snapshot: z.ZodOptional<z.ZodString>;
89
+ run: z.ZodOptional<z.ZodString>;
90
90
  }, z.core.$strict>, z.ZodObject<{
91
91
  unit: z.ZodOptional<z.ZodString>;
92
92
  format: z.ZodOptional<z.ZodString>;
@@ -102,9 +102,10 @@ declare const AUTHORING_ATOM_SCHEMAS: readonly [z.ZodObject<{
102
102
  }, z.core.$strict>>;
103
103
  inputs: z.ZodArray<z.ZodObject<{
104
104
  format: z.ZodOptional<z.ZodString>;
105
- kind: z.ZodLiteral<"artifact-value">;
106
105
  path: z.ZodString;
106
+ kind: z.ZodLiteral<"artifact-value">;
107
107
  unit: z.ZodOptional<z.ZodString>;
108
+ snapshot: z.ZodOptional<z.ZodString>;
108
109
  locator: z.ZodObject<{
109
110
  column: z.ZodString;
110
111
  rowFilter: z.ZodOptional<z.ZodObject<{
@@ -119,7 +120,6 @@ declare const AUTHORING_ATOM_SCHEMAS: readonly [z.ZodObject<{
119
120
  tolerance: z.ZodOptional<z.ZodNumber>;
120
121
  }, z.core.$strict>>;
121
122
  run: z.ZodOptional<z.ZodString>;
122
- snapshot: z.ZodOptional<z.ZodString>;
123
123
  }, z.core.$strict>>;
124
124
  }, z.core.$strict>, z.ZodObject<{
125
125
  unit: z.ZodOptional<z.ZodString>;
@@ -142,9 +142,10 @@ declare const AUTHORING_ATOM_SCHEMAS: readonly [z.ZodObject<{
142
142
  label: z.ZodString;
143
143
  value: z.ZodDiscriminatedUnion<[z.ZodObject<{
144
144
  format: z.ZodOptional<z.ZodString>;
145
- kind: z.ZodLiteral<"artifact-value">;
146
145
  path: z.ZodString;
146
+ kind: z.ZodLiteral<"artifact-value">;
147
147
  unit: z.ZodOptional<z.ZodString>;
148
+ snapshot: z.ZodOptional<z.ZodString>;
148
149
  locator: z.ZodObject<{
149
150
  column: z.ZodString;
150
151
  rowFilter: z.ZodOptional<z.ZodObject<{
@@ -159,7 +160,6 @@ declare const AUTHORING_ATOM_SCHEMAS: readonly [z.ZodObject<{
159
160
  tolerance: z.ZodOptional<z.ZodNumber>;
160
161
  }, z.core.$strict>>;
161
162
  run: z.ZodOptional<z.ZodString>;
162
- snapshot: z.ZodOptional<z.ZodString>;
163
163
  }, z.core.$strict>, z.ZodObject<{
164
164
  unit: z.ZodOptional<z.ZodString>;
165
165
  format: z.ZodOptional<z.ZodString>;
@@ -175,9 +175,10 @@ declare const AUTHORING_ATOM_SCHEMAS: readonly [z.ZodObject<{
175
175
  }, z.core.$strict>>;
176
176
  inputs: z.ZodArray<z.ZodObject<{
177
177
  format: z.ZodOptional<z.ZodString>;
178
- kind: z.ZodLiteral<"artifact-value">;
179
178
  path: z.ZodString;
179
+ kind: z.ZodLiteral<"artifact-value">;
180
180
  unit: z.ZodOptional<z.ZodString>;
181
+ snapshot: z.ZodOptional<z.ZodString>;
181
182
  locator: z.ZodObject<{
182
183
  column: z.ZodString;
183
184
  rowFilter: z.ZodOptional<z.ZodObject<{
@@ -192,7 +193,6 @@ declare const AUTHORING_ATOM_SCHEMAS: readonly [z.ZodObject<{
192
193
  tolerance: z.ZodOptional<z.ZodNumber>;
193
194
  }, z.core.$strict>>;
194
195
  run: z.ZodOptional<z.ZodString>;
195
- snapshot: z.ZodOptional<z.ZodString>;
196
196
  }, z.core.$strict>>;
197
197
  }, z.core.$strict>], "kind">;
198
198
  }, z.core.$strict>, z.ZodObject<{
@@ -202,9 +202,10 @@ declare const AUTHORING_ATOM_SCHEMAS: readonly [z.ZodObject<{
202
202
  caption: z.ZodOptional<z.ZodString>;
203
203
  binding: z.ZodObject<{
204
204
  format: z.ZodOptional<z.ZodString>;
205
- kind: z.ZodLiteral<"artifact-table">;
206
205
  path: z.ZodString;
206
+ kind: z.ZodLiteral<"artifact-table">;
207
207
  unit: z.ZodOptional<z.ZodString>;
208
+ snapshot: z.ZodOptional<z.ZodString>;
208
209
  rowBound: z.ZodOptional<z.ZodObject<{
209
210
  column: z.ZodString;
210
211
  count: z.ZodNumber;
@@ -223,14 +224,14 @@ declare const AUTHORING_ATOM_SCHEMAS: readonly [z.ZodObject<{
223
224
  }>>>;
224
225
  columnLabels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
225
226
  run: z.ZodOptional<z.ZodString>;
226
- snapshot: z.ZodOptional<z.ZodString>;
227
227
  }, z.core.$strict>;
228
228
  }, z.core.$strict>, z.ZodObject<{
229
229
  binding: z.ZodObject<{
230
230
  format: z.ZodOptional<z.ZodString>;
231
- kind: z.ZodLiteral<"artifact-table">;
232
231
  path: z.ZodString;
232
+ kind: z.ZodLiteral<"artifact-table">;
233
233
  unit: z.ZodOptional<z.ZodString>;
234
+ snapshot: z.ZodOptional<z.ZodString>;
234
235
  rowBound: z.ZodOptional<z.ZodObject<{
235
236
  column: z.ZodString;
236
237
  count: z.ZodNumber;
@@ -249,15 +250,15 @@ declare const AUTHORING_ATOM_SCHEMAS: readonly [z.ZodObject<{
249
250
  }>>>;
250
251
  columnLabels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
251
252
  run: z.ZodOptional<z.ZodString>;
252
- snapshot: z.ZodOptional<z.ZodString>;
253
253
  }, z.core.$strict>;
254
254
  statistics: z.ZodOptional<z.ZodArray<z.ZodObject<{
255
255
  label: z.ZodString;
256
256
  value: z.ZodObject<{
257
257
  format: z.ZodOptional<z.ZodString>;
258
- kind: z.ZodLiteral<"artifact-value">;
259
258
  path: z.ZodString;
259
+ kind: z.ZodLiteral<"artifact-value">;
260
260
  unit: z.ZodOptional<z.ZodString>;
261
+ snapshot: z.ZodOptional<z.ZodString>;
261
262
  locator: z.ZodObject<{
262
263
  column: z.ZodString;
263
264
  rowFilter: z.ZodOptional<z.ZodObject<{
@@ -272,7 +273,6 @@ declare const AUTHORING_ATOM_SCHEMAS: readonly [z.ZodObject<{
272
273
  tolerance: z.ZodOptional<z.ZodNumber>;
273
274
  }, z.core.$strict>>;
274
275
  run: z.ZodOptional<z.ZodString>;
275
- snapshot: z.ZodOptional<z.ZodString>;
276
276
  }, z.core.$strict>;
277
277
  }, z.core.$strict>>>;
278
278
  track: z.ZodOptional<z.ZodObject<{
@@ -282,9 +282,10 @@ declare const AUTHORING_ATOM_SCHEMAS: readonly [z.ZodObject<{
282
282
  length: z.ZodOptional<z.ZodString>;
283
283
  binding: z.ZodObject<{
284
284
  format: z.ZodOptional<z.ZodString>;
285
- kind: z.ZodLiteral<"artifact-table">;
286
285
  path: z.ZodString;
286
+ kind: z.ZodLiteral<"artifact-table">;
287
287
  unit: z.ZodOptional<z.ZodString>;
288
+ snapshot: z.ZodOptional<z.ZodString>;
288
289
  rowBound: z.ZodOptional<z.ZodObject<{
289
290
  column: z.ZodString;
290
291
  count: z.ZodNumber;
@@ -303,7 +304,6 @@ declare const AUTHORING_ATOM_SCHEMAS: readonly [z.ZodObject<{
303
304
  }>>>;
304
305
  columnLabels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
305
306
  run: z.ZodOptional<z.ZodString>;
306
- snapshot: z.ZodOptional<z.ZodString>;
307
307
  }, z.core.$strict>;
308
308
  }, z.core.$strict>>;
309
309
  trees: z.ZodOptional<z.ZodObject<{
@@ -313,9 +313,10 @@ declare const AUTHORING_ATOM_SCHEMAS: readonly [z.ZodObject<{
313
313
  height: z.ZodString;
314
314
  binding: z.ZodObject<{
315
315
  format: z.ZodOptional<z.ZodString>;
316
- kind: z.ZodLiteral<"artifact-table">;
317
316
  path: z.ZodString;
317
+ kind: z.ZodLiteral<"artifact-table">;
318
318
  unit: z.ZodOptional<z.ZodString>;
319
+ snapshot: z.ZodOptional<z.ZodString>;
319
320
  rowBound: z.ZodOptional<z.ZodObject<{
320
321
  column: z.ZodString;
321
322
  count: z.ZodNumber;
@@ -334,7 +335,6 @@ declare const AUTHORING_ATOM_SCHEMAS: readonly [z.ZodObject<{
334
335
  }>>>;
335
336
  columnLabels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
336
337
  run: z.ZodOptional<z.ZodString>;
337
- snapshot: z.ZodOptional<z.ZodString>;
338
338
  }, z.core.$strict>;
339
339
  }, z.core.$strict>>;
340
340
  y: z.ZodOptional<z.ZodObject<{
@@ -343,9 +343,10 @@ declare const AUTHORING_ATOM_SCHEMAS: readonly [z.ZodObject<{
343
343
  height: z.ZodString;
344
344
  binding: z.ZodObject<{
345
345
  format: z.ZodOptional<z.ZodString>;
346
- kind: z.ZodLiteral<"artifact-table">;
347
346
  path: z.ZodString;
347
+ kind: z.ZodLiteral<"artifact-table">;
348
348
  unit: z.ZodOptional<z.ZodString>;
349
+ snapshot: z.ZodOptional<z.ZodString>;
349
350
  rowBound: z.ZodOptional<z.ZodObject<{
350
351
  column: z.ZodString;
351
352
  count: z.ZodNumber;
@@ -364,7 +365,6 @@ declare const AUTHORING_ATOM_SCHEMAS: readonly [z.ZodObject<{
364
365
  }>>>;
365
366
  columnLabels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
366
367
  run: z.ZodOptional<z.ZodString>;
367
- snapshot: z.ZodOptional<z.ZodString>;
368
368
  }, z.core.$strict>;
369
369
  }, z.core.$strict>>;
370
370
  }, z.core.$strict>>;
@@ -817,11 +817,11 @@ declare const AUTHORING_ATOM_SCHEMAS: readonly [z.ZodObject<{
817
817
  caption: z.ZodOptional<z.ZodString>;
818
818
  binding: z.ZodObject<{
819
819
  format: z.ZodOptional<z.ZodString>;
820
- kind: z.ZodLiteral<"artifact-file">;
821
820
  path: z.ZodString;
821
+ kind: z.ZodLiteral<"artifact-file">;
822
822
  unit: z.ZodOptional<z.ZodString>;
823
- run: z.ZodOptional<z.ZodString>;
824
823
  snapshot: z.ZodOptional<z.ZodString>;
824
+ run: z.ZodOptional<z.ZodString>;
825
825
  }, z.core.$strict>;
826
826
  }, z.core.$strict>, z.ZodObject<{
827
827
  kind: z.ZodLiteral<"citation">;
@@ -18,7 +18,7 @@
18
18
  */
19
19
  import { type Result } from "neverthrow";
20
20
  import type { Querier } from "../state/db.js";
21
- import { type ResolveWorkspaceRoot } from "../workspace/paths.js";
21
+ import type { ResolveWorkspaceRoot } from "../workspace/paths.js";
22
22
  import type { ReportSnapshot } from "./reference-resolver.js";
23
23
  /**
24
24
  * The reason that the pin gave no snapshot. The ledger read and the run listing are the two operations
@@ -17,54 +17,11 @@
17
17
  * keeps the membership role, thus the record map is optional and it changes no resolution.
18
18
  */
19
19
  import { err, ok } from "neverthrow";
20
- import { open } from "node:fs/promises";
21
- import { join } from "node:path";
22
- import { tryFs } from "../lib/fs-result.js";
20
+ import { readSynthesisText } from "../execution/run-synthesis.js";
23
21
  import { queryAnalysisArtifacts } from "../state/artifacts.js";
24
22
  import { queryRunsByAnalysis } from "../state/runs.js";
25
- import { isSafeId, runDir } from "../workspace/paths.js";
26
- /** The file name of the synthesis record inside the run directory. */
27
- const SYNTHESIS_FILE = "synthesis.json";
28
- /**
29
- * The cap of one synthesis read. A synthesis record is small by construction, and the cap bounds the
30
- * cost of a file that is not. A file over the cap gives no key, because a cut JSON text cannot parse.
31
- */
32
- const SYNTHESIS_CAP_BYTES = 1024 * 1024;
33
23
  /** The page size of the run listing. The listing walks the pages until a short page ends the walk. */
34
24
  const RUN_PAGE_SIZE = 200;
35
- /**
36
- * Read a synthesis record under the cap, or give `undefined` when the bytes do not come back.
37
- *
38
- * The read takes a bounded byte window, thus a file of any size costs the cap. An absent file, a genuine
39
- * read fault, and a file over the cap each give `undefined`, because the collection reports no error for
40
- * one record.
41
- */
42
- async function readSynthesisText(absolute) {
43
- return tryFs("pinReportSnapshot.readSynthesis", async () => {
44
- const handle = await open(absolute, "r");
45
- try {
46
- // The window takes one byte more than the cap. A read that fills it states that the file
47
- // holds more bytes than the cap admits, thus the two conditions stay apart.
48
- const buffer = Buffer.alloc(SYNTHESIS_CAP_BYTES + 1);
49
- // One read of a network-backed file can give fewer bytes than the window holds. Such a
50
- // short read cuts the text in the middle of the JSON, and the record then parses to no
51
- // key at all. Thus the loop reads again from the offset that the last read reached, and
52
- // it stops when the window fills or when a read gives no byte.
53
- let filled = 0;
54
- while (filled < buffer.length) {
55
- const { bytesRead } = await handle.read(buffer, filled, buffer.length - filled, filled);
56
- if (bytesRead === 0) {
57
- break;
58
- }
59
- filled += bytesRead;
60
- }
61
- return filled > SYNTHESIS_CAP_BYTES ? undefined : buffer.subarray(0, filled).toString("utf8");
62
- }
63
- finally {
64
- await handle.close();
65
- }
66
- }, { path: absolute, onAbsent: () => undefined }).unwrapOr(undefined);
67
- }
68
25
  /** The trimmed text of a field, or `undefined` when the field is not a non-empty string. */
69
26
  function trimmedText(value) {
70
27
  if (typeof value !== "string") {
@@ -181,12 +138,7 @@ async function collectCitations(pool, resolveWorkspaceRoot, analysisId) {
181
138
  return err({ kind: "run-listing-failed", cause: page.error.cause });
182
139
  }
183
140
  for (const run of page.value) {
184
- // The path builder refuses an id that can escape the run tree. A refusal is a throw, thus
185
- // the guard keeps the collection on the value channel.
186
- if (!isSafeId(run.runId)) {
187
- continue;
188
- }
189
- const text = await readSynthesisText(join(root, runDir(run.runId), SYNTHESIS_FILE));
141
+ const text = await readSynthesisText({ workspaceRoot: root, runId: run.runId });
190
142
  if (text === undefined) {
191
143
  continue;
192
144
  }
@@ -14,8 +14,9 @@
14
14
  * `applicationVersion` stamp because all registration happens in this one call,
15
15
  * before launch — a blue/green drain treats them as a single cohort.
16
16
  */
17
- import { type Result } from "neverthrow";
17
+ import { type Result, type ResultAsync } from "neverthrow";
18
18
  import { type ConversationAgentDeps } from "../agents/conversation-agent.js";
19
+ import { type ApprovePlanInput, type ApprovePlanRefusal, type PlanApproval } from "../app/approve-plan.js";
19
20
  import { type ReportSessionRuntime } from "../app/report-session-runtime.js";
20
21
  import type { UsageRecorder } from "../billing/usage-recorder.js";
21
22
  import type { ResourcePolicy } from "../config/resource-limits.js";
@@ -235,6 +236,12 @@ export interface CoreRuntime {
235
236
  readonly reportSession: Pick<ReportSessionRuntime, "ensureSessionState">;
236
237
  readonly workflows: RegisteredWorkflows;
237
238
  readonly citationResolver: CitationResolver;
239
+ /**
240
+ * Approve a stored plan by its id and start its run with no model call. It runs over the deps that
241
+ * reach the `execute_analysis` tool of the conversation agent, thus the approval and the tool launch
242
+ * a plan the same way.
243
+ */
244
+ readonly approvePlan: (input: ApprovePlanInput) => ResultAsync<PlanApproval, ApprovePlanRefusal>;
238
245
  }
239
246
  /**
240
247
  * The eyes of the composition, or none.
@@ -17,6 +17,7 @@
17
17
  import { err, ok } from "neverthrow";
18
18
  import { createConversationAgent } from "../agents/conversation-agent.js";
19
19
  import { createReportSessionAgent } from "../agents/report-session-agent.js";
20
+ import { approvePlan } from "../app/approve-plan.js";
20
21
  import { createReportSessionRuntime } from "../app/report-session-runtime.js";
21
22
  import { createNoopUsageRecorder } from "../billing/noop-usage-recorder.js";
22
23
  import { hasBrowserUrl } from "../lib/chrome.js";
@@ -210,5 +211,15 @@ export function assembleCoreRuntime(deps) {
210
211
  deriveTableExec,
211
212
  },
212
213
  citationResolver,
214
+ approvePlan: (input) => approvePlan({
215
+ pool: conversation.pool,
216
+ executeAnalysisWorkflow: executeAnalysis,
217
+ runAuthorizer: conversation.runAuthorizer,
218
+ runLauncher: conversation.runLauncher,
219
+ ...(resourcePolicy ? { resourcePolicy } : {}),
220
+ ...(conversation.extendAnalysisFarm ? { extendAnalysisFarm: conversation.extendAnalysisFarm } : {}),
221
+ ...(conversation.logger ? { logger: conversation.logger } : {}),
222
+ ...(deps.provenance ? { provenance: deps.provenance } : {}),
223
+ }, input),
213
224
  };
214
225
  }
@@ -25,6 +25,9 @@
25
25
  * legacy-workflow reap, an agent-switch install). Runs after registration
26
26
  * so it may close over the registered callables.
27
27
  * 7. `launchDbos(...)` — the last registration-dependent step.
28
+ * 8. `reconcileOrphanedRuns(pool)` — fails each `running` run whose workflow never started. It runs
29
+ * after launch, thus a workflow that recovery re-queued counts as started. A failure is logged and does
30
+ * not stop the boot, because the repair only frees the slot of a plan.
28
31
  *
29
32
  * No step reads or rewrites stored conversation display. A boot that validated
30
33
  * every `messages` row is what let a single retired part key fail startup for a
@@ -25,6 +25,9 @@
25
25
  * legacy-workflow reap, an agent-switch install). Runs after registration
26
26
  * so it may close over the registered callables.
27
27
  * 7. `launchDbos(...)` — the last registration-dependent step.
28
+ * 8. `reconcileOrphanedRuns(pool)` — fails each `running` run whose workflow never started. It runs
29
+ * after launch, thus a workflow that recovery re-queued counts as started. A failure is logged and does
30
+ * not stop the boot, because the repair only frees the slot of a plan.
28
31
  *
29
32
  * No step reads or rewrites stored conversation display. A boot that validated
30
33
  * every `messages` row is what let a single retired part key fail startup for a
@@ -38,6 +41,7 @@
38
41
  import { SANDBOX_AGENT_META } from "../agents/sandbox/index.js";
39
42
  import { validateAgentSkills } from "../agents/sandbox/validate-skills.js";
40
43
  import { initCortexState } from "../state/init.js";
44
+ import { reconcileOrphanedRuns } from "../state/runs.js";
41
45
  import { assembleCoreRuntime } from "./assemble.js";
42
46
  import { assertConnectionBudget } from "./connection-budget.js";
43
47
  import { launchDbos, shutdownDbos } from "./dbos.js";
@@ -56,7 +60,12 @@ export async function bootHarness(deps) {
56
60
  const runtime = assembleCoreRuntime(core);
57
61
  await deps.beforeLaunch?.();
58
62
  await launchDbos({ config: deps.dbos, logger });
59
- logger.named("boot").info("harness booted", { executorId: deps.dbos.executorId });
63
+ const bootLog = logger.named("boot");
64
+ (await reconcileOrphanedRuns(pool)).match((runIds) => {
65
+ if (runIds.length > 0)
66
+ bootLog.warn("failed the runs whose workflow never started", { runIds });
67
+ }, (error) => bootLog.warn("the repair of the orphaned runs failed", bootLog.errorFields(error)));
68
+ bootLog.info("harness booted", { executorId: deps.dbos.executorId });
60
69
  const shutdown = (signal) => runShutdownSequence({
61
70
  signal,
62
71
  logger,
@@ -1,9 +1,11 @@
1
1
  /**
2
2
  * `image-packages.json` — the self-description of the sandbox image.
3
3
  *
4
- * The image bakes two package tracks that the content-addressed store cannot
5
- * hold: the conda tools at `/opt/conda` and the Node packages at `/opt/node`.
6
- * The image writes one record of them at `/opt/inflexa/image-packages.json`,
4
+ * The image bakes the package tracks that the content-addressed store cannot
5
+ * hold: the conda tools at `/opt/conda`, the Node packages at `/opt/node`,
6
+ * and the R packages that ship with the R runtime (the base and the
7
+ * recommended packages, which no farm lock lists). The image writes one
8
+ * record of them at `/opt/inflexa/image-packages.json`,
7
9
  * and the catalog build copies that record verbatim into the root of the
8
10
  * package store it packed beside it. Thus every reader of a store learns the
9
11
  * image inventory from the store alone — with no container engine, no
@@ -57,10 +59,22 @@ export declare const ImageNodePackageSchema: z.ZodObject<{
57
59
  name: z.ZodString;
58
60
  version: z.ZodString;
59
61
  }, z.core.$loose>;
62
+ /** One R package that ships with the R runtime of the image: a base package or a recommended package. */
63
+ export declare const ImageRBasePackageSchema: z.ZodObject<{
64
+ name: z.ZodString;
65
+ version: z.ZodString;
66
+ priority: z.ZodEnum<{
67
+ base: "base";
68
+ recommended: "recommended";
69
+ }>;
70
+ }, z.core.$loose>;
60
71
  /**
61
72
  * `image-packages.json` at schema version 1. The keys `system_tools` and
62
73
  * `node` are the keys of the image manifest, thus one name means one track
63
- * across the build and the reader.
74
+ * across the build and the reader. `r_base` is the track of the R runtime
75
+ * itself: the packages R ships, which no manifest names and no farm lock
76
+ * lists. It is optional, because a record from before the field existed is
77
+ * still a valid record of its image.
64
78
  */
65
79
  export declare const ImagePackagesSchema: z.ZodObject<{
66
80
  schema: z.ZodLiteral<1>;
@@ -86,6 +100,14 @@ export declare const ImagePackagesSchema: z.ZodObject<{
86
100
  name: z.ZodString;
87
101
  version: z.ZodString;
88
102
  }, z.core.$loose>>;
103
+ r_base: z.ZodOptional<z.ZodArray<z.ZodObject<{
104
+ name: z.ZodString;
105
+ version: z.ZodString;
106
+ priority: z.ZodEnum<{
107
+ base: "base";
108
+ recommended: "recommended";
109
+ }>;
110
+ }, z.core.$loose>>>;
89
111
  }, z.core.$loose>;
90
112
  export type ImagePackages = z.infer<typeof ImagePackagesSchema>;
91
113
  export type ImagePackagesError = {