9.5 KiB
W1-T3 独立复审报告(聚焦修复)
状态
完成。仅读取实现、契约、来源数据与本地 O*NET CSV,并独立执行测试和来源审计;未修改任何实现文件,仅写入本报告。
Verdict
FAIL
第一轮 Critical 已关闭,I-1、I-2 的当前数据问题已关闭;I-3 的“逐条可追溯数据”已关闭,但对应的回归测试仍未关闭:当前测试只精确断言 5/47 条 ONET 技能来源和 10/137 条非空 Importance,且没有任何 CSV 驱动的来源完整性测试。多数不存在或伪造的 ONET 行、错误 Importance 仍会通过测试。该项属于 Important,阻断 T4。
评审对象与依据
实现文件:
D:\1\zhi\zhilai\mydreamjob-server\src\main\resources\db\migration\V35__skill_cloud_taxonomy.sqlD:\1\zhi\zhilai\mydreamjob-server\src\main\resources\db\migration\V36__skill_cloud_seed.sqlD:\1\zhi\zhilai\mydreamjob-server\src\test\java\com\mydreamjob\skill\SkillTaxonomyMigrationTest.javaD:\1\zhi\zhilai\mydreamjob-server\src\test\java\com\mydreamjob\skill\SkillCloudSeedDataIntegrationTest.java
依据:
- 修订后的
execution-contract.md、design.md、tasks.md changes/n03-skill-cloud/data/source-manifest.mddocs/skill-taxonomy-sources.md- 第一轮报告
changes/n03-skill-cloud/.superpowers/sdd/reviews/W1-T3.md - 修复报告日志
mydreamjob-server/target/skill-taxonomy-fix-green.log - 本地 O*NET 31.0 CSV 与
changes/n03-skill-cloud/data/esco-skill-lookup.json - ESCO 官方只读 API(用于职位 URI 真实性核验)
独立测试结果
环境:
JAVA_HOME=D:\java\jdk- Maven:
D:\maven\apache-maven-3.9.7\bin\mvn.cmd - 工作目录:
D:\1\zhi\zhilai\mydreamjob-server
执行:
$env:JAVA_HOME='D:\java\jdk'
& 'D:\maven\apache-maven-3.9.7\bin\mvn.cmd' '-Dtest=SkillTaxonomyMigrationTest,SkillCloudSeedDataIntegrationTest' test
结果:
SkillCloudSeedDataIntegrationTest: Tests run: 6, Failures: 0, Errors: 0, Skipped: 0
SkillTaxonomyMigrationTest: Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
Total: Tests run: 8, Failures: 0, Errors: 0, Skipped: 0
BUILD SUCCESS
Total time: 40.195 s
第一轮 Finding 关闭状态
| 第一轮 Finding | 状态 | 独立证据 |
|---|---|---|
| C-1:混合来源未授权,职位与关系来源被替换 | 关闭 | execution-contract.md:7,20,56 已明确授权“ESCO 主来源 + ONET software_skills 补充”;design.md:32-43 与 source-manifest.md:35-43 同步;V36 中 10 个职位均使用 ESCO occupation URI,25 条 ESCO 技能和 47 条 ONET 补充技能分源导入。 |
| I-1:金融/风控/教育产品经理代理映射不明确或 URI 不真实 | 关闭 | V36:6-28 明确代理 SOC;V35:93-96 将目标来源与 Importance 来源拆列;V36:274-413 的 137 条非空热度均设置 importance_is_proxy=1。独立调用 ESCO 官方 API,10 个职位行对应的 8 个唯一 URI 全部返回 200,标题分别为 web developer、software developer、software tester、financial analyst、risk manager、ICT product manager、instructional designer、data analyst。 |
| I-2:manifest 分类遗漏,测试只要求至少一个分类 | 当前数据关闭 | manifest 10 个职位的分类清单与 V36:59-127 的实际 68 个分类逐项一致,测试也已改为精确比较完整清单;独立解析确认 68/68 分类至少关联 1 条技能。剩余测试弱点见 Minor-1。 |
| I-3:Importance 缺少逐技能来源映射和有效验证 | 部分关闭,仍为 Importance 阻断 | V35:94-110 已增加 SOC、Element ID、代理标记和完整性约束;V36:274-413 的 137/137 条非空热度均带完整字段,并可精确核对 CSV。但测试只覆盖少量样本,不能阻止多数来源或热度被篡改;详见 Important-1。 |
来源审计方法与数量
1. SQL 结构审计
独立解析 V36 的 INSERT 行,结果:
| 对象 | 数量 |
|---|---|
| 来源版本 | 2 |
| 行业 | 3 |
| 职位 | 10 |
| 技能分类 | 68 |
| 技能 | 72(ESCO 25,O*NET 47) |
| 技能别名 | 72 |
| 职位技能关系 | 139 |
| 非空 Importance | 137 |
| 空 Importance | 2 |
| 每个职位非空 Importance 最小值 | 12 |
V36 仅有 7 条 INSERT 语句,没有 CREATE、ALTER、DROP、UPDATE、DELETE。com.mydreamjob.skill 主代码包不存在,未提前实现 T4;V1-V34 没有改动。
2. ESCO 来源审计
- 25/25 条
source_type='ESCO'技能的 URI 都能在esco-skill-lookup.json中找到。 - 10/10 个职位行的
source_version_id=1,职位来源均为 ESCO occupation URI。 - 10 个职位使用 8 个唯一 ESCO occupation URI;
BACKEND_DEVELOPER、DEVOPS_ENGINEER、QUANTITATIVE_DEVELOPER复用 software developer URI,V36:47 已明确标注为项目代理。 - 对 8 个唯一 URI 独立调用
https://ec.europa.eu/esco/api/resource/occupation?uri=...&language=en,全部 HTTP 200,返回的 URI 与请求一致。
3. O*NET software_skills 审计
- 使用本地
mydreamjob-server/target/onet-31/software_skills.csv(31,821 行)。 - 47/47 条 O*NET 技能的
(O*NET-SOC Code, Workplace Example, Element ID)三元组精确命中 CSV,无缺失或伪造组合。 - 当前测试对这 47 条来源只有正则格式检查,另精确断言的来源样本为 5 条。
4. Importance 审计
- 使用本地
work_activities.csv、knowledge.csv、essential_skills.csv、transferable_skills.csv,共解析出 99,231 个(SOC, Element ID, Data Value)的IM/Importance键。 - 137/137 条非空 Importance 均可按
(importance_source_code, importance_element_id, importance)精确命中至少一个 CSV。 - 137/137 条均满足
importance_source_code和importance_element_id非空,且importance_is_proxy=1。 - 2/2 条空 Importance 的 SOC、Element ID 均为 NULL,
importance_is_proxy=0。 - 当前测试对 137 条非空热度中的 10 条做精确值断言,其余 127 条只检查字段存在,不检查数值是否真实。
阻断项
Important-1:回归测试不能覆盖大多数 O*NET 来源与 Importance 篡改
位置
SkillCloudSeedDataIntegrationTest.java:132-139:47 条 O*NET 来源只验证正则格式。SkillCloudSeedDataIntegrationTest.java:141-145:仅精确断言 5 条 O*NETsoftware_skills行。SkillCloudSeedDataIntegrationTest.java:152-163:只验证非空字段是否存在及来源版本名称是否为 O*NET。SkillCloudSeedDataIntegrationTest.java:165-187:仅精确断言 10 条 Importance 及 2 条 NULL。
独立量化
- O*NET 技能总数为 47,精确来源断言为 5,剩余 42 条不存在“CSV 行必须存在”的回归保护。
- 非空 Importance 总数为 137,精确值断言为 10,剩余 127 条即使被改成任意 0-5 的数值,现有测试仍会通过。
- 测试文件未读取
software_skills.csv、work_activities.csv、knowledge.csv、essential_skills.csv或transferable_skills.csv,因此无法证明“当前值来自 O*NET 31.0 CSV”。
影响
当前数据库中的 47/47 技能来源和 137/137 Importance 已由本次复审全量核对为真实;但数据正确性只存在于当前 SQL 快照,没有被自动化测试保护。未来修改若把未抽样的来源替换为格式合法但不存在的三件套,或把未抽样的 Importance 改成错误值,测试仍会通过,随后直接影响词云排序和匹配结果。
修复方向
- 增加覆盖全部 47 条 O*NET 技能来源的精确来源清单或 CSV 驱动断言。
- 增加覆盖全部 137 条非空 Importance 的精确映射断言;若 CSV 不进入正常测试运行环境,至少提交一份受版本控制的完整映射基线,并校验行数、键集合和值。
- 对 137/137 条映射逐项验证
SOC + Element ID + Data Value,而不是只验证非空和应用层来源版本。
未决问题
Minor-1:每个分类至少关联一个技能未进入断言
SkillCloudSeedDataIntegrationTest.java:89-113 验证完整分类清单,但只对职位的技能总数和非空热度总数要求 >= 10,没有验证每个分类的关联技能数 >= 1。当前 68/68 分类均通过独立数据审计,因此不阻断;后续若新增或删改分类,建议补一条分组断言。
Minor-2:Importance 越界值测试仍缺失
V35:102-104 定义了 0-5 的 CHECK,但 T3 测试覆盖的是 provenance 缺失、代理标记非法和成功带来源更新,没有直接断言 importance < 0 或 > 5 在 H2 MODE=MySQL 下失败。MySQL 8.4 会执行 CHECK,当前没有发现生产不可兼容语法,但真实 MySQL 尚未在本次环境中执行。
Minor-3:执行计划中的契约哈希未同步修订版
当前 execution-contract.md 的 SHA-256 为 98d869bc3b7e29b6fefffd973e561be50ba21ef4f59f4146ccd47cf8164957da,与 .spec-superflow.yaml 一致;但 .superpowers/sdd/execution-plan.yaml 仍记录旧哈希 9ae4be4a8561d7f303804c84d75061bbf2c8b3be2e7c79495689c19ba09d028e。不影响 T3 数据正确性,建议在 W1 复评通过后同步执行计划。
未阻断的确认项
- V35 的新增列、provenance CHECK、代理标记 CHECK 在 H2
MODE=MySQL下通过测试。 importance_source_code、importance_element_id的字段长度足以容纳当前 O*NET SOC 和 Element ID。- V36 保持纯数据迁移,未提前引入 T4 Java 业务代码。
- 未修改 V1-V34。
阻断项汇总
T3 当前不通过。第一轮 C-1、I-1、I-2 的阻断已关闭,I-3 的当前数据已清除,但对应的自动化回归保护仍不足,必须补齐 Important-1 后才能交给 T4。