| name | safe-image-reading |
| description | FantasyWord 安全读图流程。用于 AI 读取 JPG/PNG/WebP、截图、裁图、图集、SpriteSheet、规则页、OCR 图或看图验收;默认先压缩/裁切成轻量图,大图/批量/atlas/整页图再升级为子代理、OCR 或外部开图。 |
Safe Image Reading
这是 FantasyWord 项目内的安全图片读取 workflow。图片不是独立交付物,读图也不是独立报告;图片只服务用户当前需求,例如素材核对、SpriteSheet 检查、UI 截图验收、OCR 读字、图集裁片定位或 bug 排查。默认做法不是“禁止看图”,也不是把压缩图当成额外能力待确认;压缩图、轻量预览、局部裁图就是给主线程看的默认输入,目的只是减少后续对话反复携带原图/base64 时触发的上下文膨胀和请求错误。普通单图默认由主线程生成并读取压缩图,然后给出当前任务所需结论;只有大图、批量图、atlas/SpriteSheet/整页图,或用户明确要求“本会话安全读取图片”时,才升级为带目的和验收标准的子代理 / OCR / 外部开图严格链路。
核心原则
- 先锁需求再看图:先明确用户当前要判断什么、对象是什么、图片要补足哪个结论、结论要写回哪里或用于哪个验收点。
- 先做预算门禁:读取图片前必须检查文件大小、像素尺寸和待读数量;不要直接把大图、整页截图、atlas、SpriteSheet 或多张高清裁图交给模型读取。
- 默认压缩后读取:普通单图默认先生成轻量预览、单对象裁图或低分辨率副本给主线程看;压缩图就是模型读取输入,不再把压缩输入写成额外能力确认或链路兼容性问题。
- 主线程不反复读原图:默认用脚本生成低分辨率预览、局部裁图、OCR 文本或 contact sheet;必要时主线程直接读取一张已经缩小的关键图并给出结论。只有大图、批量图、atlas/SpriteSheet/整页图,或用户明确要求本会话安全读取图片时,才把图片读取升级交给短子代理、本地 OCR 或外部开图。
- 结果必须服务当前任务:数据/素材录入返回可写入表格或文档的字段;验收返回通过/不通过/无法判断和失败点;排障返回图片能证明的链路事实。
- 一次读图,多轮复用:已经形成的文字结论、证据路径、hash、裁图或 OCR 结果应被后续实现和验收复用,不要在同一长线程里反复读同一张原图。
- 图片链路失败要换路线:图片过大、OCR 不可靠、裁图不可读、上下文开始膨胀或请求报错时,停止同方式重试,改走更小裁图、文本真相源、现有合同或把具体字段标为 blocked。
- 只称规避,不称根因修复:
openai/codex#28316 说明历史图片/base64 工具输出可能被后续请求反复携带,导致上下文膨胀、请求超大和 502/524/流中断;openai/codex#28975 仍是 open 状态,只能把轻量预览、压缩/resize、OCR、外部开图称为规避或止血,不宣称根因已修复。采用压缩图的现实原因是避免原图/base64 污染后续上下文并引发请求错误,不是因为模型不能读取图片。
- 状态口径必须按当前验收目标判定:图片验收不是开放式识图汇报,也不是“识别出一点内容就 partial”。
passed / failed / blocked / partial 必须按当前用户需求的通过门槛判定;如果使用子代理,必须把目的、验收标准和返回格式传给它。
- 压缩先控像素,再选格式:这里的“压缩”不是必须把文件转成 JPG/WebP,也不是只看磁盘体积;AI 读图成本主要随像素尺寸、patch/瓦片数量、细节等级和图片张数增长。默认先裁图、降采样、生成 contact sheet 或关键帧小图,再按可读性选择格式。像素图、文字、SpriteSheet 局部优先用 PNG 或 WebP lossless;照片类、纹理类和大面积渐变可用 WebP lossy 或 JPG。JPG lossy 不能作为像素边界、帧格、UI 小字的唯一判断输入。
- 不做链路能力确认:普通压缩图就是当前 AI 要读取的图片输入;不要再问“链路是否支持读取压缩图片”,也不要把压缩图交付变成工具兼容性验证。真正要验证的是图片内容是否满足当前用户需求的验收标准。
- 子代理结论必须抽样复核后写回:当本轮升级到子代理安全读图时,主线程必须读取同一张压缩图或同批关键裁图做抽样复核;只有子代理和主线程对通过项、阻塞项、失败原因一致,才允许把结果写入真相表、验收 JSON、审计文档或代码。若不一致,先标
partial/disputed/blocked,不要硬写 passed。
- 子代理只在升级场景使用:普通单图默认由主线程读取压缩图。只有大图、批量图、atlas/SpriteSheet/整页图、长线程明确要求“本会话安全读取图片”,或用户要求验证安全读图流程本身时,才启动子代理。启动子代理的目的必须是“按验收门槛判断能否通过”,不是让它泛泛汇报识图结果。
- 端到端产物必须落到轻量图片:凡是当前任务进入端到端图片验收、截图回归、素材核对或 UI 对比,都必须先生成可复用的压缩图、低清总览、关键裁图或 contact sheet,并把这些路径写入验收产物;禁止把端到端截图、atlas、SpriteSheet 或高清原图直接作为模型读取输入。
- 原图只作为来源,不作为模型输入:原图、真实 Unity 截图、正式 atlas 和正式素材仍然是现实真相源;但给 AI 看的默认输入必须是从真相源派生的轻量图。结论必须同时记录真相源路径与轻量输入路径,避免后续会话为了复核再次读取原图。
预算门禁
读取本地图片前先用文件系统或脚本确认:
- 文件大小。
- 宽高和总像素。
- 估算模型读取成本:按
ceil(width/32) * ceil(height/32) 粗略估算 patch 数;普通素材核对优先控制在约 1024 patches 以内,高密度 UI/图集总览也应优先裁到约 1536 patches 以内。这个估算服务“先控像素”,不是替代真实验收。
- 本轮需要模型读取的图片数量。
- 图片类型:整页截图、atlas、SpriteSheet、单对象裁图、OCR 裁图、UI 截图或参考素材。
满足任一条件时,不得直接读取原图:
- 单边超过
2500px。
- 总像素超过
8MP。
- 文件超过
8MB。
- 同一轮需要连续读取多张 JPG/PNG/WebP。
- 图片是 atlas、整页截图、高清扫描图、SpriteSheet 或包含大量小字的图集。
默认处理方式:
- 总览图最长边不超过
1600px,只用于判断整体布局、行列、区域关系。
- 分块图最长边不超过
1400px,用于看局部区域。
- 文字、数值、索引、Sprite 帧边界不清时,继续裁单格或单对象图,不放大整张大图反复读取。
- 多图对比先生成低分辨率 contact sheet;如果 contact sheet 不足以判断,再只读关键单图。
状态判定口径
对子代理、本地 OCR 或主线程轻量读图的输出,必须使用以下状态定义:
passed:当前验收目标所需字段全部锁定,且可直接进入当前任务的下一步。例如 SpriteSheet 验收必须锁定帧布局、方向/动作行列和目标导入判断。
failed:图片能被明确排除为当前目标之外,或能证明不满足当前目标。例如错误素材、错误 UI 状态、错误角色、错误图层、非目标 Sprite、占位图标。只要已经能正向证明“不是本次目标”,就用 failed。
blocked:图片本身不给出足够信息,无法判断当前目标字段。例如纯色底块、空白、严重模糊、裁切缺失、文件打不开、文字区缺失。blocked 只阻塞该图片或该字段,不能扩展成整个任务失败。
partial:图片属于当前目标类别或仍有合理可能属于当前目标,但只锁定了部分必需字段,缺少另一些必需字段。例如能确认是目标角色 SpriteSheet,但无法确认完整动作行;或能确认 UI 页面,但关键失败点被遮挡。
状态边界:
- 纯色底块、空白、打不开、无可读字段:
blocked,不是 failed。
- 明确是非目标对象:
failed,不是 partial。
- 只有在“仍可能是目标对象,但字段不完整”时才使用
partial。
固定流程
-
记录判断点
- 图片路径。
- 业务对象,例如角色 SpriteSheet、MiniFantasy 装备层、Tile、Prefab 截图、UI 截图或 Console 关联截图。
- 用户当前需求:素材核对、OCR 读字、导入设置核对、实现验收、UI 对比、排障定位。
- 图片需要回答的问题。
- 结果用途:写入
.spec/knowledge/features/project/、作为当轮验收结论、指导代码/资源修改,或仅作为排障证据。
-
生成轻量输入
- 先读文件大小和尺寸。
- 普通单图默认先裁掉无关区域、降采样或生成轻量副本后由主线程读取;格式转换是第二步,不用“换格式”代替“降像素”。
- 普通截图/素材压缩优先顺序:文字、像素边界、Sprite 帧格和 UI 小字用 PNG 或 WebP lossless;一般彩图用 WebP lossy;照片或非结构化纹理可用 JPG。只有当前查看工具不稳定或需要完全保留像素边缘时,才保留 PNG,但仍必须控制尺寸和 patch 数。
- 大图先降采样或裁局部。
- SpriteSheet / atlas 先生成总览和关键帧裁图;contact sheet 优先用小尺寸 WebP lossless 或 PNG,关键是控制总览尺寸、格子间距和关键帧数量,让 AI 能看清动作/帧关系,而不是把整张原图原尺寸塞进上下文。
- OCR 任务优先生成文字提取结果;只在文字不确定时读局部裁图。
- 端到端截图、UI 回归图、素材核对图必须生成独立轻量产物;建议放在
test-results/evidence-image-validation/<e2e-id>/,按用途命名为 overview.*、crop-<对象>.*、contact-sheet.* 或 ocr.txt。
- 轻量图最长边默认不超过
1600px;关键分块或单对象裁图最长边默认不超过 1400px。文字、像素格或帧边界仍看不清时,继续裁更小区域,不放大整张原图重读。
-
读取或交接
- AI 自己读取时,只读取已经过门禁的轻量图,并带着当前需求和验收标准读,不做开放式视觉报告。
- 普通单图不要为了“更安全”默认交给子代理;主线程读压缩图给结论就是默认安全路径。
- 大图、批量图、atlas/SpriteSheet/整页图,或用户明确要求“本会话安全读取图片”时,进入子代理/OCR/外部开图的严格流程;否则普通单图默认由主线程读取压缩图并产出结论,不额外开子代理。
- 如果压缩图已经足够判断当前目标,直接给结论;不要再把同一张压缩图升级给子代理做开放式识图。
- 子代理任务必须是“按验收标准判断是否通过”,不是“返回完整识图结果汇报”。输入必须包含对象、图片路径、判断目的、通过条件、失败/阻塞/部分通过边界、结果用途和返回格式。
- 子代理调用输入必须使用最小附件形态:图片附件用本地图片类型(如
local_image),验收目的和返回格式用文本附件;不要同时传互斥的 message 与 items,也不要把普通文件类型误当图片附件。若参数错误,修正调用形态后只重试一次。
- 如果交给子任务或本地 OCR,输入只包含完成上述判断所需的最小信息。
- 委托语必须写明状态口径,尤其是
failed、blocked、partial 的边界,防止把“识别出一点内容”误写成 partial,或把纯色/空白误写成 failed。
- 返回不得包含 base64、data URL 或 markdown 图片。
-
写回可复用结果
- 素材/规则/数据结论:写明对象、路径、hash、字段、状态。
- 验收/对比结论:写明用户预期、图片判断点、通过状态、失败点和证据路径。
- 排障结论:写明图片证明了什么、不能证明什么、下一步最小动作。
-
继续主任务
locked/passed 项进入实现、验收或文档。
blocked/disputed/partial/failed 只阻塞对应字段或验收点。
- 不因为某张图看不清就暂停整个用户需求。
可选端到端验收产物
只有当前需求、既有 E2E 证据链或项目 workflow 明确要求独立图片验收产物时,主线程才把读图结果整理成每条链路独立的覆盖式产物,不能混进一个总文档:
test-results/evidence-image-validation/<e2e-id>/result.json
test-results/evidence-image-validation/<e2e-id>/result.md
test-results/evidence-image-validation/<e2e-id>/overview.<png|webp|jpg>
test-results/evidence-image-validation/<e2e-id>/crop-<对象>.<png|webp|jpg>
test-results/evidence-image-validation/<e2e-id>/contact-sheet.<png|webp|jpg>
<e2e-id> 必须能唯一表达当前验收链路,例如 fantasyword-spritesheet-import、fantasyword-ui-inventory、fantasyword-minifantasy-equipment-layer。同一链路重复跑时允许覆盖同名目录下的 result.json / result.md / 轻量图,但不得覆盖其他端到端链路的结果;需要历史留存时再另建 runs/<timestamp>/。
需要子代理参与时,验收产物必须记录子代理 ID、原始真相源路径、压缩图/轻量图路径、主线程抽样复核结论,以及哪些项升级、哪些项保留 partial/blocked/failed。
.json 最小结构:
{
"id": "<e2e-id>",
"objective": "<本链路图片验收目标>",
"criteria": ["<验收字段或判断点>"],
"sources": {
"truth": ["<原始截图/正式素材/正式 atlas 路径>"],
"lightweightInputs": ["<压缩图/总览图/裁图/contact sheet/OCR 文本路径>"]
},
"summary": {
"total": 0,
"passed": 0,
"failed": 0,
"blocked": 0,
"partial": 0
},
"items": [
{
"idx": 1,
"path": "<图片路径>",
"status": "passed/failed/blocked/partial",
"lockedFields": {},
"reason": "<通过或失败原因>"
}
],
"verdict": "<本链路裁决>"
}
写入后必须做最小校验:summary.total == items.length,且 passed + failed + blocked + partial == total。长期审计文档只引用 <e2e-id>.json/.md 和摘要结论,不复制所有原始行。
返回格式
素材 / 数据 / OCR 录入
| 对象 | 图片路径 | sha256 | 图片判断点 | 结论字段 | 状态 | 备注 |
| --- | --- | --- | --- | --- | --- | --- |
| <对象名> | <路径> | <hash> | <需要图片回答的问题> | <可复用字段> | locked/partial/blocked/disputed | <最小说明> |
验收 / 对比 / 排障
| 对象 | 用户需求 | 图片判断点 | 结果 | 失败点或证据 | 下一步 |
| --- | --- | --- | --- | --- | --- |
| <对象名> | <验收/对比/排障> | <图片需回答的问题> | passed/failed/blocked/partial | <最小证据> | <最小动作> |
禁止行为
- 禁止连续读取多张大图、整页截图、atlas 或高清裁图。
- 禁止把图片以 base64、data URL、markdown 图片形式带回主线程。
- 禁止把“看过图”当成最终证据;必须形成结论、字段、失败点或证据路径。
- 禁止用缩略图或 OCR 错字当官方原文。
- 禁止用局部裁图替代完整单对象图来决定对象结构。
- 禁止把辅助图、标注图、合成图说成真实截图证据。
- 禁止在图片链路卡死或上下文膨胀后继续用同一方式反复硬试。