# V43 给 Luna 的编码指令(整改版) 实施状态:实现完成,独立代码复验与真实 MySQL/Docker 验收通过,待 Git 检查点。 ### 本轮四项阻断的可执行证据 - `FairnessMonitoringPersistenceIntegrationTest.realServiceJdbcBudgetAt30_300_3000WithEightDimensionsAndMultipleAppeals`:Spring 管理的真实 Service 事务代理、真实 Repository/权限仓库和 `@Primary` JDBC 计数数据源;30/300/3000 人、每人八维和两份合法回滚申诉。业务查询分别为 overview=2、dimensions=2、appeals=1、drift/ranking-stability=0;权限查询逐接口单列为2。夹具与验证查询不在计数区间。每个版本仅返回一个同分频数,申诉返回最终汇总。 - `FairnessMonitoringHttpIntegrationTest.realHttpAppealsHidesSmallComparableChangeGroup`:60 人各一份非法分数回滚,其中一人在 GROWTH 另有合法回滚;真实 SQL 断言61份申诉、60人、60人非法分数、1条/1人可比、重复申诉人数0,再通过真实 HTTP 检查变分统计全部隐藏。 - 同一非空申诉夹具中,五个接口各自独立比较调用前后完整表内容(包含 version),涉及评分、申诉、申诉历史、回滚历史、非空回滚限流、审计和四张风险治理表。原全局99/1测试亦在两个接口之间分别比较。 - `FairnessMonitoringPersistenceIntegrationTest.sqlOverallMatchesPureFunctionForPartialRepeatingHalfUpAndPendingVersions`:1/2/3个有效维度、空分PENDING、10.005的HALF_UP、10.003333…及10.006666…;SQL结果逐例与既有评分纯函数对账。仅修改PENDING行版本即判MIXED,仍保留有效覆盖人数。 以上为 H2 自动化证据,不代表真实 MySQL EXPLAIN、运行时 OpenAPI 或性能验收通过。 2026-09-09 最终复验:V43专项60/60;全量 `mvn test` 与 `mvn clean verify` 均1535项,Failures=0、Errors=0、Skipped=0,构建成功。OpenAPI静态及运行时均为172 paths / 210 operations。真实MySQL完成权限、隐私、只读性、查询预算与30/300/3000人规模验收;未提交或推送。 文档类型:执行指南。先完整阅读同目录v43-candidate-scoring-fairness-design.md修订版;不要沿用旧版“calculated_at可恢复历史漂移”的结论。 ## 1. 任务与基线 项目C:/Users/15642/Desktop/zhilai,实现V43候选评分公平性与稳定性监测。 先读取项目适用AGENTS.md,执行git status --short、git diff --cached --name-only、git log -5 --oneline;核查最新迁移和OpenAPI。已知维护提交498512d、最新业务V42、Flyway V40、OpenAPI167/205,均须实测而非假设。 保护现有暂存与未跟踪文件。禁止reset/restore/checkout、git add -A、commit、push、删除移动历史文件。若已有V43实现,先评审差异,不覆盖他人修改。 本任务授权代码、自动化、正式文档;实现完成后需停止在本版本,不启动/停止Docker,不执行真实MySQL黑盒,不结束未知Java进程,不进入V44。当前实现结果须以自动化验证报告为准,真实黑盒仍待负责人另行安排。 ## 2. 实现边界 无新增Flyway、数据库表、后台任务、feature flag、公共错误码,不改V1–V40迁移。 只允许ADMIN聚合查询,无学生/企业入口,无写入、自动调分/排名/权重/封禁/申诉处理。 不读答案、题目、测评详情、sub_scores_json、audit details,不接AI。 不得调用CandidateScoringEngineService.getOverview、computeAll、upsertSnapshots等可能写快照入口。只读纯函数可以复用。 学校/城市/姓名不得作为敏感属性代理。 ## 3. 接口范围 新增五个GET: - /admin/scoring/fairness/overview:period必填。 - /admin/scoring/fairness/dimensions:period必填,dimension可选八维白名单。 - /admin/scoring/fairness/drift:无业务参数,固定UNAVAILABLE。 - /admin/scoring/fairness/ranking-stability:无业务参数,固定UNAVAILABLE。 - /admin/scoring/fairness/appeals:成对可选from/to日期,默认最近30个完整业务日,最大90日。 drift原因IMMUTABLE_SCORE_HISTORY_NOT_AVAILABLE;排名原因RANKING_SNAPSHOT_HISTORY_NOT_AVAILABLE。 无数据、不可计算、小样本是不同状态,不全部返回0或NORMAL。 匿名401,其他角色403/2002;参数400/1001。拒绝jobId/companyId/rulesVersion/granularity及其他未知业务参数。 如果实际基线167/205,最终172/210;不得通过删路径满足数字。 ## 4. 必须先落实的统计规则 以设计第4–6节为唯一口径,写测试后实现: 1. period指定一个月份。快照是“当前所存版本”,calculated_at会被覆盖,不支持历史窗口恢复。 2. N是该period至少一行快照的独立学生数。无快照全体学生不在范围,响应明确scope。 3. 每维缺行、空分、有效分、状态分别统计,分母和去重按设计,不把八维行数当人数。 4. 分布有效分为OK/ESTIMATED且0–100。统计sampleSize是独立人数。 5. 同候选所有现存维度跨规则版本即MIXED,排除V43综合分分布;单一未知版本归UNKNOWN。其计数受小样本保护。 6. 同版本综合分对有效维度等权平均,2位HALF_UP,与现有overallScoreFromSnapshots测试对账,不改V32。 7. 分位数线性插值、总体标准差、十个连续小数分桶、零分母null;内部DECIMAL128,输出2位HALF_UP。 8. 风险先用未舍入值比较。只启用分桶集中70/85%运营提示。旧版缺失率差、均值差、纠正率阈值本版不启用。 9. 不足30独立人抑制明细;30–99 LOW_CONFIDENCE,100以上NORMAL_CONFIDENCE。 10. 1–29的桶/状态/版本/异常计数抑制整组,防止补集反推。被抑制桶的关联均值/极值/分位数/集中风险也隐藏。 11. 分别使用availability/confidence/riskLevel,不把UNAVAILABLE放入风险等级。 12. 维度DTO必须独立返回 `inconsistentRecordCount`、`unknownStatusCount` 和 `outOfRangeScoreCount`;分布一旦触发桶/补集抑制,`sampleSize` 与所有统计字段、分桶及风险均置空,只保留availability/reason。 ## 5. 申诉与回滚 按created_at选[from,to)创建队列,展示截至capturedAt的当前状态,不叫历史日终状态。 APPROVED+ROLLED_BACK才是审核通过数。分别实现通过率、回滚执行率、实际变分率,严禁三者互换。 申诉主表先统计,历史先按appeal_id聚合后关联,不因JOIN重复计数。 仅唯一ROLLBACK历史、前后分非空有效、前后同一已知规则版本的申诉进入可比变分分母;重复历史只排除该申诉,不排除同一候选人的其他合法申诉。变分率包括0差的分母;规则升级不算纠错。 每个比率同时校验该分母人群>=30独立人。重复申诉按同人同维同period的窗口内记录判断。真实曝光申诉率UNAVAILABLE。 不读原文、管理员身份;不提供申诉自由切片。 ## 6. 组件与性能 建议新建独立scoringmonitoring包:Controller、Service、只读查询组件、纯统计计算器及白名单DTO;命名遵循仓库惯例。 SQL参数绑定;GROUP BY聚合、score频数而非全量个人实体;固定查询次数,不能逐维或逐候选findById。 总览<=4、维度<=3、申诉<=5条业务查询为目标预算,角色查询单计;UNAVAILABLE接口0条业务查询。同一请求capturedNow、同一只读事务。 实现可解释超时处理,不能截断样本返回成功。真实EXPLAIN在后续黑盒验证;不擅自补索引或迁移。 小样本统计数值不得绕过统一抑制组件从另一个 DTO 字段泄露。 整改实现要求由独立、可测试的 `FairnessDisclosureGuard` 统一执行小样本与互补抑制;有效集合或其补集为 1–29 人时,相关整组统计字段必须一并隐藏。 不回任何个人/申诉/答卷/结果ID、联系方式、学校、性别、简历、答案或内部JSON。完整序列化测试,不能只检查toString。 ## 7. 自动化 必须完整实现设计第10节测试。尤其: - 多行同一人不能绕过30人门槛; - 9.5/100分桶、手算分位数和标准差、69.995%风险边界; - 混合版本与未知版本; - 同月覆盖不能生成历史漂移; - APPROVED未回滚、回滚0差、跨版本、空分、重复历史和JOIN放大; - 多次申诉不足30独立人; - 互补抑制、非法筛选、权限和完整JSON脱敏; - 快照和申诉表内容/版本不变,而非只测行数; - 无N+1及既有V25/V32/V37/V38/V39/V41/V42回归。 ## 8. 文档、验证与停止 更新本设计实施状态、路线图、frontend-integration.md;新增docs/candidate-scoring-fairness-api.md。编码完成后才更新openapi-rc.json和verify_openapi.py: 五个GET恰好5path/5operation;全部200响应有真实schema;查询参数准确;schema不含个人敏感字段;两个不可用接口契约准确。 执行: ~~~powershell mvn -Dtest="*Fairness*Test,*ScoringMonitoring*Test" test mvn test mvn clean verify python docs/verify_openapi.py ~~~ 测试通配符必须匹配实际新增类,不得以0测试成功。clean verify若被运行JAR阻塞,报告已核实PID和原因,不擅自停止。 报告真实测试总数、Failures/Errors/Skipped、精确文件清单、无新增迁移、OpenAPI计数、统计口径及数据限制、小样本保护、无写入和查询预算证据、Git状态。 真实MySQL/Docker未执行必须写待验收,运行时OpenAPI未启动核验不得声称通过。 完成后停止,保持所有本轮变更未暂存,未提交未推送。