You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

10 KiB

W1-T3 独立评审报告

状态

完成。本次评审只读取实现、来源数据、契约和日志,并独立执行测试;未修改任何实现文件,仅写入本报告。

Verdict

FAIL

存在 1 项 Critical 和 3 项 Important。当前 V36 虽然能在 H2 下通过既有测试,但没有落实已批准的“ESCO 负责职位—技能—分类主关系”方案,且部分金融职位使用与目标职位不符的 O*NET SOC 替代来源;同时 T1 清单中的多个技能分类没有导入。上述问题均阻断 T4。

评审对象与依据

评审对象:

  • D:\1\zhi\zhilai\mydreamjob-server\src\main\resources\db\migration\V36__skill_cloud_seed.sql
  • D:\1\zhi\zhilai\mydreamjob-server\src\test\java\com\mydreamjob\skill\SkillCloudSeedDataIntegrationTest.java

对照依据:

  • changes/n03-skill-cloud/execution-contract.md
  • changes/n03-skill-cloud/design.md
  • changes/n03-skill-cloud/tasks.md
  • changes/n03-skill-cloud/data/source-manifest.md
  • docs/skill-taxonomy-sources.md
  • V35__skill_cloud_taxonomy.sql
  • 本地 ESCO lookup、O*NET 31.0 CSV、实现者 RED/GREEN 日志

独立检查结果

1. 数量与基本约束

独立解析和 H2 测试结果一致:

项目 结果
行业 3
职位 10
技能分类 50
技能 53
技能别名 53
职位技能关系 137
非空 Importance 133
空 Importance 4

每个职位均有 10 至 17 条职位技能关系,非空 Importance 数量均不少于 10。全部技能有中文标准名、非空 source_code 和至少一个别名;normalized_alias 无重复。当前 137 条关系的 category_id 均与同一 occupation_id 对应,未发现现有种子内的跨职位分类错配。

2. ESCO 与 O*NET 来源核验

  • V36 的 25 个 source_type='ESCO' URI 均可从 changes/n03-skill-cloud/data/esco-skill-lookup.json 找到,英文标题与 lookup 一致。
  • V36 的 28 个 O*NET 技能来源三元组 O*NET-SOC|Workplace Example|Element ID 均能在 software_skills.csv 精确命中;未发现伪造组合。
  • V36 注释声明的 43 组(SOC、Importance、语义元素)映射值均能在本地 O*NET CSV 中命中。其中 Scikit-learn 的当前工作区值已按 CSV 精确大小写修复。
  • lookup 中本身存在明显误匹配,例如 Angular→computer programming、Spring Boot→install deicing boot、Node.js→apply electrolytes to cathodes and anodes、React→react to emergency situations in a live performance environment、Redis→redistribute wagered money、Microsoft Power BI→Microsoft Access。当前 V36 没有使用这些错误 URI,因此它们不是本批次已导入数据的直接错误,但该 lookup 不能作为未经复核的可信自动映射源。

3. 独立测试

执行命令:

$env:JAVA_HOME='D:\java\jdk'
& 'D:\maven\apache-maven-3.9.7\bin\mvn.cmd' '-Dtest=SkillTaxonomyMigrationTest,SkillCloudSeedDataIntegrationTest' test

结果:

SkillCloudSeedDataIntegrationTest: Tests run: 5, Failures: 0, Errors: 0, Skipped: 0
SkillTaxonomyMigrationTest:       Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
Total:                             Tests run: 7, Failures: 0, Errors: 0, Skipped: 0
BUILD SUCCESS

该结果与实现者 GREEN 日志一致。

Findings

Critical

C-1:V36 用 O*NET/项目映射替代了已批准的 ESCO 职位—技能—分类主关系

证据:

  • 执行契约第 55 行要求“使用 ESCO 作为职位—技能—分类主关系,O*NET Importance 作为 heat”。
  • 设计 D1 第 32-42 行同样规定 ESCO 负责职位—技能—分类关系;来源清单第 34-39、51、60-63 行要求保留原上游来源 ID,并由项目维护跨源重要性映射。
  • V35 第 34 行将 skill_occupations.source_code 定义为 ESCO 职位来源 ID。
  • V36 第 30-39 行将 10 个职位的 source_code 全部写成 ONET SOC,并将 source_version_id 指向 ONET 来源版本。
  • V36 第 203-340 行 137 条职位技能关系的 source_version_id 全部为 O*NET。
  • 本地只有 ESCO 技能 lookup,没有 ESCO 职位—技能关系数据;V36 已导入的 25 个 ESCO 技能只提供了技能 URI,未提供任何 ESCO 职业关系。

影响:这不是字段命名的小问题,而是数据治理来源发生实质变化:职位节点被标成 ONET SOC,职位技能关系改由 ONET software_skills、项目分类和代理 Importance 人工组装。下游接口即使运行正确,也无法证明返回的是契约批准的 ESCO 主关系。该变化命中执行契约第 136 行的 Rewind 条件“数据来源发生实质变化”。

Important

I-1:两个金融职位使用不能代表目标职位的替代 SOC,且替代映射未获批准或写入来源清单

证据:

  • V36 第 34 行将“金融数据分析师”写成 13-2031.00。本地 occupation_data.csv 中该 SOC 的标题是 Budget Analysts;原计划目标 13-2051.00 是 Financial and Investment Analysts。
  • V36 第 35 行将“风控建模工程师”写成 13-2053.00。本地 CSV 中该 SOC 的标题是 Insurance Underwriters;原计划目标 13-2054.00 是 Financial Risk Specialists。
  • V36 第 16-17 行仅以 SQL 注释说明替换;source-manifest.md 第 22-23 行没有批准代理 SOC,也没有记录替换后的目标语义。
  • 13-2051.00 和 13-2054.00 在本地四份 Importance CSV 中确实没有行,但“原目标无数据”不等于可以用语义不同的职业覆盖其来源 ID。

影响:Budget Analysts 与 Insurance Underwriters 的 O*NET 活动分布不能代表金融数据分析师和风控建模工程师。尤其是 Insurance Underwriters 作为风控建模工程师的热度来源,会导致技能热度与目标职位脱节。必须在来源清单和契约中明确代理规则与语义合理性,或重新选择可代表目标职位的来源;不能直接把替代 SOC 写入目标职位的 source_code。

I-2:T3 清单中的多个技能分类未落表,测试只要求至少一个分类因而漏检

证据:

  • source-manifest.md 第 18-27 行给出了每个职位的首批技能分类范围,第 30 行明确这些分类是“每个职位首批应覆盖的能力域”。
  • V36 第 42-91 行为每个职位固定导入 5 个分类,共 50 个。
  • 前端开发缺少清单中的“浏览器与调试”“测试”。
  • DevOps 缺少“配置管理与 IaC”“可观测性”“安全”等独立能力域。
  • 风控建模缺少“模型验证”等能力域。
  • 教学设计师缺少“无障碍与规范”等能力域。
  • 测试第 70-71 行只断言 category_count >= 1,因此即使只导入一个分类也会通过。

影响:已批准的 T3 分类覆盖范围没有完整交付,后续接口会缺少部分可筛选分类;当前测试无法阻止该类回归。

I-3:Importance 缺少逐技能来源映射和有效验证,现有数据大量依赖同值代理

证据:

  • V36 第 5-15 行说明所有技术技能使用“Working with Computers”等职业活动代理值,而不是 O*NET software_skills 自身的 Importance。
  • V36 第 203-340 行的 133 条非空关系实际只形成 39 个不同的 (occupation, importance) 组合;多个技能共享同一代理值,例如同一职业内多数技术技能全部为同一个值。
  • V35 第 93-95 行只保存 importance 和 source_version_id,没有保存用于推导热度的 O*NET Element ID;V36 的注释不是机器可追溯的数据。
  • 测试第 106-127 行只精确校验前端 JavaScript 的 4.88 和 Figma 的 null,其余 132 条重要性记录或错误来源元素不会被发现。

影响:词云热度会因大量同值技能而主要退化为 nameZh ASC 排序,无法证明每个技能的热度确实来自对应 O*NET 来源。若继续该口径,应新增可追溯的 Importance 映射记录并扩大测试,或者重新定义可接受的代理规则和排序语义。

Minor

  1. “45 个 Importance 原值”的核验数量不实。 V36 第 5-15 行声明了 43 个职业/能力域映射,133 条非空关系只有 39 个不同 (occupation, importance) 组合;报告中“45 个 Importance 原值”没有可复现证据。这是核验报告计数问题,不代表已发现任意 CSV 伪造值。

  2. 最终提交可能漏掉 Scikit-learn 大小写修复。 当前工作区是 Scikit-learn,与 CSV 一致;但 git status 显示 V36 为 AM,即该修复尚未 staged。提交前必须确保修正包含在最终 T3 提交中。

  3. 测试主要验证行数、非空值和两个单点值,不是完整来源契约测试。 当前即使将除 JavaScript 外的 Importance 改错、将非空 ESCO/O*NET source code 改成任意非空字符串,或只保留每个职位一个分类,测试仍可能通过。分类跨职位错配也不会被测试发现,因为数据库没有覆盖 (occupation_id, category_id) 的复合外键。

已确认没有问题的部分

  • V36 是纯数据迁移:只有 7 个 INSERT,未包含 UPDATE/DELETE/DROP/ALTER/CREATE。
  • git diff HEAD 在本任务实现范围内只显示 V36 和 T3 测试;V1-V35 未修改,src/main/java/com/mydreamjob/skill 不存在,未提前实现 T4 业务代码。
  • 当前 137 条关系的技能分类均与所属 occupation 对应;所有技能、别名、来源版本和关系均满足 V35 现有外键及唯一约束。
  • 28 个 ONET 技能来源组合和 25 个 ESCO URI 均可从本地来源文件核实,没有发现伪造 ONET software row 或伪造 ESCO URI。

未决问题

  • 必须决定是恢复 ESCO 职位—技能—分类主关系,还是正式修改 design、source manifest 和执行契约,承认以 O*NET SOC 与项目映射作为主关系。后者属于数据来源实质变化,应走 Rewind。
  • 必须确认“代理 Importance”是否属于已批准方案;若属于,需记录每个技能或能力域的 O*NET Element ID、代理理由和质量规则,并重新定义同值排序的产品语义。
  • 若继续使用 13-2031.00 和 13-2053.00,需要提供可审查的职位语义映射依据并更新来源清单;否则应更换代表 SOC。
  • 本机未进行真实 MySQL 迁移验证,仅验证 H2 MODE=MySQL。该限制沿用 T2 的未决项。

阻断项

T3 不通过。C-1、I-1、I-2、I-3 均必须在开始 T4 前处理;其中 C-1 和 I-1 优先触发规划/契约 Rewind 或获得明确的来源变更批准。既有 7 项测试通过不能覆盖这些来源和分类语义问题。