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

131 lines
9.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
trio: standard-v2
trio-initialized: 2026-06-08
---
# 铁路系统发票 · Agent 操作守则
> **上来先读这份**,再看 [`INDEX.md`](./INDEX.md) 找模块和导航。
>
> **通用三件套协议**见 [`../docs/trio-protocol.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-run`uiautomator dump → 解析 XML → 匹配 text/bounds
## 上手三步
1. 读 [`INDEX.md`](./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_adb`、`Config`、CSV header 都在这里 | `python3 scripts/invoice_tool.py <subcmd>` |
| `web_ui.py` | 本地 HTTP 服务(端口 8765`import 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/start``mode` 字段:
- `h5`(默认)→ 子命令 `android-h5-page-run`H5 扫码开票单,当前主线)
- `native` → 子命令 `android-vision-page-run`(原生列表页视觉)
**Web UI 永远不会走旧的 `android-page-run`XML 路径)**。改"开始运行"按钮行为时,改的是 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模型返回归一化 bbox**0-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/adb`Apple Silicon Homebrew。换机器或换 Intel Mac 要改这里。
- **`config.local.json`**:除 `company_title / tax_id / receiver_email``config.example.json` 已示范)外,**视觉路径还需要一个 `vision` 段**`provider` / `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`**:除标准库外依赖两个三方包,需手动装:`openpyxl``import-roster` 读 xlsx 用,`invoice_tool.py` 顶部 try/except 守护,缺了只是 xlsx 子命令不可用);`pypdf``add_invoice_passenger_name.py` 硬 import缺了该脚本直接起不来
- `config.local.json`、`work/`、`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-codemap -->
## 代码图谱查询codebase-memory
本项目已由 codebase-memory 索引,结构画像见根目录 [`CODEMAP.md`](./CODEMAP.md)。
优先用图谱查询代替逐文件 grep省 ~120x token连 MCP 的 agent 直接调工具;
未连走 CLI `~/.local/bin/codebase-memory-mcp cli <tool> '<json>'`
常用工具:`get_architecture` / `search_graph` / `trace_path` / `query_graph`