dsh-meta-analysis 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/LICENSE +201 -0
  3. package/README-zh.md +101 -0
  4. package/README.md +100 -2
  5. package/cordis.patch.yml +13 -0
  6. package/lib/config.d.ts +28 -0
  7. package/lib/config.d.ts.map +1 -0
  8. package/lib/config.js +26 -0
  9. package/lib/config.js.map +1 -0
  10. package/lib/effects.d.ts +52 -0
  11. package/lib/effects.d.ts.map +1 -0
  12. package/lib/effects.js +116 -0
  13. package/lib/effects.js.map +1 -0
  14. package/lib/index.d.ts +36 -0
  15. package/lib/index.d.ts.map +1 -0
  16. package/lib/index.js +43 -0
  17. package/lib/index.js.map +1 -0
  18. package/lib/math.d.ts +26 -0
  19. package/lib/math.d.ts.map +1 -0
  20. package/lib/math.js +162 -0
  21. package/lib/math.js.map +1 -0
  22. package/lib/pool.d.ts +86 -0
  23. package/lib/pool.d.ts.map +1 -0
  24. package/lib/pool.js +172 -0
  25. package/lib/pool.js.map +1 -0
  26. package/lib/report.d.ts +46 -0
  27. package/lib/report.d.ts.map +1 -0
  28. package/lib/report.js +92 -0
  29. package/lib/report.js.map +1 -0
  30. package/lib/tools/ma-convert.d.ts +10 -0
  31. package/lib/tools/ma-convert.d.ts.map +1 -0
  32. package/lib/tools/ma-convert.js +69 -0
  33. package/lib/tools/ma-convert.js.map +1 -0
  34. package/lib/tools/ma-pool.d.ts +12 -0
  35. package/lib/tools/ma-pool.d.ts.map +1 -0
  36. package/lib/tools/ma-pool.js +66 -0
  37. package/lib/tools/ma-pool.js.map +1 -0
  38. package/lib/tools/ma-report.d.ts +10 -0
  39. package/lib/tools/ma-report.d.ts.map +1 -0
  40. package/lib/tools/ma-report.js +107 -0
  41. package/lib/tools/ma-report.js.map +1 -0
  42. package/lib/tools/shared.d.ts +20 -0
  43. package/lib/tools/shared.d.ts.map +1 -0
  44. package/lib/tools/shared.js +14 -0
  45. package/lib/tools/shared.js.map +1 -0
  46. package/lib/version.d.ts +7 -0
  47. package/lib/version.d.ts.map +1 -0
  48. package/lib/version.js +7 -0
  49. package/lib/version.js.map +1 -0
  50. package/package.json +79 -4
  51. package/src/config.ts +42 -0
  52. package/src/effects.ts +148 -0
  53. package/src/index.ts +53 -0
  54. package/src/math.ts +149 -0
  55. package/src/pool.ts +236 -0
  56. package/src/report.ts +110 -0
  57. package/src/tools/ma-convert.ts +68 -0
  58. package/src/tools/ma-pool.ts +66 -0
  59. package/src/tools/ma-report.ts +102 -0
  60. package/src/tools/shared.ts +14 -0
  61. package/src/version.ts +7 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,48 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here. The format follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project
5
+ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [Unreleased]
8
+
9
+ ### Fixed
10
+
11
+ - `level` is now applied to the pooled and per-study confidence intervals. It
12
+ was accepted (and exposed in config) but the critical value was hard-coded to
13
+ the 95% value, so a `level` other than 0.95 silently produced 95% intervals.
14
+ - `ma_report` rejects a malformed `result` payload with `INVALID_INPUT` instead
15
+ of letting a `TypeError` escape the tool boundary.
16
+ - Invalid study objects, models and confidence levels raise `RangeError` and are
17
+ reported as `INVALID_INPUT` by the tools. A study CI must be centred on the
18
+ effect (it is required to be symmetric on the analysis scale), and CI bounds
19
+ must be finite.
20
+
21
+ ### Added
22
+
23
+ - Tests for the requested confidence level, invalid models/levels/studies,
24
+ malformed `ma_report` payloads and the function-plugin mount contract (21
25
+ tests total).
26
+
27
+ ## [0.1.0] - 2026-11-08
28
+
29
+ First release: meta-analysis arithmetic.
30
+
31
+ ### Added
32
+
33
+ - `ma_pool`: fixed-effect and DerSimonian–Laird random-effects pooling with
34
+ 95% CIs, Q/df/p, I², τ², per-study weights and warnings; SE may be supplied
35
+ directly or derived from a symmetric CI (a disagreement > 5% is rejected).
36
+ - `ma_convert`: OR/RR log conversion with CI-derived SE, d⇄r, d⇄OR (logistic
37
+ approximation), SMD from two means, and SE from a CI — each with the formula
38
+ it used.
39
+ - `ma_report`: forest-plot data plus Markdown and SARIF 2.1.0.
40
+ - Egger test at k ≥ 10, labelled a screening aid.
41
+ - Dependency-free χ²/t/Φ⁻¹ special functions with documented accuracy.
42
+ - 16 tests including hand-calculated pooled estimates.
43
+
44
+ ### Notes
45
+
46
+ - No REML/Paule–Mandel, meta-regression, subgroup automation, trim-and-fill or
47
+ plots.
48
+ - Pure arithmetic: no files are written, so there is no REP record.
package/LICENSE ADDED
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
package/README-zh.md ADDED
@@ -0,0 +1,101 @@
1
+ # dsh-meta-analysis
2
+
3
+ **把效应量合并起来 —— 每一步算术都能逐行核对。**
4
+
5
+ *带具名公式的效应量换算、固定效应与 DerSimonian–Laird 随机效应合并、Q / I² / τ²、森林图数据、Markdown + SARIF,以及一项在少于十项研究时拒绝运行的轻量 Egger 检验。*
6
+
7
+ [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)
8
+ [![Node](https://img.shields.io/badge/node-%5E22.19%20%7C%7C%20%3E%3D24.9-brightgreen.svg)]()
9
+
10
+ [English](README.md) · 简体中文
11
+
12
+ ---
13
+
14
+ ## 它做什么
15
+
16
+ - **`ma_pool`** —— 在单一分析尺度上做逆方差合并。固定效应:`w = 1/v`,合并值 `Σwθ/Σw`,`SE = 1/√Σw`。随机效应:DerSimonian–Laird `τ²`,权重 `1/(v+τ²)`。报告 Q、df、p、I²、τ²、各研究权重,以及按所请求置信水平(`level`,默认 0.95)计算的合并 CI/p。
17
+ - **`ma_convert`** —— OR⇄logOR、RR⇄logRR(由 CI 求 SE)、d⇄r、d⇄OR(logistic 近似)、由两个均值求 SMD、由 CI 求 SE。每个结果都会注明所用公式及任何近似。
18
+ - **`ma_report`** —— 与渲染器无关的森林图数据(效应、CI、权重百分比 + 合并行)、Markdown、SARIF 2.1.0。
19
+ - **Egger** —— 仅在 k ≥ 10 时运行:以 `θᵢ/SEᵢ` 对 `1/SEᵢ` 做 OLS;截距用于检验小样本研究效应。它被明确标为筛查辅助手段,而不是发表偏倚的证据。
20
+
21
+ ## 它不做什么
22
+
23
+ - **除 DL 外不做模型拟合。** 不支持 REML/Paule–Mandel,不做 meta 回归,不自动做亚组分析或留一法分析(输入由你自行调整),也不做 trim-and-fill。
24
+ - **不做偏倚风险判断。** 权重不反映研究质量。
25
+ - **不做数据提取。** 效应量与 SE 必须按同一尺度提供;`ma_convert` 可帮助生成。
26
+ - **不绘图。** 只提供森林图数据;绘制交给宿主或其他工具。
27
+ - **不写证据存储。** 本插件是纯算术:不会向磁盘写入任何内容,README 如实说明这一点,而不是假装存在 REP 记录。
28
+
29
+ ## 公式
30
+
31
+ | 量 | 公式 |
32
+ |---|---|
33
+ | 固定效应合并值 | `Σwᵢθᵢ / Σwᵢ`, `wᵢ = 1/vᵢ` |
34
+ | 随机效应合并值 | 同上,权重改为 `wᵢ* = 1/(vᵢ + τ²)` |
35
+ | Q | `Σ wᵢ(θᵢ − θ_FE)²`, df = k−1 |
36
+ | I² | `max(0, (Q − df)/Q)` |
37
+ | τ² (DL) | `max(0, (Q − df)/(Σw − Σw²/Σw))` |
38
+ | 由 CI 求 SE | `(high − low)/(2·z)` |
39
+ | d→r | `d/√(d²+4)` |
40
+ | d⇄OR | `exp(d·π/√3)` / `log(OR)·√3/π` |
41
+ | SMD | `(m₁−m₂)/s_pooled`, SE `√(1/n₁+1/n₂+d²/(2(n₁+n₂)))` |
42
+ | Egger | 以 `θᵢ/SEᵢ` 对 `1/SEᵢ` 做 OLS 的截距,t 检验 df = k−2 |
43
+
44
+ 正态尾部 p 使用 A&S 7.1.26 近似(约 1e-7);χ² 与 t 使用正则化不完全 gamma/beta 连分数(约 1e-10)。两者都在 `src/math.ts` 中实现,且无依赖。
45
+
46
+ ## 工具
47
+
48
+ ### `ma_pool`
49
+
50
+ `{ studies: [{label, effect, se?, ciLow?, ciHigh?}], model?, level? }` → `{ ok, result }`。
51
+
52
+ ### `ma_convert`
53
+
54
+ `{ conversion, value?, low?, high?, level?, mean1?, sd1?, n1?, mean2?, sd2?, n2? }` → `{ ok, result }`。
55
+
56
+ ### `ma_report`
57
+
58
+ `{ result, measure? }` → `{ ok, forest, markdown, sarif }`。
59
+
60
+ ### 错误码
61
+
62
+ `INVALID_INPUT`(非有限值、非正的 SE/OR/RR、|r| ≥ 1、SE 与 CI 不一致、k < 2)。
63
+
64
+ ## 兼容性与安装
65
+
66
+ | | |
67
+ |---|---|
68
+ | DeepSeek Harness | **`dsh-v0.2.1-rc.5`**(2026-11-08 实测);peer `>=0.2.1-0 <0.3.0 \|\| >=0.2.2-0 <0.3.0` |
69
+ | Node | `^22.19.0 \|\| >=24.9.0`(实测 `24.22.1`),仅 ESM |
70
+ | Peer 依赖 | `@perrylink/dsh-research-core ^0.1.0`、`@deepseek-ai/cordis ^4.0.5-alpha.1`、`@deepseek-ai/dsh-tools`、`@deepseek-ai/schemastery ^3.18.5-alpha.1` |
71
+ | 运行时依赖 | **零** |
72
+
73
+ ```sh
74
+ dsh plugin --profile <name> add @perrylink/dsh-research-core dsh-meta-analysis
75
+ dsh --profile <name> --dump-config | grep dsh-meta-analysis
76
+ ```
77
+
78
+ ## 配置
79
+
80
+ | 键 | 默认值 | 含义 |
81
+ |---|---|---|
82
+ | `enabled` | `true` | `false` 时不挂载任何内容 |
83
+ | `model` | `both` | 默认合并模型(`fixed` / `random` / `both`) |
84
+ | `level` | `0.95` | 默认置信水平 |
85
+
86
+ ## 评测
87
+
88
+ **21 个测试**:特殊函数对照已知临界值(χ²(8,2)=0.9817、t(2.306,8)≈0.05、z(1.96)≈0.05、Φ⁻¹(0.975))、换算(logOR+SE、d⇄r、d⇄OR、SMD、不可能输入)、合并(手工计算的固定/随机效应估计,三项研究得到 Q=8、I²=0.75、τ²=0.03)、合并与各研究 CI 按所请求置信水平计算、由 CI 推导 SE 及拒绝 SE/CI 不一致、非法模型/置信水平/研究输入、Egger 在 k=10 时的门控、异质性警告、工具 schema、格式错误报告拒绝、端到端报告、插件契约、包契约。
89
+
90
+ 不声称基准测试结果:这是闭式算术,其正确性用手工计算和已发表的临界值来核对,而不是靠带标注的语料。
91
+
92
+ ## 已知限制(v0.1)
93
+
94
+ - 每次调用只处理一个分析尺度;多尺度协调由调用方负责。
95
+ - 已知 DL 的 τ² 在 k 较小时有偏;当 k < 5 时插件会警告。
96
+ - Egger 检验假设效应服从正态分布,在少于约 10 项研究时检验效能不足。
97
+ - 不提供预测区间(可以在不改变接口的情况下加入)。
98
+
99
+ ## 许可
100
+
101
+ Apache-2.0。运行时不含第三方代码。
package/README.md CHANGED
@@ -1,3 +1,101 @@
1
- # Temporary Holding Version
1
+ # dsh-meta-analysis
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ **Pool the effect sizes — with arithmetic you can check line by line.**
4
+
5
+ *Effect-size conversion with named formulas, fixed-effect and DerSimonian–Laird random-effects pooling, Q / I² / τ², forest-plot data, Markdown + SARIF, and a light Egger test that refuses to run on fewer than ten studies.*
6
+
7
+ [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)
8
+ [![Node](https://img.shields.io/badge/node-%5E22.19%20%7C%7C%20%3E%3D24.9-brightgreen.svg)]()
9
+
10
+ English · [简体中文](README-zh.md)
11
+
12
+ ---
13
+
14
+ ## What it does
15
+
16
+ - **`ma_pool`** — inverse-variance pooling on one analysis scale. Fixed: `w = 1/v`, pooled `Σwθ/Σw`, `SE = 1/√Σw`. Random: DerSimonian–Laird `τ²`, weights `1/(v+τ²)`. Reports Q, df, p, I², τ², per-study weights and the pooled CI/p at the requested confidence level (`level`, default 0.95).
17
+ - **`ma_convert`** — OR⇄logOR, RR⇄logRR (SE from a CI), d⇄r, d⇄OR (logistic approximation), SMD from two means, SE from a CI. Every result names the formula and any approximation.
18
+ - **`ma_report`** — renderer-agnostic forest data (effect, CI, weight % + pooled row), Markdown, SARIF 2.1.0.
19
+ - **Egger** — only at k ≥ 10: OLS of θᵢ/SEᵢ on 1/SEᵢ; the intercept tests small-study effects. Labelled a screening aid, not proof of reporting bias.
20
+
21
+ ## What it does not do
22
+
23
+ - **No model fitting beyond DL.** No REML/Paule–Mandel, no meta-regression, no subgroup or leave-one-out automation (the inputs are yours to vary), no trim-and-fill.
24
+ - **No risk-of-bias judgement.** Weights do not encode study quality.
25
+ - **No data extraction.** Effect sizes and SEs must be supplied on one scale; `ma_convert` helps produce them.
26
+ - **No plots.** Forest data is provided; drawing belongs to the host or another tool.
27
+ - **No evidence store.** This plugin is pure arithmetic: nothing is written to disk, and the README says so instead of pretending there is a REP record.
28
+
29
+ ## Formulas
30
+
31
+ | Quantity | Formula |
32
+ |---|---|
33
+ | Fixed pooled | `Σwᵢθᵢ / Σwᵢ`, `wᵢ = 1/vᵢ` |
34
+ | Random pooled | same with `wᵢ* = 1/(vᵢ + τ²)` |
35
+ | Q | `Σ wᵢ(θᵢ − θ_FE)²`, df = k−1 |
36
+ | I² | `max(0, (Q − df)/Q)` |
37
+ | τ² (DL) | `max(0, (Q − df)/(Σw − Σw²/Σw))` |
38
+ | SE from CI | `(high − low)/(2·z)` |
39
+ | d→r | `d/√(d²+4)` |
40
+ | d⇄OR | `exp(d·π/√3)` / `log(OR)·√3/π` |
41
+ | SMD | `(m₁−m₂)/s_pooled`, SE `√(1/n₁+1/n₂+d²/(2(n₁+n₂)))` |
42
+ | Egger | OLS intercept of `θᵢ/SEᵢ` on `1/SEᵢ`, t with df = k−2 |
43
+
44
+ Normal-tail p uses an A&S 7.1.26 approximation (~1e-7); χ² and t use regularized incomplete gamma/beta continued fractions (~1e-10). Both are implemented in `src/math.ts` with no dependencies.
45
+
46
+ ## Tools
47
+
48
+ ### `ma_pool`
49
+
50
+ `{ studies: [{label, effect, se?, ciLow?, ciHigh?}], model?, level? }` → `{ ok, result }`.
51
+
52
+ ### `ma_convert`
53
+
54
+ `{ conversion, value?, low?, high?, level?, mean1?, sd1?, n1?, mean2?, sd2?, n2? }` → `{ ok, result }`.
55
+
56
+ ### `ma_report`
57
+
58
+ `{ result, measure? }` → `{ ok, forest, markdown, sarif }`.
59
+
60
+ ### Error codes
61
+
62
+ `INVALID_INPUT` (non-finite values, non-positive SE/OR/RR, |r| ≥ 1, SE/CI disagreement, k < 2).
63
+
64
+ ## Compatibility & install
65
+
66
+ | | |
67
+ |---|---|
68
+ | DeepSeek Harness | **`dsh-v0.2.1-rc.5`** (verified 2026-11-08); peer `>=0.2.1-0 <0.3.0 \|\| >=0.2.2-0 <0.3.0` |
69
+ | Node | `^22.19.0 \|\| >=24.9.0` (tested `24.22.1`), ESM only |
70
+ | Peers | `@perrylink/dsh-research-core ^0.1.0`, `@deepseek-ai/cordis ^4.0.5-alpha.1`, `@deepseek-ai/dsh-tools`, `@deepseek-ai/schemastery ^3.18.5-alpha.1` |
71
+ | Runtime dependencies | **zero** |
72
+
73
+ ```sh
74
+ dsh plugin --profile <name> add @perrylink/dsh-research-core dsh-meta-analysis
75
+ dsh --profile <name> --dump-config | grep dsh-meta-analysis
76
+ ```
77
+
78
+ ## Configuration
79
+
80
+ | Key | Default | Meaning |
81
+ |---|---|---|
82
+ | `enabled` | `true` | `false` mounts nothing |
83
+ | `model` | `both` | default pooling model (`fixed` / `random` / `both`) |
84
+ | `level` | `0.95` | default confidence level |
85
+
86
+ ## Evaluation
87
+
88
+ **21 tests**: special functions against known critical values (χ²(8,2)=0.9817, t(2.306,8)≈0.05, z(1.96)≈0.05, Φ⁻¹(0.975)), conversions (logOR+SE, d⇄r, d⇄OR, SMD, impossible inputs), pooling (hand-calculated fixed/random estimates, Q=8, I²=0.75, τ²=0.03 from three studies), the requested confidence level for pooled and study CIs, CI-derived SE and SE/CI disagreement rejection, invalid models/levels/studies, Egger gating at k=10, heterogeneity warnings, tool schemas, malformed-report rejection, end-to-end report, plugin contract, package contract.
89
+
90
+ No benchmark is claimed: this is closed-form arithmetic whose correctness is checked against hand calculations and published critical values, not against a labelled corpus.
91
+
92
+ ## Known limitations (v0.1)
93
+
94
+ - One analysis scale per call; multi-scale harmonisation is the caller's job.
95
+ - DL τ² is known to be biased at small k; the plugin warns when k < 5.
96
+ - The Egger test assumes a normal distribution of effects and is underpowered below ~10 studies.
97
+ - No prediction interval (could be added without changing the interface).
98
+
99
+ ## License
100
+
101
+ Apache-2.0. No third-party runtime code.
@@ -0,0 +1,13 @@
1
+ # dsh-meta-analysis bundle patch: mount the pooling tools.
2
+ #
3
+ # Every key below is a Config field (Schemastery schema); invalid values fail the
4
+ # profile load loudly. Everything is local arithmetic; no network, no store.
5
+ - insert:
6
+ - id: dsh-meta-analysis
7
+ name: dsh-meta-analysis
8
+ config:
9
+ enabled: true
10
+ # Default pooling model when a call does not choose one.
11
+ model: both
12
+ # Default confidence level for pooled and study CIs.
13
+ level: 0.95
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Config schema and resolution for `dsh-meta-analysis`.
3
+ * @module dsh-meta-analysis/config
4
+ */
5
+ import z from '@deepseek-ai/schemastery';
6
+ /** Raw plugin config. */
7
+ export interface Config {
8
+ enabled?: boolean;
9
+ /** Default model when a call does not choose one. */
10
+ model?: string;
11
+ /** Default confidence level. */
12
+ level?: number;
13
+ }
14
+ /** Fully resolved config. */
15
+ export interface ResolvedConfig {
16
+ readonly enabled: boolean;
17
+ readonly model: 'fixed' | 'random' | 'both';
18
+ readonly level: number;
19
+ }
20
+ /** Schemastery schema. */
21
+ export declare const Config: z<Config>;
22
+ /**
23
+ * Validate raw values and fill explicit defaults.
24
+ * @param config - raw plugin config.
25
+ * @returns the fully resolved config.
26
+ */
27
+ export declare function resolveConfig(config?: Config): ResolvedConfig;
28
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,CAAC,MAAM,0BAA0B,CAAA;AAExC,yBAAyB;AACzB,MAAM,WAAW,MAAM;IACrB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,qDAAqD;IACrD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,gCAAgC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,6BAA6B;AAC7B,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAA;IAC3C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAED,0BAA0B;AAC1B,eAAO,MAAM,MAAM,EAAE,CAAC,CAAC,MAAM,CAI3B,CAAA;AAEF;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,GAAE,MAAW,GAAG,cAAc,CAMjE"}
package/lib/config.js ADDED
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Config schema and resolution for `dsh-meta-analysis`.
3
+ * @module dsh-meta-analysis/config
4
+ */
5
+ import z from '@deepseek-ai/schemastery';
6
+ /** Schemastery schema. */
7
+ export const Config = z.object({
8
+ enabled: z.boolean().default(true),
9
+ model: z.string().default('both'),
10
+ level: z.number().default(0.95),
11
+ });
12
+ /**
13
+ * Validate raw values and fill explicit defaults.
14
+ * @param config - raw plugin config.
15
+ * @returns the fully resolved config.
16
+ */
17
+ export function resolveConfig(config = {}) {
18
+ const model = config.model ?? 'both';
19
+ if (!['fixed', 'random', 'both'].includes(model))
20
+ throw new TypeError('model must be fixed, random or both');
21
+ const level = config.level ?? 0.95;
22
+ if (!(level > 0 && level < 1))
23
+ throw new TypeError('level must be between 0 and 1');
24
+ return { enabled: config.enabled ?? true, model: model, level };
25
+ }
26
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,CAAC,MAAM,0BAA0B,CAAA;AAkBxC,0BAA0B;AAC1B,MAAM,CAAC,MAAM,MAAM,GAAc,CAAC,CAAC,MAAM,CAAC;IACxC,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAClC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC;IACjC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;CAChC,CAAC,CAAA;AAEF;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,SAAiB,EAAE;IAC/C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,MAAM,CAAA;IACpC,IAAI,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,SAAS,CAAC,qCAAqC,CAAC,CAAA;IAC5G,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,IAAI,CAAA;IAClC,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC;QAAE,MAAM,IAAI,SAAS,CAAC,+BAA+B,CAAC,CAAA;IACnF,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,IAAI,EAAE,KAAK,EAAE,KAAoC,EAAE,KAAK,EAAE,CAAA;AAChG,CAAC"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Effect-size conversions used by `ma_convert`.
3
+ *
4
+ * The formulas are textbook ones and are named in the output, so a reader can
5
+ * check them:
6
+ * - OR/RR ⇄ log scale; SE from a CI on the analysis scale
7
+ * - Cohen's d ⇄ r (equal groups): r = d / √(d² + 4)
8
+ * - d ⇄ OR (logistic approximation): OR = exp(d·π/√3)
9
+ * - SMD from two means: d = (m1 − m2)/s_pooled with the Hedges-style SE
10
+ *
11
+ * Conversions are lossy (the d⇄OR link assumes a logistic model); every result
12
+ * carries the formula name.
13
+ *
14
+ * @module dsh-meta-analysis/effects
15
+ */
16
+ /** Supported conversion names. */
17
+ export type Conversion = 'or-to-logor' | 'logor-to-or' | 'rr-to-logr' | 'logrr-to-rr' | 'd-to-r' | 'r-to-d' | 'd-to-or' | 'or-to-d' | 'smd-from-means' | 'ci-to-se';
18
+ /** Conversion request. */
19
+ export interface ConvertRequest {
20
+ readonly conversion: Conversion;
21
+ /** Input value (interpretation depends on the conversion). */
22
+ readonly value?: number;
23
+ /** Optional CI on the input scale (used by or/rr/ci-to-se). */
24
+ readonly low?: number;
25
+ readonly high?: number;
26
+ /** Confidence level for CI-derived SE (default 0.95). */
27
+ readonly level?: number;
28
+ /** Mean/SD/n for smd-from-means. */
29
+ readonly mean1?: number;
30
+ readonly sd1?: number;
31
+ readonly n1?: number;
32
+ readonly mean2?: number;
33
+ readonly sd2?: number;
34
+ readonly n2?: number;
35
+ }
36
+ /** Conversion result. */
37
+ export interface ConvertResult {
38
+ readonly conversion: Conversion;
39
+ readonly value: number;
40
+ readonly se?: number;
41
+ readonly formula: string;
42
+ readonly notes: readonly string[];
43
+ }
44
+ /** SE from a two-sided CI on the analysis scale. */
45
+ export declare function seFromCi(low: number, high: number, level?: number): number;
46
+ /**
47
+ * Convert one effect size.
48
+ * @param request - conversion and inputs.
49
+ * @returns the converted value, optional SE and the formula used.
50
+ */
51
+ export declare function convert(request: ConvertRequest): ConvertResult;
52
+ //# sourceMappingURL=effects.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"effects.d.ts","sourceRoot":"","sources":["../src/effects.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,kCAAkC;AAClC,MAAM,MAAM,UAAU,GAClB,aAAa,GACb,aAAa,GACb,YAAY,GACZ,aAAa,GACb,QAAQ,GACR,QAAQ,GACR,SAAS,GACT,SAAS,GACT,gBAAgB,GAChB,UAAU,CAAA;AAEd,0BAA0B;AAC1B,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAA;IAC/B,8DAA8D;IAC9D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,+DAA+D;IAC/D,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,yDAAyD;IACzD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,oCAAoC;IACpC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,yBAAyB;AACzB,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAA;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;CAClC;AAQD,oDAAoD;AACpD,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,SAAO,GAAG,MAAM,CAMxE;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,aAAa,CAoE9D"}