heor-agent-mcp 1.0.2 → 1.0.4
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/README.md +104 -14
- package/dist/analytics.d.ts +9 -0
- package/dist/analytics.d.ts.map +1 -1
- package/dist/analytics.js +20 -0
- package/dist/analytics.js.map +1 -1
- package/dist/formatters/comparisonMarkdown.d.ts.map +1 -1
- package/dist/formatters/comparisonMarkdown.js +16 -0
- package/dist/formatters/comparisonMarkdown.js.map +1 -1
- package/dist/grade/eq5dImpact.d.ts +43 -0
- package/dist/grade/eq5dImpact.d.ts.map +1 -0
- package/dist/grade/eq5dImpact.js +132 -0
- package/dist/grade/eq5dImpact.js.map +1 -0
- package/dist/grade/inconsistency.d.ts +29 -0
- package/dist/grade/inconsistency.d.ts.map +1 -0
- package/dist/grade/inconsistency.js +75 -0
- package/dist/grade/inconsistency.js.map +1 -0
- package/dist/grade/upgrading.d.ts +32 -0
- package/dist/grade/upgrading.d.ts.map +1 -0
- package/dist/grade/upgrading.js +54 -0
- package/dist/grade/upgrading.js.map +1 -0
- package/dist/network/bucher.d.ts +1 -1
- package/dist/network/bucher.d.ts.map +1 -1
- package/dist/network/bucher.js +36 -10
- package/dist/network/bucher.js.map +1 -1
- package/dist/network/consistency.d.ts +51 -0
- package/dist/network/consistency.d.ts.map +1 -0
- package/dist/network/consistency.js +83 -0
- package/dist/network/consistency.js.map +1 -0
- package/dist/network/types.d.ts +9 -0
- package/dist/network/types.d.ts.map +1 -1
- package/dist/providers/types.d.ts +11 -0
- package/dist/providers/types.d.ts.map +1 -1
- package/dist/schemas/dossierInputSchemas.d.ts +118 -0
- package/dist/schemas/dossierInputSchemas.d.ts.map +1 -0
- package/dist/schemas/dossierInputSchemas.js +59 -0
- package/dist/schemas/dossierInputSchemas.js.map +1 -0
- package/dist/server.js +21 -7
- package/dist/server.js.map +1 -1
- package/dist/tools/htaDossierPrep.d.ts.map +1 -1
- package/dist/tools/htaDossierPrep.js +55 -18
- package/dist/tools/htaDossierPrep.js.map +1 -1
- package/dist/tools/indirectComparison.d.ts.map +1 -1
- package/dist/tools/indirectComparison.js +15 -2
- package/dist/tools/indirectComparison.js.map +1 -1
- package/dist/tools/utilityValueSet.d.ts.map +1 -1
- package/dist/tools/utilityValueSet.js +25 -3
- package/dist/tools/utilityValueSet.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,6 +12,21 @@ Built for pharmaceutical, biotech, CRO, and medical affairs teams who need rigor
|
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
15
|
+
## What's new in v1.0.4
|
|
16
|
+
|
|
17
|
+
Senior HEOR methodology + ChatGPT support:
|
|
18
|
+
|
|
19
|
+
- **GRADE inconsistency now uses I²** instead of study count. Single-study comparisons return `not_assessable` (per Cochrane 10.10) instead of being silently auto-downgraded as "Serious". Pass `heterogeneity_per_outcome` to `hta_dossier` and the Cochrane bands (50–74% Moderate, 75–89% Serious, ≥90% Very Serious) are applied directly.
|
|
20
|
+
- **GRADE upgrading (Guyatt 2011)** — observational evidence with strong effects can now be upgraded from Low. Three criteria via `upgrading_per_outcome`: large effect (RR <0.5/>2.0 → +1; <0.2/>5.0 → +2), dose-response (+1), plausible confounding biasing toward null (+1). Capped at +2.
|
|
21
|
+
- **Bucher consistency check** — when direct head-to-head A-vs-C evidence exists alongside the indirect A-vs-C estimate, `evidence_indirect` automatically tests Bucher's consistency assumption and flags violations (NICE DSU TSD 18). |z|≥1.96 = "substantial — consistency assumption appears violated."
|
|
22
|
+
- **EQ-5D 5L impact is baseline-utility-aware.** Biz 2026 reports category-level medians, but the new 5L value set compresses utilities in the 0.6–0.9 range — a drug for mild plaque psoriasis (baseline ~0.85) sees a much bigger ICER increase than one for severe HS (baseline ~0.45), even though both are `non_cancer_qol_only`. Pass `baseline_utility` to `utility_value_set` for a calibrated estimate.
|
|
23
|
+
- **ChatGPT Custom GPT support** — new OpenAPI 3.1 adapter at `/api/openapi` lets you build a Custom GPT in 5 minutes. See [ChatGPT Custom GPT](#chatgpt-custom-gpt) below.
|
|
24
|
+
- **Surface-tagged analytics** — every `tool_call` PostHog event now carries a `surface` property (`claude_anthropic_web` / `chatgpt_adapter` / `claude_desktop` / `direct_mcp`) so you can break down usage by client.
|
|
25
|
+
|
|
26
|
+
See [CHANGELOG.md](./CHANGELOG.md) for the full diff.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
15
30
|
## Quick Start
|
|
16
31
|
|
|
17
32
|
### Claude Code
|
|
@@ -45,15 +60,23 @@ Add to your MCP configuration:
|
|
|
45
60
|
|
|
46
61
|
---
|
|
47
62
|
|
|
48
|
-
## Tools
|
|
63
|
+
## Tools (17)
|
|
49
64
|
|
|
50
65
|
| Tool | Purpose |
|
|
51
66
|
|------|---------|
|
|
52
|
-
| `literature_search` | Search
|
|
67
|
+
| `literature_search` | Search 44 data sources with a full PRISMA-style audit trail |
|
|
53
68
|
| `screen_abstracts` | PICO-based relevance scoring and study design classification |
|
|
54
69
|
| `risk_of_bias` | Cochrane RoB 2 / ROBINS-I / AMSTAR-2 with GRADE RoB domain summary |
|
|
55
|
-
| `
|
|
56
|
-
| `
|
|
70
|
+
| `evidence_network` | Build treatment comparison network and assess NMA feasibility |
|
|
71
|
+
| `evidence_indirect` | Bucher and frequentist NMA with **automatic consistency check** vs direct h2h evidence (NICE DSU TSD 18) |
|
|
72
|
+
| `population_adjusted_comparison` | MAIC and STC for population-adjusted indirect comparisons |
|
|
73
|
+
| `survival_fitting` | Fit 5 parametric distributions to KM data (NICE DSU TSD 14) |
|
|
74
|
+
| `itc_feasibility` | Assess the 3-assumption ITC framework and recommend Bucher / NMA / MAIC / STC / ML-NMR |
|
|
75
|
+
| `cost_effectiveness_model` | Markov / PartSA / decision-tree CEA with PSA, OWSA, CEAC, EVPI, EVPPI; QALY + evLYG support |
|
|
76
|
+
| `budget_impact_model` | ISPOR-compliant BIA with year-by-year output and treatment-displacement modelling |
|
|
77
|
+
| `hta_dossier` | Draft submissions for NICE, EMA, FDA, IQWiG, HAS, and EU JCA — GRADE table uses structured RoB when `rob_results` passed; **inconsistency uses I² when `heterogeneity_per_outcome` passed**; **GRADE upgrading (Guyatt 2011) supported via `upgrading_per_outcome`** |
|
|
78
|
+
| `utility_value_set` | EQ-5D-3L / 5L value-set reference + **baseline-utility-aware** Biz 2026 ICER impact estimator (UK 5L transition) |
|
|
79
|
+
| `validate_links` | HTTP validation of citation URLs before presentation |
|
|
57
80
|
| `project_create` | Initialize a persistent project workspace |
|
|
58
81
|
| `knowledge_search` | Full-text search across a project's raw/ and wiki/ trees |
|
|
59
82
|
| `knowledge_read` | Read any file from a project's knowledge base |
|
|
@@ -61,7 +84,7 @@ Add to your MCP configuration:
|
|
|
61
84
|
|
|
62
85
|
### `literature_search`
|
|
63
86
|
|
|
64
|
-
Searches across
|
|
87
|
+
Searches across 44 sources in parallel. Every call returns a **source selection table** showing which of the 44 sources were used and why — essential for HTA audit trails.
|
|
65
88
|
|
|
66
89
|
**Example call:**
|
|
67
90
|
```json
|
|
@@ -197,7 +220,7 @@ This single prompt exercises: `project_create` → `literature_search` → `scre
|
|
|
197
220
|
|
|
198
221
|
## Data Sources
|
|
199
222
|
|
|
200
|
-
**
|
|
223
|
+
**44 sources across 10 categories.** Every `literature_search` call includes a source selection table showing used/not-used status and reason for each.
|
|
201
224
|
|
|
202
225
|
<details>
|
|
203
226
|
<summary><b>Biomedical & Clinical Trials (5)</b></summary>
|
|
@@ -270,9 +293,11 @@ This single prompt exercises: `project_create` → `literature_search` → `scre
|
|
|
270
293
|
</details>
|
|
271
294
|
|
|
272
295
|
<details>
|
|
273
|
-
<summary><b>
|
|
296
|
+
<summary><b>HEOR Methodology & Utility Reference (3)</b></summary>
|
|
274
297
|
|
|
275
298
|
- **ISPOR** — HEOR methodology and conference abstracts
|
|
299
|
+
- **OHE (Office of Health Economics)** — EQ-5D value set research and HEOR methodology
|
|
300
|
+
- **EuroQol Group** — EQ-5D instruments, value sets, and registry
|
|
276
301
|
</details>
|
|
277
302
|
|
|
278
303
|
---
|
|
@@ -293,7 +318,7 @@ DOCX files are saved to `~/.heor-agent/projects/{project}/reports/` (when a proj
|
|
|
293
318
|
|
|
294
319
|
Every tool call returns a full audit record:
|
|
295
320
|
|
|
296
|
-
- **Source selection table** — all
|
|
321
|
+
- **Source selection table** — all 44 sources with used/not-used and reason
|
|
297
322
|
- **Sources queried** — queries sent, response counts, status, latency
|
|
298
323
|
- **Inclusions / exclusions** — counts with reasons
|
|
299
324
|
- **Methodology** — PRISMA-style for literature, ISPOR/NICE for economics
|
|
@@ -333,10 +358,11 @@ A companion chat interface is available at:
|
|
|
333
358
|
|
|
334
359
|
**https://web-michael-ns-projects.vercel.app**
|
|
335
360
|
|
|
336
|
-
- Chat with Claude
|
|
361
|
+
- Chat with Claude Sonnet 4.6 + all 17 HEOR tools
|
|
337
362
|
- **BYOK (Bring Your Own Key)** — paste your Anthropic API key in the settings; it stays in your browser's localStorage and is never stored on our servers
|
|
338
|
-
- Markdown rendering with styled tables, tool call cards with live progress timers
|
|
339
|
-
-
|
|
363
|
+
- Markdown rendering with styled tables, tool call cards with live progress timers, and theme-aware mermaid network diagrams
|
|
364
|
+
- 12 example prompts covering literature search, CEA, BIA, NMA, ITC feasibility, RoB, EQ-5D 5L, EU JCA dossiers
|
|
365
|
+
- Per-request MCP sessions (no cross-user session bleed)
|
|
340
366
|
|
|
341
367
|
The web UI calls the hosted MCP server on Railway for tool execution. No setup required — just add your API key and start querying.
|
|
342
368
|
|
|
@@ -353,6 +379,70 @@ Set `MCP_SERVER_URL` to point to your own MCP server instance (default: the publ
|
|
|
353
379
|
|
|
354
380
|
---
|
|
355
381
|
|
|
382
|
+
## ChatGPT Custom GPT
|
|
383
|
+
|
|
384
|
+
HEORAgent can also be used as a ChatGPT Custom GPT Action — useful when you (or your team) prefer the ChatGPT interface or have a ChatGPT Plus/Team account but no Anthropic API access.
|
|
385
|
+
|
|
386
|
+
The web tier exposes an OpenAPI 3.1 adapter at `/api/openapi`, with one POST endpoint per tool at `/api/v1/{tool_name}`. ChatGPT speaks this contract natively.
|
|
387
|
+
|
|
388
|
+
### What's different from the Anthropic surface
|
|
389
|
+
|
|
390
|
+
| | Web UI / MCP / Claude Desktop | ChatGPT Custom GPT |
|
|
391
|
+
|---|---|---|
|
|
392
|
+
| Streaming | yes (SSE) | no (45s single response) |
|
|
393
|
+
| `psa_iterations` | up to 10,000 | capped to 1,000 (CEA) / 500 (BIA) |
|
|
394
|
+
| `literature_search.runs` | 1–5 | capped to 1 |
|
|
395
|
+
| `literature_search.max_results` | up to 100 | capped to 30 |
|
|
396
|
+
| Auth model | BYOK Anthropic | optional `X-API-Key` header (server-side `CHATGPT_ADAPTER_TOKEN`) |
|
|
397
|
+
| Surface label in PostHog | `claude_anthropic_web` / `claude_desktop` | `chatgpt_adapter` |
|
|
398
|
+
|
|
399
|
+
The caps exist because ChatGPT Actions hard-fail at the 45-second response timeout. PSA, multi-run literature search, and full max_results would routinely exceed it. The web UI and MCP clients are unaffected.
|
|
400
|
+
|
|
401
|
+
### Build a Custom GPT (ChatGPT Plus / Team required)
|
|
402
|
+
|
|
403
|
+
1. Visit [chatgpt.com/gpts/editor](https://chatgpt.com/gpts/editor) and click **Create**.
|
|
404
|
+
2. **Configure** tab — fill in name (e.g., "HEORAgent"), description, and conversation starters. Paste the system prompt from `web/lib/claude.ts` (or write your own — the tool descriptions are self-documenting).
|
|
405
|
+
3. **Actions** → **Create new action** → **Import from URL** → paste:
|
|
406
|
+
```
|
|
407
|
+
https://web-michael-ns-projects.vercel.app/api/openapi
|
|
408
|
+
```
|
|
409
|
+
ChatGPT auto-imports all 17 endpoints with their schemas.
|
|
410
|
+
4. **Authentication** — choose **None** for the open public endpoint, or **API Key** with the `CHATGPT_ADAPTER_TOKEN` value if you've configured one (recommended for prod).
|
|
411
|
+
5. **Privacy policy URL** — required by GPT Store. Use the web UI's privacy URL or your own.
|
|
412
|
+
6. **Test** in the playground (right pane), then **Publish** → "Anyone with the link" or "GPT Store".
|
|
413
|
+
|
|
414
|
+
### Securing the adapter for production
|
|
415
|
+
|
|
416
|
+
By default the `/api/v1/*` endpoint is open. Two layers of protection are recommended for any public-facing GPT:
|
|
417
|
+
|
|
418
|
+
```bash
|
|
419
|
+
# 1. Token-gate the endpoint
|
|
420
|
+
cd web
|
|
421
|
+
vercel env add CHATGPT_ADAPTER_TOKEN production # generate a long random token
|
|
422
|
+
# Configure the same token in your Custom GPT under Authentication → API Key
|
|
423
|
+
|
|
424
|
+
# 2. Built-in rate limit
|
|
425
|
+
# 60 req/min per IP is enforced automatically (lib/rateLimit.ts).
|
|
426
|
+
# For multi-region/high-traffic prod, swap in @upstash/ratelimit + Vercel KV.
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
### Sample call (manual, no GPT needed)
|
|
430
|
+
|
|
431
|
+
```bash
|
|
432
|
+
curl -X POST https://web-michael-ns-projects.vercel.app/api/v1/utility_value_set \
|
|
433
|
+
-H "Content-Type: application/json" \
|
|
434
|
+
-d '{
|
|
435
|
+
"action": "estimate_impact",
|
|
436
|
+
"indication_type": "non_cancer_qol_only",
|
|
437
|
+
"baseline_utility": 0.85,
|
|
438
|
+
"base_icer": 30000
|
|
439
|
+
}'
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
Returns the Biz 2026 baseline-utility-adjusted ICER projection (the new EQ-5D 5L impact estimator).
|
|
443
|
+
|
|
444
|
+
---
|
|
445
|
+
|
|
356
446
|
## HTTP Transport
|
|
357
447
|
|
|
358
448
|
The server supports both **stdio** (default, for local MCP clients) and **Streamable HTTP** (for hosted deployment).
|
|
@@ -379,7 +469,7 @@ HTTP endpoints:
|
|
|
379
469
|
git clone https://github.com/neptun2000/heor-agent-mcp
|
|
380
470
|
cd heor-agent-mcp
|
|
381
471
|
npm install
|
|
382
|
-
npm test #
|
|
472
|
+
npm test # 401 tests across 84 suites
|
|
383
473
|
npm run build # Compile TypeScript to dist/
|
|
384
474
|
npm run dev # Run with tsx (no build step)
|
|
385
475
|
```
|
|
@@ -398,10 +488,10 @@ npm run dev # Run with tsx (no build step)
|
|
|
398
488
|
┌────────────────▼──────────────────────────┐
|
|
399
489
|
│ heor-agent-mcp server │
|
|
400
490
|
│ ┌──────────────────────────────────────┐ │
|
|
401
|
-
│ │
|
|
491
|
+
│ │ 17 MCP tools (Zod-validated) │ │
|
|
402
492
|
│ ├──────────────────────────────────────┤ │
|
|
403
493
|
│ │ DirectProvider (default) │ │
|
|
404
|
-
│ │ ├─
|
|
494
|
+
│ │ ├─ 44 source fetchers │ │
|
|
405
495
|
│ │ ├─ Audit builder + PRISMA trail │ │
|
|
406
496
|
│ │ ├─ Markov / PartSA economic models │ │
|
|
407
497
|
│ │ ├─ Markdown + DOCX formatters │ │
|
package/dist/analytics.d.ts
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Map MCP `clientInfo.name` (set by the calling client during initialize)
|
|
3
|
+
* to a canonical surface label so PostHog can distinguish events from
|
|
4
|
+
* Claude Desktop, the Vercel web UI, the ChatGPT Custom GPT adapter, etc.
|
|
5
|
+
*
|
|
6
|
+
* Returns "direct_mcp" for unknown / npx / third-party clients.
|
|
7
|
+
*/
|
|
8
|
+
export type ClientSurface = "claude_anthropic_web" | "chatgpt_adapter" | "claude_desktop" | "smithery" | "glama" | "pulsemcp" | "direct_mcp";
|
|
9
|
+
export declare function inferSurface(clientName: string | undefined): ClientSurface;
|
|
1
10
|
export declare function trackEvent(event: string, properties?: Record<string, unknown>, sessionId?: string): void;
|
|
2
11
|
export declare function trackToolCall(toolName: string, durationMs: number, status: "ok" | "error", sessionId?: string, properties?: Record<string, unknown>): void;
|
|
3
12
|
export declare function trackSession(event: "session_start" | "session_end", sessionId: string, properties?: Record<string, unknown>): void;
|
package/dist/analytics.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../src/analytics.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../src/analytics.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,GACrB,sBAAsB,GACtB,iBAAiB,GACjB,gBAAgB,GAChB,UAAU,GACV,OAAO,GACP,UAAU,GACV,YAAY,CAAC;AAEjB,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,aAAa,CAe1E;AAgBD,wBAAgB,UAAU,CACxB,KAAK,EAAE,MAAM,EACb,UAAU,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACxC,SAAS,CAAC,EAAE,MAAM,QAanB;AAED,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,IAAI,GAAG,OAAO,EACtB,SAAS,CAAC,EAAE,MAAM,EAClB,UAAU,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,QAYzC;AAED,wBAAgB,YAAY,CAC1B,KAAK,EAAE,eAAe,GAAG,aAAa,EACtC,SAAS,EAAE,MAAM,EACjB,UAAU,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,QAGzC;AAED,wBAAsB,iBAAiB,kBAKtC"}
|
package/dist/analytics.js
CHANGED
|
@@ -1,4 +1,24 @@
|
|
|
1
1
|
import { PostHog } from "posthog-node";
|
|
2
|
+
export function inferSurface(clientName) {
|
|
3
|
+
if (!clientName)
|
|
4
|
+
return "direct_mcp";
|
|
5
|
+
const n = clientName.toLowerCase();
|
|
6
|
+
if (n.startsWith("heor-web-ui"))
|
|
7
|
+
return "claude_anthropic_web";
|
|
8
|
+
if (n.startsWith("chatgpt-adapter"))
|
|
9
|
+
return "chatgpt_adapter";
|
|
10
|
+
if (n === "claude" ||
|
|
11
|
+
n.startsWith("claude-ai") ||
|
|
12
|
+
n.startsWith("claude-desktop"))
|
|
13
|
+
return "claude_desktop";
|
|
14
|
+
if (n.startsWith("smithery"))
|
|
15
|
+
return "smithery";
|
|
16
|
+
if (n.startsWith("glama"))
|
|
17
|
+
return "glama";
|
|
18
|
+
if (n.startsWith("pulsemcp"))
|
|
19
|
+
return "pulsemcp";
|
|
20
|
+
return "direct_mcp";
|
|
21
|
+
}
|
|
2
22
|
let client = null;
|
|
3
23
|
function getClient() {
|
|
4
24
|
if (client)
|
package/dist/analytics.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analytics.js","sourceRoot":"","sources":["../src/analytics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"analytics.js","sourceRoot":"","sources":["../src/analytics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAkBvC,MAAM,UAAU,YAAY,CAAC,UAA8B;IACzD,IAAI,CAAC,UAAU;QAAE,OAAO,YAAY,CAAC;IACrC,MAAM,CAAC,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;IACnC,IAAI,CAAC,CAAC,UAAU,CAAC,aAAa,CAAC;QAAE,OAAO,sBAAsB,CAAC;IAC/D,IAAI,CAAC,CAAC,UAAU,CAAC,iBAAiB,CAAC;QAAE,OAAO,iBAAiB,CAAC;IAC9D,IACE,CAAC,KAAK,QAAQ;QACd,CAAC,CAAC,UAAU,CAAC,WAAW,CAAC;QACzB,CAAC,CAAC,UAAU,CAAC,gBAAgB,CAAC;QAE9B,OAAO,gBAAgB,CAAC;IAC1B,IAAI,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,UAAU,CAAC;IAChD,IAAI,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,OAAO,CAAC;IAC1C,IAAI,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,UAAU,CAAC;IAChD,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,IAAI,MAAM,GAAmB,IAAI,CAAC;AAElC,SAAS,SAAS;IAChB,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAC1B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;IACxC,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,MAAM,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE;QACxB,IAAI,EAAE,0BAA0B;QAChC,OAAO,EAAE,CAAC;QACV,aAAa,EAAE,KAAK;KACrB,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,UAAU,CACxB,KAAa,EACb,aAAsC,EAAE,EACxC,SAAkB;IAElB,MAAM,EAAE,GAAG,SAAS,EAAE,CAAC;IACvB,IAAI,CAAC,EAAE;QAAE,OAAO;IAEhB,EAAE,CAAC,OAAO,CAAC;QACT,UAAU,EAAE,SAAS,IAAI,WAAW;QACpC,KAAK;QACL,UAAU,EAAE;YACV,cAAc,EAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,SAAS;YAC5D,GAAG,UAAU;SACd;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,QAAgB,EAChB,UAAkB,EAClB,MAAsB,EACtB,SAAkB,EAClB,aAAsC,EAAE;IAExC,UAAU,CACR,WAAW,EACX;QACE,SAAS,EAAE,QAAQ;QACnB,WAAW,EAAE,UAAU;QACvB,MAAM;QACN,GAAG,UAAU;KACd,EACD,SAAS,CACV,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,KAAsC,EACtC,SAAiB,EACjB,aAAsC,EAAE;IAExC,UAAU,CAAC,KAAK,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,MAAM,CAAC,QAAQ,EAAE,CAAC;QACxB,MAAM,GAAG,IAAI,CAAC;IAChB,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"comparisonMarkdown.d.ts","sourceRoot":"","sources":["../../src/formatters/comparisonMarkdown.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAYpE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,wBAAwB,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"comparisonMarkdown.d.ts","sourceRoot":"","sources":["../../src/formatters/comparisonMarkdown.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAYpE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,wBAAwB,GAAG,MAAM,CA2H7E"}
|
|
@@ -47,6 +47,22 @@ export function comparisonToMarkdown(result) {
|
|
|
47
47
|
lines.push(`| ${e.intervention} vs ${e.comparator} | ${est} | ${ci} | ${p} | ${via} | ${method} |`);
|
|
48
48
|
}
|
|
49
49
|
lines.push("");
|
|
50
|
+
// Bucher consistency check (when direct h2h evidence available)
|
|
51
|
+
const conflicts = estimates.filter((e) => e.consistency_check && e.consistency_check.severity !== "none");
|
|
52
|
+
if (conflicts.length > 0) {
|
|
53
|
+
lines.push("**Bucher consistency check (direct vs indirect):**");
|
|
54
|
+
lines.push("");
|
|
55
|
+
for (const e of conflicts) {
|
|
56
|
+
const c = e.consistency_check;
|
|
57
|
+
const icon = c.severity === "substantial"
|
|
58
|
+
? "🚨"
|
|
59
|
+
: c.severity === "moderate"
|
|
60
|
+
? "⚠️"
|
|
61
|
+
: "ℹ️";
|
|
62
|
+
lines.push(`${icon} **${e.intervention} vs ${e.comparator}** (severity: ${c.severity}): ${c.rationale}`);
|
|
63
|
+
}
|
|
64
|
+
lines.push("");
|
|
65
|
+
}
|
|
50
66
|
}
|
|
51
67
|
// Heterogeneity statistics (I², Cochran Q)
|
|
52
68
|
if (result.heterogeneity && result.heterogeneity.length > 0) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"comparisonMarkdown.js","sourceRoot":"","sources":["../../src/formatters/comparisonMarkdown.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"comparisonMarkdown.js","sourceRoot":"","sources":["../../src/formatters/comparisonMarkdown.ts"],"names":[],"mappings":"AAEA,SAAS,SAAS,CAAC,CAAS,EAAE,WAAmB,CAAC;IAChD,OAAO,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AAC7B,CAAC;AAED,SAAS,OAAO,CAAC,CAAS;IACxB,IAAI,CAAC,GAAG,KAAK;QAAE,OAAO,QAAQ,CAAC;IAC/B,IAAI,CAAC,GAAG,IAAI;QAAE,OAAO,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACrC,OAAO,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,MAAgC;IACnE,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;IAChD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEf,MAAM,WAAW,GACf,MAAM,CAAC,MAAM,KAAK,QAAQ;QACxB,CAAC,CAAC,eAAe;QACjB,CAAC,CAAC,MAAM,CAAC,MAAM,KAAK,iBAAiB;YACnC,CAAC,CAAC,mCAAmC;YACrC,CAAC,CAAC,eAAe,CAAC;IACxB,KAAK,CAAC,IAAI,CAAC,eAAe,WAAW,EAAE,CAAC,CAAC;IACzC,KAAK,CAAC,IAAI,CAAC,oBAAoB,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;IAC1D,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEf,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,KAAK,CAAC,IAAI,CACR,2HAA2H,CAC5H,CAAC;QACF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,mBAAmB;IACnB,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAmC,CAAC;IAC5D,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QACjC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC;YAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAC1D,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACnC,CAAC;IAED,KAAK,MAAM,CAAC,OAAO,EAAE,SAAS,CAAC,IAAI,QAAQ,EAAE,CAAC;QAC5C,KAAK,CAAC,IAAI,CAAC,OAAO,OAAO,EAAE,CAAC,CAAC;QAC7B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEf,MAAM,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;QACrC,MAAM,KAAK,GAAG,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC;QAEhD,KAAK,CAAC,IAAI,CAAC,kBAAkB,KAAK,sCAAsC,CAAC,CAAC;QAC1E,KAAK,CAAC,IAAI,CAAC,4DAA4D,CAAC,CAAC;QAEzE,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;YAC1B,MAAM,GAAG,GACP,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;YACnE,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC;YAClE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;YAC7B,MAAM,GAAG,GAAG,CAAC,CAAC,gBAAgB,CAAC;YAC/B,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC;YAE9D,KAAK,CAAC,IAAI,CACR,KAAK,CAAC,CAAC,YAAY,OAAO,CAAC,CAAC,UAAU,MAAM,GAAG,MAAM,EAAE,MAAM,CAAC,MAAM,GAAG,MAAM,MAAM,IAAI,CACxF,CAAC;QACJ,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEf,gEAAgE;QAChE,MAAM,SAAS,GAAG,SAAS,CAAC,MAAM,CAChC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,iBAAiB,IAAI,CAAC,CAAC,iBAAiB,CAAC,QAAQ,KAAK,MAAM,CACtE,CAAC;QACF,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzB,KAAK,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAC;YACjE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACf,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;gBAC1B,MAAM,CAAC,GAAG,CAAC,CAAC,iBAAkB,CAAC;gBAC/B,MAAM,IAAI,GACR,CAAC,CAAC,QAAQ,KAAK,aAAa;oBAC1B,CAAC,CAAC,IAAI;oBACN,CAAC,CAAC,CAAC,CAAC,QAAQ,KAAK,UAAU;wBACzB,CAAC,CAAC,IAAI;wBACN,CAAC,CAAC,IAAI,CAAC;gBACb,KAAK,CAAC,IAAI,CACR,GAAG,IAAI,MAAM,CAAC,CAAC,YAAY,OAAO,CAAC,CAAC,UAAU,iBAAiB,CAAC,CAAC,QAAQ,MAAM,CAAC,CAAC,SAAS,EAAE,CAC7F,CAAC;YACJ,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjB,CAAC;IACH,CAAC;IAED,2CAA2C;IAC3C,IAAI,MAAM,CAAC,aAAa,IAAI,MAAM,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5D,KAAK,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;QAC3C,KAAK,CAAC,IAAI,CACR,oIAAoI,CACrI,CAAC;QACF,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CACR,8EAA8E,CAC/E,CAAC;QACF,KAAK,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAC;QACtD,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;YACrC,KAAK,CAAC,IAAI,CACR,KAAK,CAAC,CAAC,gBAAgB,MAAM,CAAC,CAAC,SAAS,MAAM,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,mBAAmB,IAAI,CACtM,CAAC;QACJ,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,CAAC,aAAa,CAAC,IAAI,CACvC,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,cAAc,KAAK,aAAa;YAClC,CAAC,CAAC,cAAc,KAAK,cAAc,CACtC,CAAC;QACF,IAAI,OAAO,EAAE,CAAC;YACZ,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACf,KAAK,CAAC,IAAI,CACR,mNAAmN,CACpN,CAAC;QACJ,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IAED,WAAW;IACX,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC3B,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YAChC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC1B,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IAED,cAAc;IACd,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAC9B,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QACnC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACvB,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Baseline-utility-aware EQ-5D 3L→5L impact estimator.
|
|
3
|
+
*
|
|
4
|
+
* Biz, Hernández Alava, Wailoo (2026) report category-level medians for the
|
|
5
|
+
* UK 3L→5L value-set transition. The new 5L value set has compressed utilities
|
|
6
|
+
* in mild–moderate health states relative to 3L (DSU mapping), which means
|
|
7
|
+
* the ICER impact of the transition depends strongly on the patient cohort's
|
|
8
|
+
* baseline utility:
|
|
9
|
+
*
|
|
10
|
+
* - non_cancer_qol_only: utility loss is concentrated in the 0.6–0.9 zone.
|
|
11
|
+
* Drugs treating MILD chronic conditions (baseline ~0.85, e.g., mild
|
|
12
|
+
* plaque psoriasis) see the biggest ICER increase. SEVERE versions of
|
|
13
|
+
* these conditions (baseline ~0.45, e.g., severe HS Hurley III) see
|
|
14
|
+
* less impact because patients spend more time in low-utility states
|
|
15
|
+
* where 5L compression is less severe.
|
|
16
|
+
*
|
|
17
|
+
* - cancer_life_extending: improvement is concentrated in severe states
|
|
18
|
+
* (5L assigns higher utility to the worst states than DSU mapping does),
|
|
19
|
+
* so a drug treating advanced/metastatic disease (baseline ~0.4) sees
|
|
20
|
+
* a bigger ICER decrease than one treating early-stage disease.
|
|
21
|
+
*
|
|
22
|
+
* - non_cancer_life_extending: Biz report mixed direction (7/11 decreased,
|
|
23
|
+
* 4/11 increased). Modulation is not defensible without the underlying
|
|
24
|
+
* state-by-state utility differences, so we return median + warning.
|
|
25
|
+
*
|
|
26
|
+
* The modulation factor is deliberately conservative — labelled as an
|
|
27
|
+
* extrapolation, not a finding from the paper. Users are advised to re-run
|
|
28
|
+
* their economic model with both value sets for an exact estimate.
|
|
29
|
+
*/
|
|
30
|
+
import type { IndicationType } from "../data/eq5dValueSets.js";
|
|
31
|
+
export interface BaselineAdjustedImpact {
|
|
32
|
+
indication_type: IndicationType;
|
|
33
|
+
icer_change_pct: {
|
|
34
|
+
point: number;
|
|
35
|
+
lower: number;
|
|
36
|
+
upper: number;
|
|
37
|
+
};
|
|
38
|
+
is_baseline_adjusted: boolean;
|
|
39
|
+
baseline_utility?: number;
|
|
40
|
+
rationale: string;
|
|
41
|
+
}
|
|
42
|
+
export declare function estimateBaselineAdjustedImpact(indication: IndicationType, baseline_utility: number | undefined): BaselineAdjustedImpact;
|
|
43
|
+
//# sourceMappingURL=eq5dImpact.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eq5dImpact.d.ts","sourceRoot":"","sources":["../../src/grade/eq5dImpact.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAG/D,MAAM,WAAW,sBAAsB;IACrC,eAAe,EAAE,cAAc,CAAC;IAChC,eAAe,EAAE;QACf,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,oBAAoB,EAAE,OAAO,CAAC;IAC9B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;CACnB;AA4BD,wBAAgB,8BAA8B,CAC5C,UAAU,EAAE,cAAc,EAC1B,gBAAgB,EAAE,MAAM,GAAG,SAAS,GACnC,sBAAsB,CAsFxB"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Baseline-utility-aware EQ-5D 3L→5L impact estimator.
|
|
3
|
+
*
|
|
4
|
+
* Biz, Hernández Alava, Wailoo (2026) report category-level medians for the
|
|
5
|
+
* UK 3L→5L value-set transition. The new 5L value set has compressed utilities
|
|
6
|
+
* in mild–moderate health states relative to 3L (DSU mapping), which means
|
|
7
|
+
* the ICER impact of the transition depends strongly on the patient cohort's
|
|
8
|
+
* baseline utility:
|
|
9
|
+
*
|
|
10
|
+
* - non_cancer_qol_only: utility loss is concentrated in the 0.6–0.9 zone.
|
|
11
|
+
* Drugs treating MILD chronic conditions (baseline ~0.85, e.g., mild
|
|
12
|
+
* plaque psoriasis) see the biggest ICER increase. SEVERE versions of
|
|
13
|
+
* these conditions (baseline ~0.45, e.g., severe HS Hurley III) see
|
|
14
|
+
* less impact because patients spend more time in low-utility states
|
|
15
|
+
* where 5L compression is less severe.
|
|
16
|
+
*
|
|
17
|
+
* - cancer_life_extending: improvement is concentrated in severe states
|
|
18
|
+
* (5L assigns higher utility to the worst states than DSU mapping does),
|
|
19
|
+
* so a drug treating advanced/metastatic disease (baseline ~0.4) sees
|
|
20
|
+
* a bigger ICER decrease than one treating early-stage disease.
|
|
21
|
+
*
|
|
22
|
+
* - non_cancer_life_extending: Biz report mixed direction (7/11 decreased,
|
|
23
|
+
* 4/11 increased). Modulation is not defensible without the underlying
|
|
24
|
+
* state-by-state utility differences, so we return median + warning.
|
|
25
|
+
*
|
|
26
|
+
* The modulation factor is deliberately conservative — labelled as an
|
|
27
|
+
* extrapolation, not a finding from the paper. Users are advised to re-run
|
|
28
|
+
* their economic model with both value sets for an exact estimate.
|
|
29
|
+
*/
|
|
30
|
+
import { getImpactEstimate } from "../data/eq5dValueSets.js";
|
|
31
|
+
/**
|
|
32
|
+
* Modulate the published median by baseline utility.
|
|
33
|
+
*
|
|
34
|
+
* Reference baselines (calibrated so multiplier=1.0 ≈ published median):
|
|
35
|
+
* - non_cancer_qol_only: ref_baseline = 0.65 (typical of NICE TA dataset)
|
|
36
|
+
* - cancer_life_extending: ref_baseline = 0.55
|
|
37
|
+
*
|
|
38
|
+
* Linear scaling within plausible bounds (×0.4 to ×1.7) — wider than the
|
|
39
|
+
* IQR of the published distribution to acknowledge extrapolation uncertainty.
|
|
40
|
+
*/
|
|
41
|
+
function multiplierForQolOnly(baseline) {
|
|
42
|
+
const ref = 0.65;
|
|
43
|
+
const slope = 1.5; // each +0.1 baseline → +15% multiplier
|
|
44
|
+
const raw = 1 + slope * (baseline - ref);
|
|
45
|
+
return Math.min(1.7, Math.max(0.4, raw));
|
|
46
|
+
}
|
|
47
|
+
function multiplierForCancer(baseline) {
|
|
48
|
+
// For cancer life-extending, a LOWER baseline means BIGGER impact (more negative %).
|
|
49
|
+
// ref=0.55 → multiplier=1.0
|
|
50
|
+
const ref = 0.55;
|
|
51
|
+
const slope = -2.0; // each +0.1 baseline → -20% multiplier (less impact)
|
|
52
|
+
const raw = 1 + slope * (baseline - ref);
|
|
53
|
+
return Math.min(1.7, Math.max(0.4, raw));
|
|
54
|
+
}
|
|
55
|
+
export function estimateBaselineAdjustedImpact(indication, baseline_utility) {
|
|
56
|
+
if (baseline_utility !== undefined) {
|
|
57
|
+
if (baseline_utility < 0 || baseline_utility > 1) {
|
|
58
|
+
throw new Error(`baseline_utility must be in [0, 1]; got ${baseline_utility}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
const published = getImpactEstimate(indication);
|
|
62
|
+
// Guard: indication categories without a published median (future entries
|
|
63
|
+
// added before data is populated) must not silently return a degenerate
|
|
64
|
+
// {0, 0, 0} range. Return is_baseline_adjusted=false with an explicit
|
|
65
|
+
// "no estimate available" rationale so callers can branch.
|
|
66
|
+
if (!published) {
|
|
67
|
+
return {
|
|
68
|
+
indication_type: indication,
|
|
69
|
+
icer_change_pct: { point: 0, lower: 0, upper: 0 },
|
|
70
|
+
is_baseline_adjusted: false,
|
|
71
|
+
baseline_utility,
|
|
72
|
+
rationale: `No published impact estimate for ${indication} — this category has no Biz 2026 entry yet. Re-run your model under both value sets for a direct estimate.`,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
const median = published.median_icer_change_pct;
|
|
76
|
+
// Range for unmodulated estimate (±25% of median to reflect inter-study spread)
|
|
77
|
+
const baseRange = {
|
|
78
|
+
point: median,
|
|
79
|
+
lower: median - Math.abs(median) * 0.25,
|
|
80
|
+
upper: median + Math.abs(median) * 0.25,
|
|
81
|
+
};
|
|
82
|
+
if (baseline_utility === undefined) {
|
|
83
|
+
return {
|
|
84
|
+
indication_type: indication,
|
|
85
|
+
icer_change_pct: baseRange,
|
|
86
|
+
is_baseline_adjusted: false,
|
|
87
|
+
rationale: `Published median for ${indication} (Biz et al. 2026, n=${published.examples?.length ?? 0} indication examples).`,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
if (indication === "non_cancer_life_extending") {
|
|
91
|
+
return {
|
|
92
|
+
indication_type: indication,
|
|
93
|
+
icer_change_pct: baseRange,
|
|
94
|
+
is_baseline_adjusted: false,
|
|
95
|
+
baseline_utility,
|
|
96
|
+
rationale: "Mixed/heterogeneous direction in Biz 2026 (7/11 decreased, 4/11 increased) — cannot reliably modulate by baseline utility. Re-run the model with both value sets for an exact estimate.",
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
let multiplier;
|
|
100
|
+
let directionalNote;
|
|
101
|
+
if (indication === "non_cancer_qol_only") {
|
|
102
|
+
multiplier = multiplierForQolOnly(baseline_utility);
|
|
103
|
+
directionalNote =
|
|
104
|
+
baseline_utility > 0.75
|
|
105
|
+
? `MILD baseline utility (${baseline_utility.toFixed(2)}) → 5L compression in mild-moderate states hits this cohort harder; expect larger ICER increase than category median.`
|
|
106
|
+
: baseline_utility < 0.55
|
|
107
|
+
? `SEVERE baseline utility (${baseline_utility.toFixed(2)}) → patients spend more time in low-utility states where 5L compression is less severe; expect smaller ICER increase than category median.`
|
|
108
|
+
: `Baseline utility (${baseline_utility.toFixed(2)}) near typical NICE TA dataset average — expect impact close to published median.`;
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
multiplier = multiplierForCancer(baseline_utility);
|
|
112
|
+
directionalNote =
|
|
113
|
+
baseline_utility < 0.45
|
|
114
|
+
? `Advanced/metastatic disease (baseline=${baseline_utility.toFixed(2)}) — 5L assigns higher utility to severe states than DSU mapping; expect larger ICER decrease than median.`
|
|
115
|
+
: baseline_utility > 0.65
|
|
116
|
+
? `Earlier-stage disease (baseline=${baseline_utility.toFixed(2)}) — patients spend less time in severe states; expect smaller ICER decrease than median.`
|
|
117
|
+
: `Baseline utility (${baseline_utility.toFixed(2)}) near typical advanced-cancer dataset average — expect impact close to published median.`;
|
|
118
|
+
}
|
|
119
|
+
const adjustedPoint = median * multiplier;
|
|
120
|
+
return {
|
|
121
|
+
indication_type: indication,
|
|
122
|
+
icer_change_pct: {
|
|
123
|
+
point: adjustedPoint,
|
|
124
|
+
lower: adjustedPoint - Math.abs(adjustedPoint) * 0.3,
|
|
125
|
+
upper: adjustedPoint + Math.abs(adjustedPoint) * 0.3,
|
|
126
|
+
},
|
|
127
|
+
is_baseline_adjusted: true,
|
|
128
|
+
baseline_utility,
|
|
129
|
+
rationale: `${directionalNote} This is an EXTRAPOLATION beyond Biz 2026 (which reports only category-level medians) — not a direct finding. Approximation: multiplier ${multiplier.toFixed(2)}× applied to published median ${median}%. Validate by re-running your model under both value sets.`,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=eq5dImpact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eq5dImpact.js","sourceRoot":"","sources":["../../src/grade/eq5dImpact.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GRADE Inconsistency assessment.
|
|
3
|
+
*
|
|
4
|
+
* Per Cochrane Handbook Ch. 10.10 / GRADE Handbook 5.1, inconsistency reflects
|
|
5
|
+
* heterogeneity of effect estimates across studies — NOT the number of studies.
|
|
6
|
+
*
|
|
7
|
+
* Single-study comparisons cannot be assessed for inconsistency; they are
|
|
8
|
+
* downgraded for imprecision instead. This function returns "not_assessable"
|
|
9
|
+
* for k=1, mapping I² bands to GRADE inconsistency levels otherwise.
|
|
10
|
+
*
|
|
11
|
+
* I² interpretation bands (Cochrane):
|
|
12
|
+
* 0–40% might not be important
|
|
13
|
+
* 30–60% moderate heterogeneity
|
|
14
|
+
* 50–90% substantial heterogeneity
|
|
15
|
+
* 75–100% considerable heterogeneity
|
|
16
|
+
*
|
|
17
|
+
* GRADE downgrade mapping:
|
|
18
|
+
* <50% Low (no downgrade)
|
|
19
|
+
* 50–75% Moderate (consider 1-step downgrade — "Serious")
|
|
20
|
+
* >75% Serious (1-step downgrade — "Very Serious" if ≥90%)
|
|
21
|
+
*/
|
|
22
|
+
export type GradeInconsistency = "not_assessable" | "Low" | "Moderate" | "Serious" | "Very Serious";
|
|
23
|
+
export interface InconsistencyAssessment {
|
|
24
|
+
level: GradeInconsistency;
|
|
25
|
+
downgrade_steps: 0 | 1 | 2;
|
|
26
|
+
rationale: string;
|
|
27
|
+
}
|
|
28
|
+
export declare function assessInconsistency(n_studies: number, i_squared_pct: number | null): InconsistencyAssessment;
|
|
29
|
+
//# sourceMappingURL=inconsistency.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inconsistency.d.ts","sourceRoot":"","sources":["../../src/grade/inconsistency.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,MAAM,MAAM,kBAAkB,GAC1B,gBAAgB,GAChB,KAAK,GACL,UAAU,GACV,SAAS,GACT,cAAc,CAAC;AAEnB,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,kBAAkB,CAAC;IAC1B,eAAe,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,GAAG,IAAI,GAC3B,uBAAuB,CAsDzB"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GRADE Inconsistency assessment.
|
|
3
|
+
*
|
|
4
|
+
* Per Cochrane Handbook Ch. 10.10 / GRADE Handbook 5.1, inconsistency reflects
|
|
5
|
+
* heterogeneity of effect estimates across studies — NOT the number of studies.
|
|
6
|
+
*
|
|
7
|
+
* Single-study comparisons cannot be assessed for inconsistency; they are
|
|
8
|
+
* downgraded for imprecision instead. This function returns "not_assessable"
|
|
9
|
+
* for k=1, mapping I² bands to GRADE inconsistency levels otherwise.
|
|
10
|
+
*
|
|
11
|
+
* I² interpretation bands (Cochrane):
|
|
12
|
+
* 0–40% might not be important
|
|
13
|
+
* 30–60% moderate heterogeneity
|
|
14
|
+
* 50–90% substantial heterogeneity
|
|
15
|
+
* 75–100% considerable heterogeneity
|
|
16
|
+
*
|
|
17
|
+
* GRADE downgrade mapping:
|
|
18
|
+
* <50% Low (no downgrade)
|
|
19
|
+
* 50–75% Moderate (consider 1-step downgrade — "Serious")
|
|
20
|
+
* >75% Serious (1-step downgrade — "Very Serious" if ≥90%)
|
|
21
|
+
*/
|
|
22
|
+
export function assessInconsistency(n_studies, i_squared_pct) {
|
|
23
|
+
if (n_studies <= 0) {
|
|
24
|
+
return {
|
|
25
|
+
level: "not_assessable",
|
|
26
|
+
downgrade_steps: 0,
|
|
27
|
+
rationale: "No studies — domain not assessable",
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
if (n_studies === 1) {
|
|
31
|
+
return {
|
|
32
|
+
level: "not_assessable",
|
|
33
|
+
downgrade_steps: 0,
|
|
34
|
+
rationale: "Single study — inconsistency not assessable (consider imprecision instead)",
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
if (i_squared_pct == null) {
|
|
38
|
+
// Was: level="Moderate", downgrade_steps=0 — internally inconsistent
|
|
39
|
+
// (every other Moderate path uses 1 step). Returning not_assessable
|
|
40
|
+
// with 0 downgrade forces an explicit manual decision instead of
|
|
41
|
+
// silently inflating GRADE certainty.
|
|
42
|
+
return {
|
|
43
|
+
level: "not_assessable",
|
|
44
|
+
downgrade_steps: 0,
|
|
45
|
+
rationale: "Multiple studies but I² not computed — manual heterogeneity review recommended",
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
if (i_squared_pct >= 90) {
|
|
49
|
+
return {
|
|
50
|
+
level: "Very Serious",
|
|
51
|
+
downgrade_steps: 2,
|
|
52
|
+
rationale: `I²=${i_squared_pct.toFixed(0)}% (considerable heterogeneity, ≥90%)`,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
if (i_squared_pct >= 75) {
|
|
56
|
+
return {
|
|
57
|
+
level: "Serious",
|
|
58
|
+
downgrade_steps: 1,
|
|
59
|
+
rationale: `I²=${i_squared_pct.toFixed(0)}% (considerable heterogeneity, 75–89%)`,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
if (i_squared_pct >= 50) {
|
|
63
|
+
return {
|
|
64
|
+
level: "Moderate",
|
|
65
|
+
downgrade_steps: 1,
|
|
66
|
+
rationale: `I²=${i_squared_pct.toFixed(0)}% (substantial heterogeneity, 50–74%)`,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
level: "Low",
|
|
71
|
+
downgrade_steps: 0,
|
|
72
|
+
rationale: `I²=${i_squared_pct.toFixed(0)}% (low heterogeneity, <50%)`,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=inconsistency.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inconsistency.js","sourceRoot":"","sources":["../../src/grade/inconsistency.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAeH,MAAM,UAAU,mBAAmB,CACjC,SAAiB,EACjB,aAA4B;IAE5B,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;QACnB,OAAO;YACL,KAAK,EAAE,gBAAgB;YACvB,eAAe,EAAE,CAAC;YAClB,SAAS,EAAE,oCAAoC;SAChD,CAAC;IACJ,CAAC;IACD,IAAI,SAAS,KAAK,CAAC,EAAE,CAAC;QACpB,OAAO;YACL,KAAK,EAAE,gBAAgB;YACvB,eAAe,EAAE,CAAC;YAClB,SAAS,EACP,4EAA4E;SAC/E,CAAC;IACJ,CAAC;IACD,IAAI,aAAa,IAAI,IAAI,EAAE,CAAC;QAC1B,qEAAqE;QACrE,oEAAoE;QACpE,iEAAiE;QACjE,sCAAsC;QACtC,OAAO;YACL,KAAK,EAAE,gBAAgB;YACvB,eAAe,EAAE,CAAC;YAClB,SAAS,EACP,gFAAgF;SACnF,CAAC;IACJ,CAAC;IACD,IAAI,aAAa,IAAI,EAAE,EAAE,CAAC;QACxB,OAAO;YACL,KAAK,EAAE,cAAc;YACrB,eAAe,EAAE,CAAC;YAClB,SAAS,EAAE,MAAM,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,sCAAsC;SAChF,CAAC;IACJ,CAAC;IACD,IAAI,aAAa,IAAI,EAAE,EAAE,CAAC;QACxB,OAAO;YACL,KAAK,EAAE,SAAS;YAChB,eAAe,EAAE,CAAC;YAClB,SAAS,EAAE,MAAM,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,wCAAwC;SAClF,CAAC;IACJ,CAAC;IACD,IAAI,aAAa,IAAI,EAAE,EAAE,CAAC;QACxB,OAAO;YACL,KAAK,EAAE,UAAU;YACjB,eAAe,EAAE,CAAC;YAClB,SAAS,EAAE,MAAM,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,uCAAuC;SACjF,CAAC;IACJ,CAAC;IACD,OAAO;QACL,KAAK,EAAE,KAAK;QACZ,eAAe,EAAE,CAAC;QAClB,SAAS,EAAE,MAAM,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,6BAA6B;KACvE,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GRADE Upgrading assessment for observational evidence (Guyatt 2011).
|
|
3
|
+
*
|
|
4
|
+
* GRADE allows upgrading observational studies that start at "Low" certainty
|
|
5
|
+
* for three specific reasons:
|
|
6
|
+
* 1. Large magnitude of effect (RR < 0.5 or > 2.0 → +1; RR < 0.2 or > 5.0 → +2)
|
|
7
|
+
* 2. Dose-response gradient
|
|
8
|
+
* 3. Plausible confounding/bias would reduce the observed effect (i.e.,
|
|
9
|
+
* bias is biasing toward null, so the true effect is likely larger)
|
|
10
|
+
*
|
|
11
|
+
* Total upgrade is capped at +2 steps. Upgrading does NOT apply when the
|
|
12
|
+
* starting certainty is High (RCTs) — RCTs cannot be upgraded above High.
|
|
13
|
+
*
|
|
14
|
+
* Reference: Guyatt GH et al. GRADE guidelines: 9. Rating up the quality
|
|
15
|
+
* of evidence. J Clin Epidemiol. 2011;64(12):1311-1316.
|
|
16
|
+
*/
|
|
17
|
+
export interface UpgradingInput {
|
|
18
|
+
/** Starting certainty before downgrades — "High" for RCTs, "Low" for observational. */
|
|
19
|
+
start_certainty: "High" | "Low";
|
|
20
|
+
/** Magnitude of effect (effect size relative to control). */
|
|
21
|
+
large_effect?: "none" | "large" | "very_large";
|
|
22
|
+
/** Documented dose-response gradient. */
|
|
23
|
+
dose_response?: boolean;
|
|
24
|
+
/** Plausible residual confounding would bias the effect toward null. */
|
|
25
|
+
plausible_confounding_toward_null?: boolean;
|
|
26
|
+
}
|
|
27
|
+
export interface UpgradingAssessment {
|
|
28
|
+
upgrade_steps: 0 | 1 | 2;
|
|
29
|
+
rationale: string;
|
|
30
|
+
}
|
|
31
|
+
export declare function assessUpgrading(input: UpgradingInput): UpgradingAssessment;
|
|
32
|
+
//# sourceMappingURL=upgrading.d.ts.map
|