heor-agent-mcp 1.2.2 → 1.3.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/README.md +2 -2
- package/dist/pv/decisionTree.d.ts +2 -0
- package/dist/pv/decisionTree.d.ts.map +1 -1
- package/dist/pv/decisionTree.js +92 -14
- package/dist/pv/decisionTree.js.map +1 -1
- package/dist/pv/gvpModules.d.ts +2 -1
- package/dist/pv/gvpModules.d.ts.map +1 -1
- package/dist/pv/gvpModules.js +7 -7
- package/dist/pv/gvpModules.js.map +1 -1
- package/dist/pv/signalDecision.d.ts +54 -0
- package/dist/pv/signalDecision.d.ts.map +1 -0
- package/dist/pv/signalDecision.js +115 -0
- package/dist/pv/signalDecision.js.map +1 -0
- package/dist/pv/signalStatistics.d.ts +67 -0
- package/dist/pv/signalStatistics.d.ts.map +1 -0
- package/dist/pv/signalStatistics.js +186 -0
- package/dist/pv/signalStatistics.js.map +1 -0
- package/dist/pv/types.d.ts +8 -1
- package/dist/pv/types.d.ts.map +1 -1
- package/dist/server.js +5 -0
- package/dist/server.js.map +1 -1
- package/dist/tools/htaDossierPrep.js +3 -3
- package/dist/tools/htaDossierPrep.js.map +1 -1
- package/dist/tools/pvClassify.d.ts +1 -1
- package/dist/tools/pvClassify.d.ts.map +1 -1
- package/dist/tools/pvClassify.js +20 -7
- package/dist/tools/pvClassify.js.map +1 -1
- package/dist/tools/pvSignalWorkflow.d.ts +82 -0
- package/dist/tools/pvSignalWorkflow.d.ts.map +1 -0
- package/dist/tools/pvSignalWorkflow.js +315 -0
- package/dist/tools/pvSignalWorkflow.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -70,7 +70,7 @@ Add to your MCP configuration:
|
|
|
70
70
|
|
|
71
71
|
---
|
|
72
72
|
|
|
73
|
-
## Tools (
|
|
73
|
+
## Tools (22)
|
|
74
74
|
|
|
75
75
|
| Tool | Purpose |
|
|
76
76
|
|------|---------|
|
|
@@ -368,7 +368,7 @@ A companion chat interface is available at:
|
|
|
368
368
|
|
|
369
369
|
**https://web-michael-ns-projects.vercel.app**
|
|
370
370
|
|
|
371
|
-
- Chat with Claude Sonnet 4.6 + all
|
|
371
|
+
- Chat with Claude Sonnet 4.6 + all 22 HEOR tools
|
|
372
372
|
- **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
|
|
373
373
|
- Markdown rendering with styled tables, tool call cards with live progress timers, and theme-aware mermaid network diagrams
|
|
374
374
|
- 12 example prompts covering literature search, CEA, BIA, NMA, ITC feasibility, RoB, EQ-5D 5L, EU JCA dossiers
|
|
@@ -17,6 +17,8 @@ interface Decision {
|
|
|
17
17
|
primary_category: PvCategory;
|
|
18
18
|
alternatives: PvCategory[];
|
|
19
19
|
rationale: string;
|
|
20
|
+
/** Optional advisory warnings surfaced from edge cases — handler attaches to audit. */
|
|
21
|
+
advisory_warnings?: string[];
|
|
20
22
|
}
|
|
21
23
|
export declare function classifyPv(input: PvClassifyInput): Decision;
|
|
22
24
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decisionTree.d.ts","sourceRoot":"","sources":["../../src/pv/decisionTree.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE9D,UAAU,QAAQ;IAChB,gBAAgB,EAAE,UAAU,CAAC;IAC7B,YAAY,EAAE,UAAU,EAAE,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"decisionTree.d.ts","sourceRoot":"","sources":["../../src/pv/decisionTree.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE9D,UAAU,QAAQ;IAChB,gBAAgB,EAAE,UAAU,CAAC;IAC7B,YAAY,EAAE,UAAU,EAAE,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,uFAAuF;IACvF,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,QAAQ,CAmI3D"}
|
package/dist/pv/decisionTree.js
CHANGED
|
@@ -1,39 +1,75 @@
|
|
|
1
1
|
export function classifyPv(input) {
|
|
2
|
-
// 1. Pre-authorisation: never PASS — characterise via ICH E2E plan
|
|
2
|
+
// 1. Pre-authorisation: never PASS — characterise via ICH E2E plan
|
|
3
|
+
// (which is an ICH guideline, NOT a GVP module). The plan informs
|
|
4
|
+
// the initial RMP that's submitted at MA grant under GVP Module V.
|
|
3
5
|
if (input.regulatory_context === "pre_authorisation") {
|
|
4
6
|
return withPregnancyOverride(input, {
|
|
5
7
|
primary_category: "ICH_E2E_pharmacovigilance_plan",
|
|
6
8
|
alternatives: [],
|
|
7
|
-
rationale: "Study is pre-authorisation. PASS designations require an existing marketing authorisation (Article 107a). Pharmacovigilance planning at this stage falls under ICH E2E
|
|
9
|
+
rationale: "Study is pre-authorisation. PASS designations require an existing marketing authorisation (Article 107a). Pharmacovigilance planning at this stage falls under ICH E2E — note that ICH E2E is a standalone ICH guideline, not a GVP module; the GVP Module V reference reflects the downstream RMP that the E2E plan informs at MAA submission, not a direct mapping.",
|
|
8
10
|
});
|
|
9
11
|
}
|
|
10
12
|
// 2. Spontaneous reports stand alone — Module VI baseline obligation.
|
|
13
|
+
// imposed_by_authority is contradictory here (spontaneous reporting
|
|
14
|
+
// is an inherent obligation, not something an authority can impose
|
|
15
|
+
// as a study) — surface a warning rather than silently dropping the
|
|
16
|
+
// flag.
|
|
11
17
|
if (input.study_design === "spontaneous_reports") {
|
|
18
|
+
const warnings = input.imposed_by_authority
|
|
19
|
+
? [
|
|
20
|
+
"Contradictory inputs: study_design='spontaneous_reports' AND imposed_by_authority=true. Spontaneous adverse-event reporting is an inherent PV obligation under GVP Module VI, not a designed study an authority can impose. The imposed_by_authority flag has been ignored.",
|
|
21
|
+
]
|
|
22
|
+
: undefined;
|
|
12
23
|
return withPregnancyOverride(input, {
|
|
13
24
|
primary_category: "spontaneous_reporting_only",
|
|
14
25
|
alternatives: [],
|
|
15
26
|
rationale: "Spontaneous adverse-event reporting is the baseline PV obligation under GVP Module VI, not a designed study. Categorised as spontaneous_reporting_only.",
|
|
27
|
+
advisory_warnings: warnings,
|
|
16
28
|
});
|
|
17
29
|
}
|
|
18
|
-
// 3.
|
|
30
|
+
// 3. Imposed PASS takes precedence over plain RMP_Annex_4_study —
|
|
31
|
+
// Article 107n imposition outranks Annex 4 listing. The Annex 4
|
|
32
|
+
// listing is then a downstream consequence of the imposition.
|
|
33
|
+
if (input.imposed_by_authority) {
|
|
34
|
+
const warnings = [];
|
|
35
|
+
if ((input.regulatory_context === "conditional_approval" ||
|
|
36
|
+
input.regulatory_context === "accelerated_approval") &&
|
|
37
|
+
!input.imposed_by_authority) {
|
|
38
|
+
// dead branch (imposed=true above) — guarded for clarity if reordered
|
|
39
|
+
}
|
|
40
|
+
return withPregnancyOverride(input, {
|
|
41
|
+
primary_category: "PASS_imposed",
|
|
42
|
+
alternatives: input.regulatory_context === "rmp_commitment"
|
|
43
|
+
? ["RMP_Annex_4_study"]
|
|
44
|
+
: ["RMP_Annex_4_study"],
|
|
45
|
+
rationale: input.regulatory_context === "rmp_commitment"
|
|
46
|
+
? "Authority-imposed obligation that is also tracked as an RMP Annex 4 commitment. Article 107n imposition is the primary classification — the Annex 4 listing is a consequence, not the primary route. Falls under GVP Module VIII (PASS imposed); PRAC pre-review of the protocol is required."
|
|
47
|
+
: "Authority-imposed obligation in a post-authorisation context (Article 107n). Falls under GVP Module VIII as a Post-Authorisation Safety Study (imposed). PRAC pre-review of the protocol is required.",
|
|
48
|
+
advisory_warnings: warnings.length > 0 ? warnings : undefined,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
// 4. RMP commitment context → Annex 4 listed study (when not imposed).
|
|
19
52
|
if (input.regulatory_context === "rmp_commitment") {
|
|
20
|
-
const alts = input.imposed_by_authority
|
|
21
|
-
? ["PASS_imposed"]
|
|
22
|
-
: ["PASS_voluntary"];
|
|
23
53
|
return withPregnancyOverride(input, {
|
|
24
54
|
primary_category: "RMP_Annex_4_study",
|
|
25
|
-
alternatives:
|
|
55
|
+
alternatives: ["PASS_voluntary"],
|
|
26
56
|
rationale: "Study is an explicit RMP commitment, listed in RMP Annex 4 with milestone tracking. Per EMA GVP Module V.",
|
|
27
57
|
});
|
|
28
58
|
}
|
|
29
|
-
//
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
-
|
|
59
|
+
// 4a. Conditional / accelerated approval WITHOUT imposed_by_authority —
|
|
60
|
+
// warn about Specific Obligations (CMA SOBs) per Article 14-a.
|
|
61
|
+
// Falling through to objective-based classification but the user
|
|
62
|
+
// should confirm whether the obligation is actually imposed.
|
|
63
|
+
if ((input.regulatory_context === "conditional_approval" ||
|
|
64
|
+
input.regulatory_context === "accelerated_approval") &&
|
|
65
|
+
!input.imposed_by_authority) {
|
|
66
|
+
const out = classifyByObjective(input);
|
|
33
67
|
return withPregnancyOverride(input, {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
68
|
+
...out,
|
|
69
|
+
advisory_warnings: [
|
|
70
|
+
...(out.advisory_warnings ?? []),
|
|
71
|
+
`regulatory_context='${input.regulatory_context}' typically carries Specific Obligations (CMA Article 14-a / accelerated-approval SOBs) that function as an imposed PASS even without imposed_by_authority=true. Confirm SOB status with regulatory affairs; if confirmed, re-run with imposed_by_authority=true to get the correct PASS_imposed classification + Module VIII PRAC pre-review obligations.`,
|
|
72
|
+
],
|
|
37
73
|
});
|
|
38
74
|
}
|
|
39
75
|
// 5. Otherwise classify by primary objective + study design.
|
|
@@ -82,6 +118,7 @@ function withPregnancyOverride(input, decision) {
|
|
|
82
118
|
alternatives: ["pregnancy_registry"],
|
|
83
119
|
rationale: decision.rationale +
|
|
84
120
|
" Pregnancy population: a pregnancy registry will be required as a post-authorisation commitment per ICH E2E and EMA pregnancy-registry guidance.",
|
|
121
|
+
advisory_warnings: decision.advisory_warnings,
|
|
85
122
|
};
|
|
86
123
|
}
|
|
87
124
|
if (decision.primary_category === "pregnancy_registry")
|
|
@@ -94,6 +131,47 @@ function withPregnancyOverride(input, decision) {
|
|
|
94
131
|
rationale: "Pregnancy population in scope → pregnancy registry takes priority over the primary classification. " +
|
|
95
132
|
decision.rationale +
|
|
96
133
|
" The original classification is retained as an alternative for protocol-design context.",
|
|
134
|
+
advisory_warnings: decision.advisory_warnings,
|
|
97
135
|
};
|
|
98
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* Pure classification by primary_objective. Extracted so the
|
|
139
|
+
* conditional_approval / accelerated_approval branch can reuse it without
|
|
140
|
+
* duplicating the switch.
|
|
141
|
+
*/
|
|
142
|
+
function classifyByObjective(input) {
|
|
143
|
+
switch (input.primary_objective) {
|
|
144
|
+
case "safety":
|
|
145
|
+
return {
|
|
146
|
+
primary_category: "PASS_voluntary",
|
|
147
|
+
alternatives: ["active_surveillance_registry"],
|
|
148
|
+
rationale: "Safety-objective post-authorisation study without an imposed obligation → voluntary PASS under GVP Module VIII.",
|
|
149
|
+
};
|
|
150
|
+
case "efficacy":
|
|
151
|
+
case "effectiveness":
|
|
152
|
+
return {
|
|
153
|
+
primary_category: "PAES",
|
|
154
|
+
alternatives: ["PASS_voluntary"],
|
|
155
|
+
rationale: "Effectiveness/efficacy-objective post-authorisation study → Post-Authorisation Efficacy Study (PAES).",
|
|
156
|
+
};
|
|
157
|
+
case "drug_utilization":
|
|
158
|
+
return {
|
|
159
|
+
primary_category: "DUS",
|
|
160
|
+
alternatives: ["PASS_voluntary"],
|
|
161
|
+
rationale: "Drug utilisation objective → DUS under GVP Module VIII Addendum I.",
|
|
162
|
+
};
|
|
163
|
+
case "natural_history":
|
|
164
|
+
return {
|
|
165
|
+
primary_category: "active_surveillance_registry",
|
|
166
|
+
alternatives: ["PASS_voluntary"],
|
|
167
|
+
rationale: "Natural history / disease epidemiology objective → active surveillance registry.",
|
|
168
|
+
};
|
|
169
|
+
case "risk_minimisation_evaluation":
|
|
170
|
+
return {
|
|
171
|
+
primary_category: "PASS_voluntary",
|
|
172
|
+
alternatives: ["DUS"],
|
|
173
|
+
rationale: "Evaluation of risk-minimisation measure effectiveness → categorised as PASS (voluntary unless imposed).",
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
}
|
|
99
177
|
//# sourceMappingURL=decisionTree.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decisionTree.js","sourceRoot":"","sources":["../../src/pv/decisionTree.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"decisionTree.js","sourceRoot":"","sources":["../../src/pv/decisionTree.ts"],"names":[],"mappings":"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"}
|
package/dist/pv/gvpModules.d.ts
CHANGED
|
@@ -9,7 +9,8 @@ import type { GvpModule, PvCategory } from "./types.js";
|
|
|
9
9
|
export declare const GVP_REVISION: "rev_4";
|
|
10
10
|
interface CategoryMapping {
|
|
11
11
|
gvp_module: GvpModule;
|
|
12
|
-
|
|
12
|
+
/** Plain-language ENCePP category label — NOT a registered protocol ID. */
|
|
13
|
+
encepp_study_category?: string;
|
|
13
14
|
rmp_implications: string[];
|
|
14
15
|
fda_analogue?: string;
|
|
15
16
|
submission_obligations: string[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gvpModules.d.ts","sourceRoot":"","sources":["../../src/pv/gvpModules.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExD,eAAO,MAAM,YAAY,EAAG,OAAgB,CAAC;AAE7C,UAAU,eAAe;IACvB,UAAU,EAAE,SAAS,CAAC;IACtB,
|
|
1
|
+
{"version":3,"file":"gvpModules.d.ts","sourceRoot":"","sources":["../../src/pv/gvpModules.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExD,eAAO,MAAM,YAAY,EAAG,OAAgB,CAAC;AAE7C,UAAU,eAAe;IACvB,UAAU,EAAE,SAAS,CAAC;IACtB,2EAA2E;IAC3E,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sBAAsB,EAAE,MAAM,EAAE,CAAC;CAClC;AAED,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,UAAU,EAAE,eAAe,CA2HhE,CAAC;AAEF,wBAAgB,MAAM,CAAC,QAAQ,EAAE,UAAU,GAAG,eAAe,CAE5D"}
|
package/dist/pv/gvpModules.js
CHANGED
|
@@ -2,7 +2,7 @@ export const GVP_REVISION = "rev_4";
|
|
|
2
2
|
export const CATEGORY_MAPPING = {
|
|
3
3
|
PASS_imposed: {
|
|
4
4
|
gvp_module: "VIII",
|
|
5
|
-
|
|
5
|
+
encepp_study_category: "PASS — post-authorisation safety study (imposed, GVP Module VIII). Use the ENCePP Code of Conduct checklist for protocol structure",
|
|
6
6
|
rmp_implications: [
|
|
7
7
|
"Update RMP Part III (PV Plan) to list this study as an imposed PASS.",
|
|
8
8
|
"Annex 4 of the RMP must reference the protocol and timelines.",
|
|
@@ -16,7 +16,7 @@ export const CATEGORY_MAPPING = {
|
|
|
16
16
|
},
|
|
17
17
|
PASS_voluntary: {
|
|
18
18
|
gvp_module: "VIII",
|
|
19
|
-
|
|
19
|
+
encepp_study_category: "PASS — post-authorisation safety study (voluntary, GVP Module VIII). ENCePP registration in EUPAS encouraged",
|
|
20
20
|
rmp_implications: [
|
|
21
21
|
"Document study as a voluntary PASS in RMP Part III.",
|
|
22
22
|
"No PRAC pre-approval required; encouraged ENCePP registration.",
|
|
@@ -29,7 +29,7 @@ export const CATEGORY_MAPPING = {
|
|
|
29
29
|
},
|
|
30
30
|
PAES: {
|
|
31
31
|
gvp_module: "VIII",
|
|
32
|
-
|
|
32
|
+
encepp_study_category: "PAES — post-authorisation efficacy study (GVP Module VIII)",
|
|
33
33
|
rmp_implications: [
|
|
34
34
|
"PAES results may trigger MA variation if effectiveness diverges from MA assumptions.",
|
|
35
35
|
],
|
|
@@ -41,7 +41,7 @@ export const CATEGORY_MAPPING = {
|
|
|
41
41
|
},
|
|
42
42
|
RMP_Annex_4_study: {
|
|
43
43
|
gvp_module: "V",
|
|
44
|
-
|
|
44
|
+
encepp_study_category: "RMP Annex 4 study (GVP Module V)",
|
|
45
45
|
rmp_implications: [
|
|
46
46
|
"Listed in RMP Annex 4 with study ID, status, milestone dates.",
|
|
47
47
|
"Study completion is a tracked RMP commitment.",
|
|
@@ -54,7 +54,7 @@ export const CATEGORY_MAPPING = {
|
|
|
54
54
|
},
|
|
55
55
|
DUS: {
|
|
56
56
|
gvp_module: "VIII_Addendum_I",
|
|
57
|
-
|
|
57
|
+
encepp_study_category: "DUS — drug utilisation study (GVP Module VIII Addendum I)",
|
|
58
58
|
rmp_implications: [
|
|
59
59
|
"DUS may be referenced in RMP Part III for risk minimisation effectiveness.",
|
|
60
60
|
],
|
|
@@ -66,7 +66,7 @@ export const CATEGORY_MAPPING = {
|
|
|
66
66
|
},
|
|
67
67
|
active_surveillance_registry: {
|
|
68
68
|
gvp_module: "VIII",
|
|
69
|
-
|
|
69
|
+
encepp_study_category: "Active surveillance registry (GVP Module VIII)",
|
|
70
70
|
rmp_implications: [
|
|
71
71
|
"Registry serves as data source for ongoing PV signal detection in RMP Part III.",
|
|
72
72
|
],
|
|
@@ -78,7 +78,7 @@ export const CATEGORY_MAPPING = {
|
|
|
78
78
|
},
|
|
79
79
|
pregnancy_registry: {
|
|
80
80
|
gvp_module: "VIII",
|
|
81
|
-
|
|
81
|
+
encepp_study_category: "Pregnancy registry (GVP Module VIII; refer to GVP Considerations P.III)",
|
|
82
82
|
rmp_implications: [
|
|
83
83
|
"Pregnancy registry is a standard RMP commitment for teratogenic-risk drugs (Annex 4).",
|
|
84
84
|
"Outcomes feed into the Pregnancy section of every PSUR.",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gvpModules.js","sourceRoot":"","sources":["../../src/pv/gvpModules.ts"],"names":[],"mappings":"AASA,MAAM,CAAC,MAAM,YAAY,GAAG,OAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"gvpModules.js","sourceRoot":"","sources":["../../src/pv/gvpModules.ts"],"names":[],"mappings":"AASA,MAAM,CAAC,MAAM,YAAY,GAAG,OAAgB,CAAC;AAW7C,MAAM,CAAC,MAAM,gBAAgB,GAAwC;IACnE,YAAY,EAAE;QACZ,UAAU,EAAE,MAAM;QAClB,qBAAqB,EAAE,oIAAoI;QAC3J,gBAAgB,EAAE;YAChB,sEAAsE;YACtE,+DAA+D;SAChE;QACD,YAAY,EAAE,0CAA0C;QACxD,sBAAsB,EAAE;YACtB,6EAA6E;YAC7E,8CAA8C;YAC9C,wDAAwD;SACzD;KACF;IACD,cAAc,EAAE;QACd,UAAU,EAAE,MAAM;QAClB,qBAAqB,EAAE,8GAA8G;QACrI,gBAAgB,EAAE;YAChB,qDAAqD;YACrD,gEAAgE;SACjE;QACD,YAAY,EAAE,oCAAoC;QAClD,sBAAsB,EAAE;YACtB,wDAAwD;YACxD,4CAA4C;SAC7C;KACF;IACD,IAAI,EAAE;QACJ,UAAU,EAAE,MAAM;QAClB,qBAAqB,EAAE,4DAA4D;QACnF,gBAAgB,EAAE;YAChB,sFAAsF;SACvF;QACD,YAAY,EAAE,kDAAkD;QAChE,sBAAsB,EAAE;YACtB,mDAAmD;YACnD,4CAA4C;SAC7C;KACF;IACD,iBAAiB,EAAE;QACjB,UAAU,EAAE,GAAG;QACf,qBAAqB,EAAE,kCAAkC;QACzD,gBAAgB,EAAE;YAChB,+DAA+D;YAC/D,+CAA+C;SAChD;QACD,YAAY,EAAE,2BAA2B;QACzC,sBAAsB,EAAE;YACtB,iDAAiD;YACjD,kCAAkC;SACnC;KACF;IACD,GAAG,EAAE;QACH,UAAU,EAAE,iBAAiB;QAC7B,qBAAqB,EAAE,2DAA2D;QAClF,gBAAgB,EAAE;YAChB,4EAA4E;SAC7E;QACD,YAAY,EAAE,iDAAiD;QAC/D,sBAAsB,EAAE;YACtB,mDAAmD;YACnD,8DAA8D;SAC/D;KACF;IACD,4BAA4B,EAAE;QAC5B,UAAU,EAAE,MAAM;QAClB,qBAAqB,EAAE,gDAAgD;QACvE,gBAAgB,EAAE;YAChB,iFAAiF;SAClF;QACD,YAAY,EAAE,sCAAsC;QACpD,sBAAsB,EAAE;YACtB,gCAAgC;YAChC,2CAA2C;SAC5C;KACF;IACD,kBAAkB,EAAE;QAClB,UAAU,EAAE,MAAM;QAClB,qBAAqB,EAAE,yEAAyE;QAChG,gBAAgB,EAAE;YAChB,uFAAuF;YACvF,yDAAyD;SAC1D;QACD,YAAY,EAAE,iCAAiC;QAC/C,sBAAsB,EAAE;YACtB,gCAAgC;YAChC,0DAA0D;YAC1D,6DAA6D;SAC9D;KACF;IACD,0BAA0B,EAAE;QAC1B,UAAU,EAAE,IAAI;QAChB,gBAAgB,EAAE;YAChB,gGAAgG;SACjG;QACD,YAAY,EAAE,WAAW;QACzB,sBAAsB,EAAE;YACtB,4DAA4D;YAC5D,wBAAwB;SACzB;KACF;IACD,8BAA8B,EAAE;QAC9B,UAAU,EAAE,GAAG;QACf,gBAAgB,EAAE;YAChB,iGAAiG;SAClG;QACD,YAAY,EAAE,0DAA0D;QACxE,sBAAsB,EAAE;YACtB,sDAAsD;YACtD,qCAAqC;SACtC;KACF;IACD,YAAY,EAAE;QACZ,UAAU,EAAE,MAAM;QAClB,gBAAgB,EAAE;YAChB,gFAAgF;SACjF;QACD,YAAY,EAAE,KAAK;QACnB,sBAAsB,EAAE;YACtB,mDAAmD;SACpD;KACF;CACF,CAAC;AAEF,MAAM,UAAU,MAAM,CAAC,QAAoB;IACzC,OAAO,gBAAgB,CAAC,QAAQ,CAAC,CAAC;AACpC,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure decision logic for pv_signal_workflow. Given disproportionality
|
|
3
|
+
* statistics, decide the signal verdict per EMA GVP Module IX rev 2 +
|
|
4
|
+
* common Bayesian / frequentist thresholds.
|
|
5
|
+
*/
|
|
6
|
+
import { type CaseCounts } from "./signalStatistics.js";
|
|
7
|
+
export type SignalVerdict = "no_signal" | "strengthening_signal" | "confirmed_signal" | "previously_known_signal" | "refuted_signal";
|
|
8
|
+
export interface SignalThresholds {
|
|
9
|
+
/** PRR ≥ this AND chi-squared ≥ chi2 AND N ≥ n_min triggers PRR */
|
|
10
|
+
prr_min: number;
|
|
11
|
+
ror_min: number;
|
|
12
|
+
ic025_min: number;
|
|
13
|
+
eb05_min: number;
|
|
14
|
+
chi2_min: number;
|
|
15
|
+
n_min: number;
|
|
16
|
+
}
|
|
17
|
+
export interface SignalStatisticsResult {
|
|
18
|
+
prr: {
|
|
19
|
+
value: number;
|
|
20
|
+
ci_low: number;
|
|
21
|
+
ci_high: number;
|
|
22
|
+
threshold_met: boolean;
|
|
23
|
+
};
|
|
24
|
+
ror: {
|
|
25
|
+
value: number;
|
|
26
|
+
ci_low: number;
|
|
27
|
+
ci_high: number;
|
|
28
|
+
threshold_met: boolean;
|
|
29
|
+
};
|
|
30
|
+
ic: {
|
|
31
|
+
value: number;
|
|
32
|
+
ic025: number;
|
|
33
|
+
threshold_met: boolean;
|
|
34
|
+
};
|
|
35
|
+
mgps: {
|
|
36
|
+
ebgm: number;
|
|
37
|
+
eb05: number;
|
|
38
|
+
eb95: number;
|
|
39
|
+
threshold_met: boolean;
|
|
40
|
+
};
|
|
41
|
+
chi_squared: number;
|
|
42
|
+
n_cases: number;
|
|
43
|
+
thresholds_used: "default" | "serious";
|
|
44
|
+
}
|
|
45
|
+
export declare function computeAllStats(counts: CaseCounts, outcomeSerious: boolean): SignalStatisticsResult;
|
|
46
|
+
export interface SignalDecisionInput {
|
|
47
|
+
stats: SignalStatisticsResult;
|
|
48
|
+
prior_known_signals: string[];
|
|
49
|
+
outcome_serious: boolean;
|
|
50
|
+
reported_event?: string;
|
|
51
|
+
thresholds?: SignalThresholds;
|
|
52
|
+
}
|
|
53
|
+
export declare function decideVerdict(input: SignalDecisionInput): SignalVerdict;
|
|
54
|
+
//# sourceMappingURL=signalDecision.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signalDecision.d.ts","sourceRoot":"","sources":["../../src/pv/signalDecision.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EACL,KAAK,UAAU,EAKhB,MAAM,uBAAuB,CAAC;AAE/B,MAAM,MAAM,aAAa,GACrB,WAAW,GACX,sBAAsB,GACtB,kBAAkB,GAClB,yBAAyB,GACzB,gBAAgB,CAAC;AAErB,MAAM,WAAW,gBAAgB;IAC/B,mEAAmE;IACnE,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAqBD,MAAM,WAAW,sBAAsB;IACrC,GAAG,EAAE;QACH,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,aAAa,EAAE,OAAO,CAAC;KACxB,CAAC;IACF,GAAG,EAAE;QACH,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,aAAa,EAAE,OAAO,CAAC;KACxB,CAAC;IACF,EAAE,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,OAAO,CAAA;KAAE,CAAC;IAC7D,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,OAAO,CAAA;KAAE,CAAC;IAC3E,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,SAAS,GAAG,SAAS,CAAC;CACxC;AAED,wBAAgB,eAAe,CAC7B,MAAM,EAAE,UAAU,EAClB,cAAc,EAAE,OAAO,GACtB,sBAAsB,CAqCxB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,sBAAsB,CAAC;IAC9B,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,eAAe,EAAE,OAAO,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC/B;AAyBD,wBAAgB,aAAa,CAAC,KAAK,EAAE,mBAAmB,GAAG,aAAa,CAwCvE"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure decision logic for pv_signal_workflow. Given disproportionality
|
|
3
|
+
* statistics, decide the signal verdict per EMA GVP Module IX rev 2 +
|
|
4
|
+
* common Bayesian / frequentist thresholds.
|
|
5
|
+
*/
|
|
6
|
+
import { computeIc, computeMgps, computePrr, computeRor, } from "./signalStatistics.js";
|
|
7
|
+
const DEFAULT_THRESHOLDS = {
|
|
8
|
+
prr_min: 2.0,
|
|
9
|
+
ror_min: 2.0,
|
|
10
|
+
ic025_min: 0.0,
|
|
11
|
+
eb05_min: 2.0,
|
|
12
|
+
chi2_min: 4.0,
|
|
13
|
+
n_min: 3,
|
|
14
|
+
};
|
|
15
|
+
/** Lower thresholds when the AE is serious (fatal / life-threatening / hospitalisation). */
|
|
16
|
+
const SERIOUS_THRESHOLDS = {
|
|
17
|
+
prr_min: 1.5,
|
|
18
|
+
ror_min: 1.5,
|
|
19
|
+
ic025_min: 0.0,
|
|
20
|
+
eb05_min: 1.5,
|
|
21
|
+
chi2_min: 4.0,
|
|
22
|
+
n_min: 3,
|
|
23
|
+
};
|
|
24
|
+
export function computeAllStats(counts, outcomeSerious) {
|
|
25
|
+
const T = outcomeSerious ? SERIOUS_THRESHOLDS : DEFAULT_THRESHOLDS;
|
|
26
|
+
const prr = computePrr(counts);
|
|
27
|
+
const ror = computeRor(counts);
|
|
28
|
+
const ic = computeIc(counts);
|
|
29
|
+
const mgps = computeMgps(counts);
|
|
30
|
+
return {
|
|
31
|
+
prr: {
|
|
32
|
+
value: prr.value,
|
|
33
|
+
ci_low: prr.ci_low,
|
|
34
|
+
ci_high: prr.ci_high,
|
|
35
|
+
threshold_met: prr.value >= T.prr_min &&
|
|
36
|
+
prr.chi_squared >= T.chi2_min &&
|
|
37
|
+
counts.drug_event >= T.n_min,
|
|
38
|
+
},
|
|
39
|
+
ror: {
|
|
40
|
+
value: ror.value,
|
|
41
|
+
ci_low: ror.ci_low,
|
|
42
|
+
ci_high: ror.ci_high,
|
|
43
|
+
threshold_met: ror.value >= T.ror_min && counts.drug_event >= T.n_min,
|
|
44
|
+
},
|
|
45
|
+
ic: {
|
|
46
|
+
value: ic.value,
|
|
47
|
+
ic025: ic.ic025,
|
|
48
|
+
threshold_met: ic.ic025 > T.ic025_min,
|
|
49
|
+
},
|
|
50
|
+
mgps: {
|
|
51
|
+
ebgm: mgps.ebgm,
|
|
52
|
+
eb05: mgps.eb05,
|
|
53
|
+
eb95: mgps.eb95,
|
|
54
|
+
threshold_met: mgps.eb05 >= T.eb05_min,
|
|
55
|
+
},
|
|
56
|
+
chi_squared: prr.chi_squared,
|
|
57
|
+
n_cases: counts.drug_event,
|
|
58
|
+
thresholds_used: outcomeSerious ? "serious" : "default",
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Returns true if `reported_event` matches any string in `prior_known_signals`
|
|
63
|
+
* by case-insensitive substring containment in either direction. Avoids both
|
|
64
|
+
* false negatives ("severe lactic acidosis" should match prior "lactic
|
|
65
|
+
* acidosis") and false positives ("myocardial infarction" must NOT match
|
|
66
|
+
* prior "lactic acidosis" just because both are non-empty strings).
|
|
67
|
+
*/
|
|
68
|
+
function reportedEventMatchesPriorSignal(reportedEvent, priorKnownSignals) {
|
|
69
|
+
if (!reportedEvent)
|
|
70
|
+
return false;
|
|
71
|
+
if (!priorKnownSignals || priorKnownSignals.length === 0)
|
|
72
|
+
return false;
|
|
73
|
+
const ev = reportedEvent.trim().toLowerCase();
|
|
74
|
+
if (!ev)
|
|
75
|
+
return false;
|
|
76
|
+
for (const prior of priorKnownSignals) {
|
|
77
|
+
const p = prior.trim().toLowerCase();
|
|
78
|
+
if (!p)
|
|
79
|
+
continue;
|
|
80
|
+
if (ev.includes(p) || p.includes(ev))
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
export function decideVerdict(input) {
|
|
86
|
+
const triggers = [
|
|
87
|
+
input.stats.prr.threshold_met,
|
|
88
|
+
input.stats.ror.threshold_met,
|
|
89
|
+
input.stats.ic.threshold_met,
|
|
90
|
+
input.stats.mgps.threshold_met,
|
|
91
|
+
].filter(Boolean).length;
|
|
92
|
+
// Previously-known classification fires only when the SPECIFIC reported
|
|
93
|
+
// event matches one of the prior known signals. Bare "prior_known_signals
|
|
94
|
+
// is non-empty" is NOT sufficient — that would suppress new signals for
|
|
95
|
+
// any drug with any known signal in its RMP.
|
|
96
|
+
if (triggers >= 2 &&
|
|
97
|
+
reportedEventMatchesPriorSignal(input.reported_event, input.prior_known_signals)) {
|
|
98
|
+
return "previously_known_signal";
|
|
99
|
+
}
|
|
100
|
+
// Refuted: all methods well below threshold AND N is reasonably large
|
|
101
|
+
if (triggers === 0 &&
|
|
102
|
+
input.stats.n_cases >= 10 &&
|
|
103
|
+
input.stats.prr.value < 0.5) {
|
|
104
|
+
return "refuted_signal";
|
|
105
|
+
}
|
|
106
|
+
if (triggers === 0)
|
|
107
|
+
return "no_signal";
|
|
108
|
+
if (triggers >= 2 &&
|
|
109
|
+
input.stats.n_cases >= 3 &&
|
|
110
|
+
input.stats.chi_squared >= 4) {
|
|
111
|
+
return "confirmed_signal";
|
|
112
|
+
}
|
|
113
|
+
return "strengthening_signal";
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=signalDecision.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signalDecision.js","sourceRoot":"","sources":["../../src/pv/signalDecision.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Disproportionality statistics for pharmacovigilance signal detection.
|
|
3
|
+
* Pure math, no I/O.
|
|
4
|
+
*
|
|
5
|
+
* Implements:
|
|
6
|
+
* - PRR (Proportional Reporting Ratio) — Evans 2001
|
|
7
|
+
* - ROR (Reporting Odds Ratio) — van Puijenbroek 2002
|
|
8
|
+
* - IC (Information Component, BCPNN posterior) — Bate 1998 / Norén 2006
|
|
9
|
+
* - MGPS (Multi-item Gamma-Poisson Shrinker) — DuMouchel 1999, with EBGM
|
|
10
|
+
* and EB05/EB95 via gamma-Poisson shrinkage
|
|
11
|
+
*
|
|
12
|
+
* 2x2 table convention:
|
|
13
|
+
* event not-event
|
|
14
|
+
* drug: a b drug_total = a + b
|
|
15
|
+
* not-drug: c d not-drug-total = c + d
|
|
16
|
+
* event_total = a + c; grand_total = a+b+c+d
|
|
17
|
+
*
|
|
18
|
+
* Inputs to the public functions are the four cell counts.
|
|
19
|
+
*/
|
|
20
|
+
export interface CaseCounts {
|
|
21
|
+
drug_event: number;
|
|
22
|
+
drug_total: number;
|
|
23
|
+
event_total: number;
|
|
24
|
+
grand_total: number;
|
|
25
|
+
}
|
|
26
|
+
/** PRR per Evans 2001. Two-sided 95% CI on log scale. */
|
|
27
|
+
export declare function computePrr(counts: CaseCounts): {
|
|
28
|
+
value: number;
|
|
29
|
+
ci_low: number;
|
|
30
|
+
ci_high: number;
|
|
31
|
+
chi_squared: number;
|
|
32
|
+
};
|
|
33
|
+
/** ROR per van Puijenbroek 2002. Two-sided 95% CI on log scale. */
|
|
34
|
+
export declare function computeRor(counts: CaseCounts): {
|
|
35
|
+
value: number;
|
|
36
|
+
ci_low: number;
|
|
37
|
+
ci_high: number;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* IC (Information Component) per Bate 1998 / Norén 2006 BCPNN.
|
|
41
|
+
* IC = log2(P(drug, event) / (P(drug) * P(event)))
|
|
42
|
+
* with shrinkage so IC values for low-N pairs shrink toward 0.
|
|
43
|
+
* IC025 is the 2.5th percentile of the posterior distribution (lower 95% CI).
|
|
44
|
+
*/
|
|
45
|
+
export declare function computeIc(counts: CaseCounts): {
|
|
46
|
+
value: number;
|
|
47
|
+
ic025: number;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* MGPS (Multi-item Gamma-Poisson Shrinker) per DuMouchel 1999.
|
|
51
|
+
* EBGM = empirical Bayes geometric mean of the relative reporting ratio,
|
|
52
|
+
* with gamma-Poisson shrinkage that pulls EBGM toward 1 when N is small.
|
|
53
|
+
*
|
|
54
|
+
* Simplified single-stratum implementation: prior alpha=beta=0.5 (Jeffreys).
|
|
55
|
+
* EB05 / EB95 are 5th / 95th percentiles of the posterior gamma
|
|
56
|
+
* distribution, approximated via the Wilson-Hilferty cube-root transformation.
|
|
57
|
+
*
|
|
58
|
+
* Suitable for educational / first-pass screening use; matches FDA-Sentinel
|
|
59
|
+
* shape but uses single-stratum (not stratified) shrinkage. Stratification
|
|
60
|
+
* by sex / age can be added in a future revision.
|
|
61
|
+
*/
|
|
62
|
+
export declare function computeMgps(counts: CaseCounts): {
|
|
63
|
+
ebgm: number;
|
|
64
|
+
eb05: number;
|
|
65
|
+
eb95: number;
|
|
66
|
+
};
|
|
67
|
+
//# sourceMappingURL=signalStatistics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signalStatistics.d.ts","sourceRoot":"","sources":["../../src/pv/signalStatistics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB;AAeD,yDAAyD;AACzD,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG;IAC9C,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACrB,CAkCA;AAED,mEAAmE;AACnE,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG;IAC9C,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB,CAaA;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,UAAU,GAAG;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAyBA;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,UAAU,GAAG;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAsBA"}
|