@inflexa-ai/harness 0.35.8 → 0.36.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.
- package/dist/auth/types.d.ts +5 -14
- package/dist/auth/types.js +3 -10
- package/dist/billing/usage-recorder.d.ts +1 -1
- package/dist/contracts/analogy-report.d.ts +1 -1
- package/dist/contracts/analogy-report.js +1 -1
- package/dist/contracts/chat-parts.d.ts +2 -3
- package/dist/contracts/index.d.ts +0 -4
- package/dist/contracts/index.js +0 -2
- package/dist/index.d.ts +0 -7
- package/dist/index.js +0 -21
- package/dist/lib/metrics.d.ts +1 -1
- package/dist/lib/otel-spans.d.ts +0 -2
- package/dist/lib/otel-spans.js +0 -2
- package/dist/loop/genai-spans.d.ts +14 -0
- package/dist/loop/genai-spans.js +35 -0
- package/dist/loop/run-agent.d.ts +1 -1
- package/dist/loop/run-agent.js +37 -4
- package/dist/runtime/assemble.d.ts +0 -3
- package/dist/runtime/assemble.js +0 -3
- package/dist/state/index.d.ts +0 -2
- package/dist/state/index.js +0 -1
- package/dist/state/init.js +1 -60
- package/dist/state/purge-analysis.d.ts +1 -2
- package/dist/state/purge-analysis.js +1 -2
- package/dist/tasks/regulatory-corpus-boot-refresh.js +1 -1
- package/dist/tools/bio/gene-preclinical-profile.d.ts +1 -3
- package/dist/tools/bio/gene-preclinical-profile.js +1 -3
- package/dist/tools/lib/chembl-client.d.ts +1 -4
- package/dist/tools/lib/chembl-client.js +1 -4
- package/dist/tools/lib/clinical-benchmarks-client.d.ts +1 -1
- package/dist/tools/lib/clinical-benchmarks-client.js +1 -1
- package/dist/tools/lib/clinical-trials-client.d.ts +0 -3
- package/dist/tools/lib/clinical-trials-client.js +0 -3
- package/dist/tools/lib/identifier-resolver.d.ts +5 -7
- package/dist/tools/lib/identifier-resolver.js +5 -7
- package/dist/tools/lib/iuphar-client.d.ts +1 -3
- package/dist/tools/lib/iuphar-client.js +1 -3
- package/dist/tools/lib/opentargets-client.d.ts +1 -1
- package/dist/tools/lib/opentargets-client.js +1 -1
- package/dist/tools/lib/protein-family-normalize.d.ts +5 -7
- package/dist/tools/lib/protein-family-normalize.js +5 -7
- package/dist/tools/lib/uniprot-client.d.ts +0 -7
- package/dist/tools/lib/uniprot-client.js +2 -9
- package/package.json +1 -1
- package/dist/contracts/target-assessment-row.d.ts +0 -85
- package/dist/contracts/target-assessment-row.js +0 -37
- package/dist/contracts/target-dossier.d.ts +0 -12423
- package/dist/contracts/target-dossier.js +0 -1282
- package/dist/prompts/target-assessment/briefs/executive-recommendation.d.ts +0 -1
- package/dist/prompts/target-assessment/briefs/executive-recommendation.js +0 -85
- package/dist/prompts/target-assessment/briefs/index.d.ts +0 -4
- package/dist/prompts/target-assessment/briefs/index.js +0 -4
- package/dist/prompts/target-assessment/briefs/liability-bullets.d.ts +0 -1
- package/dist/prompts/target-assessment/briefs/liability-bullets.js +0 -114
- package/dist/prompts/target-assessment/briefs/target-organ-liabilities.d.ts +0 -1
- package/dist/prompts/target-assessment/briefs/target-organ-liabilities.js +0 -37
- package/dist/prompts/target-assessment/briefs/translational-commentary.d.ts +0 -1
- package/dist/prompts/target-assessment/briefs/translational-commentary.js +0 -23
- package/dist/prompts/target-assessment/drugs-in-class.d.ts +0 -1
- package/dist/prompts/target-assessment/drugs-in-class.js +0 -29
- package/dist/prompts/target-assessment/investigation/adversarial-critique.d.ts +0 -1
- package/dist/prompts/target-assessment/investigation/adversarial-critique.js +0 -67
- package/dist/prompts/target-assessment/investigation/claim-reverification.d.ts +0 -1
- package/dist/prompts/target-assessment/investigation/claim-reverification.js +0 -49
- package/dist/prompts/target-assessment/investigation/index.d.ts +0 -3
- package/dist/prompts/target-assessment/investigation/index.js +0 -3
- package/dist/prompts/target-assessment/investigation/mechanism-proposal.d.ts +0 -1
- package/dist/prompts/target-assessment/investigation/mechanism-proposal.js +0 -49
- package/dist/prompts/target-assessment/modulator-triage.d.ts +0 -1
- package/dist/prompts/target-assessment/modulator-triage.js +0 -31
- package/dist/prompts/target-assessment/off-target-annotator.d.ts +0 -1
- package/dist/prompts/target-assessment/off-target-annotator.js +0 -28
- package/dist/prompts/target-assessment/tox-voice/core.d.ts +0 -1
- package/dist/prompts/target-assessment/tox-voice/core.js +0 -74
- package/dist/prompts/target-assessment/tox-voice/critique.d.ts +0 -7
- package/dist/prompts/target-assessment/tox-voice/critique.js +0 -109
- package/dist/prompts/target-assessment/tox-voice/exemplars.d.ts +0 -8
- package/dist/prompts/target-assessment/tox-voice/exemplars.js +0 -24
- package/dist/prompts/target-assessment/tox-voice/index.d.ts +0 -4
- package/dist/prompts/target-assessment/tox-voice/index.js +0 -4
- package/dist/prompts/target-assessment/tox-voice/vocabulary.d.ts +0 -18
- package/dist/prompts/target-assessment/tox-voice/vocabulary.js +0 -61
- package/dist/state/target-assessments.d.ts +0 -68
- package/dist/state/target-assessments.js +0 -222
- package/dist/workflows/execute-target-assessment.d.ts +0 -118
- package/dist/workflows/execute-target-assessment.js +0 -631
- package/dist/workflows/target-assessment/assemblers/index.d.ts +0 -5
- package/dist/workflows/target-assessment/assemblers/index.js +0 -4
- package/dist/workflows/target-assessment/assemblers/literature.d.ts +0 -281
- package/dist/workflows/target-assessment/assemblers/literature.js +0 -971
- package/dist/workflows/target-assessment/assemblers/orchestrator.d.ts +0 -118
- package/dist/workflows/target-assessment/assemblers/orchestrator.js +0 -945
- package/dist/workflows/target-assessment/assemblers/safety.d.ts +0 -374
- package/dist/workflows/target-assessment/assemblers/safety.js +0 -1068
- package/dist/workflows/target-assessment/assemblers/trials.d.ts +0 -30
- package/dist/workflows/target-assessment/assemblers/trials.js +0 -75
- package/dist/workflows/target-assessment/collectors/index.d.ts +0 -114
- package/dist/workflows/target-assessment/collectors/index.js +0 -538
- package/dist/workflows/target-assessment/coverage.d.ts +0 -97
- package/dist/workflows/target-assessment/coverage.js +0 -86
- package/dist/workflows/target-assessment/decisions/index.d.ts +0 -86
- package/dist/workflows/target-assessment/decisions/index.js +0 -127
- package/dist/workflows/target-assessment/fanout/index.d.ts +0 -32
- package/dist/workflows/target-assessment/fanout/index.js +0 -156
- package/dist/workflows/target-assessment/investigation/index.d.ts +0 -97
- package/dist/workflows/target-assessment/investigation/index.js +0 -419
- package/dist/workflows/target-assessment/lib/approval-precedents.d.ts +0 -73
- package/dist/workflows/target-assessment/lib/approval-precedents.js +0 -185
- package/dist/workflows/target-assessment/lib/citation-validator.d.ts +0 -46
- package/dist/workflows/target-assessment/lib/citation-validator.js +0 -316
- package/dist/workflows/target-assessment/lib/clinical-consequence-annotator.d.ts +0 -65
- package/dist/workflows/target-assessment/lib/clinical-consequence-annotator.js +0 -174
- package/dist/workflows/target-assessment/lib/clinical-evidence-attribution.d.ts +0 -44
- package/dist/workflows/target-assessment/lib/clinical-evidence-attribution.js +0 -152
- package/dist/workflows/target-assessment/lib/compute-derived.d.ts +0 -20
- package/dist/workflows/target-assessment/lib/compute-derived.js +0 -261
- package/dist/workflows/target-assessment/lib/compute-selectivity.d.ts +0 -15
- package/dist/workflows/target-assessment/lib/compute-selectivity.js +0 -18
- package/dist/workflows/target-assessment/lib/dedup-modulators.d.ts +0 -37
- package/dist/workflows/target-assessment/lib/dedup-modulators.js +0 -157
- package/dist/workflows/target-assessment/lib/evidence-conflict-detector.d.ts +0 -17
- package/dist/workflows/target-assessment/lib/evidence-conflict-detector.js +0 -100
- package/dist/workflows/target-assessment/lib/expression-constants.d.ts +0 -21
- package/dist/workflows/target-assessment/lib/expression-constants.js +0 -21
- package/dist/workflows/target-assessment/lib/family-complex-supplement.d.ts +0 -20
- package/dist/workflows/target-assessment/lib/family-complex-supplement.js +0 -36
- package/dist/workflows/target-assessment/lib/fda-label-safety.d.ts +0 -72
- package/dist/workflows/target-assessment/lib/fda-label-safety.js +0 -166
- package/dist/workflows/target-assessment/lib/heterodimer-filter.d.ts +0 -30
- package/dist/workflows/target-assessment/lib/heterodimer-filter.js +0 -44
- package/dist/workflows/target-assessment/lib/hpo-organ-map.d.ts +0 -34
- package/dist/workflows/target-assessment/lib/hpo-organ-map.js +0 -63
- package/dist/workflows/target-assessment/lib/impc-organ-map.d.ts +0 -19
- package/dist/workflows/target-assessment/lib/impc-organ-map.js +0 -39
- package/dist/workflows/target-assessment/lib/intended-polypharm-filter.d.ts +0 -4
- package/dist/workflows/target-assessment/lib/intended-polypharm-filter.js +0 -24
- package/dist/workflows/target-assessment/lib/llm-step.d.ts +0 -80
- package/dist/workflows/target-assessment/lib/llm-step.js +0 -101
- package/dist/workflows/target-assessment/lib/meddra-organ-map.d.ts +0 -40
- package/dist/workflows/target-assessment/lib/meddra-organ-map.js +0 -138
- package/dist/workflows/target-assessment/lib/recommendation-quality-gates.d.ts +0 -17
- package/dist/workflows/target-assessment/lib/recommendation-quality-gates.js +0 -99
- package/dist/workflows/target-assessment/lib/recommendation-sanitizer.d.ts +0 -2
- package/dist/workflows/target-assessment/lib/recommendation-sanitizer.js +0 -51
- package/dist/workflows/target-assessment/lib/regulatory-actions.d.ts +0 -25
- package/dist/workflows/target-assessment/lib/regulatory-actions.js +0 -176
- package/dist/workflows/target-assessment/lib/safety-corroboration.d.ts +0 -44
- package/dist/workflows/target-assessment/lib/safety-corroboration.js +0 -273
- package/dist/workflows/target-assessment/lib/structured-llm.d.ts +0 -61
- package/dist/workflows/target-assessment/lib/structured-llm.js +0 -102
- package/dist/workflows/target-assessment/lib/target-identity-filter.d.ts +0 -59
- package/dist/workflows/target-assessment/lib/target-identity-filter.js +0 -95
- package/dist/workflows/target-assessment/lib/therapeutic-programs.d.ts +0 -20
- package/dist/workflows/target-assessment/lib/therapeutic-programs.js +0 -68
- package/dist/workflows/target-assessment/metrics.d.ts +0 -16
- package/dist/workflows/target-assessment/metrics.js +0 -30
- package/dist/workflows/target-assessment/phase4-assemble.d.ts +0 -3182
- package/dist/workflows/target-assessment/phase4-assemble.js +0 -39
- package/dist/workflows/target-assessment/phase5-persist.d.ts +0 -59
- package/dist/workflows/target-assessment/phase5-persist.js +0 -349
- package/dist/workflows/target-assessment/progress-stream.d.ts +0 -75
- package/dist/workflows/target-assessment/progress-stream.js +0 -110
- package/dist/workflows/target-assessment/progress.d.ts +0 -39
- package/dist/workflows/target-assessment/progress.js +0 -77
- package/dist/workflows/target-assessment/schemas.d.ts +0 -970
- package/dist/workflows/target-assessment/schemas.js +0 -318
- package/dist/workflows/target-assessment/steps/collectors/pathways.d.ts +0 -15
- package/dist/workflows/target-assessment/steps/collectors/pathways.js +0 -58
- package/dist/workflows/target-assessment/steps/fanout/aes-for-one-class-drug-step.d.ts +0 -34
- package/dist/workflows/target-assessment/steps/fanout/aes-for-one-class-drug-step.js +0 -31
- package/dist/workflows/target-assessment/steps/fanout/aes-for-one-trial-step.d.ts +0 -57
- package/dist/workflows/target-assessment/steps/fanout/aes-for-one-trial-step.js +0 -54
- package/dist/workflows/target-assessment/steps/fanout/faers-for-one-modulator-step.d.ts +0 -35
- package/dist/workflows/target-assessment/steps/fanout/faers-for-one-modulator-step.js +0 -32
- package/dist/workflows/target-assessment/steps/fanout/index.d.ts +0 -14
- package/dist/workflows/target-assessment/steps/fanout/index.js +0 -10
- package/dist/workflows/target-assessment/steps/fanout/polypharm-for-one-modulator-step.d.ts +0 -29
- package/dist/workflows/target-assessment/steps/fanout/polypharm-for-one-modulator-step.js +0 -29
- package/dist/workflows/target-assessment/steps/phase2-aggregate.d.ts +0 -657
- package/dist/workflows/target-assessment/steps/phase2-aggregate.js +0 -34
- package/dist/workflows/target-assessment/steps/phase3-aggregate.d.ts +0 -806
- package/dist/workflows/target-assessment/steps/phase3-aggregate.js +0 -16
- package/dist/workflows/target-assessment/steps/synthesis/diagnostics.d.ts +0 -28
- package/dist/workflows/target-assessment/steps/synthesis/diagnostics.js +0 -27
- package/dist/workflows/target-assessment/sub-workflows/index.d.ts +0 -15
- package/dist/workflows/target-assessment/sub-workflows/index.js +0 -11
- package/dist/workflows/target-assessment/sub-workflows/per-class-drug-aes.d.ts +0 -41
- package/dist/workflows/target-assessment/sub-workflows/per-class-drug-aes.js +0 -12
- package/dist/workflows/target-assessment/sub-workflows/per-modulator-faers.d.ts +0 -41
- package/dist/workflows/target-assessment/sub-workflows/per-modulator-faers.js +0 -12
- package/dist/workflows/target-assessment/sub-workflows/per-modulator-polypharm.d.ts +0 -37
- package/dist/workflows/target-assessment/sub-workflows/per-modulator-polypharm.js +0 -12
- package/dist/workflows/target-assessment/sub-workflows/per-trial-aes.d.ts +0 -66
- package/dist/workflows/target-assessment/sub-workflows/per-trial-aes.js +0 -12
- package/dist/workflows/target-assessment/synthesis/index.d.ts +0 -607
- package/dist/workflows/target-assessment/synthesis/index.js +0 -354
- package/dist/workflows/target-assessment/synthesis-probes.d.ts +0 -56
- package/dist/workflows/target-assessment/synthesis-probes.js +0 -320
|
@@ -1,354 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Phase-5 synthesis functions for the harness DBOS workflow.
|
|
3
|
-
*
|
|
4
|
-
* Four functions:
|
|
5
|
-
* - `liabilityBullets` (per-section, parallel-safe)
|
|
6
|
-
* - `safetyFlagsTrail` (per-section, parallel-safe)
|
|
7
|
-
* - `translationalCommentary` (per-section, parallel-safe)
|
|
8
|
-
* - `dossierRecommendation` (whole-dossier, sequential after the three above)
|
|
9
|
-
*
|
|
10
|
-
* Each function is a pure async `(input, deps) => Promise<EnvelopeWithDiagnostic>`.
|
|
11
|
-
* Every call is single-shot structured-output through `structuredLlmCall`.
|
|
12
|
-
*
|
|
13
|
-
* The `runSynthesisWithProbe` helper preserves the bounded-retry-on-probe-
|
|
14
|
-
* failure semantics: attempt 1 → probe → critique-driven retry → probe.
|
|
15
|
-
* Each attempt is its own attempt-numbered DBOS step so a resumed
|
|
16
|
-
* post-402 call lands a fresh cache slot.
|
|
17
|
-
*/
|
|
18
|
-
import { z } from "zod";
|
|
19
|
-
import { SynthesisDiagnosticRowSchema } from "@inflexa-ai/harness/contracts/target-dossier.js";
|
|
20
|
-
import { OrganSystemSchema } from "../../../contracts/organ-system.js";
|
|
21
|
-
import { SeveritySchema } from "../../../contracts/severity.js";
|
|
22
|
-
import { executiveRecommendationBrief, liabilityBulletsBrief, targetOrganLiabilitiesBrief, translationalCommentaryBrief, } from "../../../prompts/target-assessment/briefs/index.js";
|
|
23
|
-
import { toxVoiceCore, toxVoiceExemplars } from "../../../prompts/target-assessment/tox-voice/index.js";
|
|
24
|
-
import { SerializedErrorSchema } from "../coverage.js";
|
|
25
|
-
import { buildDiagnosticsRow } from "../steps/synthesis/diagnostics.js";
|
|
26
|
-
import { probeLiabilityBullets, probeRecommendation, probeSafetyFlags, probeTranslationalCommentary } from "../synthesis-probes.js";
|
|
27
|
-
import { structuredLlmCall } from "../lib/structured-llm.js";
|
|
28
|
-
// ── Output schemas ────────────────────────────────────────────────────
|
|
29
|
-
export const LiabilityBulletsOutputSchema = z.object({
|
|
30
|
-
bullets: z.array(z.object({
|
|
31
|
-
organ_or_axis: z.string(),
|
|
32
|
-
severity: z.enum(["high", "medium", "low"]),
|
|
33
|
-
text: z.string(),
|
|
34
|
-
evidence_pointer: z.string(),
|
|
35
|
-
rationale: z.string(),
|
|
36
|
-
category: z.enum(["fatal_post_market", "class_liability", "off_target_safety", "high_safety_organ_expression", "broad_expression", "other"]),
|
|
37
|
-
})),
|
|
38
|
-
notes: z.string(),
|
|
39
|
-
});
|
|
40
|
-
export const SafetyFlagsTrailOutputSchema = z.object({
|
|
41
|
-
flags: z.array(z.object({
|
|
42
|
-
organ: OrganSystemSchema,
|
|
43
|
-
severity: SeveritySchema,
|
|
44
|
-
trail: z.string(),
|
|
45
|
-
mechanism_hypothesis: z.string().nullable(),
|
|
46
|
-
})),
|
|
47
|
-
});
|
|
48
|
-
export const TranslationalCommentaryOutputSchema = z.object({
|
|
49
|
-
rows: z.array(z.object({
|
|
50
|
-
topic: z.enum(["ko_phenotype", "expression_translation", "organ_system_match", "family_context"]),
|
|
51
|
-
predicate: z.string(),
|
|
52
|
-
commentary: z.string(),
|
|
53
|
-
})),
|
|
54
|
-
});
|
|
55
|
-
export const ExternalCitationSchema = z.object({
|
|
56
|
-
id: z.string(),
|
|
57
|
-
kind: z.enum(["fda_anda", "fda_nda", "pubmed", "clinicaltrials", "regulatory_guidance"]),
|
|
58
|
-
retrieved_via: z.string(),
|
|
59
|
-
fetched_at: z.string().datetime().optional(),
|
|
60
|
-
excerpt: z.string().max(500),
|
|
61
|
-
});
|
|
62
|
-
export const DossierRecommendationOutputSchema = z.object({
|
|
63
|
-
disposition: z.enum(["pursue", "conditional", "de_prioritize", "insufficient_evidence"]),
|
|
64
|
-
confidence: z.enum(["high", "medium", "low"]),
|
|
65
|
-
rationale: z.string(),
|
|
66
|
-
key_strengths: z.array(z.string()),
|
|
67
|
-
key_risks: z.array(z.string()),
|
|
68
|
-
modality_choice: z.object({
|
|
69
|
-
modality: z.string(),
|
|
70
|
-
rationale: z.string(),
|
|
71
|
-
}),
|
|
72
|
-
coverage_qualifier: z.object({
|
|
73
|
-
sections_consulted: z.array(z.string()),
|
|
74
|
-
sections_unavailable: z.array(z.string()),
|
|
75
|
-
note: z.string(),
|
|
76
|
-
}),
|
|
77
|
-
external_citations: z.array(ExternalCitationSchema).default([]),
|
|
78
|
-
});
|
|
79
|
-
// ── Per-step envelope schemas ─────────────────────────────────────────
|
|
80
|
-
function withDiagnosticAndCoverage(dataSchema) {
|
|
81
|
-
return z.discriminatedUnion("coverage", [
|
|
82
|
-
z.object({
|
|
83
|
-
coverage: z.literal("available"),
|
|
84
|
-
data: dataSchema,
|
|
85
|
-
diagnostic: SynthesisDiagnosticRowSchema,
|
|
86
|
-
}),
|
|
87
|
-
z.object({
|
|
88
|
-
coverage: z.literal("queried_no_data"),
|
|
89
|
-
error: SerializedErrorSchema.extend({
|
|
90
|
-
kind: z.enum(["synthesis-too-shallow", "synthesis-unavailable", "voice-violation"]).optional(),
|
|
91
|
-
}).optional(),
|
|
92
|
-
diagnostic: SynthesisDiagnosticRowSchema,
|
|
93
|
-
}),
|
|
94
|
-
]);
|
|
95
|
-
}
|
|
96
|
-
export const LiabilityBulletsStepOutputSchema = withDiagnosticAndCoverage(LiabilityBulletsOutputSchema);
|
|
97
|
-
export const SafetyFlagsTrailStepOutputSchema = withDiagnosticAndCoverage(SafetyFlagsTrailOutputSchema);
|
|
98
|
-
export const TranslationalCommentaryStepOutputSchema = withDiagnosticAndCoverage(TranslationalCommentaryOutputSchema);
|
|
99
|
-
export const DossierRecommendationStepOutputSchema = withDiagnosticAndCoverage(DossierRecommendationOutputSchema);
|
|
100
|
-
// ── Instruction composer ─────────────────────────────────────────────
|
|
101
|
-
function composeInstructions(brief, section) {
|
|
102
|
-
const exemplarBlock = toxVoiceExemplars[section].map((ex, i) => `### Exemplar ${i + 1}\n\n${ex}`).join("\n\n");
|
|
103
|
-
return [toxVoiceCore, "---", brief, "---", "## Voice exemplars", exemplarBlock].join("\n\n");
|
|
104
|
-
}
|
|
105
|
-
function isBudgetExceeded(v) {
|
|
106
|
-
return typeof v === "object" && v !== null && "kind" in v && v.kind === "budget-exceeded";
|
|
107
|
-
}
|
|
108
|
-
/**
|
|
109
|
-
* Run a synthesis call with one bounded retry on probe failure. Returns
|
|
110
|
-
* the final output (or null on permanent failure) plus a diagnostics row.
|
|
111
|
-
* On a billing-gateway 402 at any attempt, propagates the budget-exceeded sentinel.
|
|
112
|
-
*/
|
|
113
|
-
async function runSynthesisWithProbe(input) {
|
|
114
|
-
let firstError = null;
|
|
115
|
-
let firstProbe = null;
|
|
116
|
-
// Attempt 1
|
|
117
|
-
try {
|
|
118
|
-
const result = await structuredLlmCall({
|
|
119
|
-
stepName: `${input.baseStepName}:0`,
|
|
120
|
-
agentId: input.stepId,
|
|
121
|
-
provider: input.chatProvider,
|
|
122
|
-
session: input.session,
|
|
123
|
-
system: input.system,
|
|
124
|
-
prompt: input.basePrompt,
|
|
125
|
-
schema: input.outputSchema,
|
|
126
|
-
model: input.modelId,
|
|
127
|
-
});
|
|
128
|
-
if (result.kind === "budget-exceeded") {
|
|
129
|
-
return { kind: "budget-exceeded", sentinel: result.sentinel };
|
|
130
|
-
}
|
|
131
|
-
const firstOutput = result.value;
|
|
132
|
-
firstProbe = input.probe(firstOutput);
|
|
133
|
-
if (firstProbe.verdict === "pass" || firstProbe.verdict === "relaxed") {
|
|
134
|
-
return {
|
|
135
|
-
kind: "ok",
|
|
136
|
-
finalOut: firstOutput,
|
|
137
|
-
diagnostic: buildDiagnosticsRow({
|
|
138
|
-
stepId: input.stepId,
|
|
139
|
-
modelId: input.modelId,
|
|
140
|
-
attemptCount: 1,
|
|
141
|
-
retryCritique: null,
|
|
142
|
-
finalProbe: firstProbe,
|
|
143
|
-
finalCoverage: "available",
|
|
144
|
-
}),
|
|
145
|
-
errorKind: null,
|
|
146
|
-
errorMessage: null,
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
catch (err) {
|
|
151
|
-
firstError = err instanceof Error ? err : new Error(String(err));
|
|
152
|
-
}
|
|
153
|
-
// Attempt 2 — critique-driven retry. On hard first-attempt throw, the
|
|
154
|
-
// retry uses the base prompt prefixed with the throw message.
|
|
155
|
-
const retryCritique = firstProbe?.critique ?? (firstError ? `Your prior attempt threw: ${firstError.message}. Try again.` : null);
|
|
156
|
-
const retryPrompt = retryCritique != null ? `${input.basePrompt}\n\n---\n\nIMPORTANT: ${retryCritique}` : input.basePrompt;
|
|
157
|
-
try {
|
|
158
|
-
const result = await structuredLlmCall({
|
|
159
|
-
stepName: `${input.baseStepName}:1`,
|
|
160
|
-
agentId: input.stepId,
|
|
161
|
-
provider: input.chatProvider,
|
|
162
|
-
session: input.session,
|
|
163
|
-
system: input.system,
|
|
164
|
-
prompt: retryPrompt,
|
|
165
|
-
schema: input.outputSchema,
|
|
166
|
-
model: input.modelId,
|
|
167
|
-
});
|
|
168
|
-
if (result.kind === "budget-exceeded") {
|
|
169
|
-
return { kind: "budget-exceeded", sentinel: result.sentinel };
|
|
170
|
-
}
|
|
171
|
-
const retryOutput = result.value;
|
|
172
|
-
const retryProbe = input.probe(retryOutput);
|
|
173
|
-
if (retryProbe.verdict === "pass" || retryProbe.verdict === "relaxed") {
|
|
174
|
-
return {
|
|
175
|
-
kind: "ok",
|
|
176
|
-
finalOut: retryOutput,
|
|
177
|
-
diagnostic: buildDiagnosticsRow({
|
|
178
|
-
stepId: input.stepId,
|
|
179
|
-
modelId: input.modelId,
|
|
180
|
-
attemptCount: 2,
|
|
181
|
-
retryCritique,
|
|
182
|
-
finalProbe: retryProbe,
|
|
183
|
-
finalCoverage: "available",
|
|
184
|
-
}),
|
|
185
|
-
errorKind: null,
|
|
186
|
-
errorMessage: null,
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
const errorKind = retryProbe.verdict === "fail-voice" ? "voice-violation" : "synthesis-too-shallow";
|
|
190
|
-
return {
|
|
191
|
-
kind: "ok",
|
|
192
|
-
finalOut: null,
|
|
193
|
-
diagnostic: buildDiagnosticsRow({
|
|
194
|
-
stepId: input.stepId,
|
|
195
|
-
modelId: input.modelId,
|
|
196
|
-
attemptCount: 2,
|
|
197
|
-
retryCritique,
|
|
198
|
-
finalProbe: retryProbe,
|
|
199
|
-
finalCoverage: "queried_no_data",
|
|
200
|
-
errorKind,
|
|
201
|
-
errorMessage: retryProbe.critique,
|
|
202
|
-
}),
|
|
203
|
-
errorKind,
|
|
204
|
-
errorMessage: retryProbe.critique,
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
catch (err) {
|
|
208
|
-
const errMsg = err instanceof Error ? err.message : String(err);
|
|
209
|
-
return {
|
|
210
|
-
kind: "ok",
|
|
211
|
-
finalOut: null,
|
|
212
|
-
diagnostic: buildDiagnosticsRow({
|
|
213
|
-
stepId: input.stepId,
|
|
214
|
-
modelId: input.modelId,
|
|
215
|
-
attemptCount: 2,
|
|
216
|
-
retryCritique,
|
|
217
|
-
finalProbe: firstProbe ?? {
|
|
218
|
-
verdict: "skipped",
|
|
219
|
-
critique: errMsg,
|
|
220
|
-
output_chars: 0,
|
|
221
|
-
},
|
|
222
|
-
finalCoverage: "queried_no_data",
|
|
223
|
-
errorKind: "synthesis-unavailable",
|
|
224
|
-
errorMessage: errMsg,
|
|
225
|
-
}),
|
|
226
|
-
errorKind: "synthesis-unavailable",
|
|
227
|
-
errorMessage: errMsg,
|
|
228
|
-
};
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
function envelopeFromDriverResult(driver) {
|
|
232
|
-
if (driver.finalOut) {
|
|
233
|
-
return {
|
|
234
|
-
coverage: "available",
|
|
235
|
-
data: driver.finalOut,
|
|
236
|
-
diagnostic: driver.diagnostic,
|
|
237
|
-
};
|
|
238
|
-
}
|
|
239
|
-
return {
|
|
240
|
-
coverage: "queried_no_data",
|
|
241
|
-
error: {
|
|
242
|
-
message: driver.errorMessage ?? "synthesis failed",
|
|
243
|
-
name: driver.errorKind ?? "synthesis-unavailable",
|
|
244
|
-
kind: driver.errorKind ?? "synthesis-unavailable",
|
|
245
|
-
},
|
|
246
|
-
diagnostic: driver.diagnostic,
|
|
247
|
-
};
|
|
248
|
-
}
|
|
249
|
-
export async function liabilityBullets(phase4, deps) {
|
|
250
|
-
const prompt = [
|
|
251
|
-
"Phase-4 dossier — write evidence-cited liability bullets.",
|
|
252
|
-
"The full assembled dossier follows. Cite section paths and counts; do not fabricate.",
|
|
253
|
-
"",
|
|
254
|
-
JSON.stringify(phase4.dossier, null, 2),
|
|
255
|
-
"",
|
|
256
|
-
deps.approvalPrecedents,
|
|
257
|
-
].join("\n");
|
|
258
|
-
const result = await runSynthesisWithProbe({
|
|
259
|
-
stepId: "liability-bullets",
|
|
260
|
-
modelId: deps.model,
|
|
261
|
-
system: composeInstructions(liabilityBulletsBrief, "liability-bullets"),
|
|
262
|
-
basePrompt: prompt,
|
|
263
|
-
outputSchema: LiabilityBulletsOutputSchema,
|
|
264
|
-
probe: (out) => probeLiabilityBullets(out, phase4.dossier),
|
|
265
|
-
chatProvider: deps.chatProvider,
|
|
266
|
-
session: deps.session,
|
|
267
|
-
baseStepName: `ta-synth:liability-bullets:${deps.attempt}`,
|
|
268
|
-
});
|
|
269
|
-
if (result.kind === "budget-exceeded")
|
|
270
|
-
return result;
|
|
271
|
-
return envelopeFromDriverResult(result);
|
|
272
|
-
}
|
|
273
|
-
export async function safetyFlagsTrail(phase4, deps) {
|
|
274
|
-
const prompt = [
|
|
275
|
-
"Phase-4 dossier — write per-organ safety-flag audit trails.",
|
|
276
|
-
"The full assembled dossier follows. Cite source counts; do not fabricate.",
|
|
277
|
-
"",
|
|
278
|
-
JSON.stringify(phase4.dossier, null, 2),
|
|
279
|
-
"",
|
|
280
|
-
deps.approvalPrecedents,
|
|
281
|
-
].join("\n");
|
|
282
|
-
const result = await runSynthesisWithProbe({
|
|
283
|
-
stepId: "safety-flags-trail",
|
|
284
|
-
modelId: deps.model,
|
|
285
|
-
system: composeInstructions(targetOrganLiabilitiesBrief, "target-organ-liabilities"),
|
|
286
|
-
basePrompt: prompt,
|
|
287
|
-
outputSchema: SafetyFlagsTrailOutputSchema,
|
|
288
|
-
probe: probeSafetyFlags,
|
|
289
|
-
chatProvider: deps.chatProvider,
|
|
290
|
-
session: deps.session,
|
|
291
|
-
baseStepName: `ta-synth:safety-flags-trail:${deps.attempt}`,
|
|
292
|
-
});
|
|
293
|
-
if (result.kind === "budget-exceeded")
|
|
294
|
-
return result;
|
|
295
|
-
return envelopeFromDriverResult(result);
|
|
296
|
-
}
|
|
297
|
-
export async function translationalCommentary(phase4, deps) {
|
|
298
|
-
const prompt = [
|
|
299
|
-
"Phase-4 dossier — write preclinical-to-clinical translational commentary.",
|
|
300
|
-
"The full assembled dossier follows. Cite tissues and species literally; do not fabricate.",
|
|
301
|
-
"",
|
|
302
|
-
JSON.stringify(phase4.dossier, null, 2),
|
|
303
|
-
"",
|
|
304
|
-
deps.approvalPrecedents,
|
|
305
|
-
].join("\n");
|
|
306
|
-
const result = await runSynthesisWithProbe({
|
|
307
|
-
stepId: "translational-commentary",
|
|
308
|
-
modelId: deps.model,
|
|
309
|
-
system: composeInstructions(translationalCommentaryBrief, "translational-commentary"),
|
|
310
|
-
basePrompt: prompt,
|
|
311
|
-
outputSchema: TranslationalCommentaryOutputSchema,
|
|
312
|
-
probe: probeTranslationalCommentary,
|
|
313
|
-
chatProvider: deps.chatProvider,
|
|
314
|
-
session: deps.session,
|
|
315
|
-
baseStepName: `ta-synth:translational-commentary:${deps.attempt}`,
|
|
316
|
-
});
|
|
317
|
-
if (result.kind === "budget-exceeded")
|
|
318
|
-
return result;
|
|
319
|
-
return envelopeFromDriverResult(result);
|
|
320
|
-
}
|
|
321
|
-
export async function dossierRecommendation(input, deps) {
|
|
322
|
-
// Surface just the data envelopes from the per-section synthesis outputs;
|
|
323
|
-
// drop the diagnostic so the recommendation agent isn't tempted to read
|
|
324
|
-
// its own machinery.
|
|
325
|
-
const perSectionPrompt = {
|
|
326
|
-
liability_bullets: input.perSection.liabilityBullets.coverage === "available" ? input.perSection.liabilityBullets.data : { coverage: "queried_no_data" },
|
|
327
|
-
target_organ_liabilities: input.perSection.safetyFlagsTrail.coverage === "available" ? input.perSection.safetyFlagsTrail.data : { coverage: "queried_no_data" },
|
|
328
|
-
translational_commentary: input.perSection.translationalCommentary.coverage === "available" ? input.perSection.translationalCommentary.data : { coverage: "queried_no_data" },
|
|
329
|
-
};
|
|
330
|
-
const prompt = [
|
|
331
|
-
"Phase-4 dossier — produce the executive recommendation.",
|
|
332
|
-
"Inputs are: (1) the full assembled dossier, (2) the three per-section synthesis outputs.",
|
|
333
|
-
"Cite at least three section paths from the dossier, integrate the per-section bullets/flags/commentary, and disclose coverage gaps explicitly.",
|
|
334
|
-
"",
|
|
335
|
-
JSON.stringify({ dossier: input.phase4.dossier, per_section_synthesis: perSectionPrompt }, null, 2),
|
|
336
|
-
"",
|
|
337
|
-
deps.approvalPrecedents,
|
|
338
|
-
].join("\n");
|
|
339
|
-
const result = await runSynthesisWithProbe({
|
|
340
|
-
stepId: "dossier-recommendation",
|
|
341
|
-
modelId: deps.model,
|
|
342
|
-
system: composeInstructions(executiveRecommendationBrief, "executive-recommendation"),
|
|
343
|
-
basePrompt: prompt,
|
|
344
|
-
outputSchema: DossierRecommendationOutputSchema,
|
|
345
|
-
probe: (out) => probeRecommendation(out, input.phase4.dossier),
|
|
346
|
-
chatProvider: deps.chatProvider,
|
|
347
|
-
session: deps.session,
|
|
348
|
-
baseStepName: `ta-synth:dossier-recommendation:${deps.attempt}`,
|
|
349
|
-
});
|
|
350
|
-
if (result.kind === "budget-exceeded")
|
|
351
|
-
return result;
|
|
352
|
-
return envelopeFromDriverResult(result);
|
|
353
|
-
}
|
|
354
|
-
export { isBudgetExceeded as isSynthesisBudgetExceeded };
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Synthesis content probes — deterministic floor on Phase-5 LLM output
|
|
3
|
-
* depth.
|
|
4
|
-
*
|
|
5
|
-
* Each per-section synthesis step runs its agent's structured output
|
|
6
|
-
* through the relevant probe before accepting it. A failed probe
|
|
7
|
-
* triggers one bounded retry with a critique appended; a second failure
|
|
8
|
-
* marks the section `coverage: "queried_no_data"` with
|
|
9
|
-
* `error.kind: "synthesis-too-shallow"` (the workflow proceeds — the
|
|
10
|
-
* dossier still persists with the rest of the data intact).
|
|
11
|
-
*
|
|
12
|
-
* Probes are deliberately deterministic regex/length checks — not
|
|
13
|
-
* LLM-as-judge. The prompts already require evidence citation; the
|
|
14
|
-
* probes are a regression-prevention floor for the rare LLM regression
|
|
15
|
-
* that produces fragment-length output anyway.
|
|
16
|
-
*
|
|
17
|
-
* Threshold tuning: the constants block at the top of this file is the
|
|
18
|
-
* single source of truth. Adjust there, never inline.
|
|
19
|
-
*/
|
|
20
|
-
import type { DossierBody } from "@inflexa-ai/harness/contracts/target-dossier.js";
|
|
21
|
-
import type { DossierRecommendationOutput, LiabilityBulletsOutput, SafetyFlagsTrailOutput, TranslationalCommentaryOutput } from "./synthesis/index.js";
|
|
22
|
-
export declare const PROBE_THRESHOLDS: {
|
|
23
|
-
readonly recommendation: {
|
|
24
|
-
readonly rationaleMinChars: 600;
|
|
25
|
-
readonly rationaleMinCharsRelaxed: 200;
|
|
26
|
-
readonly requiredSectionRefs: 3;
|
|
27
|
-
readonly requiredKeyItems: 1;
|
|
28
|
-
};
|
|
29
|
-
readonly liabilityBullet: {
|
|
30
|
-
readonly rationaleMinChars: 80;
|
|
31
|
-
readonly requiresSourceOrCounter: true;
|
|
32
|
-
};
|
|
33
|
-
readonly safetyFlag: {
|
|
34
|
-
readonly trailMinChars: 100;
|
|
35
|
-
readonly requiredSourceRefs: 2;
|
|
36
|
-
};
|
|
37
|
-
readonly translationalCommentary: {
|
|
38
|
-
readonly commentaryMinChars: 120;
|
|
39
|
-
};
|
|
40
|
-
};
|
|
41
|
-
export type ProbeVerdict = "pass" | "fail-length" | "fail-section-references" | "fail-key-strengths-risks" | "fail-source-references" | "fail-numeric-claim" | "fail-voice" | "relaxed" | "skipped";
|
|
42
|
-
export interface ProbeResult {
|
|
43
|
-
verdict: ProbeVerdict;
|
|
44
|
-
critique: string | null;
|
|
45
|
-
output_chars: number;
|
|
46
|
-
}
|
|
47
|
-
export declare function countSectionReferences(text: string): {
|
|
48
|
-
matchedSections: string[];
|
|
49
|
-
};
|
|
50
|
-
export declare function countSourceReferences(text: string): {
|
|
51
|
-
matchedSources: string[];
|
|
52
|
-
};
|
|
53
|
-
export declare function probeRecommendation(out: DossierRecommendationOutput, dossier: DossierBody): ProbeResult;
|
|
54
|
-
export declare function probeLiabilityBullets(out: LiabilityBulletsOutput, dossier?: DossierBody): ProbeResult;
|
|
55
|
-
export declare function probeSafetyFlags(out: SafetyFlagsTrailOutput): ProbeResult;
|
|
56
|
-
export declare function probeTranslationalCommentary(out: TranslationalCommentaryOutput): ProbeResult;
|