@inflexa-ai/harness 0.16.0 → 0.18.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 (295) hide show
  1. package/dist/agents/conversation-agent.d.ts +3 -0
  2. package/dist/agents/conversation-agent.js +5 -2
  3. package/dist/agents/report-builder.d.ts +2 -0
  4. package/dist/agents/report-builder.js +2 -0
  5. package/dist/agents/sandbox/shared.d.ts +3 -0
  6. package/dist/agents/sandbox/shared.js +5 -0
  7. package/dist/agents/sandbox/types.d.ts +1 -1
  8. package/dist/app/chat-turn.d.ts +2 -0
  9. package/dist/app/chat-turn.js +11 -2
  10. package/dist/app/spawn-report-session.d.ts +85 -0
  11. package/dist/app/spawn-report-session.js +83 -0
  12. package/dist/app/synthesize-run.d.ts +3 -0
  13. package/dist/app/synthesize-run.js +2 -1
  14. package/dist/citations/__fixtures__/resolver.d.ts +3 -0
  15. package/dist/citations/__fixtures__/resolver.js +9 -0
  16. package/dist/citations/aggregate.d.ts +3 -0
  17. package/dist/citations/aggregate.js +44 -0
  18. package/dist/citations/clients/arxiv.d.ts +6 -0
  19. package/dist/citations/clients/arxiv.js +34 -0
  20. package/dist/citations/clients/common.d.ts +11 -0
  21. package/dist/citations/clients/common.js +43 -0
  22. package/dist/citations/clients/crossref.d.ts +8 -0
  23. package/dist/citations/clients/crossref.js +98 -0
  24. package/dist/citations/clients/doi-registry.d.ts +3 -0
  25. package/dist/citations/clients/doi-registry.js +95 -0
  26. package/dist/citations/clients/pubmed.d.ts +6 -0
  27. package/dist/citations/clients/pubmed.js +83 -0
  28. package/dist/citations/clients/semantic-scholar.d.ts +6 -0
  29. package/dist/citations/clients/semantic-scholar.js +60 -0
  30. package/dist/citations/compare.d.ts +9 -0
  31. package/dist/citations/compare.js +72 -0
  32. package/dist/citations/match.d.ts +11 -0
  33. package/dist/citations/match.js +173 -0
  34. package/dist/citations/normalize.d.ts +31 -0
  35. package/dist/citations/normalize.js +187 -0
  36. package/dist/citations/plan.d.ts +2 -0
  37. package/dist/citations/plan.js +59 -0
  38. package/dist/citations/resolve.d.ts +28 -0
  39. package/dist/citations/resolve.js +238 -0
  40. package/dist/citations/types.d.ts +583 -0
  41. package/dist/citations/types.js +129 -0
  42. package/dist/contracts/chat-events.d.ts +9 -0
  43. package/dist/contracts/index.d.ts +6 -2
  44. package/dist/contracts/index.js +3 -1
  45. package/dist/contracts/organ-system.d.ts +49 -0
  46. package/dist/contracts/organ-system.js +67 -0
  47. package/dist/contracts/report-blocks.d.ts +564 -0
  48. package/dist/contracts/report-blocks.js +117 -0
  49. package/dist/contracts/report-reference.d.ts +459 -0
  50. package/dist/contracts/report-reference.js +256 -0
  51. package/dist/contracts/schemas/chat-events.d.ts +2 -0
  52. package/dist/contracts/schemas/chat-events.js +2 -0
  53. package/dist/contracts/schemas/chat-parts.d.ts +8 -8
  54. package/dist/contracts/severity.d.ts +15 -0
  55. package/dist/contracts/severity.js +10 -0
  56. package/dist/contracts/target-dossier.d.ts +8673 -12970
  57. package/dist/contracts/target-dossier.js +534 -591
  58. package/dist/data/safety-panel-schema.d.ts +18 -5
  59. package/dist/data/safety-panel-schema.js +4 -4
  60. package/dist/execution/artifact-metadata.js +1 -0
  61. package/dist/execution/report-runner.js +1 -3
  62. package/dist/execution/run-synthesis.d.ts +3 -0
  63. package/dist/execution/run-synthesis.js +3 -0
  64. package/dist/index.d.ts +12 -1
  65. package/dist/index.js +22 -0
  66. package/dist/lib/async-utils.d.ts +16 -4
  67. package/dist/lib/async-utils.js +20 -15
  68. package/dist/lib/cache.d.ts +8 -0
  69. package/dist/lib/cache.js +35 -0
  70. package/dist/lib/host-concurrency.js +1 -0
  71. package/dist/lib/rate-limit.d.ts +35 -0
  72. package/dist/lib/rate-limit.js +121 -0
  73. package/dist/literature/sources/arxiv.d.ts +22 -0
  74. package/dist/literature/sources/arxiv.js +103 -0
  75. package/dist/literature/sources/http.d.ts +28 -0
  76. package/dist/literature/sources/http.js +97 -0
  77. package/dist/literature/sources/pubmed.d.ts +68 -0
  78. package/dist/literature/sources/pubmed.js +266 -0
  79. package/dist/literature/sources/semantic-scholar.d.ts +24 -0
  80. package/dist/literature/sources/semantic-scholar.js +71 -0
  81. package/dist/loop/__fixtures__/scripted-provider.js +23 -2
  82. package/dist/loop/run-agent.js +58 -10
  83. package/dist/loop/tool-detail.d.ts +40 -0
  84. package/dist/loop/tool-detail.js +35 -3
  85. package/dist/loop/types.d.ts +13 -0
  86. package/dist/memory/thread-history.d.ts +10 -0
  87. package/dist/memory/thread-history.js +12 -1
  88. package/dist/memory/thread-store.d.ts +142 -25
  89. package/dist/memory/thread-store.js +228 -40
  90. package/dist/prompts/literature-reviewer.d.ts +1 -1
  91. package/dist/prompts/literature-reviewer.js +2 -0
  92. package/dist/prompts/target-assessment/briefs/executive-recommendation.d.ts +1 -1
  93. package/dist/prompts/target-assessment/briefs/executive-recommendation.js +5 -5
  94. package/dist/prompts/target-assessment/briefs/liability-bullets.d.ts +1 -1
  95. package/dist/prompts/target-assessment/briefs/liability-bullets.js +1 -1
  96. package/dist/prompts/target-assessment/briefs/target-organ-liabilities.d.ts +1 -1
  97. package/dist/prompts/target-assessment/briefs/target-organ-liabilities.js +11 -3
  98. package/dist/prompts/target-assessment/investigation/adversarial-critique.d.ts +1 -0
  99. package/dist/prompts/target-assessment/investigation/adversarial-critique.js +67 -0
  100. package/dist/prompts/target-assessment/investigation/claim-reverification.d.ts +1 -0
  101. package/dist/prompts/target-assessment/investigation/claim-reverification.js +49 -0
  102. package/dist/prompts/target-assessment/investigation/index.d.ts +3 -0
  103. package/dist/prompts/target-assessment/investigation/index.js +3 -0
  104. package/dist/prompts/target-assessment/investigation/mechanism-proposal.d.ts +1 -0
  105. package/dist/prompts/target-assessment/investigation/mechanism-proposal.js +49 -0
  106. package/dist/prompts/target-assessment/tox-voice/index.d.ts +1 -1
  107. package/dist/prompts/target-assessment/tox-voice/vocabulary.d.ts +8 -5
  108. package/dist/prompts/target-assessment/tox-voice/vocabulary.js +9 -20
  109. package/dist/providers/__fixtures__/session.d.ts +5 -4
  110. package/dist/providers/__fixtures__/session.js +4 -4
  111. package/dist/report-model/block-walk.d.ts +56 -0
  112. package/dist/report-model/block-walk.js +89 -0
  113. package/dist/report-model/draft-finish.d.ts +60 -0
  114. package/dist/report-model/draft-finish.js +56 -0
  115. package/dist/report-model/draft-operations.d.ts +125 -0
  116. package/dist/report-model/draft-operations.js +341 -0
  117. package/dist/report-model/draft-read.d.ts +59 -0
  118. package/dist/report-model/draft-read.js +109 -0
  119. package/dist/report-model/draft.d.ts +51 -0
  120. package/dist/report-model/draft.js +32 -0
  121. package/dist/report-model/fixture-resolver.d.ts +8 -0
  122. package/dist/report-model/fixture-resolver.js +252 -0
  123. package/dist/report-model/mint-snapshot.d.ts +30 -0
  124. package/dist/report-model/mint-snapshot.js +40 -0
  125. package/dist/report-model/reference-resolver.d.ts +113 -0
  126. package/dist/report-model/reference-resolver.js +60 -0
  127. package/dist/report-model/structural-validation.d.ts +22 -0
  128. package/dist/report-model/structural-validation.js +68 -0
  129. package/dist/report-model/validate.d.ts +40 -0
  130. package/dist/report-model/validate.js +80 -0
  131. package/dist/report-render/chart.d.ts +33 -0
  132. package/dist/report-render/chart.js +538 -0
  133. package/dist/report-render/page.d.ts +127 -0
  134. package/dist/report-render/page.js +307 -0
  135. package/dist/report-render/references.d.ts +32 -0
  136. package/dist/report-render/references.js +44 -0
  137. package/dist/report-render/render.d.ts +25 -0
  138. package/dist/report-render/render.js +125 -0
  139. package/dist/report-render/script-json.d.ts +13 -0
  140. package/dist/report-render/script-json.js +15 -0
  141. package/dist/report-render/types.d.ts +39 -0
  142. package/dist/report-render/types.js +10 -0
  143. package/dist/report-render/views/chart-view.d.ts +11 -0
  144. package/dist/report-render/views/chart-view.js +23 -0
  145. package/dist/report-render/views/page-view.d.ts +20 -0
  146. package/dist/report-render/views/page-view.js +49 -0
  147. package/dist/report-render/views/prose.d.ts +28 -0
  148. package/dist/report-render/views/prose.js +75 -0
  149. package/dist/report-render/views/references-view.d.ts +20 -0
  150. package/dist/report-render/views/references-view.js +64 -0
  151. package/dist/report-render/views/values.d.ts +42 -0
  152. package/dist/report-render/views/values.js +43 -0
  153. package/dist/runtime/assemble.d.ts +50 -4
  154. package/dist/runtime/assemble.js +47 -3
  155. package/dist/runtime/boot.d.ts +3 -3
  156. package/dist/runtime/boot.js +22 -5
  157. package/dist/runtime/dbos.d.ts +4 -4
  158. package/dist/state/artifacts.d.ts +16 -0
  159. package/dist/state/artifacts.js +18 -0
  160. package/dist/state/init.js +77 -1
  161. package/dist/state/purge-analysis.js +1 -0
  162. package/dist/state/report-versions.d.ts +132 -0
  163. package/dist/state/report-versions.js +194 -0
  164. package/dist/state/schema.d.ts +2 -2
  165. package/dist/tasks/data-profile.js +1 -0
  166. package/dist/tools/bio/chembl.js +1 -0
  167. package/dist/tools/bio/comptox.js +1 -0
  168. package/dist/tools/bio/drug-gene-interactions.js +1 -0
  169. package/dist/tools/bio/gene-disease-evidence.js +1 -0
  170. package/dist/tools/bio/gene-preclinical-profile.d.ts +1 -1
  171. package/dist/tools/bio/gene-preclinical-profile.js +1 -0
  172. package/dist/tools/bio/keys.d.ts +4 -2
  173. package/dist/tools/bio/keys.js +3 -2
  174. package/dist/tools/bio/lookup-annotation.js +1 -0
  175. package/dist/tools/bio/opentargets.d.ts +3 -3
  176. package/dist/tools/bio/opentargets.js +4 -3
  177. package/dist/tools/bio/pubchem.js +1 -0
  178. package/dist/tools/bio/pubmed.js +4 -4
  179. package/dist/tools/bio/search-clinical-trials.js +1 -0
  180. package/dist/tools/bio/search-faers.js +1 -0
  181. package/dist/tools/bio/search-geo-datasets.js +1 -0
  182. package/dist/tools/bio/search-interactions.js +1 -0
  183. package/dist/tools/bio/target-safety.d.ts +4 -6
  184. package/dist/tools/bio/target-safety.js +7 -6
  185. package/dist/tools/define-tool.d.ts +19 -12
  186. package/dist/tools/define-tool.js +4 -2
  187. package/dist/tools/display/show-user.js +1 -0
  188. package/dist/tools/iterate-report.js +2 -0
  189. package/dist/tools/lib/chembl-client.d.ts +2 -0
  190. package/dist/tools/lib/chembl-client.js +1 -0
  191. package/dist/tools/lib/monarch-client.d.ts +42 -0
  192. package/dist/tools/lib/monarch-client.js +100 -0
  193. package/dist/tools/lib/ncbi-utils.d.ts +3 -58
  194. package/dist/tools/lib/ncbi-utils.js +2 -286
  195. package/dist/tools/lib/pubmed-client.d.ts +5 -12
  196. package/dist/tools/lib/pubmed-client.js +20 -79
  197. package/dist/tools/report/build-report.js +1 -0
  198. package/dist/tools/report/mint-preview-url.js +1 -0
  199. package/dist/tools/report/preview-snapshot.js +1 -0
  200. package/dist/tools/report/submit-report.js +1 -0
  201. package/dist/tools/report/version-fs.js +4 -0
  202. package/dist/tools/report-authoring/authoring-tools.d.ts +134 -0
  203. package/dist/tools/report-authoring/authoring-tools.js +352 -0
  204. package/dist/tools/research/context7-docs.js +2 -0
  205. package/dist/tools/research/generate-analogy-report.js +3 -2
  206. package/dist/tools/research/generate-plan.js +3 -0
  207. package/dist/tools/research/index.d.ts +1 -0
  208. package/dist/tools/research/index.js +1 -0
  209. package/dist/tools/research/inspect-data-profile.js +4 -0
  210. package/dist/tools/research/inspect-run.d.ts +1 -1
  211. package/dist/tools/research/literature-reviewer.d.ts +3 -0
  212. package/dist/tools/research/literature-reviewer.js +3 -0
  213. package/dist/tools/research/resolve-citation.d.ts +3 -0
  214. package/dist/tools/research/resolve-citation.js +15 -0
  215. package/dist/tools/research/search-arxiv.d.ts +3 -19
  216. package/dist/tools/research/search-arxiv.js +10 -105
  217. package/dist/tools/research/search-github-repos.js +1 -0
  218. package/dist/tools/research/search-semantic-scholar.d.ts +8 -33
  219. package/dist/tools/research/search-semantic-scholar.js +30 -88
  220. package/dist/tools/sandbox/list-available-packages.js +23 -0
  221. package/dist/tools/sandbox/list-available-refs.js +37 -2
  222. package/dist/tools/sandbox/report-blocker.js +1 -0
  223. package/dist/tools/sandbox/skills.js +2 -0
  224. package/dist/tools/workspace/file-stat.js +1 -0
  225. package/dist/tools/workspace/show-file.js +2 -0
  226. package/dist/tools/workspace/show-plan.js +1 -0
  227. package/dist/workflows/execute-analysis.d.ts +8 -1
  228. package/dist/workflows/execute-analysis.js +6 -5
  229. package/dist/workflows/execute-target-assessment.d.ts +13 -2
  230. package/dist/workflows/execute-target-assessment.js +78 -16
  231. package/dist/workflows/sandbox-step.d.ts +5 -0
  232. package/dist/workflows/sandbox-step.js +1 -0
  233. package/dist/workflows/target-assessment/assemblers/index.d.ts +1 -1
  234. package/dist/workflows/target-assessment/assemblers/index.js +1 -1
  235. package/dist/workflows/target-assessment/assemblers/literature.d.ts +9 -27
  236. package/dist/workflows/target-assessment/assemblers/literature.js +32 -48
  237. package/dist/workflows/target-assessment/assemblers/orchestrator.d.ts +17 -9
  238. package/dist/workflows/target-assessment/assemblers/orchestrator.js +195 -85
  239. package/dist/workflows/target-assessment/assemblers/safety.d.ts +70 -48
  240. package/dist/workflows/target-assessment/assemblers/safety.js +125 -42
  241. package/dist/workflows/target-assessment/collectors/index.d.ts +5 -2
  242. package/dist/workflows/target-assessment/collectors/index.js +48 -5
  243. package/dist/workflows/target-assessment/coverage.d.ts +43 -27
  244. package/dist/workflows/target-assessment/coverage.js +33 -29
  245. package/dist/workflows/target-assessment/fanout/index.js +1 -0
  246. package/dist/workflows/target-assessment/investigation/index.d.ts +97 -0
  247. package/dist/workflows/target-assessment/investigation/index.js +419 -0
  248. package/dist/workflows/target-assessment/lib/approval-precedents.d.ts +26 -5
  249. package/dist/workflows/target-assessment/lib/approval-precedents.js +95 -29
  250. package/dist/workflows/target-assessment/lib/citation-validator.js +1 -1
  251. package/dist/workflows/target-assessment/lib/clinical-consequence-annotator.d.ts +2 -2
  252. package/dist/workflows/target-assessment/lib/clinical-evidence-attribution.d.ts +2 -3
  253. package/dist/workflows/target-assessment/lib/clinical-evidence-attribution.js +0 -4
  254. package/dist/workflows/target-assessment/lib/compute-derived.d.ts +6 -5
  255. package/dist/workflows/target-assessment/lib/compute-derived.js +14 -5
  256. package/dist/workflows/target-assessment/lib/family-complex-supplement.d.ts +5 -6
  257. package/dist/workflows/target-assessment/lib/family-complex-supplement.js +2 -3
  258. package/dist/workflows/target-assessment/lib/fda-label-safety.d.ts +72 -0
  259. package/dist/workflows/target-assessment/lib/fda-label-safety.js +166 -0
  260. package/dist/workflows/target-assessment/lib/heterodimer-filter.d.ts +0 -9
  261. package/dist/workflows/target-assessment/lib/heterodimer-filter.js +0 -10
  262. package/dist/workflows/target-assessment/lib/hpo-organ-map.d.ts +34 -0
  263. package/dist/workflows/target-assessment/lib/hpo-organ-map.js +63 -0
  264. package/dist/workflows/target-assessment/lib/impc-organ-map.d.ts +19 -0
  265. package/dist/workflows/target-assessment/lib/impc-organ-map.js +39 -0
  266. package/dist/workflows/target-assessment/lib/meddra-organ-map.d.ts +24 -14
  267. package/dist/workflows/target-assessment/lib/meddra-organ-map.js +59 -47
  268. package/dist/workflows/target-assessment/lib/recommendation-sanitizer.js +1 -1
  269. package/dist/workflows/target-assessment/lib/regulatory-actions.d.ts +2 -3
  270. package/dist/workflows/target-assessment/lib/regulatory-actions.js +33 -4
  271. package/dist/workflows/target-assessment/lib/safety-corroboration.d.ts +44 -0
  272. package/dist/workflows/target-assessment/lib/safety-corroboration.js +273 -0
  273. package/dist/workflows/target-assessment/lib/target-identity-filter.d.ts +5 -7
  274. package/dist/workflows/target-assessment/lib/target-identity-filter.js +5 -7
  275. package/dist/workflows/target-assessment/metrics.d.ts +1 -6
  276. package/dist/workflows/target-assessment/metrics.js +1 -13
  277. package/dist/workflows/target-assessment/phase4-assemble.d.ts +2149 -809
  278. package/dist/workflows/target-assessment/phase4-assemble.js +19 -19
  279. package/dist/workflows/target-assessment/phase5-persist.d.ts +20 -21
  280. package/dist/workflows/target-assessment/phase5-persist.js +56 -173
  281. package/dist/workflows/target-assessment/schemas.d.ts +48 -3
  282. package/dist/workflows/target-assessment/schemas.js +19 -0
  283. package/dist/workflows/target-assessment/steps/fanout/polypharm-for-one-modulator-step.d.ts +1 -0
  284. package/dist/workflows/target-assessment/steps/fanout/polypharm-for-one-modulator-step.js +2 -0
  285. package/dist/workflows/target-assessment/steps/phase2-aggregate.d.ts +27 -63
  286. package/dist/workflows/target-assessment/steps/phase2-aggregate.js +0 -4
  287. package/dist/workflows/target-assessment/steps/phase3-aggregate.d.ts +28 -155
  288. package/dist/workflows/target-assessment/steps/phase3-aggregate.js +0 -6
  289. package/dist/workflows/target-assessment/steps/synthesis/diagnostics.d.ts +0 -6
  290. package/dist/workflows/target-assessment/steps/synthesis/diagnostics.js +0 -18
  291. package/dist/workflows/target-assessment/sub-workflows/per-modulator-polypharm.d.ts +1 -0
  292. package/dist/workflows/target-assessment/synthesis/index.d.ts +52 -5
  293. package/dist/workflows/target-assessment/synthesis/index.js +4 -1
  294. package/dist/workflows/target-assessment/synthesis-probes.d.ts +3 -3
  295. package/package.json +4 -1
@@ -1,37 +1,37 @@
1
1
  /**
2
- * Phase 4 — deterministic dossier assembly.
2
+ * Phase 4 — dossier assembly.
3
3
  *
4
- * Pure function over a Phase-3 bundle. Calls `assembleDossier` (~3.5K LOC
5
- * of pure compute) and returns the assembled `DossierV4Body`. The Phase-5
6
- * synthesis sections (translational commentary, liability bullets, safety-
7
- * flags trail) are stamped by the Phase-5 persist step after this step
8
- * completes.
4
+ * Calls `assembleDossier` (~3.5K LOC of aggregation over the Phase-3 bundle)
5
+ * and returns the assembled `DossierBody`. The safety-corroboration and
6
+ * claim-investigation sections are stamped by the workflow body between this
7
+ * step and synthesis; the Phase-5 synthesis sections (translational commentary,
8
+ * liability bullets, safety-flags trail) are stamped by the Phase-5 persist
9
+ * step.
9
10
  *
10
11
  * The DBOS workflow body wraps this in `DBOS.runStep({name: "phase4-assemble"})`
11
12
  * so recovery on a fresh replica replays the cached output without re-running
12
- * the ~1-3 sec compute.
13
- *
14
- * `assembleDossier` accepts an optional `ClinicalConsequenceAnnotatorDeps`
15
- * bundle that is threaded through to `annotateOffTargetPanel`. For the
16
- * DBOS workflow the parameter is undefined — the annotator falls back to
17
- * its DB cache + no-LLM path. Threading a real deps bundle (provider +
18
- * session + model) through Phase-4 is a follow-up tracked in §17 cleanup.
13
+ * the compute. Replay caching earns its keep here because `annotatorDeps`
14
+ * carries the per-row clinical-consequence annotator's LLM seam: assembly makes
15
+ * bounded model calls for off-target rows that have no cached annotation. Those
16
+ * calls are per-row best-effort — a failure leaves the row's original fallback —
17
+ * and their results are cached in Postgres, so a repeat assessment of the same
18
+ * target reaches them without an LLM call at all.
19
19
  */
20
- import { DossierV4BodySchema } from "@inflexa-ai/harness/contracts/target-dossier.js";
20
+ import { DossierBodySchema } from "@inflexa-ai/harness/contracts/target-dossier.js";
21
21
  import { z } from "zod";
22
22
  import { assembleDossier } from "./assemblers/index.js";
23
23
  import { Phase3BundleSchema } from "./steps/phase3-aggregate.js";
24
24
  export const Phase4OutputSchema = z.object({
25
25
  assessmentId: z.string(),
26
- dossier: DossierV4BodySchema,
26
+ dossier: DossierBodySchema,
27
27
  });
28
28
  export { Phase3BundleSchema };
29
29
  /**
30
- * Run Phase 4 — assemble the v4 dossier body from the Phase-3 bundle.
31
- * Deterministic over its inputs; safely cached on DBOS replay.
30
+ * Run Phase 4 — assemble the dossier body from the Phase-3 bundle.
31
+ * Safely cached on DBOS replay; the caller supplies the annotator seam.
32
32
  */
33
- export async function phase4Assemble(pool, phase3) {
34
- const dossier = await assembleDossier(pool, phase3.phase2, phase3, undefined);
33
+ export async function phase4Assemble(pool, phase3, annotatorDeps) {
34
+ const dossier = await assembleDossier(pool, phase3.phase2, phase3, annotatorDeps);
35
35
  return {
36
36
  assessmentId: phase3.phase2.phase1.resolved.assessmentId,
37
37
  dossier,
@@ -2,21 +2,21 @@
2
2
  * Phase 5 — stamps the four Phase-5 synthesis outputs into the Phase-4 dossier,
3
3
  * runs the deterministic refinement passes (coverage-qualifier reconcile,
4
4
  * no-liabilities disclosure rewrite, recommendation citation validation +
5
- * demotion, recommendation quality gates), upgrades the v4 body to v5,
6
- * computes derived fields, and validates against `DossierV5Schema`.
5
+ * demotion, recommendation quality gates), computes derived fields, and
6
+ * validates against `DossierSchema`.
7
7
  *
8
- * The DB write (`setDossier` / `markFailed`) lives in the workflow's terminal
9
- * handler in §6. This module returns the validated dossier instead of writing it.
8
+ * The DB write (`setDossier` / `markFailed`) belongs to the workflow's terminal
9
+ * handler; this module returns the validated dossier instead of writing it.
10
10
  * Typed throws (`DossierSchemaViolationError`, `DossierDerivedInvariantError`)
11
- * let the terminal handler dispatch to `markFailed` with the matching `error.kind`.
11
+ * let that handler dispatch to `markFailed` with the matching `error.kind`.
12
12
  *
13
- * The direction-of-effect audit (`auditCitationDirections`) is NOT called here —
14
- * it requires an LLM and is not on the PR #4 critical path. Follow-up tracked
15
- * in §17 if a harness-native audit pipeline is wired.
13
+ * Every pass here is deterministic. The direction-of-effect audit
14
+ * (`auditCitationDirections`) is not among them because it needs an LLM call,
15
+ * and this module runs after synthesis has closed.
16
16
  */
17
- import { z } from "zod";
18
17
  import type { Logger } from "../../lib/logger.js";
19
- import { type DossierV4Body } from "@inflexa-ai/harness/contracts/target-dossier.js";
18
+ import { type DossierBody } from "@inflexa-ai/harness/contracts/target-dossier.js";
19
+ import type { OrganSignalProjection } from "./lib/fda-label-safety.js";
20
20
  import type { Phase2Bundle } from "./steps/phase2-aggregate.js";
21
21
  import type { DossierRecommendationStepOutput, LiabilityBulletsStepOutput, SafetyFlagsTrailStepOutput, TranslationalCommentaryStepOutput } from "./synthesis/index.js";
22
22
  export declare class DossierSchemaViolationError extends Error {
@@ -31,8 +31,13 @@ export interface Phase5PersistInput {
31
31
  /** Operational logging seam; omitted falls back to no-op. */
32
32
  readonly logger?: Logger;
33
33
  readonly assessmentId: string;
34
- readonly phase4Dossier: DossierV4Body;
34
+ readonly phase4Dossier: DossierBody;
35
35
  readonly phase2: Phase2Bundle;
36
+ /**
37
+ * Per-organ signals segmented from the FDA labels the approval-precedent
38
+ * step fetched. Null when no indication resolved and no label was queried.
39
+ */
40
+ readonly regulatoryOrganSignals: OrganSignalProjection | null;
36
41
  readonly synthesis: {
37
42
  readonly bullets: LiabilityBulletsStepOutput;
38
43
  readonly flags: SafetyFlagsTrailStepOutput;
@@ -40,21 +45,15 @@ export interface Phase5PersistInput {
40
45
  readonly recommendation: DossierRecommendationStepOutput;
41
46
  };
42
47
  }
43
- export declare const Phase5PersistResultSchema: z.ZodObject<{
44
- assessmentId: z.ZodString;
45
- dossier: z.ZodRecord<z.ZodString, z.ZodUnknown>;
46
- bytes: z.ZodNumber;
47
- }, z.core.$strip>;
48
48
  export interface Phase5PersistResult {
49
49
  readonly assessmentId: string;
50
50
  readonly dossier: Record<string, unknown>;
51
51
  readonly bytes: number;
52
52
  }
53
53
  /**
54
- * Run Phase-5 persist as a pure function. Returns the validated v5
55
- * dossier (and computed bytes) on success. Throws
56
- * `DossierDerivedInvariantError` when `computeDerivedFields` rejects the
57
- * dossier; throws `DossierSchemaViolationError` when the v5 schema
58
- * rejects the final dossier.
54
+ * Run Phase-5 persist as a pure function. Returns the validated dossier (and
55
+ * computed bytes) on success. Throws `DossierDerivedInvariantError` when
56
+ * `computeDerivedFields` rejects the dossier; throws
57
+ * `DossierSchemaViolationError` when the schema rejects the final dossier.
59
58
  */
60
59
  export declare function phase5Persist(input: Phase5PersistInput): Promise<Phase5PersistResult>;
@@ -2,30 +2,26 @@
2
2
  * Phase 5 — stamps the four Phase-5 synthesis outputs into the Phase-4 dossier,
3
3
  * runs the deterministic refinement passes (coverage-qualifier reconcile,
4
4
  * no-liabilities disclosure rewrite, recommendation citation validation +
5
- * demotion, recommendation quality gates), upgrades the v4 body to v5,
6
- * computes derived fields, and validates against `DossierV5Schema`.
5
+ * demotion, recommendation quality gates), computes derived fields, and
6
+ * validates against `DossierSchema`.
7
7
  *
8
- * The DB write (`setDossier` / `markFailed`) lives in the workflow's terminal
9
- * handler in §6. This module returns the validated dossier instead of writing it.
8
+ * The DB write (`setDossier` / `markFailed`) belongs to the workflow's terminal
9
+ * handler; this module returns the validated dossier instead of writing it.
10
10
  * Typed throws (`DossierSchemaViolationError`, `DossierDerivedInvariantError`)
11
- * let the terminal handler dispatch to `markFailed` with the matching `error.kind`.
11
+ * let that handler dispatch to `markFailed` with the matching `error.kind`.
12
12
  *
13
- * The direction-of-effect audit (`auditCitationDirections`) is NOT called here —
14
- * it requires an LLM and is not on the PR #4 critical path. Follow-up tracked
15
- * in §17 if a harness-native audit pipeline is wired.
13
+ * Every pass here is deterministic. The direction-of-effect audit
14
+ * (`auditCitationDirections`) is not among them because it needs an LLM call,
15
+ * and this module runs after synthesis has closed.
16
16
  */
17
- import { z } from "zod";
18
17
  import { createNoopLogger } from "../../lib/console-logger.js";
19
- import { DossierV5Schema, } from "@inflexa-ai/harness/contracts/target-dossier.js";
20
- import { getDrugPrimaryTargetUniprots } from "../../tools/lib/chembl-client.js";
21
- import { deterministicTranslationalCommentary } from "./assemblers/index.js";
18
+ import { DossierSchema, } from "@inflexa-ai/harness/contracts/target-dossier.js";
19
+ import { assembleRegulatoryOrganSignals, deterministicTranslationalCommentary } from "./assemblers/index.js";
22
20
  import { validateRecommendationCitations } from "./lib/citation-validator.js";
23
- import { classifyClinicalEvidenceTrial } from "./lib/clinical-evidence-attribution.js";
24
21
  import { computeDerivedFields } from "./lib/compute-derived.js";
25
22
  import { detectStructuralEvidenceConflicts } from "./lib/evidence-conflict-detector.js";
26
23
  import { applyRecommendationQualityGates } from "./lib/recommendation-quality-gates.js";
27
24
  import { sanitizeRecommendation } from "./lib/recommendation-sanitizer.js";
28
- import { resolveFamilySiblingUniprots } from "./lib/target-identity-filter.js";
29
25
  const SOFT_CAP_BYTES = 16 * 1024 * 1024;
30
26
  // ── Typed throws — handled in §6 terminal handler ────────────────────
31
27
  export class DossierSchemaViolationError extends Error {
@@ -44,11 +40,6 @@ export class DossierDerivedInvariantError extends Error {
44
40
  this.name = "DossierDerivedInvariantError";
45
41
  }
46
42
  }
47
- export const Phase5PersistResultSchema = z.object({
48
- assessmentId: z.string(),
49
- dossier: z.record(z.string(), z.unknown()),
50
- bytes: z.number(),
51
- });
52
43
  // ── Internal helpers ─────────────────────────────────────────────────
53
44
  function approximateSize(d) {
54
45
  return Buffer.byteLength(JSON.stringify(d), "utf-8");
@@ -85,13 +76,45 @@ function pickCommentarySeverity(row) {
85
76
  }
86
77
  return "ok";
87
78
  }
88
- function stampSynthesis(logger, phase4Dossier, syn, phase2) {
79
+ const CITED_PMID_RE = /\bPMID[:\s]?(\d{6,9})\b/gi;
80
+ /**
81
+ * A synthesised claim stands on the papers it cites. One that cites none says
82
+ * so — a section path is a pointer into this dossier, not a record a reader
83
+ * can independently check.
84
+ */
85
+ function supportFromCitedPmids(text, reasonWhenUncited) {
86
+ const pmids = [...new Set([...text.matchAll(CITED_PMID_RE)].map((m) => m[1]))];
87
+ if (pmids.length === 0)
88
+ return { state: "unknown", reason: reasonWhenUncited };
89
+ return { state: "scored", evidence: pmids.map((pmid) => ({ pmid, source: "pubmed" })) };
90
+ }
91
+ function stampSynthesis(logger, phase4Dossier, syn, phase2, regulatoryOrganSignals) {
89
92
  const next = structuredClone(phase4Dossier);
93
+ next.safety_profile.regulatory_organ_signals = assembleRegulatoryOrganSignals(regulatoryOrganSignals);
90
94
  if (syn.bullets.coverage === "available") {
91
- next.liability_summary.liability_bullets = syn.bullets.data.bullets.map((b) => ({ text: b.text, rationale: b.rationale, category: b.category }));
95
+ next.liability_summary.liability_bullets = syn.bullets.data.bullets.map((b) => ({
96
+ text: b.text,
97
+ rationale: b.rationale,
98
+ category: b.category,
99
+ support: supportFromCitedPmids(`${b.text} ${b.rationale} ${b.evidence_pointer}`, `bullet cites ${b.evidence_pointer} rather than a paper`),
100
+ }));
92
101
  }
93
102
  if (syn.flags.coverage === "available" && syn.flags.data.flags.length > 0) {
94
- next.safety_profile.target_organ_liabilities = syn.flags.data.flags;
103
+ next.safety_profile.target_organ_liabilities = {
104
+ coverage: "available",
105
+ data: {
106
+ rows: syn.flags.data.flags.map((f) => ({
107
+ organ: f.organ,
108
+ severity: f.severity,
109
+ trail: f.trail,
110
+ mechanism_hypothesis: f.mechanism_hypothesis,
111
+ support: supportFromCitedPmids(f.trail, "the audit trail is assembled from dossier sections and cites no paper"),
112
+ })),
113
+ },
114
+ };
115
+ }
116
+ else if (syn.flags.coverage === "queried_no_data") {
117
+ next.safety_profile.target_organ_liabilities = { coverage: "queried_no_data", error: syn.flags.error };
95
118
  }
96
119
  const deterministicAll = deterministicTranslationalCommentary(phase2);
97
120
  const deterministicSorted = [...deterministicAll].sort((a, b) => {
@@ -245,160 +268,21 @@ function reconcileCoverageQualifier(dossier) {
245
268
  return coverage !== "available";
246
269
  });
247
270
  }
248
- function makeUnknownAttribution(reason) {
249
- return {
250
- relationship: "unknown",
251
- evidence_role: "excluded",
252
- basis: [{ kind: "text_match", source: "legacy-v4-upgrade" }],
253
- resolved_interventions: [],
254
- exclusion_reason: reason,
255
- };
256
- }
257
- async function buildAttributionContext(phase2, knownClassDrugsBase, therapeuticPrograms) {
258
- const ctgov = phase2.phase1.collectors.ctgov.coverage === "available"
259
- ? [...phase2.phase1.collectors.ctgov.data.active, ...phase2.phase1.collectors.ctgov.data.failed]
260
- : [];
261
- const assessmentUniprot = phase2.phase1.resolved.ids?.uniprot ?? "";
262
- const geneSymbol = phase2.phase1.resolved.geneSymbol ?? "";
263
- const [familyUniprots, resolvedDrugs] = await Promise.all([
264
- assessmentUniprot || geneSymbol ? resolveFamilySiblingUniprots(assessmentUniprot || geneSymbol) : Promise.resolve([]),
265
- Promise.all(knownClassDrugsBase.map(async (drug) => {
266
- const resolved = drug.moleculeChemblId ? await getDrugPrimaryTargetUniprots(drug.moleculeChemblId).catch(() => []) : [];
267
- const targetUniprots = resolved.length > 0 ? resolved : assessmentUniprot ? [assessmentUniprot] : [];
268
- return { ...drug, targetUniprots };
269
- })),
270
- ]);
271
- return {
272
- byNct: new Map(ctgov.map((trial) => [trial.nctId, trial])),
273
- classifyOpts: {
274
- assessmentSymbol: geneSymbol,
275
- assessmentUniprot,
276
- familyUniprots,
277
- knownClassDrugs: resolvedDrugs,
278
- therapeuticPrograms,
279
- },
280
- };
281
- }
282
- function attachAttribution(row, ctx) {
283
- const source = ctx.byNct.get(row.nct_id);
284
- const classified = source
285
- ? classifyClinicalEvidenceTrial(source, ctx.classifyOpts)
286
- : {
287
- attribution: makeUnknownAttribution("No normalized CT.gov source row was available for this legacy row."),
288
- eligible_for_toxicology_aggregation: false,
289
- };
290
- return {
291
- ...row,
292
- attribution: classified.attribution,
293
- eligible_for_toxicology_aggregation: classified.eligible_for_toxicology_aggregation,
294
- };
295
- }
296
- function upgradeTrialRows(rows, ctx) {
297
- const kept = [];
298
- const excluded = [];
299
- for (const row of rows) {
300
- const upgraded = attachAttribution(row, ctx);
301
- if (upgraded.eligible_for_toxicology_aggregation)
302
- kept.push(upgraded);
303
- else
304
- excluded.push(upgraded);
305
- }
306
- return { rows: kept, excluded_rows: excluded };
307
- }
308
- function normalizeRegulatoryActionRows(rows) {
309
- return rows.map((row) => {
310
- if (row.source_kind)
311
- return row;
312
- const action_kind = row.action_kind;
313
- const agency = row.agency;
314
- const source_kind = action_kind === "black_box"
315
- ? "boxed_warning"
316
- : action_kind === "REMS"
317
- ? "rems"
318
- : action_kind === "withdrawal"
319
- ? "withdrawal"
320
- : agency === "EMA"
321
- ? "referral"
322
- : "label_warning";
323
- return {
324
- ...row,
325
- source_kind,
326
- action_kind: source_kind === "label_warning" && action_kind === "safety_communication" ? "label_warning" : action_kind,
327
- source_date: row.action_date,
328
- };
329
- });
330
- }
331
- async function upgradeDossierToV5(body, phase2) {
332
- const next = structuredClone(body);
333
- next.schema_version = "5";
334
- const drugInteractions = next.drug_interactions;
335
- const knownClassDrugsBase = drugInteractions?.coverage === "available"
336
- ? (drugInteractions.data?.rows ?? []).map((row) => ({
337
- name: String(row.drug_name ?? ""),
338
- moleculeChemblId: row.drug_id ?? null,
339
- }))
340
- : [];
341
- const tpCollector = phase2.phase1.collectors.therapeuticPrograms;
342
- const therapeuticPrograms = tpCollector?.coverage === "available"
343
- ? tpCollector.data.programs.map((program) => ({
344
- programId: program.programId,
345
- name: program.name,
346
- targetSymbol: program.targetSymbol,
347
- targetUniprot: program.targetUniprot,
348
- modality: program.modality,
349
- nctIds: program.nctIds,
350
- }))
351
- : [];
352
- const attributionCtx = await buildAttributionContext(phase2, knownClassDrugsBase, therapeuticPrograms);
353
- const cd = next.clinical_development;
354
- if (cd?.trials?.coverage === "available") {
355
- const upgraded = upgradeTrialRows(cd.trials.data.rows, attributionCtx);
356
- cd.trials.data.rows = upgraded.rows;
357
- cd.trials.data.excluded_rows = [...(cd.trials.data.excluded_rows ?? []), ...upgraded.excluded_rows];
358
- }
359
- if (cd?.failed_trials?.coverage === "available") {
360
- const upgraded = upgradeTrialRows(cd.failed_trials.data.rows, attributionCtx);
361
- cd.failed_trials.data.rows = upgraded.rows;
362
- cd.failed_trials.data.excluded_rows = [...(cd.failed_trials.data.excluded_rows ?? []), ...upgraded.excluded_rows];
363
- }
364
- if (cd?.outcomes?.coverage === "available") {
365
- cd.outcomes.data.rows = cd.outcomes.data.rows.map((row) => attachAttribution(row, attributionCtx));
366
- }
367
- const analytics = next.analytics;
368
- if (analytics?.discovery_trials?.coverage === "available") {
369
- const upgraded = upgradeTrialRows(analytics.discovery_trials.data.rows, attributionCtx);
370
- analytics.discovery_trials.data.rows = upgraded.rows;
371
- analytics.discovery_trials.data.excluded_rows = [...(analytics.discovery_trials.data.excluded_rows ?? []), ...upgraded.excluded_rows];
372
- delete analytics.discovery_trials.data.related_target_trials;
373
- delete analytics.discovery_trials.data.related_receptor;
374
- }
375
- const sp = next.safety_profile;
376
- const regulatory = sp?.regulatory_actions;
377
- if (regulatory?.coverage === "available") {
378
- regulatory.data.rows = normalizeRegulatoryActionRows(regulatory.data.rows ?? []);
379
- }
380
- next.analytics.quality_gates ??= {
381
- coverage: "available",
382
- data: { rows: [] },
383
- };
384
- return next;
385
- }
386
271
  // ── Pure-function entry point ────────────────────────────────────────
387
272
  /**
388
- * Run Phase-5 persist as a pure function. Returns the validated v5
389
- * dossier (and computed bytes) on success. Throws
390
- * `DossierDerivedInvariantError` when `computeDerivedFields` rejects the
391
- * dossier; throws `DossierSchemaViolationError` when the v5 schema
392
- * rejects the final dossier.
273
+ * Run Phase-5 persist as a pure function. Returns the validated dossier (and
274
+ * computed bytes) on success. Throws `DossierDerivedInvariantError` when
275
+ * `computeDerivedFields` rejects the dossier; throws
276
+ * `DossierSchemaViolationError` when the schema rejects the final dossier.
393
277
  */
394
278
  export async function phase5Persist(input) {
395
279
  const logger = (input.logger ?? createNoopLogger()).named("phase5-persist").with({ assessmentId: input.assessmentId });
396
280
  // The dossier rides through this function as an untyped working blob; the
397
- // `as unknown as DossierV{4,5}Body` casts below are version-shim views that
398
- // let the typed helpers operate on it. None of these casts is load-bearing
399
- // for soundness: `DossierV5Schema.safeParse(fullDossier)` at the end is the
400
- // single validation gate, and it throws before anything is returned.
401
- let dossier = stampSynthesis(logger, input.phase4Dossier, input.synthesis, input.phase2);
281
+ // `as unknown as DossierBody` casts below let the typed helpers operate on
282
+ // it. None of these casts is load-bearing for soundness:
283
+ // `DossierSchema.safeParse(fullDossier)` at the end is the single
284
+ // validation gate, and it throws before anything is returned.
285
+ let dossier = stampSynthesis(logger, input.phase4Dossier, input.synthesis, input.phase2, input.regulatoryOrganSignals);
402
286
  // Demote organ-claim flagged bullets into coverage_qualifier.unverified_bullets.
403
287
  const exec = dossier.executive_recommendation;
404
288
  if (exec?.coverage === "available") {
@@ -409,7 +293,6 @@ export async function phase5Persist(input) {
409
293
  }
410
294
  reconcileCoverageQualifier(dossier);
411
295
  rewriteNoLiabilitiesDisclosure(dossier);
412
- dossier = (await upgradeDossierToV5(dossier, input.phase2));
413
296
  const recommendationAudit = dossier.analytics.recommendation_audit?.data;
414
297
  const synthesisDiagnostics = dossier.analytics.synthesis_diagnostics?.coverage ===
415
298
  "available"
@@ -454,9 +337,9 @@ export async function phase5Persist(input) {
454
337
  data: { rows: [...existingRows, ...structuralConflicts] },
455
338
  };
456
339
  }
457
- const parsed = DossierV5Schema.safeParse(fullDossier);
340
+ const parsed = DossierSchema.safeParse(fullDossier);
458
341
  if (!parsed.success) {
459
- throw new DossierSchemaViolationError("Dossier failed v5 schema validation", parsed.error.issues);
342
+ throw new DossierSchemaViolationError("Dossier failed schema validation", parsed.error.issues);
460
343
  }
461
344
  return {
462
345
  assessmentId: input.assessmentId,
@@ -12,7 +12,6 @@ export declare const TargetAssessmentInputSchema: z.ZodObject<{
12
12
  organizationId: z.ZodString;
13
13
  requestedBy: z.ZodString;
14
14
  }, z.core.$strip>;
15
- export type TargetAssessmentInput = z.infer<typeof TargetAssessmentInputSchema>;
16
15
  export declare const ResolvedTargetSchema: z.ZodObject<{
17
16
  assessmentId: z.ZodString;
18
17
  goal: z.ZodNullable<z.ZodString>;
@@ -250,10 +249,10 @@ export declare const ExpressionMultiSpeciesBundleSchema: z.ZodObject<{
250
249
  tissues: z.ZodArray<z.ZodObject<{
251
250
  tissue: z.ZodString;
252
251
  rank: z.ZodEnum<{
252
+ absent: "absent";
253
253
  high: "high";
254
254
  medium: "medium";
255
255
  low: "low";
256
- absent: "absent";
257
256
  }>;
258
257
  expressionScore: z.ZodNullable<z.ZodNumber>;
259
258
  }, z.core.$strip>>;
@@ -384,6 +383,7 @@ export declare const TherapeuticProgramsBundleSchema: z.ZodObject<{
384
383
  evidence: z.ZodArray<z.ZodObject<{
385
384
  pmid: z.ZodOptional<z.ZodString>;
386
385
  doi: z.ZodOptional<z.ZodString>;
386
+ accession: z.ZodOptional<z.ZodString>;
387
387
  source: z.ZodString;
388
388
  predicate: z.ZodOptional<z.ZodString>;
389
389
  score: z.ZodOptional<z.ZodNumber>;
@@ -407,6 +407,25 @@ export declare const TherapeuticProgramsBundleSchema: z.ZodObject<{
407
407
  }, z.core.$strip>>;
408
408
  }, z.core.$strip>;
409
409
  export type TherapeuticProgramsBundle = z.infer<typeof TherapeuticProgramsBundleSchema>;
410
+ /**
411
+ * Curated human phenotype and causal-disease evidence from Monarch.
412
+ *
413
+ * `ancestorIds` is the HPO ancestor closure, carried through so the consumer
414
+ * resolves a phenotype onto an organ by identifier rather than by its label.
415
+ */
416
+ export declare const MonarchBundleSchema: z.ZodObject<{
417
+ geneCurie: z.ZodString;
418
+ phenotypes: z.ZodArray<z.ZodObject<{
419
+ hpoId: z.ZodString;
420
+ label: z.ZodString;
421
+ ancestorIds: z.ZodArray<z.ZodString>;
422
+ publications: z.ZodArray<z.ZodString>;
423
+ diseaseContext: z.ZodNullable<z.ZodString>;
424
+ frequencyPercent: z.ZodNullable<z.ZodNumber>;
425
+ primaryKnowledgeSource: z.ZodNullable<z.ZodString>;
426
+ }, z.core.$strip>>;
427
+ }, z.core.$strip>;
428
+ export type MonarchBundle = z.infer<typeof MonarchBundleSchema>;
410
429
  export declare const Phase1BundleSchema: z.ZodObject<{
411
430
  resolved: z.ZodObject<{
412
431
  assessmentId: z.ZodString;
@@ -669,10 +688,10 @@ export declare const Phase1BundleSchema: z.ZodObject<{
669
688
  tissues: z.ZodArray<z.ZodObject<{
670
689
  tissue: z.ZodString;
671
690
  rank: z.ZodEnum<{
691
+ absent: "absent";
672
692
  high: "high";
673
693
  medium: "medium";
674
694
  low: "low";
675
- absent: "absent";
676
695
  }>;
677
696
  expressionScore: z.ZodNullable<z.ZodNumber>;
678
697
  }, z.core.$strip>>;
@@ -876,6 +895,31 @@ export declare const Phase1BundleSchema: z.ZodObject<{
876
895
  coverage: z.ZodLiteral<"not_loaded">;
877
896
  reason: z.ZodOptional<z.ZodString>;
878
897
  }, z.core.$strip>], "coverage">;
898
+ monarch: z.ZodDiscriminatedUnion<[z.ZodObject<{
899
+ coverage: z.ZodLiteral<"available">;
900
+ data: z.ZodObject<{
901
+ geneCurie: z.ZodString;
902
+ phenotypes: z.ZodArray<z.ZodObject<{
903
+ hpoId: z.ZodString;
904
+ label: z.ZodString;
905
+ ancestorIds: z.ZodArray<z.ZodString>;
906
+ publications: z.ZodArray<z.ZodString>;
907
+ diseaseContext: z.ZodNullable<z.ZodString>;
908
+ frequencyPercent: z.ZodNullable<z.ZodNumber>;
909
+ primaryKnowledgeSource: z.ZodNullable<z.ZodString>;
910
+ }, z.core.$strip>>;
911
+ }, z.core.$strip>;
912
+ }, z.core.$strip>, z.ZodObject<{
913
+ coverage: z.ZodLiteral<"queried_no_data">;
914
+ error: z.ZodOptional<z.ZodObject<{
915
+ message: z.ZodString;
916
+ name: z.ZodOptional<z.ZodString>;
917
+ stack: z.ZodOptional<z.ZodString>;
918
+ }, z.core.$strip>>;
919
+ }, z.core.$strip>, z.ZodObject<{
920
+ coverage: z.ZodLiteral<"not_loaded">;
921
+ reason: z.ZodOptional<z.ZodString>;
922
+ }, z.core.$strip>], "coverage">;
879
923
  therapeuticPrograms: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
880
924
  coverage: z.ZodLiteral<"available">;
881
925
  data: z.ZodObject<{
@@ -893,6 +937,7 @@ export declare const Phase1BundleSchema: z.ZodObject<{
893
937
  evidence: z.ZodArray<z.ZodObject<{
894
938
  pmid: z.ZodOptional<z.ZodString>;
895
939
  doi: z.ZodOptional<z.ZodString>;
940
+ accession: z.ZodOptional<z.ZodString>;
896
941
  source: z.ZodString;
897
942
  predicate: z.ZodOptional<z.ZodString>;
898
943
  score: z.ZodOptional<z.ZodNumber>;
@@ -271,6 +271,24 @@ export const TherapeuticProgramsBundleSchema = z.object({
271
271
  confidence: z.enum(["high", "medium", "low"]),
272
272
  })),
273
273
  });
274
+ /**
275
+ * Curated human phenotype and causal-disease evidence from Monarch.
276
+ *
277
+ * `ancestorIds` is the HPO ancestor closure, carried through so the consumer
278
+ * resolves a phenotype onto an organ by identifier rather than by its label.
279
+ */
280
+ export const MonarchBundleSchema = z.object({
281
+ geneCurie: z.string(),
282
+ phenotypes: z.array(z.object({
283
+ hpoId: z.string(),
284
+ label: z.string(),
285
+ ancestorIds: z.array(z.string()),
286
+ publications: z.array(z.string()),
287
+ diseaseContext: z.string().nullable(),
288
+ frequencyPercent: z.number().nullable(),
289
+ primaryKnowledgeSource: z.string().nullable(),
290
+ })),
291
+ });
274
292
  // ── Phase-1 keyed bundle (output of phase1Aggregate) ─────────────────
275
293
  export const Phase1BundleSchema = z.object({
276
294
  resolved: ResolvedTargetSchema,
@@ -288,6 +306,7 @@ export const Phase1BundleSchema = z.object({
288
306
  pathways: withCoverage(PathwaysBundleSchema),
289
307
  stringPpi: withCoverage(StringPpiBundleSchema),
290
308
  familyComplexes: withCoverage(FamilyComplexesBundleSchema),
309
+ monarch: withCoverage(MonarchBundleSchema),
291
310
  therapeuticPrograms: withCoverage(TherapeuticProgramsBundleSchema).optional(),
292
311
  }),
293
312
  });
@@ -19,6 +19,7 @@ export declare const PerModulatorPolypharmItemSchema: z.ZodObject<{
19
19
  hits: z.ZodArray<z.ZodObject<{
20
20
  targetChemblId: z.ZodString;
21
21
  targetName: z.ZodNullable<z.ZodString>;
22
+ assayChemblId: z.ZodNullable<z.ZodString>;
22
23
  pchemblValue: z.ZodNullable<z.ZodNumber>;
23
24
  standardType: z.ZodNullable<z.ZodString>;
24
25
  standardValue: z.ZodNullable<z.ZodNumber>;
@@ -19,6 +19,8 @@ export const PerModulatorPolypharmItemSchema = z.object({
19
19
  hits: z.array(z.object({
20
20
  targetChemblId: z.string(),
21
21
  targetName: z.string().nullable(),
22
+ /** The ChEMBL assay record the binding was measured in, when there is one. */
23
+ assayChemblId: z.string().nullable(),
22
24
  pchemblValue: z.number().nullable(),
23
25
  standardType: z.string().nullable(),
24
26
  standardValue: z.number().nullable(),