rdmp-data-skill 0.0.0-stage → 1.0.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/.agents/skills/rdmp-data-skill/SKILL.md +91 -0
- package/.agents/skills/rdmp-data-skill/references/module-glossary.md +60 -0
- package/.agents/skills/rdmp-data-skill/references/quality-checks.md +74 -0
- package/LICENSE +18 -0
- package/README.md +84 -2
- package/bin/install.js +165 -0
- package/bin/manifest.js +44 -0
- package/checksums.json +12 -0
- package/package.json +41 -4
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rdmp-data-skill
|
|
3
|
+
description: 对已经拿到的 RDMP 数据做本地处理,覆盖数据理解、质量检查、基础分析、规范输出四项能力。当用户让你解读、检查、汇总、对比或规范呈现 RDMP 相关数据(项目计划、任务、审批、文件元数据、工时、项目洞察的入组/PD/SAE 聚合指标、Insight/BI 看板、EDC 报表),把表格或查询结果粘贴到对话里要你处理,说"帮我分析这份数据""检查数据有没有问题""算一下完成率/逾期情况""整理成规范报表"时,用这个技能。只处理对话中已有或用户提供的数据,不连接 RDMP、不发起查询。
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# RDMP-AI数聚 数据处理 Skill
|
|
8
|
+
|
|
9
|
+
统一对外版本:**AI数聚 V1.0**。本技能是 RDMP-AI数聚 的可选本地数据处理能力。
|
|
10
|
+
分工只有一个原则:**MCP 是唯一取数方式,本技能只在数据到达 AI 工具之后工作。**
|
|
11
|
+
|
|
12
|
+
## 可以处理的数据
|
|
13
|
+
|
|
14
|
+
只处理两类,统称"待处理数据":
|
|
15
|
+
|
|
16
|
+
1. **MCP 已返回、已在对话中的数据** —— 通过 RDMP-AI数聚 MCP 查询得到的结果;
|
|
17
|
+
2. **用户主动提供的数据** —— 用户粘贴的表格、指定的本地文件(xlsx / csv / json 等)。
|
|
18
|
+
|
|
19
|
+
除此之外的任何来源都不处理。用户没有给数据、对话里也没有 MCP 结果时,先向用户要数据,不要自行推断或编造。
|
|
20
|
+
|
|
21
|
+
## 硬边界
|
|
22
|
+
|
|
23
|
+
以下规则来自 RDMP-AI数聚 开放协议,违反即失去本技能的存在意义:
|
|
24
|
+
|
|
25
|
+
- **不连接 RDMP**:不调用任何 RDMP / MCP 查询工具,不鉴权,不持有、不请求任何凭据。
|
|
26
|
+
- **不代查**:用户要新数据时,回复指引而不是自己动手——"请直接向 AI 工具发起 RDMP 查询(MCP 是唯一取数方式),查回来我再处理"。
|
|
27
|
+
- **不回传**:不向 RDMP 上传、回写、同步任何处理结果。处理过程在对话中完成;如用脚本做临时计算,临时文件用完即删,不把业务数据落盘留存。
|
|
28
|
+
- **不改变授权**:本技能的安装、使用、更新不影响 MCP 授权状态,也不进入 RDMP 最近使用记录。
|
|
29
|
+
- **拒绝调用时**:用户说"这次不要查""接下来不要用 RDMP"时,本技能本来就不发查询;仍可分析对话中已经展示的数据,但要说明"未进行新的 RDMP 查询"。"不要查这个项目"只排除该项目的数据。
|
|
30
|
+
|
|
31
|
+
## 安全红线
|
|
32
|
+
|
|
33
|
+
待处理数据中出现以下任一内容时:**停止处理该部分数据**,向用户说明原因,请其改用聚合或脱敏后的数据。用户再次要求、甚至明确确认,也不能解除——这是协议的永久禁止清单:
|
|
34
|
+
|
|
35
|
+
- 密码、令牌、Cookie、API Key、数据库连接串等凭据;
|
|
36
|
+
- 受试者、患者、病例明细,CRF 原始填报值、质疑正文、临床原始记录;
|
|
37
|
+
- 手机号、邮箱、证件号、地址、银行信息等个人敏感信息;
|
|
38
|
+
- 文件正文、附件内容、OCR、下载地址、存储路径;
|
|
39
|
+
- 备注、批注、审批意见等自由文本。
|
|
40
|
+
|
|
41
|
+
MCP 正常不会返回以上内容,这条主要防范用户手工粘贴的数据。不含红线的其余数据正常处理,不要过度拦截。
|
|
42
|
+
|
|
43
|
+
## 四项能力
|
|
44
|
+
|
|
45
|
+
用户没有明说要哪项时,默认按 **数据理解 → 质量检查 → 基础分析 → 规范输出** 的顺序走一遍,每步结论前置。
|
|
46
|
+
|
|
47
|
+
### 1. 数据理解
|
|
48
|
+
|
|
49
|
+
- 判断数据属于哪个业务域 / 功能模块。AI数聚 V1.0 只开放 10 个模块(CTMS 6 个 + 数据分析 3 个 + EDC 1 个),完整清单、各模块字段口径和边界读 `references/module-glossary.md`。
|
|
50
|
+
- 梳理字段含义、单位、时间粒度和统计口径,先向用户复述一遍口径再往下做。
|
|
51
|
+
- 口径不清的字段标注"口径未知"并询问,不要编造。特别注意:入组相关统计包含**人工录入与 EDC 同步**两种来源,不得表述为纯 EDC 数据。
|
|
52
|
+
|
|
53
|
+
### 2. 质量检查
|
|
54
|
+
|
|
55
|
+
按 `references/quality-checks.md` 的分模块规则检查,输出问题清单,每条包含:字段 / 记录、问题类型、影响范围、建议动作(调整查询条件,还是数据本身可疑)。没有问题时明确说"未发现问题",并列出检查过的维度。
|
|
56
|
+
|
|
57
|
+
### 3. 基础分析
|
|
58
|
+
|
|
59
|
+
只做基于待处理数据的计算,不外推:
|
|
60
|
+
|
|
61
|
+
- **汇总**:计数、占比、工时求和、按人员 / 项目 / 时间分组;
|
|
62
|
+
- **趋势**:月份趋势(入组、PD、SAE 等),检查月份连续性;
|
|
63
|
+
- **对比**:计划 vs 实际、同期对比、维度拆分(中心、项目、人员);
|
|
64
|
+
- **异常识别**:逾期任务、延期节点、异常工时、入组延迟升高。
|
|
65
|
+
|
|
66
|
+
指标公式以 `references/module-glossary.md` 的口径为准;RDMP 已算好的聚合指标(入组率、筛败率、脱落率等)直接引用返回值,不要用自造公式重算。数据不足以支撑结论时明说"数据不足",不要硬给。
|
|
67
|
+
|
|
68
|
+
### 4. 规范输出
|
|
69
|
+
|
|
70
|
+
- 结论前置:第一句给结论 / 数字,过程和明细放后面。
|
|
71
|
+
- **数据与分析分开**:RDMP 返回的原值直接呈现,不加推测;本技能计算或推断的部分明确标注为"分析",不混入数据本身。
|
|
72
|
+
- 表格呈现数值;本技能计算的指标用脚注标明口径(分母、时间范围、单位)。
|
|
73
|
+
- 百分比保留 1 位小数;日期用 `YYYY-MM-DD`;缺失写"无数据"或"缺失",不写 0。
|
|
74
|
+
- 超过约 30 行的明细先聚合呈现,注明总条数;单页 MCP 上限 100 条,汇总前先确认是否覆盖全量。
|
|
75
|
+
- 生成文件(报表 / 图表)时输出到用户指定位置或当前目录,并在对话中同步给出关键数字。
|
|
76
|
+
|
|
77
|
+
## 处理 MCP 返回状态
|
|
78
|
+
|
|
79
|
+
处理 MCP 结果时沿用协议的标准反馈语义:
|
|
80
|
+
|
|
81
|
+
| 情况 | 处理方式 |
|
|
82
|
+
| --- | --- |
|
|
83
|
+
| 无结果 | "当前条件下没有符合的数据",可建议调整条件,不编造 |
|
|
84
|
+
| 部分成功 | 分开展示成功与失败模块,不把部分结果说成完整结果 |
|
|
85
|
+
| 无权限 | 只说明当前无权查看,不推测不可见对象是否存在 |
|
|
86
|
+
| 结果被分页截断 | 汇总前说明只覆盖已返回部分,提示可能不完整 |
|
|
87
|
+
|
|
88
|
+
## 参考文件
|
|
89
|
+
|
|
90
|
+
- `references/module-glossary.md` —— 10 个开放模块的能力、字段口径、指标定义与边界。做数据理解或计算指标前读。
|
|
91
|
+
- `references/quality-checks.md` —— 通用检查 + 分模块质量检查规则。做质量检查前读。
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# AI数聚 V1.0 开放模块口径表
|
|
2
|
+
|
|
3
|
+
来源:《RDMP 开放协议规则 V1.0_PRD》第 3 章。层级定义:**业务域 → 功能模块 → RDMP 正式功能/页签 → 开放数据能力**。
|
|
4
|
+
|
|
5
|
+
## 10 个开放模块
|
|
6
|
+
|
|
7
|
+
| 业务域 | 功能模块 | 开放数据能力 | 必要边界 |
|
|
8
|
+
| --- | --- | --- | --- |
|
|
9
|
+
| CTMS | 项目计划管理 | 里程碑、阶段计划、完成情况、延期节点 | 项目维度;统计需时间 |
|
|
10
|
+
| CTMS | 任务管理 | 任务列表、状态、统计、逾期、责任人任务 | 项目或人员维度;统计需时间 |
|
|
11
|
+
| CTMS | 项目配置 | 项目基本信息、成员、角色、阶段 | 只读 |
|
|
12
|
+
| CTMS | 审批管理 | 审批记录、状态、待审批、审批时效 | 只查询 |
|
|
13
|
+
| CTMS | 项目文件管理 | 文件目录、名称、类型、版本、上传人、更新时间 | 只返回元数据 |
|
|
14
|
+
| CTMS | 工时管理 | 工时记录、统计、人员工时、项目工时、异常工时 | 项目或人员维度;统计需时间 |
|
|
15
|
+
| 数据分析 | 项目洞察 | 项目进度、健康度、风险概览及关键指标;入组与受试者进度、受试者状态汇总、PD 数据、SAE 数据(见下) | 仅项目级、中心级和月份趋势汇总 |
|
|
16
|
+
| 数据分析 | Insight 看板 | 指标、趋势、维度拆分、同期对比 | 需指定指标、时间、维度与口径 |
|
|
17
|
+
| 数据分析 | BI 看板 | 看板指标、图表数据、筛选结果、汇总 | 不开放底层 SQL 和配置 |
|
|
18
|
+
| EDC | EDC 数据报表 | EDC 正式报表及其授权范围内的数据 | 报表、项目与筛选条件 |
|
|
19
|
+
|
|
20
|
+
## 模块边界(做数据理解和分析时的红线)
|
|
21
|
+
|
|
22
|
+
- 项目文件管理只有元数据,没有正文、附件内容、下载地址。
|
|
23
|
+
- 项目配置只读;审批管理只查询——分析结论里不要出现"建议代为审批/撤回"之类的动作。
|
|
24
|
+
- Insight / BI 不涉及底层 SQL、数据源配置和权限配置。
|
|
25
|
+
- EDC 数据报表只含正式报表;不出现受试者/患者明细、CRF 原始填报值、质疑正文、临床原始值。
|
|
26
|
+
- 项目洞察中的 EDC 相关数据仅指入组/受试者状态、PD、SAE/SUSAR 的**聚合指标**,不得下钻到受试者、表单或事件明细。
|
|
27
|
+
- **入组相关统计包含人工录入与 EDC 同步两种来源**,任何表述不得说成"纯 EDC 数据"。
|
|
28
|
+
|
|
29
|
+
## 项目洞察指标口径
|
|
30
|
+
|
|
31
|
+
RDMP 返回的是已算好的聚合值,直接引用,不要用自造公式重算。验算或本地补算时按以下口径:
|
|
32
|
+
|
|
33
|
+
| 指标 | 口径 |
|
|
34
|
+
| --- | --- |
|
|
35
|
+
| 入组率 | 实际入组数 ÷ 计划样本量 |
|
|
36
|
+
| 计划完成率 | 实际入组数 ÷ 计划入组数 |
|
|
37
|
+
| 入组延迟率 | 以 RDMP 返回口径为准,口径未知时先问 |
|
|
38
|
+
| 筛败率 | 筛败人数 ÷ 总筛选人数 |
|
|
39
|
+
| 脱落率 | 退出人数 ÷ 入组人数 |
|
|
40
|
+
| 完成率 | 完成人数 ÷ 入组人数 |
|
|
41
|
+
| 受试者状态汇总 | 总筛选、筛败、入组、退出、完成五项人数 + 对应率 |
|
|
42
|
+
| PD 数据 | 轻微 / 重大 / 待定分类计数及总数;发生率以 RDMP 返回口径为准 |
|
|
43
|
+
| SAE 数据 | 普通 SAE、SUSAR、SAE 总数及发生率 |
|
|
44
|
+
|
|
45
|
+
## 常用判定规则
|
|
46
|
+
|
|
47
|
+
- **逾期任务**:未完成,且当前日期 > 计划结束时间。
|
|
48
|
+
- **里程碑延期**:已完成的,实际完成时间 > 计划完成时间;未完成的,当前日期已过计划完成时间。
|
|
49
|
+
- **审批时效**:从提交到当前(待审批)或到审批完成的时间跨度。
|
|
50
|
+
- **异常工时**:负数、单日超长(如 > 12h,阈值可按用户口径调整)、同一人同一天跨项目重复填报。
|
|
51
|
+
|
|
52
|
+
## 请求与返回特征
|
|
53
|
+
|
|
54
|
+
以下特征可用于识别"这是 MCP 查回来的数据":
|
|
55
|
+
|
|
56
|
+
- 请求是结构化的:`module_id` + `filters`(`project_ref` / `person_ref` / `status` 等)+ `pagination` + `sort`。
|
|
57
|
+
- `person_ref: current_user` 表示当前用户自己的数据。
|
|
58
|
+
- 项目和人员通过不透明 `entity_ref` 引用(如 `ref_7f92...`),不是数据库主键。
|
|
59
|
+
- 明细接口单页最多 100 条;常见排序字段如 `planned_end_time`。
|
|
60
|
+
- 无权限对象与不存在对象的反馈相同,无法区分。
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# 质量检查规则库
|
|
2
|
+
|
|
3
|
+
先跑通用检查,再按数据所属模块跑分模块检查。输出问题清单,格式:
|
|
4
|
+
|
|
5
|
+
```text
|
|
6
|
+
| # | 字段/记录 | 问题类型 | 说明 | 建议动作 |
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
问题类型从这些里选:缺失、重复、格式、范围、逻辑、口径、截断、一致性。
|
|
10
|
+
建议动作区分两种:**调整查询条件重新取数**(数据没问题,取法有问题)或 **数据可疑**(需要用户回 RDMP 核实)。
|
|
11
|
+
|
|
12
|
+
## 通用检查(所有模块先过一遍)
|
|
13
|
+
|
|
14
|
+
- **完整性**:空值、空行、关键列(项目、时间、状态)缺失;缺失写"缺失",不当作 0。
|
|
15
|
+
- **截断**:结果是否正好 100 条(单页上限)或明显不全——汇总前必须说明覆盖范围。
|
|
16
|
+
- **重复**:主键或业务键(任务编号、文件路径+版本、人+日期+项目)重复。
|
|
17
|
+
- **格式**:日期是否可解析、数值列是否混入文本、单位是否一致。
|
|
18
|
+
- **范围**:比例 / 率应在 0–100%;工期、工时不应为负。
|
|
19
|
+
- **一致性**:汇总数 = 分项之和;占比之和 ≈ 100%(允许四舍五入误差并注明)。
|
|
20
|
+
- **口径**:率的分母是什么、时间范围是什么——不清楚就列为口径问题,不要猜。
|
|
21
|
+
|
|
22
|
+
## CTMS · 项目计划管理
|
|
23
|
+
|
|
24
|
+
- 里程碑时间顺序:计划开始 ≤ 计划结束;阶段之间不应重叠出负区间。
|
|
25
|
+
- 延期节点判定见 module-glossary.md「常用判定规则」;已完成与未完成分开统计。
|
|
26
|
+
- 同一里程碑多次记录时,以最新状态为准并注明。
|
|
27
|
+
|
|
28
|
+
## CTMS · 任务管理
|
|
29
|
+
|
|
30
|
+
- 逾期 = 未完成 且 当前日期 > 计划结束时间;已完成任务不参与逾期统计。
|
|
31
|
+
- 状态枚举是否合法(如 overdue 等以返回数据为准);未知状态列为口径问题。
|
|
32
|
+
- 责任人为空的任务单独列出。
|
|
33
|
+
- `person_ref: current_user` 的数据只代表当前用户,不要推广成全员结论。
|
|
34
|
+
|
|
35
|
+
## CTMS · 项目配置
|
|
36
|
+
|
|
37
|
+
- 成员、角色、阶段清单与项目基本信息是否自洽(如角色有成员、阶段有起止)。
|
|
38
|
+
- 只读数据,检查结论里不出现修改配置类建议。
|
|
39
|
+
|
|
40
|
+
## CTMS · 审批管理
|
|
41
|
+
|
|
42
|
+
- 待审批时长 = 当前时间 − 提交时间;审批时效 = 审批完成时间 − 提交时间。
|
|
43
|
+
- 状态与时间逻辑一致:已审批的必须有审批完成时间,待审批的不应有。
|
|
44
|
+
|
|
45
|
+
## CTMS · 项目文件管理
|
|
46
|
+
|
|
47
|
+
- 只有元数据:目录、名称、类型、版本、上传人、更新时间。出现正文类字段即触发安全红线。
|
|
48
|
+
- 同一路径下版本号重复或回退;更新时间早于上传时间的记录单独列出。
|
|
49
|
+
- 文件类型与扩展名一致性。
|
|
50
|
+
|
|
51
|
+
## CTMS · 工时管理
|
|
52
|
+
|
|
53
|
+
- 异常工时:负数、单日超长、同一人同一天跨项目重复日期段。
|
|
54
|
+
- 人员工时 / 项目工时汇总与明细记录之和核对。
|
|
55
|
+
- 统计必须带时间范围;无时间范围的工时统计列为口径问题。
|
|
56
|
+
|
|
57
|
+
## 数据分析 · 项目洞察
|
|
58
|
+
|
|
59
|
+
- 率与绝对数互相验算(两者都返回时):入组率 × 计划样本量 ≈ 实际入组数,误差超过四舍五入范围列为一致性问题。
|
|
60
|
+
- 月份趋势的月份是否连续,缺月注明是"无数据"还是"未返回"。
|
|
61
|
+
- 中心级数据按中心分组核对与项目级总数的关系(注意口径可能是进度快照,不一定可加)。
|
|
62
|
+
- 只应有项目级 / 中心级 / 月份趋势聚合;出现受试者级行即触发安全红线。
|
|
63
|
+
|
|
64
|
+
## 数据分析 · Insight / BI 看板
|
|
65
|
+
|
|
66
|
+
- 同名指标在不同维度 / 时间段下口径是否一致(分母、是否含某类排除)。
|
|
67
|
+
- 同期对比的两期时间长度是否可比(如 30 天 vs 31 天)。
|
|
68
|
+
- 维度拆分之和与总计核对,差异注明口径还是数据问题。
|
|
69
|
+
|
|
70
|
+
## EDC · EDC 数据报表
|
|
71
|
+
|
|
72
|
+
- 只应是正式报表数据;核对报表名、项目与筛选条件与用户所述一致。
|
|
73
|
+
- 筛选条件本身要记录在输出脚注里,保证结果可复述。
|
|
74
|
+
- 出现受试者/患者明细、CRF 原始值、质疑正文即触发安全红线。
|
package/LICENSE
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
RDMP-AI数聚 数据处理 Skill(rdmp-data-skill)
|
|
2
|
+
版权所有 © 2026 蓝气球(北京)医学研究有限公司
|
|
3
|
+
|
|
4
|
+
一、授予许可。在遵守本许可的前提下,任何获得本软件包副本的个人或组织("你")被免费授予以下权利:
|
|
5
|
+
|
|
6
|
+
1. 安装、使用本软件包及其包含的数据处理 Skill(以下简称"本 Skill");
|
|
7
|
+
2. 以未经修改的完整副本形式复制、分发本软件包。
|
|
8
|
+
|
|
9
|
+
二、限制。
|
|
10
|
+
|
|
11
|
+
1. 你不得移除或修改本软件包中的版权声明、许可声明或完整性校验信息(checksums.json);
|
|
12
|
+
2. 你不得以修改后的版本以原名重新分发,或以可能引起混淆的方式使用 "RDMP"、"AI数聚" 等名称;
|
|
13
|
+
3. 本许可不授予任何商标权。
|
|
14
|
+
4. 本 Skill 仅对使用者自行提供或经合法授权获得的数据进行本地处理,不提供对 RDMP 系统的访问能力。使用者应遵守其所在组织及适用法律(包括个人信息与人类受试者数据保护相关规定)对数据处理的要求。
|
|
15
|
+
|
|
16
|
+
三、按"现状"提供。本软件包按"现状"和"现有"基础提供,不作任何明示或默示的保证,包括但不限于适销性、特定用途适用性和不侵权。在任何情况下,版权人均不对因使用本软件包而产生的任何索赔、损害或其他责任负责。
|
|
17
|
+
|
|
18
|
+
(本许可文本为发布占位版本,正式发布前请由法务确认或替换为最终文本。)
|
package/README.md
CHANGED
|
@@ -1,3 +1,85 @@
|
|
|
1
|
-
#
|
|
1
|
+
# RDMP-AI数聚 数据处理 Skill
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/rdmp-data-skill)
|
|
4
|
+
|
|
5
|
+
RDMP-AI数聚 的可选本地数据处理能力。统一对外版本:**AI数聚 V1.0**(与 skill 版本 1.0.0 对应)。
|
|
6
|
+
|
|
7
|
+
> 分工原则:**MCP 是唯一取数方式,本 skill 只在数据到达 AI 工具之后工作。**
|
|
8
|
+
> 本包不连接 RDMP、不发起查询、不鉴权、不持有任何凭据;安装与更新不影响 MCP 配置、凭据和授权有效期。
|
|
9
|
+
|
|
10
|
+
## 四项能力
|
|
11
|
+
|
|
12
|
+
| 能力 | 做什么 |
|
|
13
|
+
| --- | --- |
|
|
14
|
+
| 数据理解 | 识别数据属于哪个开放模块(CTMS 6 个 + 数据分析 3 个 + EDC 1 个),梳理字段口径与统计口径 |
|
|
15
|
+
| 质量检查 | 完整性、一致性、时间逻辑、重复、分页截断、指标口径核对,输出带建议动作的问题清单 |
|
|
16
|
+
| 基础分析 | 汇总统计、月份趋势、计划 vs 实际、同期对比、维度拆分、异常识别(逾期任务、延期节点、异常工时) |
|
|
17
|
+
| 规范输出 | 结论前置、数据与分析分开、口径脚注、缺失不写 0、大表先聚合 |
|
|
18
|
+
|
|
19
|
+
## 安装
|
|
20
|
+
|
|
21
|
+
任选一条路线。安装完成后重启 AI 工具或新开会话即可生效;不安装本 skill 也可正常使用 MCP 查询 RDMP 数据。也可以直接把安装命令发给 AI 工具,由它执行。
|
|
22
|
+
|
|
23
|
+
**路线一:skills CLI**(需要 [vercel-labs/skills](https://github.com/vercel-labs/skills) 支持的 AI 工具;`<owner>` 为官方 GitHub 组织名,以 RDMP「接入配置」页面展示的命令为准)
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npx skills add <owner>/rdmp-data-skill # 最新版
|
|
27
|
+
npx skills add <owner>/rdmp-data-skill#v1.0.0 # 固定版本(# 指定 git tag)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
注意:`skills` CLI 中 `@` 是"选择仓库内哪个 skill",**不是版本号**;固定版本用 `#`。
|
|
31
|
+
|
|
32
|
+
**路线二:npm 直装**(需要 Node.js ≥ 16;零依赖、不联网、安装前校验 SHA-256)
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# 通用目录(ZCode 等,推荐)
|
|
36
|
+
npx rdmp-data-skill install
|
|
37
|
+
|
|
38
|
+
# 指定 AI 工具
|
|
39
|
+
npx rdmp-data-skill install --target zcode # ~/.zcode/skills/
|
|
40
|
+
npx rdmp-data-skill install --target claude # ~/.claude/skills/
|
|
41
|
+
|
|
42
|
+
# 仅安装到当前项目
|
|
43
|
+
npx rdmp-data-skill install --project
|
|
44
|
+
|
|
45
|
+
# 更新(覆盖安装,不影响 MCP 授权)
|
|
46
|
+
npx rdmp-data-skill install --force
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## 输入 / 输出规范
|
|
50
|
+
|
|
51
|
+
**只接受两类输入**:
|
|
52
|
+
|
|
53
|
+
1. RDMP-AI数聚 MCP 已返回、已在对话中的数据;
|
|
54
|
+
2. 用户主动提供的数据(粘贴的表格、本地 xlsx / csv / json 文件)。
|
|
55
|
+
|
|
56
|
+
**输出遵循**:
|
|
57
|
+
|
|
58
|
+
- 结论前置;RDMP 返回的原值直接呈现,不加推测;skill 计算或推断的部分明确标注为分析;
|
|
59
|
+
- 本 skill 计算的指标用脚注标明口径(分母、时间范围、单位);百分比 1 位小数;日期 `YYYY-MM-DD`;
|
|
60
|
+
- 缺失写"无数据"或"缺失",不写 0;超过约 30 行的明细先聚合呈现并注明总条数;
|
|
61
|
+
- 处理过程不回传 RDMP,不进入 RDMP 最近使用记录。
|
|
62
|
+
|
|
63
|
+
**安全红线(不可解除)**:待处理数据中出现凭据、受试者/患者明细、CRF 原始填报值、个人敏感信息、文件正文、审批意见等自由文本时,拒绝处理该部分数据。
|
|
64
|
+
|
|
65
|
+
## 完整性与供应链
|
|
66
|
+
|
|
67
|
+
- 安装器零依赖、不联网、不采集任何用户或设备信息;
|
|
68
|
+
- 每个文件随包发布 SHA-256 清单(`checksums.json`),安装前强制校验,清单外文件一律拒装;
|
|
69
|
+
- npm 制品按版本不可变;只提供当前正式版,不提供历史版本降级;
|
|
70
|
+
- 可校验已安装包完整性:`node node_modules/rdmp-data-skill/bin/install.js --check-only`。
|
|
71
|
+
|
|
72
|
+
## 版本对照
|
|
73
|
+
|
|
74
|
+
| AI数聚 统一版本 | skill / npm 版本 |
|
|
75
|
+
| --- | --- |
|
|
76
|
+
| V1.0 | 1.0.0 |
|
|
77
|
+
|
|
78
|
+
## 更多信息
|
|
79
|
+
|
|
80
|
+
- 能力与边界详情见包内 `SKILL.md` 与 `references/`;
|
|
81
|
+
- 在 RDMP 工作台顶栏「AI数聚」入口可获取 MCP 配置与本 skill 的最新安装方式。
|
|
82
|
+
|
|
83
|
+
## 许可
|
|
84
|
+
|
|
85
|
+
© 2026 蓝气球(北京)医学研究有限公司。见 [LICENSE](LICENSE)。
|
package/bin/install.js
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* RDMP-AI数聚 数据处理 Skill 安装器。
|
|
4
|
+
* 约束(来自 RDMP 开放协议 9.6):不联网、不采集任何用户/设备信息、
|
|
5
|
+
* 不触碰 MCP 配置与授权;安装/更新 = 校验 SHA-256 后覆盖复制文件。
|
|
6
|
+
*/
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const fs = require('node:fs');
|
|
10
|
+
const path = require('node:path');
|
|
11
|
+
const crypto = require('node:crypto');
|
|
12
|
+
const os = require('node:os');
|
|
13
|
+
|
|
14
|
+
const PKG_ROOT = path.resolve(__dirname, '..');
|
|
15
|
+
const SKILL_DIR = path.join(PKG_ROOT, '.agents', 'skills', 'rdmp-data-skill');
|
|
16
|
+
const SKILL_NAME = 'rdmp-data-skill';
|
|
17
|
+
|
|
18
|
+
function usage() {
|
|
19
|
+
return `RDMP-AI数聚 数据处理 Skill 安装器 (v${pkgVersion()})
|
|
20
|
+
|
|
21
|
+
用法:
|
|
22
|
+
npx rdmp-data-skill install [选项]
|
|
23
|
+
|
|
24
|
+
选项:
|
|
25
|
+
--target <agents|zcode|claude> 安装目标(默认 agents)
|
|
26
|
+
agents → ~/.agents/skills/${SKILL_NAME}/ (通用,ZCode 等推荐)
|
|
27
|
+
zcode → ~/.zcode/skills/${SKILL_NAME}/
|
|
28
|
+
claude → ~/.claude/skills/${SKILL_NAME}/
|
|
29
|
+
--project 安装到当前目录 .agents/skills/ 下(仅本项目可用)
|
|
30
|
+
--path <dir> 直接指定安装目录(将创建或覆盖该目录)
|
|
31
|
+
--force 目标已存在时覆盖安装(更新即覆盖)
|
|
32
|
+
--check-only 只校验包内文件 SHA-256,不安装
|
|
33
|
+
--version 显示包版本
|
|
34
|
+
-h, --help 显示本说明
|
|
35
|
+
|
|
36
|
+
安装和更新不会改变 MCP 配置、凭据和授权有效期。`;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function pkgVersion() {
|
|
40
|
+
try {
|
|
41
|
+
return require(path.join(PKG_ROOT, 'package.json')).version;
|
|
42
|
+
} catch {
|
|
43
|
+
return 'unknown';
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function fail(msg) {
|
|
48
|
+
console.error(`错误: ${msg}`);
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function sha256(file) {
|
|
53
|
+
const h = crypto.createHash('sha256');
|
|
54
|
+
h.update(fs.readFileSync(file));
|
|
55
|
+
return h.digest('hex');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function walk(dir) {
|
|
59
|
+
const out = [];
|
|
60
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
61
|
+
const full = path.join(dir, entry.name);
|
|
62
|
+
if (entry.isDirectory()) out.push(...walk(full));
|
|
63
|
+
else if (entry.isFile()) out.push(full);
|
|
64
|
+
}
|
|
65
|
+
return out;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function loadManifest() {
|
|
69
|
+
const manifestPath = path.join(PKG_ROOT, 'checksums.json');
|
|
70
|
+
if (!fs.existsSync(manifestPath)) fail('缺少 checksums.json,包不完整,拒绝安装。');
|
|
71
|
+
return JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function verify() {
|
|
75
|
+
const manifest = loadManifest();
|
|
76
|
+
const problems = [];
|
|
77
|
+
for (const [rel, expected] of Object.entries(manifest.files || {})) {
|
|
78
|
+
const abs = path.join(PKG_ROOT, rel);
|
|
79
|
+
if (!fs.existsSync(abs)) {
|
|
80
|
+
problems.push(`${rel}: 文件缺失`);
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
const actual = sha256(abs);
|
|
84
|
+
if (actual !== expected) problems.push(`${rel}: SHA-256 不匹配(期望 ${expected},实际 ${actual})`);
|
|
85
|
+
}
|
|
86
|
+
// 反向检查:技能目录里的文件必须都在清单里,防止夹带未登记内容
|
|
87
|
+
for (const abs of walk(SKILL_DIR)) {
|
|
88
|
+
const rel = path.relative(PKG_ROOT, abs);
|
|
89
|
+
if (!(rel in (manifest.files || {}))) problems.push(`${rel}: 不在 checksums.json 清单中`);
|
|
90
|
+
}
|
|
91
|
+
if (problems.length) {
|
|
92
|
+
console.error('完整性校验失败:');
|
|
93
|
+
for (const p of problems) console.error(' - ' + p);
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
return manifest;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function copyTree(src, dest) {
|
|
100
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
101
|
+
for (const abs of walk(src)) {
|
|
102
|
+
const rel = path.relative(src, abs);
|
|
103
|
+
const target = path.join(dest, rel);
|
|
104
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
105
|
+
fs.copyFileSync(abs, target);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function parseArgs(argv) {
|
|
110
|
+
const opts = { action: 'install', target: 'agents', project: false, force: false, checkOnly: false, path: null };
|
|
111
|
+
for (let i = 0; i < argv.length; i++) {
|
|
112
|
+
const a = argv[i];
|
|
113
|
+
if (a === 'install') continue;
|
|
114
|
+
else if (a === '--target') opts.target = argv[++i];
|
|
115
|
+
else if (a === '--project') opts.project = true;
|
|
116
|
+
else if (a === '--path') opts.path = argv[++i];
|
|
117
|
+
else if (a === '--force') opts.force = true;
|
|
118
|
+
else if (a === '--check-only') opts.checkOnly = true;
|
|
119
|
+
else if (a === '--version') { console.log(pkgVersion()); process.exit(0); }
|
|
120
|
+
else if (a === '-h' || a === '--help') { console.log(usage()); process.exit(0); }
|
|
121
|
+
else fail(`未知参数: ${a}\n\n${usage()}`);
|
|
122
|
+
}
|
|
123
|
+
if (opts.target && !['agents', 'zcode', 'claude'].includes(opts.target)) {
|
|
124
|
+
fail(`无效的 --target: ${opts.target}(可选 agents / zcode / claude)`);
|
|
125
|
+
}
|
|
126
|
+
return opts;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function destDir(opts) {
|
|
130
|
+
if (opts.path) return path.resolve(opts.path);
|
|
131
|
+
if (opts.project) return path.join(process.cwd(), '.agents', 'skills', SKILL_NAME);
|
|
132
|
+
const home = os.homedir();
|
|
133
|
+
const roots = { agents: '.agents', zcode: '.zcode', claude: '.claude' };
|
|
134
|
+
return path.join(home, roots[opts.target], 'skills', SKILL_NAME);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function main() {
|
|
138
|
+
const opts = parseArgs(process.argv.slice(2));
|
|
139
|
+
if (!fs.existsSync(path.join(SKILL_DIR, 'SKILL.md'))) fail('包内缺少 SKILL.md,包不完整。');
|
|
140
|
+
|
|
141
|
+
const manifest = verify();
|
|
142
|
+
if (manifest.version && manifest.version !== pkgVersion()) {
|
|
143
|
+
fail(`checksums.json 版本(${manifest.version})与 package.json(${pkgVersion()})不一致,请先运行 npm run manifest。`);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (opts.checkOnly) {
|
|
147
|
+
console.log(`完整性校验通过:${Object.keys(manifest.files).length} 个文件,SHA-256 全部匹配。`);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const dest = destDir(opts);
|
|
152
|
+
if (fs.existsSync(dest) && !opts.force) {
|
|
153
|
+
fail(`目标目录已存在: ${dest}\n更新请加 --force 覆盖安装(不会影响 MCP 配置与授权)。`);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
copyTree(SKILL_DIR, dest);
|
|
157
|
+
|
|
158
|
+
const files = walk(SKILL_DIR).map((f) => path.relative(SKILL_DIR, f));
|
|
159
|
+
console.log(`安装完成: RDMP-AI数聚 数据处理 Skill v${pkgVersion()}(AI数聚 V1.0)`);
|
|
160
|
+
console.log(`位置: ${dest}`);
|
|
161
|
+
for (const f of files) console.log(` - ${f}`);
|
|
162
|
+
console.log('重启 AI 工具或新开会话后生效;本次安装不改变 MCP 配置、凭据和授权有效期。');
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
main();
|
package/bin/manifest.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* 生成 checksums.json:对技能目录内全部文件计算 SHA-256。
|
|
4
|
+
* 任何技能文件改动后、发布前都必须重新运行(npm run manifest)。
|
|
5
|
+
*/
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const fs = require('node:fs');
|
|
9
|
+
const path = require('node:path');
|
|
10
|
+
const crypto = require('node:crypto');
|
|
11
|
+
|
|
12
|
+
const PKG_ROOT = path.resolve(__dirname, '..');
|
|
13
|
+
const SKILL_DIR = path.join(PKG_ROOT, '.agents', 'skills', 'rdmp-data-skill');
|
|
14
|
+
const pkg = require(path.join(PKG_ROOT, 'package.json'));
|
|
15
|
+
|
|
16
|
+
function walk(dir) {
|
|
17
|
+
const out = [];
|
|
18
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
19
|
+
const full = path.join(dir, entry.name);
|
|
20
|
+
if (entry.isDirectory()) out.push(...walk(full));
|
|
21
|
+
else if (entry.isFile()) out.push(full);
|
|
22
|
+
}
|
|
23
|
+
return out;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const files = {};
|
|
27
|
+
for (const abs of walk(SKILL_DIR)) {
|
|
28
|
+
const rel = path.relative(PKG_ROOT, abs);
|
|
29
|
+
const h = crypto.createHash('sha256');
|
|
30
|
+
h.update(fs.readFileSync(abs));
|
|
31
|
+
files[rel] = h.digest('hex');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const manifest = {
|
|
35
|
+
name: pkg.name,
|
|
36
|
+
version: pkg.version,
|
|
37
|
+
aiShujuUnifiedVersion: (pkg.aiShuju && pkg.aiShuju.unifiedVersion) || null,
|
|
38
|
+
algorithm: 'sha256',
|
|
39
|
+
generatedAt: new Date().toISOString(),
|
|
40
|
+
files,
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
fs.writeFileSync(path.join(PKG_ROOT, 'checksums.json'), JSON.stringify(manifest, null, 2) + '\n');
|
|
44
|
+
console.log(`checksums.json 已生成:${Object.keys(files).length} 个文件(版本 ${pkg.version})。`);
|
package/checksums.json
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "rdmp-data-skill",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"aiShujuUnifiedVersion": "1.0",
|
|
5
|
+
"algorithm": "sha256",
|
|
6
|
+
"generatedAt": "2026-10-16T10:02:49.765Z",
|
|
7
|
+
"files": {
|
|
8
|
+
".agents/skills/rdmp-data-skill/SKILL.md": "88b5480ad54f7b844088c2130472e8217b29b918c340077459b99aefbb03fe0c",
|
|
9
|
+
".agents/skills/rdmp-data-skill/references/module-glossary.md": "ce35dcf2e3a0f52be0beef1766bb9e546748222b813ca868a84f27c762408332",
|
|
10
|
+
".agents/skills/rdmp-data-skill/references/quality-checks.md": "08c9ece41c3af30d000e694e387c490255413f6243ba6d05df0a684180160a5b"
|
|
11
|
+
}
|
|
12
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,43 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rdmp-data-skill",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "RDMP-AI数聚 数据处理 Skill:对已获取的 RDMP 数据做本地处理,覆盖数据理解、质量检查、基础分析、规范输出。只处理用户提供或 MCP 已返回的数据,不连接 RDMP、不发起查询。",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"rdmp",
|
|
7
|
+
"ai数聚",
|
|
8
|
+
"skill",
|
|
9
|
+
"agent-skills",
|
|
10
|
+
"skills",
|
|
11
|
+
"mcp",
|
|
12
|
+
"data-processing",
|
|
13
|
+
"ctms",
|
|
14
|
+
"edc",
|
|
15
|
+
"clinical-trial",
|
|
16
|
+
"claude-code",
|
|
17
|
+
"zcode"
|
|
18
|
+
],
|
|
19
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
20
|
+
"files": [
|
|
21
|
+
".agents/skills/rdmp-data-skill",
|
|
22
|
+
"bin",
|
|
23
|
+
"checksums.json",
|
|
24
|
+
"README.md",
|
|
25
|
+
"LICENSE"
|
|
26
|
+
],
|
|
27
|
+
"bin": {
|
|
28
|
+
"rdmp-data-skill": "bin/install.js"
|
|
29
|
+
},
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=16"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"manifest": "node bin/manifest.js",
|
|
35
|
+
"verify": "node bin/install.js --check-only",
|
|
36
|
+
"prepublishOnly": "node bin/install.js --check-only"
|
|
37
|
+
},
|
|
38
|
+
"aiShuju": {
|
|
39
|
+
"product": "RDMP-AI数聚",
|
|
40
|
+
"unifiedVersion": "1.0",
|
|
41
|
+
"skillName": "rdmp-data-skill"
|
|
42
|
+
}
|
|
43
|
+
}
|