dsh-data-cleaning-agent 0.2.1 → 0.4.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.
@@ -0,0 +1,241 @@
1
+ # QCC 能力设计:企业名单补全(G4 · 方案 A 模型中介式)
2
+
3
+ > 状态:设计稿(待评审通过后实施)
4
+ > 日期:2026-09-01
5
+ > 关联:`docs/PLAN-OSS.md` §8(Phase 2 接入规划)
6
+ > 决策:先做 **方案 A(模型中介式,快、可发布)**;同阶段开 **Spike #7** 验证方案 B 的程序化调用面。
7
+ > 范围:本文档只设计 G4(方案 A)。方案 B(`lib/qcc.js` 后台批量)见 Spike #7 另行设计。
8
+
9
+ ---
10
+
11
+ ## 1. 目标与非目标
12
+
13
+ ### 1.1 目标
14
+
15
+ 让"数据清洗补全智能体"在**已连接企查查 MCP** 的前提下,把一批**企业名单**
16
+ (只有企业名,或企业名 + 少量残缺字段)补全为带最新工商信息的结构化名单:
17
+
18
+ ```
19
+ 输入:企业名(必填,支持模糊名/简称)
20
+ 输出:credit_no / legal_rep / reg_capital / establish_date /
21
+ reg_status / biz_status / risk_tags
22
+ ```
23
+
24
+ ### 1.2 非目标(本次不做)
25
+
26
+ - **不重造 OAuth**:完全复用 `qcc-dsh-mcp-oauth` 已上架的授权与工具面
27
+ (`qcc_oauth_connect` / `mcp__qcc-company__*` / `mcp__qcc-risk__*`)。
28
+ - **不做后台程序化批量**(方案 B):模型中介式就是让模型亲自调 QCC 工具,
29
+ 本插件不新增 `lib/qcc.js`、不直接调用 mcp-client 服务。
30
+ - **不改现有清洗/补全/概览引擎**:`data_clean_rows` / `data_complete_rows` /
31
+ `data_profile` 的确定性语义保持原样;企业补全作为**新 Skill + 新流程**叠加,不污染旧路径。
32
+
33
+ ---
34
+
35
+ ## 2. 复用机制与工具契约
36
+
37
+ ### 2.1 依赖的已上架插件
38
+
39
+ | 插件 | npm 包 | 提供的工具面 | 与本插件关系 |
40
+ | --- | --- | --- | --- |
41
+ | 企查查 MCP OAuth | `qcc-dsh-mcp-oauth` | `qcc_oauth_connect/status/disconnect` + `mcp__qcc-company__*` + `mcp__qcc-risk__*` | **前置依赖**:用户先连企查查,本插件才有数据源 |
42
+
43
+ 共存约束(已写入 `docs/COMPATIBILITY.md`):
44
+
45
+ | | qcc-dsh-mcp-oauth | 本插件(数据清洗) |
46
+ | --- | --- | --- |
47
+ | 工具名前缀 | `qcc_oauth_*` + `mcp__qcc-*` | `data_clean_rows` / `data_complete_rows` / `data_profile` |
48
+ | 存储域 | 自有 grant store | `dc_tasks_v1` |
49
+ | 能否共存 | ✅ 工具名/存储域/条目 id 全独立 | ✅ |
50
+
51
+ ### 2.2 方案 A 用到的 QCC 工具(真实工具名)
52
+
53
+ | 步骤 | 工具 | 用途 |
54
+ | --- | --- | --- |
55
+ | 1. 消歧 | `mcp__qcc-company__get_company_by_query` | 企业名 → 唯一精确匹配(自动锁定,带统一社会信用代码)或多候选(最多 5 个) |
56
+ | 2. 工商详情 | `mcp__qcc-company__get_company_registration_info` | 用锁定实体(名称或统一社会信用代码)取法定代表人/注册资本/成立日期/登记状态等 |
57
+ | 3. 风险标签 | `mcp__qcc-risk__get_company_risk_scan` | 用锁定实体取 35 项风险因子计数(失信/被执行/裁判文书/行政处罚/股权冻结…) |
58
+
59
+ > 字段名以 QCC MCP 工具**实际返回**为准,实施时逐字段核对;本文档用概念名
60
+ > (`creditNo`/`legalRep`/`regCapital`/`establishDate`/`regStatus`/`bizStatus`)
61
+ > 表达契约,落地时映射到工具真实字段。
62
+
63
+ ---
64
+
65
+ ## 3. 数据路径
66
+
67
+ ```
68
+ 用户:帮我补全这份企业名单(CSV/JSON/文本,或直接给企业名列表)
69
+
70
+ ├─ 模型解析名单(可复用现有 data_profile 概览 + 本地解析)
71
+
72
+ ├─ 模型确认「已连接企查查」:
73
+ │ 调 qcc_oauth_status;或发现 mcp__qcc-company__* 工具存在
74
+
75
+ ├─ 对每个企业名:
76
+ │ mcp__qcc-company__get_company_by_query(name)
77
+ │ └─ 唯一精确匹配 → 锁定实体(creditNo)
78
+ │ └─ 多候选 → 暂停,交用户确认(禁止自动取第一名,见 §6)
79
+ │ mcp__qcc-company__get_company_registration_info(锁定实体)
80
+ │ mcp__qcc-risk__get_company_risk_scan(锁定实体) [可选,取风险标签]
81
+
82
+ ├─ 模型把 QCC 返回字段按 §5 契约组装为结构化行
83
+
84
+ └─ 产出:补全后的名单(对话摘要 + 可下载 CSV)
85
+ 明细经同源 web 下载链路交付,不把完整明细直接吐回对话(沿用现有安全边界)
86
+ ```
87
+
88
+ 关键点:**QCC 调用是模型亲自完成的**(模型 → MCP 工具 → 模型),本插件只提供
89
+ (1)名单解析与(2)结果写回/下载,(3)Skill 工作流指引。这正好落在
90
+ "数据由模型组装"的既有边界内,零后端改造。
91
+
92
+ ---
93
+
94
+ ## 4. Skill 设计
95
+
96
+ ### 4.1 方案:新增 `enterprise-enrichment` Skill(不改 `data-cleaning`)
97
+
98
+ - 现有 `data-cleaning` Skill 语义是"确定性清洗/补全/概览",不应混入"外部工商数据补全"
99
+ (职责不同、失败模式不同、依赖不同)。
100
+ - 新增 Skill `enterprise-enrichment`,触发语:用户说"补全企业名单""补齐工商信息"
101
+ "用企查查补全""查一下这些公司的统一社会信用代码/法人/注册资本"等。
102
+
103
+ ### 4.2 Skill 内容草案
104
+
105
+ ```text
106
+ name: enterprise-enrichment
107
+ description: Enrich a list of company names with the latest Qichacha (QCC)
108
+ business-registration fields via the QCC MCP tools.
109
+ whenToUse: When the user gives a list of company names (possibly incomplete or
110
+ fuzzy) and asks to fill in credit code / legal representative / registered
111
+ capital / establishment date / registration & business status / risk tags,
112
+ or to "enrich / complete with Qichacha".
113
+ source: dsh-data-cleaning-agent
114
+ content:
115
+ - Workflow:
116
+ 1. Detect QCC availability: run `qcc_oauth_status`. If not connected,
117
+ tell the user to run `qcc_oauth_connect` first, and stop.
118
+ 2. Parse the company-name list (from pasted text / CSV / JSON). Keep only
119
+ the distinct company-name column.
120
+ 3. For EACH name: `mcp__qcc-company__get_company_by_query`.
121
+ - unique exact match → lock the entity (use its credit code).
122
+ - multiple candidates → DO NOT auto-pick the first; show the candidates
123
+ (name + region + credit code) and ask the user which one.
124
+ - no match → mark that row as `unresolved` and continue.
125
+ 4. For each locked entity: `mcp__qcc-company__get_company_registration_info`
126
+ (fill credit_no / legal_rep / reg_capital / establish_date / reg_status /
127
+ biz_status) and, when risk tags are wanted,
128
+ `mcp__qcc-risk__get_company_risk_scan` (fill risk_tags).
129
+ 5. Assemble the enriched table. NEVER invent a field — if QCC returns no
130
+ value, leave it empty and mark the row/field as unresolved.
131
+ 6. Report only a summary (enriched N / unresolved M / multi-candidate K)
132
+ plus the enriched CSV via the download link. Never dump full detail rows
133
+ into the chat.
134
+ - Safety rules:
135
+ - Never fabricate a credit code, legal rep, capital, or status.
136
+ - Never auto-select among ambiguous candidates.
137
+ - Never expose QCC tokens or credentials.
138
+ ```
139
+
140
+ > 具体措辞在实施时打磨,并与 QCC OAuth 插件的 `qcc_oauth_connect` 引导语对齐。
141
+
142
+ ### 4.3 是否新增模型工具
143
+
144
+ 方案 A 可做到**零新工具**(模型直接调 QCC 工具 + 复用现有 web 解析/下载)。
145
+ 可选加一个轻量工具 `data_rows_to_csv`(把模型组装的补全行数组 → CSV 下载链接),
146
+ 避免模型手拼 CSV。**实施时评估**:若模型拼 CSV 易错,再加;否则不加,保持零后端改动。
147
+
148
+ ---
149
+
150
+ ## 5. v1 字段契约与映射表
151
+
152
+ | 输出字段 | 中文 | 来源工具 | 备注 |
153
+ | --- | --- | --- | --- |
154
+ | `credit_no` | 统一社会信用代码 | `get_company_by_query` 锁定实体时带回 / `get_company_registration_info` | 消歧成功即有 |
155
+ | `legal_rep` | 法定代表人 | `get_company_registration_info` | 缺失留空 + 标记 |
156
+ | `reg_capital` | 注册资本 | `get_company_registration_info` | 原样引用,不四舍五入 |
157
+ | `establish_date` | 成立日期 | `get_company_registration_info` | 原样引用 |
158
+ | `reg_status` | 登记状态 | `get_company_registration_info` | 原样引用(存续/在业/吊销/注销…) |
159
+ | `biz_status` | 经营状态 | `get_company_registration_info`(若含)/ `get_company_profile` 兜底 | 实施时核对字段落点 |
160
+ | `risk_tags` | 风险标签 | `get_company_risk_scan`(35 项计数中命中项) | 仅陈述"命中维度+计数",不下定性结论 |
161
+
162
+ > 对齐 QCC 工具的数据纪律:金额/比例/计数一律**逐字引用工具返回值**,
163
+ > 禁止模型自行相加、相乘或估算;聚合/穿透值以工具返回为准。
164
+
165
+ ---
166
+
167
+ ## 6. 消歧与安全策略
168
+
169
+ 1. **多候选必须交用户确认**:`get_company_by_query` 返回 >1 候选时,模型列出候选
170
+ (企业名 + 地区 + 统一社会信用代码),等待用户选定,**禁止自动取排名第一**。
171
+ - 这是 QCC 工具契约的硬性要求(错误选择会对错误主体做补全)。
172
+ 2. **模糊名先行提示**:对明显残缺/简称的名称,先提示用户补充地区等线索,
173
+ 减少多候选与错配。
174
+ 3. **不编造**:QCC 未返回值 → 留空 + `unresolved`,绝不占位编造。
175
+ 4. **凭据安全**:整个流程不接触、不回显 QCC token;token 只存在于 qcc-mcp-oauth
176
+ 自己的 grant store,本插件不读它。
177
+ 5. **数据边界**:完整明细经同源 web 下载交付(沿用 `isTrusted` + `no-store` 响应头),
178
+ 对话内只给摘要 + 下载链接。
179
+
180
+ ---
181
+
182
+ ## 7. 未连接企查查时的引导路径
183
+
184
+ - Skill 第一步 `qcc_oauth_status`:
185
+ - **未连接** → 模型告知用户先运行 `qcc_oauth_connect`(QCC OAuth 插件提供),并停止补全。
186
+ - **已连接但 token 过期** → 引导 `qcc_oauth_connect`(OAuth 插件会复用授权自动刷新,不重复弹授权页)。
187
+ - **已连接** → 继续。
188
+ - 兜底:若模型在未连接时直接调 `mcp__qcc-company__*`,QCC MCP 工具会返回
189
+ 未授权错误(401 语义),Skill 的失败处理同样引导到 `qcc_oauth_connect`。
190
+
191
+ ---
192
+
193
+ ## 8. 验收 Gate(G4 达成标准)
194
+
195
+ 1. **双基线 headless 真实模型**:给一段企业名单(含 1 个精确名 + 1 个模糊名 + 1 个多候选名),
196
+ 在已连接企查查的环境下,模型按 Skill 完成:
197
+ - 精确名 → 工商字段回填正确;
198
+ - 多候选名 → 模型停下询问而非乱选;
199
+ - 未命中名 → `unresolved` 标记。
200
+ 2. **未连接环境**:模型第一步即引导 `qcc_oauth_connect` 并停止,不假装补全。
201
+ 3. **安全回归**:`npm run check` 全绿;现有 13 例引擎测试不受影响;
202
+ 补全明细只经下载链路交付,对话内无完整明细泄露。
203
+ 4. **文档同步**:`docs/USER-GUIDE.md` 增补"企业名单补全"一节;
204
+ `docs/COMPATIBILITY.md` 的共存表若缺 `enterprise-enrichment` 技能则补上。
205
+
206
+ ---
207
+
208
+ ## 9. 与方案 B 的边界与预留
209
+
210
+ - 方案 A 不改 `lib/`(最多可选加 `data_rows_to_csv` 工具)。
211
+ - 方案 B 已新增 `lib/qcc.js`:Spike #7 双基线证明公共 `ctx.tools.execute()` 可程序化调度动态
212
+ MCP 工具;G5-2 幂等、候选续跑、人工重试与安全 Runner 的 Mock/Contract 已通过。
213
+ 禁止访问 mcp-client 私有 client;真实 OAuth/QCC 主路径已验收,token 到期刷新与
214
+ 2026-09-02 已完成自然过期 token refresh 与 401/429/配额故障注入验收;
215
+ 故障注入使用本地 ToolRuntime,不重复真实付费批次。
216
+ - 两者**共享**:§5 字段契约、§6 消歧策略、§7 未连接引导。方案 B 落地时直接复用,
217
+ 不重定义契约。
218
+
219
+ ---
220
+
221
+ ## 10. 实施变更清单(评审通过后执行)
222
+
223
+ | # | 变更 | 文件 | 可逆 |
224
+ | --- | --- | --- | --- |
225
+ | 1 | 新增 `enterprise-enrichment` Skill | `lib/skill.js`(或新 `lib/skill-enrich.js`) | ✅ 本地 |
226
+ | 2 | (可选)新增 `data_rows_to_csv` 工具 | `lib/tools.js` | ✅ 本地 |
227
+ | 3 | `docs/USER-GUIDE.md` 增补企业名单补全一节 | `docs/USER-GUIDE.md` | ✅ 本地 |
228
+ | 4 | `docs/COMPATIBILITY.md` 补共存说明 | `docs/COMPATIBILITY.md` | ✅ 本地 |
229
+ | 5 | `npm run check` + 双基线 headless 真实模型验收 | — | ✅ 本地 |
230
+ | 6 | 版本号 bump + CHANGELOG + README 版本同步 | 多文件 | ✅ 本地 |
231
+ | 7 | tag → OIDC 自动发布(已跑通链路) | — | ⚠️ 外发,需授权 |
232
+
233
+ ---
234
+
235
+ ## 11. 风险
236
+
237
+ 1. **名单大时 token 消耗大、逐条慢**:方案 A 是逐企业调用 QCC 工具,百级名单成本高;
238
+ → Skill 里写明批处理节奏(一次一批,批间汇报进度);百级以上建议走方案 B。
239
+ 2. **多候选误配**:靠 §6 的"必须确认"策略兜底,但模型可能未遵守;
240
+ → Skill 强调 + 验收用例覆盖。
241
+ 3. **QCC 工具字段名漂移**:本文档用概念名,落地时以工具真实返回为准并冻结到实现里。
@@ -0,0 +1,254 @@
1
+ # 企查查数据维度补全 · 二期 / 三期路线图与字段清单
2
+
3
+ > 本文档是 `dsh-data-cleaning-agent` 接入企查查(QCC)MCP 的**分期规划与可清洗/补全维度字段清单**。
4
+ > 一期(方案 A 模型中介式,已落地于 0.3.0)见 [QCC-ENRICHMENT-DESIGN.md](QCC-ENRICHMENT-DESIGN.md)。
5
+
6
+ ## 0. 工具面口径
7
+
8
+ 企查查 MCP 当前按 **6 大资源域** 暴露数据工具,**合计 185 个**(16 + 38 + 18 + 35 + 34 + 44 = 185),
9
+ 另加招投标附加域 6 个:
10
+
11
+ | 资源域 | MCP 前缀 | 工具数 | 授权要求 | 数据主题 |
12
+ | --- | --- | --- | --- | --- |
13
+ | 工商 | `mcp__qcc-company__*` | 16 | 基础授权 | 主体、股权、人员、财务、上市 |
14
+ | 风险 | `mcp__qcc-risk__*` | 38 | 基础授权 | 司法、失信、执行、处罚、冻结 |
15
+ | 知产 | `mcp__qcc-ipr__*` | 18 | 基础授权 | 专利、商标、软著、数字资产 |
16
+ | 经营 | `mcp__qcc-operation__*` | 35 | 基础授权 | 资质、招投标、融资、舆情、监管 |
17
+ | 历史 | `mcp__qcc-history__*` | 34 | **企业认证账号** | 历史股东/法人/变更/风险 |
18
+ | 人员 | `mcp__qcc-executive__*` | 44 | 基础授权 | 董监高个人风险与关联 |
19
+ | 招投标(附加) | `mcp__qcc-tender__*` | 6 | 基础授权 | 标讯、拟建项目、企业标讯画像 |
20
+
21
+ > 6 大资源域恰好 185 个;招投标域为附加能力。实际可用工具数随授权资源域(`QCC_RESOURCES`)
22
+ > 与账号等级变化。各工具的具体输入输出字段以官方 MCP 工具 schema 为准,本文只列
23
+ > 「补全维度 → 关键字段 → 来源工具」的映射。
24
+
25
+ ---
26
+
27
+ ## 1. 分期总览
28
+
29
+ | 阶段 | 版本 | 交付形态 | 覆盖维度 | 依赖 |
30
+ | --- | --- | --- | --- | --- |
31
+ | 一期 | 0.3.0 ✅ | 方案 A:模型中介式 Skill `enterprise-enrichment` | 核心工商 7 字段 + 风险标签 | `qcc-dsh-mcp-oauth` 已连接 |
32
+ | 二期 | 0.4.0 | 方案 A 扩展 Skill:工商全景 + 股权穿透 | 工商域 16 工具 + 历史工商 | 同上 |
33
+ | 三期 | 0.5.0 | 方案 A 扩展 Skill:风险/知产/经营 + 方案 B 批量后端 | 风险 38 + 知产 18 + 经营 35 | 同上;S7 PASS,G5-2 安全闭环已落地 |
34
+ | 四期(可选) | 0.6.0 | 历史轨迹 + 董监高 + 招投标 | 历史 34 + 人员 44 + 招投标 6 | 企业认证账号(历史域) |
35
+
36
+ 每期之间不互相阻塞:二期工商全景、三期风险知产都可独立评审与合入。
37
+
38
+ ---
39
+
40
+ ## 2. 一期(0.3.0,已落地)· 核心工商字段
41
+
42
+ v1 字段契约(方案 A):
43
+
44
+ | 字段 | 含义 | 来源工具 |
45
+ | --- | --- | --- |
46
+ | `credit_no` | 统一社会信用代码 | `mcp__qcc-company__get_company_registration_info` |
47
+ | `legal_rep` | 法定代表人 | 同上 |
48
+ | `reg_capital` | 注册资本 | 同上 |
49
+ | `establish_date` | 成立日期 | 同上 |
50
+ | `reg_status` | 登记状态 | 同上 |
51
+ | `biz_status` | 经营状态 | 同上 |
52
+ | `risk_tags` | 风险标签(命中维度 + 计数) | `mcp__qcc-risk__get_company_risk_scan` |
53
+
54
+ ---
55
+
56
+ ## 3. 二期(0.4.0)· 工商全景 + 股权穿透
57
+
58
+ 目标:把「只补身份证」升级为「补全家福」——主体详情、股权结构、对外投资、人员、财务、上市、
59
+ 联系方式、开票信息,以及历史工商沿革(历史域)。
60
+
61
+ ### 3.1 工商域(`mcp__qcc-company__*`)
62
+
63
+ | 补全维度 | 关键字段 | 来源工具 |
64
+ | --- | --- | --- |
65
+ | 主体锚定 | 企业名、统一社会信用代码、注册号 | `get_company_by_query` / `get_company_registration_info` |
66
+ | 企业画像 | 简介、行业、产业链 | `get_company_profile` |
67
+ | 二要素核验 | 名称 ↔ 信用代码是否一致 | `verify_company_accuracy` |
68
+ | 实控人 | 总持股比例、表决权比例、最终受益股份 | `get_actual_controller` |
69
+ | 受益所有人 | UBO 识别(央行口径) | `get_beneficial_owners` |
70
+ | 股东构成 | 股东名、持股比例、认缴出资额、出资时间 | `get_shareholder_info` |
71
+ | 对外投资 | 被投企业、持股比例、认缴额 | `get_external_investments` |
72
+ | 分支机构 | 机构名、负责人、地区、状态 | `get_branches` |
73
+ | 主要人员 | 姓名、职务(董监高) | `get_key_personnel` |
74
+ | 变更记录 | 变更事项、前后值、日期 | `get_change_records` |
75
+ | 年报 | 报告年度、从业人数、资产/营收 | `get_annual_reports` |
76
+ | 联系方式 | 电话、邮箱、网站、ICP 备案 | `get_contact_info` |
77
+ | 开票信息 | 税号、地址、开户行 | `get_tax_invoice_info` |
78
+ | 上市信息 | 代码、简称、交易所、市值 | `get_listing_info` |
79
+ | 财务数据 | 营收、利润、资产负债率、增长率 | `get_financial_data` |
80
+
81
+ ### 3.2 历史工商(`mcp__qcc-history__*`,需企业认证账号)
82
+
83
+ | 补全维度 | 关键字段 | 来源工具 |
84
+ | --- | --- | --- |
85
+ | 历史股东 | 曾持股比例、退出日期 | `get_historical_shareholders` |
86
+ | 历史法人 | 历任法代、任职起止 | `get_historical_legal_rep` |
87
+ | 历史高管 | 历任高管、任职起止 | `get_historical_executives` |
88
+ | 历史登记 | 曾用名、历史注册资本/地址/经营范围 | `get_historical_registration` |
89
+
90
+ ### 3.3 二期验收门
91
+
92
+ - Skill 对一份 20 条企业名单,能在二期字段契约内输出**每企业 ≥ 15 个维度**的补全表。
93
+ - 消歧规则不变(`get_company_by_query` 多候选必须询问用户)。
94
+ - 金额/比例/计数逐字引用工具返回值,禁止自算、禁止臆测。
95
+
96
+ ### 3.4 实施状态(0.4.0 发布候选)
97
+
98
+ - ✅ 第一切片:`lib/qcc-phase2.js` 已固化本地 QCC MCP 一手源码核对过的
99
+ 16 个工商工具和 4 个历史工商工具;`enterprise-enrichment` 已扩展为按维度组调用。
100
+ - ✅ 安全规则:多候选人工确认、付费组按需调用、数值原样保留、来源工具标记、
101
+ 历史域无权显式降级。
102
+ - ✅ 验收自动化:`e2e:phase2` 默认关闭,检查 20 企业 / 每企业 ≥15 维、
103
+ 来源工具、原值一致性、主体消歧和历史账号门,拒绝合成证据替代真实 E2E。
104
+ - ✅ DSH 冒烟:当前工作树 tarball 已在隔离 `0.1.1-rc.2` 和 `0.1.2-alpha.2` Host
105
+ 完成加载,两者 seam 均返回 `enrichSkillRegistered:true`;测试 Host 已停止,生产端口未触碰。
106
+ - ✅ 预检状态冒烟:无 OAuth 插件时返回 `oauth-plugin-missing`;安装插件但未授权时
107
+ 返回 `not-connected-or-refreshing`。两种情况都不执行 QCC 工具,不产生付费调用。
108
+ - ✅ 真实发布门主路径:隔离 rc.2 Host 完成 OAuth、20 企业、400 次调用;20/20 主体解析,
109
+ 每企业当前最低 15 维、历史 4 维,严格验收通过。
110
+ - ✅ 2026-09-02 发布门收口:自然过期 token 真实刷新、16+4 动态工具恢复、续期后 1 行真实 enrich;
111
+ 401/429/配额耗尽通过 Web→Bridge→ToolRuntime 故障注入验证,无自动重试且审计脱敏。
112
+
113
+ ---
114
+
115
+ ## 4. 三期(0.5.0)· 风险 / 知产 / 经营 + 批量后端
116
+
117
+ 目标:覆盖风控名单、供应商尽调、招投标核查三类场景;同时启动方案 B 批量后端。
118
+
119
+ ### 4.1 风险域(`mcp__qcc-risk__*`,38 工具)
120
+
121
+ | 补全维度 | 关键字段 | 来源工具 |
122
+ | --- | --- | --- |
123
+ | 风险总览 | 35 项因子命中计数 | `get_company_risk_scan` |
124
+ | 关联风险 | 股东/投资/法人等关联方命中 | `get_company_related_risk_scan` |
125
+ | 行政处罚 | 处罚结果、金额、机关、日期 | `get_administrative_penalty` |
126
+ | 环保处罚 | 处罚结果、金额、机关 | `get_environmental_penalty` |
127
+ | 经营异常 | 列入原因、日期、决定机关 | `get_business_exception` |
128
+ | 严重违法 | 列入原因、日期、移出 | `get_serious_violation` |
129
+ | 失信被执行人 | 案号、金额、法院、日期 | `get_dishonest_info` |
130
+ | 被执行人 | 案号、执行标的、法院 | `get_judgment_debtor_info` |
131
+ | 终本案件 | 案号、终本日期、未履行金额 | `get_terminated_cases` |
132
+ | 限制高消费 | 案号、申请人、对象 | `get_high_consumption_restriction` |
133
+ | 股权冻结 | 股权数额、法院、期限 | `get_equity_freeze` |
134
+ | 股权出质 | 出质人、质权人、数额 | `get_equity_pledge_info` |
135
+ | 动产/土地抵押 | 抵押物、担保债权额、抵押权人 | `get_chattel_mortgage_info` / `get_land_mortgage_info` |
136
+ | 破产重整 | 案号、申请人、被申请人 | `get_bankruptcy_reorganization` |
137
+ | 立案信息 | 案号、案由、当事人 | `get_case_filing_info` |
138
+ | 开庭公告 | 案号、案由、开庭时间 | `get_hearing_notice` |
139
+ | 法院公告/送达 | 公告类型、案号、当事人 | `get_court_notice` / `get_service_notice` |
140
+ | 裁判文书 | 文书 ID、标题、案由、金额 | `get_judicial_documents`(详情 `get_judicial_document_detail`) |
141
+ | 欠税/税收违法 | 税种、金额、机关 | `get_tax_arrears_notice` / `get_tax_violation` / `get_tax_abnormal` |
142
+ | 违约 | 债券/票据/非标违约本金利息 | `get_default_info` |
143
+ | 担保/惩戒/限出境 | 担保金额、惩戒类型、案号 | `get_guarantee_info` / `get_disciplinary_list` / `get_exit_restriction` |
144
+ | 司法拍卖/悬赏/询价 | 起拍价、案号、财产 | `get_judicial_auction` / `get_property_asset_announcement` / `get_valuation_inquiry` |
145
+ | 诉前调解/公示催告/清算/注销 | 案号、案由、状态 | `get_pre_litigation_mediation` / `get_public_exhortation` / `get_liquidation_info` / `get_cancellation_record_info` / `get_simple_cancellation_info` / `get_service_announcement` |
146
+
147
+ ### 4.2 知产域(`mcp__qcc-ipr__*`,18 工具)
148
+
149
+ | 补全维度 | 关键字段 | 来源工具 |
150
+ | --- | --- | --- |
151
+ | 专利 | 专利名、类型、法律状态、申请日 | `get_patent_info` |
152
+ | 国际专利 | 发明名、公开号、发明人 | `get_international_patent` |
153
+ | 商标 | 商标名、类别、状态 | `get_trademark_info` |
154
+ | 商标文书 | 文书号、申请人、被申请人 | `get_trademark_document` |
155
+ | 软著 | 软件名、版本、登记号 | `get_software_copyright_info` |
156
+ | 作品著作权 | 作品名、登记号 | `get_copyright_work_info` |
157
+ | 标准 | 标准名、编号 | `get_standard_info` |
158
+ | 知产出质 | 出质类型、名称、期限 | `get_ipr_pledge` |
159
+ | 集成电路布图 | 布图名、登记号 | `get_integrated_circuit_layout` |
160
+ | 数字资产 | APP / 小程序 / 公众号 / 抖音 / 快手 / 微博 / 网店 | `get_app_info` / `get_mini_program` / `get_wechat_official_account` / `get_douyin_account` / `get_kuaishou_account` / `get_weibo_account` / `get_online_store` |
161
+ | 备案 | ICP/APP/小程序/算法备案 | `get_internet_service_info` |
162
+ | 特许经营 | 备案号、特许人 | `get_commercial_franchise` |
163
+
164
+ ### 4.3 经营域(`mcp__qcc-operation__*`,35 工具)
165
+
166
+ | 补全维度 | 关键字段 | 来源工具 |
167
+ | --- | --- | --- |
168
+ | 行政许可 | 许可证名称、编号、有效期 | `get_administrative_license` |
169
+ | 资质证书 | 证书类型、等级、状态 | `get_qualifications` |
170
+ | 纳税资质 | 纳税人类型、税务机关 | `get_taxpayer_qualification` |
171
+ | 信用评价 | 纳税信用、海关信用等级 | `get_credit_evaluation` |
172
+ | 信用承诺 | 类型、履行状态 | `get_credit_commitments` |
173
+ | 荣誉/榜单 | 荣誉名、榜单名、排名 | `get_honor_info` / `get_ranking_list_info` |
174
+ | 招投标 | 项目名、角色、金额 | `get_bidding_info` |
175
+ | 融资记录 | 轮次、金额、时间 | `get_financing_records` |
176
+ | 融资租赁 | 出租/承租、租赁价值 | `get_financing_lease_info` |
177
+ | 私募基金 | 管理人编号、规模区间 | `get_private_fund_manager` |
178
+ | 投资机构 | 机构类型、管理规模 | `get_investment_institution` |
179
+ | 上市公告 | 公告标题、类型、日期 | `get_company_announcement` / `get_related_announcement` |
180
+ | 舆情 | 新闻标题、情感倾向、时间 | `get_news_sentiment` |
181
+ | 政府约谈/公告 | 约谈问题、机关、日期 | `get_government_interview` / `get_government_announcement` |
182
+ | 监管抽查 | 抽查事项、结果、机关 | `get_random_check` / `get_spot_check_info` / `get_product_spot_check` |
183
+ | 食品安全 | 抽检结果、生产商 | `get_food_safety` |
184
+ | 违规通报 | 软件/化妆品/未准入境/召回 | `get_software_violation` / `get_counterfeit_cosmetics` / `get_entry_denied` / `get_product_recall` |
185
+ | 进出口信用 | 信用等级、备案 | `get_import_export_credit` |
186
+ | 土地/产权 | 受让/转让/产权交易 | `get_land_grant_info` / `get_land_transfer_info` / `get_property_rights_transaction` |
187
+ | 电信/游戏/广告 | 许可、版号、审查 | `get_telecom_license` / `get_game_approval` / `get_advertising_review` |
188
+ | 科技成果 | 成果名、登记号 | `get_tech_achievement` |
189
+ | 资产拍卖/招聘 | 起拍价、职位、薪酬 | `get_asset_auction` / `get_recruitment_info` |
190
+
191
+ ### 4.4 三期并行 · 方案 B 批量后端
192
+
193
+ 一期/二期/三期均为模型中介式(模型逐个调 QCC 工具)。当名单规模进入百级/千级,模型逐调成本高,
194
+ 方案 B 已启动:插件内 `lib/qcc.js` 经公共 `ctx.tools.execute()` 调用 mcp-client 动态注册的工具;
195
+ 不直接访问 `ctx.loader` 条目或 mcp-client 私有 client。
196
+
197
+ - Spike #7:rc.2 / alpha.2 双基线 PASS。
198
+ - G5-2:在 G5-1 基础上完成默认关闭 E2E Runner、脱敏、请求幂等、多候选确认续跑、
199
+ retryable 失败人工重试、细分错误分类与安全审计,均已通过 Mock/Contract 测试。
200
+ - 已通过:真实 OAuth 首连、授权跨重启恢复、真实 QCC 主调用路径、token 自然到期刷新与续期后调用。
201
+ - 已通过:401/429/配额耗尽故障注入;仅 retryable 错误允许用户显式重试,非 retryable 配额错误在派发前阻断。
202
+
203
+ ---
204
+
205
+ ## 5. 四期(0.6.0,可选)· 历史轨迹 + 董监高 + 招投标
206
+
207
+ ### 5.1 人员域(`mcp__qcc-executive__*`,44 工具)
208
+
209
+ | 补全维度 | 关键字段 | 来源工具 |
210
+ | --- | --- | --- |
211
+ | 个人风险总览 | 18 项命中计数 | `get_executive_risk_scan` |
212
+ | 关联企业风险 | 其任法代/董监高/控制企业的风险 | `get_executive_related_risk_scan` |
213
+ | 任职 | 在外任职企业、职务 | `get_executive_positions` |
214
+ | 法代角色 | 担任法代的企业列表 | `get_executive_legal_rep_roles` |
215
+ | 对外投资 | 直接 + 间接持股 | `get_executive_investments` |
216
+ | 控制企业 | 实控企业、投资比例 | `get_executive_controlled_companies` |
217
+ | 关联企业 | 全部关联企业 + 角色 | `get_executive_related_companies` |
218
+ | 个人司法/处罚 | 失信/被执行/限高/限出境/处罚/冻结/出质 | 对应 `get_executive_*`(18 维 + 历史版本) |
219
+ | 历史轨迹 | 历史任职/法代/投资/合伙 | `get_executive_historical_*`(约 20 个) |
220
+
221
+ ### 5.2 招投标域(`mcp__qcc-tender__*`,6 工具)
222
+
223
+ | 补全维度 | 关键字段 | 来源工具 |
224
+ | --- | --- | --- |
225
+ | 企业标讯画像 | 招采/投标/中标/代理数量 | `search_companies` |
226
+ | 企业标讯明细 | 标讯列表 + 角色 | `search_company_tenders` |
227
+ | 招标/中标公告 | 标题、金额、时间 | `search_tenders`(详情 `get_tender_detail`) |
228
+ | 拟建项目 | 项目、投资、阶段 | `search_proposed_projects`(详情 `get_proposed_project_detail`) |
229
+
230
+ ---
231
+
232
+ ## 6. 可清洗补全的通用维度(跨期复用的「列」模型)
233
+
234
+ 无论哪一期,补全输出的列都归入以下**通用维度族**,便于用户勾选与 CSV 回写:
235
+
236
+ 1. **身份维度**:企业名、统一社会信用代码、注册号、曾用名、股票代码/简称。
237
+ 2. **主体维度**:法定代表人、注册资本、成立日期、登记状态、经营状态、注册地址、行业、简介。
238
+ 3. **股权维度**:股东构成、实控人、受益所有人、对外投资、分支机构、历史股东/法人。
239
+ 4. **人员维度**:董监高、主要人员、个人任职/投资/风险。
240
+ 5. **财务维度**:营收、利润、资产负债率、增长率、融资记录、年报。
241
+ 6. **合规风险维度**:经营异常、严重违法、行政处罚、环保处罚、欠税、税收违法、食品/产品/违规通报。
242
+ 7. **司法风险维度**:立案、开庭、裁判文书、失信、被执行、终本、限高、股权冻结/出质、抵押、破产。
243
+ 8. **知产维度**:专利、商标、软著、著作权、标准、数字资产、备案。
244
+ 9. **经营资质维度**:行政许可、资质、纳税资质、信用评价、荣誉、榜单、进出口信用。
245
+ 10. **市场活动维度**:招投标、拟建项目、融资、上市公告、舆情、招聘。
246
+
247
+ ---
248
+
249
+ ## 7. 分期评审与合入规则
250
+
251
+ - 每期交付前须通过 `npm run check`(lint + docs:check + marketing:check + verify-pack + 13 例测试)。
252
+ - 每期新增 Skill 内容须遵守安全不变量:不编造字段、多候选必询问、金额比例计数逐字引用。
253
+ - 历史域(`qcc-history`)与四期人员历史工具需企业认证账号,未授权时 Skill 须显式降级并说明,不得假装补全。
254
+ - 版本号按 SemVer:二期 0.4.0、三期 0.5.0、四期 0.6.0,均需 CHANGELOG + README 版本同步后走 OIDC 发布。
@@ -0,0 +1,57 @@
1
+ # 0.4.0 发布候选检查单
2
+
3
+ - 源码版本:`0.4.0`
4
+ - 状态:发布候选,尚未创建 `v0.4.0` tag、GitHub Release 或 npm 发布
5
+ - 基线日期:2026-09-02
6
+
7
+ ## 已纳入范围
8
+
9
+ - `enterprise-enrichment` 扩展为工商全景、股权、治理和历史工商维度组按需调用。
10
+ - 固化 16 个当前工商工具与 4 个历史工商工具契约,并兼容
11
+ `qcc-dsh-mcp-oauth@0.1.7` 实测 legacy serverName。
12
+ - 新增只读 `/data-cleaning/api/phase2/capabilities` 预检、真实证据验收器与默认关闭的本地 Runner。
13
+ - G5 Host Bridge 提供批量幂等、多候选人工续跑、retryable 失败人工重试、取消/超时、错误分类和脱敏审计。
14
+ - 发布 workflow 在发布前执行完整 `npm run check`,并强制 Git tag 与 `package.json` 版本一致。
15
+
16
+ ## 已通过门
17
+
18
+ - 单元、契约、Web 路由、Skill、脱敏和 Runner 自动测试。
19
+ - npm 打包白名单与 README/包版本一致性检查。
20
+ - DSH `0.1.1-rc.2` / `0.1.2-alpha.2` 隔离 Host 加载冒烟。
21
+ - rc.2 隔离 Host 真实 OAuth、授权跨重启恢复、20 家公开企业、400 次 QCC 调用:
22
+ 20/20 主体解析,每企业当前工商最低 15 维、历史工商 4 维。
23
+ - rc.2 隔离 Host 的旧 access token 已自然过期;重新启动后持久 grant 自动刷新、到期时间前移,
24
+ 16 个 company + 4 个 history 动态工具恢复,并以 1 行真实 enrich(1/1 成功、2 条安全审计)确认新 token 可用。
25
+ - Web→Bridge→Mock ToolRuntime 故障注入覆盖 401、429 与配额耗尽:除 `UNKNOWN_TOOL` 刷新竞态外
26
+ 均不自动重试;401/429 只能显式人工重试,配额耗尽在重新派发前阻断;审计不含参数、原始响应或秘密。
27
+ - `main` 提交 `0c8cb75` 的远端 CI `33569931224` 已通过 Linux Node 22、Linux Node 24 与 Windows Node 24 全矩阵。
28
+ - 真实证据与报告仅保存在 Git 忽略的本机目录,不进入仓库或 npm 包。
29
+
30
+ ## 发布阻断门(已通过)
31
+
32
+ 2026-09-02 已完成此前两个剩余门:
33
+
34
+ 1. ✅ access token 自然到期后的真实 refresh、持久 grant 更新、动态工具恢复与续期后最小真实调用。
35
+ 2. ✅ 401、429、配额不足的本地故障注入、稳定错误码、人工重试门及审计脱敏。
36
+
37
+ 代码审查、本机 `npm run check`、干净工作树和远端 CI 已完成;剩余只是创建/推送 tag 所触发的正式发布操作,
38
+ 不再有 0.4.0 功能实现缺口。
39
+
40
+ ## 发布命令(阻断门全部通过后)
41
+
42
+ ```bash
43
+ npm run check
44
+ git status --short
45
+ git tag -a v0.4.0 -m "Release v0.4.0"
46
+ git push origin v0.4.0
47
+ ```
48
+
49
+ `v0.4.0` tag 会触发 `.github/workflows/release.yml`:校验 tag/包版本、执行完整检查、
50
+ 通过 npm OIDC Trusted Publishing 发布并生成 GitHub Release。不要手工写入生产密钥。
51
+
52
+ ## 回滚
53
+
54
+ - tag 尚未推送:删除本地 tag,修复后重新检查。
55
+ - tag 已推送但 workflow 未发布 npm:停止 workflow,修复后使用新的补丁版本;不要复用已公开 tag。
56
+ - npm 已发布:npm 版本不可覆盖。立即在 GitHub/npm 标记受影响版本,必要时执行 `npm deprecate`,
57
+ 修复后发布 `0.4.1`;代码回滚使用普通 revert commit,不改写 `main` 历史。
@@ -31,12 +31,59 @@ bash <(curl -fsSL https://raw.githubusercontent.com/duhu2000/dsh-data-cleaning-a
31
31
 
32
32
  ## 3. 能力说明
33
33
 
34
+ ### 3.1 本地清洗 / 补全 / 画像(Skill `data-cleaning`)
35
+
34
36
  | 工具 | 作用 |
35
37
  | --- | --- |
36
38
  | `data_profile` | 输出列概览与金额分布(min/max/sum/count) |
37
39
  | `data_clean_rows` | trim、手机号规范化、剔除缺失必填/负金额/重复行 |
38
40
  | `data_complete_rows` | 空金额填 0、空姓名填占位、报告不可确定性补全的项 |
39
41
 
42
+ ### 3.2 企查查企业名单补全(Skill `enterprise-enrichment`)
43
+
44
+ 先用企查查 MCP 连接插件(`qcc-dsh-mcp-oauth`)完成授权,然后对对话说:
45
+
46
+ > 帮我补全这份企业名单:工商全景 + 股权穿透,不要历史工商。
47
+
48
+ 模型会按 `enterprise-enrichment` Skill 逐个企业调 `mcp__qcc-company__get_company_by_query`
49
+ (消歧,多候选时停下询问)→ `get_company_registration_info`(工商详情),
50
+ 然后只调用请求的维度组:
51
+
52
+ - `panorama`:企业画像、联系方式、开票、上市、财务;
53
+ - `ownership`:实控人、受益所有人、股东和对外投资;
54
+ - `governance`:分支机构、主要人员、变更记录和年报;
55
+ - `history`:历史股东、法人、高管和登记信息(需企业认证账号)。
56
+
57
+ 如果请求没有明确维度,Skill 会先让用户选择,不默认调用全部付费工具。
58
+ 历史域无权时只标记 `permission_required`,当前工商组仍继续。对话默认返回统计摘要和小量预览;
59
+ 完整明细只在 Host 确实提供同源下载/产物能力时交付。
60
+ 开发者可在真实调用前 GET `/data-cleaning/api/phase2/capabilities`,只读检查 16+4 工具面;
61
+ 该预检不发起 QCC 或付费调用,也不会把「工具已注册」误报为「历史账号已授权」。
62
+
63
+ **前置条件**:先连接企查查 MCP(未连接时 Skill 会引导执行 `qcc_oauth_connect`)。
64
+
65
+ **本阶段边界**(方案 A,模型中介式):
66
+ - 不重造 OAuth;工具面来自 `qcc-dsh-mcp-oauth`。
67
+ - 逐企业调用,适合中小名单(几十条以内)。
68
+ - 金额、比例、计数保留 QCC 原值,不自算股权链、不将缺失值写成「无」或 0。
69
+ - 0.4.0 尚未发布;20 企业、每企业至少 15 个当前维度并含 4 个历史维度的真实账号验收已通过。
70
+ access token 自然到期后的真实刷新、动态工具恢复以及限流/配额故障注入已在隔离环境验收。
71
+
72
+ ### 3.3 QCC 后台批量 Host Bridge(0.4.0 发布候选 / G5-2)
73
+
74
+ 源码 `main` 已提供 `/data-cleaning/api/g5/capabilities`(只读能力探测)和
75
+ `/data-cleaning/api/g5/enrich`(同源批量补全)基础层。它按企业名去重调用、只对唯一精确主体继续补全,
76
+ 多候选进入人工确认队列,模型不接触完整明细。
77
+
78
+ 这是 0.4.0 尚未发布的候选能力:真实 OAuth、授权跨重启恢复、QCC 主调用路径、token 自然到期刷新
79
+ 与 401 / 429 / 配额故障注入均已完成隔离验收;正式可用版本仍以 npm/GitHub Release 为准。
80
+ 调用批量端点必须由 UI 在用户确认后同时发送 `confirmPaidCalls:true` 和唯一 `idempotencyKey`;
81
+ 未确认或缺少幂等键时不会产生任何 QCC 调用。
82
+
83
+ 初次请求返回 `runId`:多候选进入 `awaiting-review`,只能通过 `/g5/resolve` 选择返回候选中的
84
+ 信用代码后续跑;retryable 失败只能由用户通过 `/g5/retry` 显式重试。run 仅在 Host 内存保留
85
+ 30 分钟,Host 重启后失效,不把原始企业行持久化落盘。
86
+
40
87
  ## 4. 数据边界
41
88
 
42
89
  - 模型只收到统计摘要(total / kept / dropped / incomplete),**从不读取原始明细行**。
@@ -54,4 +101,9 @@ bash <(curl -fsSL https://raw.githubusercontent.com/duhu2000/dsh-data-cleaning-a
54
101
  - **Q:安装后工具不出现?** A:确认已完全重启 DSH;确认 `dsh plugin list`(或 profile 的
55
102
  `package.json` → `dsh.profile.bundles`)含 `dsh-data-cleaning-agent`。
56
103
  - **Q:XLSX 解析报 `XLSX_UNAVAILABLE`?** A:当前 DSH 组合未安装 `xlsx`;web 组合默认可用。
57
- - **Q:能接企查查补全企业信息吗?** A:路线图见 [PLAN-OSS.md](PLAN-OSS.md)(方案 A 模型中介,后续版本)。
104
+ - **Q:能接企查查补全企业信息吗?** A:可以。先安装并连接 `qcc-dsh-mcp-oauth`;rc.2 隔离 Profile
105
+ 需同时显式安装同版本 `@deepseek-ai/dsh-mcp-client`。再说"帮我补全这份企业名单",会自动走
106
+ `enterprise-enrichment` Skill(方案 A 模型中介式)。字段契约与二期规划见
107
+ [QCC-ENRICHMENT-DESIGN.md](QCC-ENRICHMENT-DESIGN.md)。
108
+ - **Q:可以在后台批量补全吗?** A:`main` 已有 G5-2 Host Bridge 安全闭环,真实 OAuth/QCC 主路径已验收但尚未发布;
109
+ 生产使用前仍需通过 `docs/G5-HOST-BRIDGE.md` 的 token 到期刷新与计费错误门。
package/lib/index.js CHANGED
@@ -6,6 +6,7 @@
6
6
  * 2. ctx.skills —— 注册内嵌 Skill `data-cleaning`(正文指引模型调上述工具)
7
7
  * 3. webServer/webRuntime —— 挂载上传/解析/同步清洗补全/异步任务/UI 路由
8
8
  * 4. ctx.jobs + ctx.storageDomain —— 异步任务状态机(web 组合内可用)
9
+ * 5. ctx.tools.execute —— G5 QCC Host Bridge(程序化批量补全,web 组合内可用)
9
10
  *
10
11
  * headless 组合无 webServer/webRuntime:用 ctx.get() 存在性守卫跳过 web 半区,
11
12
  * 工具与 Skill 照常注册(端到端真实模型路径依赖它们)。
@@ -13,6 +14,7 @@
13
14
  import { mountWebRoutes } from './web.js';
14
15
  import { registerTools, TOOL_CLEAN } from './tools.js';
15
16
  import { registerSkill, SKILL_NAME } from './skill.js';
17
+ import { registerEnrichSkill, ENRICH_SKILL_NAME } from './skill-enrich.js';
16
18
 
17
19
  export const name = 'data-cleaning-agent';
18
20
  export const inject = [];
@@ -25,6 +27,7 @@ export function apply(ctx, config) {
25
27
  skillRegistered: false,
26
28
  webMounted: false,
27
29
  webSkipped: false,
30
+ qccBridgeMounted: false,
28
31
  };
29
32
  const disposers = [];
30
33
 
@@ -46,7 +49,9 @@ export function apply(ctx, config) {
46
49
  report.skills = 'present';
47
50
  report.skillRegister = typeof sctx.skills?.register === 'function' ? 'ok' : String(typeof sctx.skills?.register);
48
51
  disposers.push(registerSkill(sctx.skills));
52
+ disposers.push(registerEnrichSkill(sctx.skills));
49
53
  report.skillRegistered = true;
54
+ report.enrichSkillRegistered = true;
50
55
  });
51
56
  } catch (error) {
52
57
  report.skills = `absent: ${error instanceof Error ? error.message : String(error)}`;