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.
- package/CHANGELOG.md +48 -0
- package/LICENSE +201 -0
- package/README-zh.md +101 -0
- package/README.md +100 -2
- package/cordis.patch.yml +13 -0
- package/lib/config.d.ts +28 -0
- package/lib/config.d.ts.map +1 -0
- package/lib/config.js +26 -0
- package/lib/config.js.map +1 -0
- package/lib/effects.d.ts +52 -0
- package/lib/effects.d.ts.map +1 -0
- package/lib/effects.js +116 -0
- package/lib/effects.js.map +1 -0
- package/lib/index.d.ts +36 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +43 -0
- package/lib/index.js.map +1 -0
- package/lib/math.d.ts +26 -0
- package/lib/math.d.ts.map +1 -0
- package/lib/math.js +162 -0
- package/lib/math.js.map +1 -0
- package/lib/pool.d.ts +86 -0
- package/lib/pool.d.ts.map +1 -0
- package/lib/pool.js +172 -0
- package/lib/pool.js.map +1 -0
- package/lib/report.d.ts +46 -0
- package/lib/report.d.ts.map +1 -0
- package/lib/report.js +92 -0
- package/lib/report.js.map +1 -0
- package/lib/tools/ma-convert.d.ts +10 -0
- package/lib/tools/ma-convert.d.ts.map +1 -0
- package/lib/tools/ma-convert.js +69 -0
- package/lib/tools/ma-convert.js.map +1 -0
- package/lib/tools/ma-pool.d.ts +12 -0
- package/lib/tools/ma-pool.d.ts.map +1 -0
- package/lib/tools/ma-pool.js +66 -0
- package/lib/tools/ma-pool.js.map +1 -0
- package/lib/tools/ma-report.d.ts +10 -0
- package/lib/tools/ma-report.d.ts.map +1 -0
- package/lib/tools/ma-report.js +107 -0
- package/lib/tools/ma-report.js.map +1 -0
- package/lib/tools/shared.d.ts +20 -0
- package/lib/tools/shared.d.ts.map +1 -0
- package/lib/tools/shared.js +14 -0
- package/lib/tools/shared.js.map +1 -0
- package/lib/version.d.ts +7 -0
- package/lib/version.d.ts.map +1 -0
- package/lib/version.js +7 -0
- package/lib/version.js.map +1 -0
- package/package.json +79 -4
- package/src/config.ts +42 -0
- package/src/effects.ts +148 -0
- package/src/index.ts +53 -0
- package/src/math.ts +149 -0
- package/src/pool.ts +236 -0
- package/src/report.ts +110 -0
- package/src/tools/ma-convert.ts +68 -0
- package/src/tools/ma-pool.ts +66 -0
- package/src/tools/ma-report.ts +102 -0
- package/src/tools/shared.ts +14 -0
- 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)
|
|
8
|
+
[]()
|
|
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
|
-
#
|
|
1
|
+
# dsh-meta-analysis
|
|
2
2
|
|
|
3
|
-
|
|
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)
|
|
8
|
+
[]()
|
|
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.
|
package/cordis.patch.yml
ADDED
|
@@ -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
|
package/lib/config.d.ts
ADDED
|
@@ -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"}
|
package/lib/effects.d.ts
ADDED
|
@@ -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"}
|