autotrain/AGENTS.md
xinxin6623 7a01ed4db9 feat: add invoice batch wrap-up (name extraction + roster annotation) and web ui automation improvements
- add scripts/annotate_roster_invoices.py: match passenger names to invoice PDFs, write status + relative encoded hyperlinks into roster xlsx
- add scripts/add_invoice_passenger_name.py, scripts/calibrate.py
- add .opencode/skills/invoice-wrapup skill
- improve invoice_tool.py / web_ui.py / vision_fallback.py automation
- add device/screen/windows adaptation docs
- ignore out/ (delivered invoice PDFs contain sensitive data)
2026-07-10 00:11:45 +08:00

9.5 KiB
Raw Permalink Blame History

trio trio-initialized
standard-v2 2026-06-08

铁路系统发票 · Agent 操作守则

上来先读这份,再看 INDEX.md 找模块和导航。

通用三件套协议../docs/trio-protocol.md(文档维护节奏 / Handoff 写入 / 子项目嵌套 / 记忆三条线边界 / 语言规则 / 跨项目反例)。本文件只列本项目专属守则

trio: standard-v2 = 本项目按当前标准维护三件套。

这是什么项目

铁路系统发票专项工作区,用于沉淀铁路系统相关发票资料、处理脚本、核对记录和衍生产出。

核心愿景Core Vision

最终目标:用户在 Web UI 上操作,脚本全自动完成开票、状态记录、结果文档输出。

技术路线

  • 截屏驱动ADB 截屏 → 视觉 LLMQwen3-VL via SiliconFlow识别页面元素、脱敏姓名、按钮位置
  • 脚本编排:视觉 LLM 返回归一化 bbox0-1000 坐标系)→ 脚本判断当前页面状态 → 决定下一步动作tap / scroll / back
  • UI 配合Web UI 负责触发、监控进度、展示结果;脚本在子进程中运行,通过 CSV 文件与 UI 交换状态
  • 对话调试James 和 Claude Code 通过实际运行观察手机行为,持续修正脚本的判断逻辑和边界条件

当前阶段H5 扫码开票单页面自动化。页面结构:单个开票单下挂 N 个乘客(脱敏姓名 + 身份证类型 + 脱敏身份证号 + 「开具」按钮),需要逐人点击「开具」走完子流程,记录每个乘客的开票结果。

已完成的路径(保留不动):

  1. 原生列表页视觉驱动批量(android-vision-page-run):截图 → list-rows 识行 → anchor 去重 → 点击 → 核验/发票管理子流程
  2. 原生列表页 XML 驱动(android-page-runuiautomator dump → 解析 XML → 匹配 text/bounds

上手三步

  1. INDEX.md,看项目结构和子模块导航。
  2. 找到目标模块目录,先读它的本地文档(如 <module>/README.md<module>/AGENTS.md 若存在)。
  3. 看根目录或模块里有没有脚本入口、配置文件、环境变量样例。

项目专属硬规则

  • 不要随手改 .env / 凭证 / settings.json:敏感配置由项目所有者维护。
  • 不要主动删除文件:废弃 / 旧版本 / 半成品请移动到 archive/不加载/ 这类约定目录,不要 rm
  • 不要重命名公共接口、路由、对外 API 字段:除非明确授权,这些是契约。
  • 涉及发票、金额、税号、单位名称等字段时先保留原始值:规范化和清洗产物另存,不覆盖来源资料。
  • 改动前确认是否有依赖你正在改的代码的其他模块:先 grep 引用再下手。

目录命名约定

子目录 用途
data/ 本项目自有数据与导入材料
scripts/ 可执行脚本
src/lib/ 主代码
tests/ 测试
docs/ 详细文档
assets/ 静态素材
templates/ 模板文件
archive/不加载/ 归档区,不参与构建

项目专属"不要做的事"

  • 删除文件(应该 mv 到归档目录)
  • 自动提交 secrets / 凭证
  • 覆盖原始发票资料或人工核对记录
  • 未经确认修改发票字段含义、金额口径、税率口径

架构与关键依赖

本节是给 Claude Code 看的"big picture"。具体命令清单在 INDEX.md 的"常用操作"段;详细用法在 docs/usage.md。这里只写读多个文件才能拼出来的事

脚本分工

scripts/ 下没有 src/lib,所有逻辑都在独立 Python 文件里彼此通过文件CSV / 配置 / 截图)耦合,而不是 import图谱里 IMPORTS 边仅 1 条,可印证):

脚本 角色 入口形式
invoice_tool.py 主 CLI~3200 行argparse 多子命令。覆盖:台账 / 名单 / 邮件归集 / 网页辅助页 / Android ADB 自动化3 条路径)/ 视觉驱动批量。所有路径常量、run_adbConfig、CSV header 都在这里 python3 scripts/invoice_tool.py <subcmd>
web_ui.py 本地 HTTP 服务(端口 8765import invoice_tool 复用其常量和 run_adb,把批处理包成子进程跑;日常启动优先用稳定重启脚本 ./scripts/restart_web_ui.sh(推荐)/ python3 scripts/web_ui.py(前台调试)
vision_fallback.py 视觉调用层adb 截屏 -> base64 -> 调 SiliconFlow Qwen3-VL grounding API -> 解析归一化 bbox python3 scripts/vision_fallback.py {ping,detect-page,ask,list-rows}
record_step.py 录制工具:adb uiautomator dump + screencap 落盘到 work/replay/<session>/<NN_label>/,用于"人工演示 -> 反推脚本" python3 scripts/record_step.py "label" [--new] [--list]
add_invoice_passenger_name.py 从发票 PDF 抽取乘客姓名并补进文件名(pypdf 硬依赖)。处理 out/ 下已交付 PDF python3 scripts/add_invoice_passenger_name.py <dir>

Web UI 的运行模式start_runner in web_ui.py:294):前端 <select id="runMode"> 选模式POST /api/startmode 字段:

  • h5(默认)→ 子命令 android-h5-page-runH5 扫码开票单,当前主线)
  • native → 子命令 android-vision-page-run(原生列表页视觉)

Web UI 永远不会走旧的 android-page-runXML 路径)。改"开始运行"按钮行为时,改的是 mode 映射,不是子命令名硬编码。

三条 Android 自动化路径并存

12306 App 是脱敏姓名(张*岩+ 输入身份证后 8 位的开票流程。代码里有三套实现,都保留

  1. 旧:android-page-run / android-page-step — 走 uiautomator dump 读 XML按 text / bounds 匹配。问题是 12306 列表页很多控件没有 text全靠坐标。Web UI 已不走此路径,仅 CLI 可达。
  2. 原生列表视觉:android-vision-page-run — 截屏交给 Qwen3-VL模型返回归一化 bbox0-1000 坐标系,不是像素),脚本再 denormalize 到屏幕像素后 tap。流程截图 → vision_fallback.list-rows 识所有可见行 → anchor 去重防滑动后重复 tap → 子流程(核验 / 发票管理 / 成功页)走旧的状态机。
  3. 当前主线:android-h5-page-run - H5 扫码开票单页面。与原生列表的区别(见 android_h5_page_run docstring at invoice_tool.py:1939单页内滚动不是翻页scroll 用 --h5-scroll-*back 后 scroll 重置到顶部,每轮重新截屏;不用 anchor 去重back 重置后无重叠行。precheck 不在列表页时会尝试 auto_scan_qr_to_list 自动扫码进入。

配置与外部依赖

  • ADB 路径硬编码invoice_tool.py:43 写死 /opt/homebrew/share/android-commandlinetools/platform-tools/adbApple Silicon Homebrew。换机器或换 Intel Mac 要改这里。
  • config.local.json:除 company_title / tax_id / receiver_emailconfig.example.json 已示范)外,视觉路径还需要一个 visionprovider / base_url / api_key / model(当前用 SiliconFlow + Qwen/Qwen3-VL-8B-Instruct,详见 memory reference_siliconflow_qwen_vl.md)。vision_fallback.load_vision_config 缺任一键直接抛错。
  • Python 依赖(无 requirements.txt:除标准库外依赖两个三方包,需手动装:openpyxlimport-roster 读 xlsx 用,invoice_tool.py 顶部 try/except 守护,缺了只是 xlsx 子命令不可用);pypdfadd_invoice_passenger_name.py 硬 import缺了该脚本直接起不来
  • config.local.jsonwork/data/input|mail|attachments/output/ 全在 .gitignore 里。

关键工作文件(都在 work/CSVUTF-8-BOM

文件 内容 写入者
passenger_roster.csv 名单:姓名 / 身份证号 / 后 8 位 / 来源 import-roster
invoice_tasks.csv 开票码主台账 import-codes
android_invoice_progress.csv 逐人处理结果masked_name / real_name / id_last8 / status Android 子命令 + Web UI 读
android_page_queue.csv 当前可见页的待点击队列 android-build-page-queue
qr_page_order.csv 二维码扫描顺序 import-codes / H5 流程
last_qr_url.txt / last_qr_image.png 上次扫码的 URL 与二维码图 android-h5-* precheck
agent_id_last8.txt 代理人证件后 8 位(核验/扫码备用) Web UI / CLI
replay/<session>/ record_step.py 的演示快照ui.xml + screen.png + texts.txt + meta.json record_step.py

CSV header 常量都集中在 invoice_tool.py 顶部(TASK_HEADERS / ROSTER_HEADERS / PROGRESS_HEADERS / PAGE_QUEUE_HEADERS)。改字段要同步改这里 + 所有读它的子命令。

测试

tests/ 当前是空目录。没有单测 / 集成测试框架;验证靠 --dry-run 子命令 + 真机跑 + work/replay/ 录制比对。新增功能不强求加测试,但如果改了 CSV schema 或 ADB 命令组合,至少跑一次 --dry-run --max-actions 1

代码图谱查询codebase-memory

本项目已由 codebase-memory 索引,结构画像见根目录 CODEMAP.md。 优先用图谱查询代替逐文件 grep省 ~120x token连 MCP 的 agent 直接调工具; 未连走 CLI ~/.local/bin/codebase-memory-mcp cli <tool> '<json>'。 常用工具:get_architecture / search_graph / trace_path / query_graph