摘要

游戏的战斗日志(Logs)是一段一行一条的文字记录,例如“[01:02:03]某玩家:某单位失去了 9 魔力。”读取程序对日志截图做 OCR,再把每一行解析成结构化事件(谁、做了什么、数值)。项目的日志读取规范要求:每条事件必须来自完整的同一位置文字行,不能把两行截断的文字拼成一条。

问题在于:解析函数原本只拒绝回车和换行两种字符;而截图读取器在解析之前先做了 Unicode 规范化(NFKC)和去首尾空白,导致首尾的分行符被悄悄删掉,其他八种分行符甚至可能混进玩家名字里。修正方法是在规范化之前,就对原始 OCR 字符串检查十种分行符,任何一次合格读数含分行符就整行判为未知,保留原始证据。

本目录保存的是一个历史测试回放:冻结的旧测试原本断言“旧版验证器会接受 27 个边界缺陷”,在修正后的解析器上这 27 条断言当然失败;脚本从当时冻结版本取回旧解析器、只在内存中绑定给旧测试运行,125 项全部通过,证明历史结果可复现、无需改写旧测试。

要回答的问题

  1. 修正后的生产代码是否拒收所有含分行符的读数,同时保留合法单行的正常规范化?
  2. 冻结的历史测试与当时的结果能否在不修改源码、不保存旧实现副本的情况下原样复现?

数据与来源

  • 30 个合成软件反例:用合成字符串“[01:02:03]p:A失去了9魔力。”,在十种分行符(回车、换行、垂直制表、换页、文件/组/记录分隔符、NEL、Unicode 行分隔符和段分隔符)× 行首、行尾、姓名内部三个位置构造。修正前,原文解析器从中产生 24 个解析结果,截图共识产生 30 个文本、28 个解析结果。这些是软件反例,不是 30 个实测 OCR 错误。
  • 本目录不读取图片、已保存的 OCR 结果或参考答案。

方法

生产修正:只针对原始 OCR 字符串,在规范化和去空白之前检查十种分行符。任一合格读数含分行符,截图共识返回已有的“规范化文本无效”结果,原文解析器返回空;日志读取由既有路径得到未知,保留原行编号、位置框和三次读取的原文、分数与变体。不拆行、不截取、不清洗原证据。公共格式、三遍读取要求、0.90 门槛不变;合法单行中的普通空格、制表、全角规范化和数字 0 仍保留。

下游确认:战斗记录 App、参考应用和状态估计(SE)三方负责人分别用真实的校验器检查了“拟议的未知结果”,都明确同意;SE 中这些未知行仍作为原位置的屏障,不会越行配对。

历史回放:脚本用版本控制从冻结提交取回旧解析器,只在一个独立进程的内存里把它绑定给原 v3 测试,运行后退出;不修改源文件,也不保存旧实现的副本。

设置

当前生产代码另行用四个日志相关测试文件验证;完整 Perception 测试集和集成测试分别运行。

结果

检查 结果
新增原文边界回归(修正前) 214 失败、9 通过
新增原文边界回归(修正后) 223 通过
新增 + 原有相关生产/集成检查 474 通过
完整 Perception 测试集 6,147 通过
冻结 v3 测试 在修正后解析器上 98 通过、27 个预期的历史断言失败
冻结 v3 测试 在回放的历史解析器上 125/125 通过
完整集成测试(Perception 环境) 1,257 通过、15 失败、1 跳过

集成测试中的 15 个失败来自在 Perception 环境里调用 SE 子进程——该环境没有安装 SE。把三个相关 SE 测试文件放到核心环境里运行,31 项全部通过,包括这 15 个;两个环境合计覆盖 1,272 个不同的通过案例。没有修改任何依赖或测试。

另保留一组 30 例修正前后的合成探针结果,不覆盖。

失败与负结果

  • 27 个历史断言在新解析器上失败是预期的:它们记录的是旧验证器接受缺陷的历史事实,按要求保留,不改写。
  • 集成测试的 15 个失败是环境问题而非代码问题,已在另一环境中确认通过。

局限

  • 所有结果都是软件兼容性检查,不是 OCR 准确率测量。
  • 本轮没有重新执行完整的桌面 App 实际流程,下游意见基于真实校验器的软件控制,不等于完整界面验收。
  • 历史保存的结果不迁移、不改写。

结论与下一步

“完整单行”约束已在生产中恢复,跨行文字不会再被悄悄拼成一条日志事件,同时历史测试与结果可以原样复现。如需回退,只要撤回两处原文检查,不需要存储迁移。