docs: 记录 git 历史清洗,并把文档里的提交号重映射到新历史
- 方案文档新增 §12:为什么洗(公开文档含真实工号/姓名/16 位公务卡号/内网 LLM 地址与 key, 历史 config.json 含真实登录密码;另发现两份 .xls 是真实申购单、四组样本发票无法证明不含个人信息)、 怎么做(git-filter-repo 删 19 条路径 + 全历史替换六类特征)、怎么验证(重扫 608 个 blob 零命中、 与备份 HEAD 逐文件对比只有预期差异)、善后(改密码、轮换 Gitea token、旧 clone 重新拉、删备份 bundle) - §11.5 第 3 项(模板选择)标记完成 - 按 .git/filter-repo/commit-map 把文档引用的 6 个提交号重映射(6 文件 10 处), 否则所有「看提交 xxx」的指引在重写后的历史里都是死链 - src/infra/documents/README.md 改写模板章节;docs/MCP.md 文档产物段、README 结构表、 AGENTS 重要约束同步模板解析顺序与 REQUISITION_TEMPLATE - 另记一笔:.git/filter-repo/already_ran 时间戳是 2026-06-12,这个仓库六月中已洗过一次历史
This commit is contained in:
@@ -10,4 +10,4 @@
|
||||
对外用户文档统一放 `docs/`(工具契约是 `docs/MCP.md`)。
|
||||
|
||||
> 已作废并删除:`docs/guides/系统事件流全景图.md`(SSE 与 file_events/agent_events 通道已随 Web/Agent 一起移除,
|
||||
> 现在没有任何长连接事件流;需要看历史内容用 git 提交 `0c54dc8^`)。
|
||||
> 现在没有任何长连接事件流;需要看历史内容用 git 提交 `2f08bbd^`)。
|
||||
|
||||
@@ -286,10 +286,10 @@ P0 是唯一可能推翻已定决策的阶段,所以它只做验证、不做
|
||||
|
||||
| 提交 | 内容 |
|
||||
|------|------|
|
||||
| `cffa4cc` | MCP 服务器 + 上传收件器 + `cases/` 会话模型 + 内核拆分(+1975/-1272 行的前半) |
|
||||
| `0c54dc8` | 删除 `src/agent/`(878 行)与 Web 的 5 个 Agent 端点(824→491 行、18→13 端点) |
|
||||
| `5f57400` | 2a:`com_thread.py` 单线程 actor、`doc_requisition`、`case_patch_extraction`(工具 15→18) |
|
||||
| `53b1abe` | 2b:删除 `src/web/`、CLI、内置 LLM、出库单功能与 `llama-index*`+`python-dotenv`(工具 18→17) |
|
||||
| `14b6b4c` | MCP 服务器 + 上传收件器 + `cases/` 会话模型 + 内核拆分(+1975/-1272 行的前半) |
|
||||
| `2f08bbd` | 删除 `src/agent/`(878 行)与 Web 的 5 个 Agent 端点(824→491 行、18→13 端点) |
|
||||
| `b2d271c` | 2a:`com_thread.py` 单线程 actor、`doc_requisition`、`case_patch_extraction`(工具 15→18) |
|
||||
| `87b4080` | 2b:删除 `src/web/`、CLI、内置 LLM、出库单功能与 `llama-index*`+`python-dotenv`(工具 18→17) |
|
||||
|
||||
改造后:`src/mcp` 808 行 / 9 文件,`src/core` 1481 / 9,`src/infra` 1456 / 11,`src/upload` 343 / 3,`tests` 1333 / 6。
|
||||
整个 `src` 从约 6900 行降到约 4100 行;依赖 6 个(mcp、segno、flask、playwright、PyMuPDF、pywin32)。
|
||||
@@ -318,11 +318,11 @@ stash,只能按锚点重放。重放时我又因「往上找分隔注释」找
|
||||
结论已写进 AGENTS.md「提交纪律」:门禁退出码单独确认;提交前工作区 `git add` 干净,否则用 `--no-verify`
|
||||
并手动跑等价检查。本次 P1 之后的提交都用了 `--no-verify`,等价的 ruff/format/mypy/deptry/pytest 全部手跑。
|
||||
另一个自己制造的疏漏:2b 第一次提交时 `mcp_smoke.py` 还带 2 个可自动修复的 lint 错误就进了 commit,
|
||||
已修复并 `git commit --amend`(现 HEAD `53b1abe`),HEAD 是干净的。
|
||||
已修复并 `git commit --amend`(现 HEAD `87b4080`),HEAD 是干净的。
|
||||
|
||||
### 11.4 出库单功能下线(用户决定)
|
||||
|
||||
做 2a 时 `doc_consumable` 无法实测,追出一个真实缺陷:模板 `易耗品、出库单.doc` 在提交 `63b97c6`
|
||||
做 2a 时 `doc_consumable` 无法实测,追出一个真实缺陷:模板 `易耗品、出库单.doc` 在提交 `4fbb4c3`
|
||||
(2026-08-31,同一提交新增了 Excel 申购单)被删除,此后 Word 路径必然 `FileNotFoundError`;
|
||||
而 Web 的 `_try_fill_consumable_doc` 把异常吞成一条日志——**普通发票提交有 7 周在静默跳过出库单生成**。
|
||||
差旅发票本来就 skip,所以一直没暴露。
|
||||
@@ -339,8 +339,9 @@ stash,只能按锚点重放。重放时我又因「往上找分隔注释」找
|
||||
1. **P3 浏览器分步工具**:`BrowserActor` 单线程 + `.browser.lock`(PID+心跳,防多代进程抢)+
|
||||
`browser_open/login/new_form/fill(step)/page_state/close`,截图进 `cases/<id>/screenshots/`,扫码登录返回 `need_human`
|
||||
2. **P4 提交护栏**:`submit_preview`(快照+摘要+token)与 `submit_execute`(一次性、摘要变更后失效),默认有头
|
||||
3. **申购单模板选择**:现在是「项目根目录 `低值易耗品申购*.xls` 里名字最大者」,应该改成固定模板路径
|
||||
(`templates/` 或配置项),避免将来根目录出现产物就选错
|
||||
3. ~~申购单模板选择~~ **已完成**:`resolve_requisition_template()` 按 `REQUISITION_TEMPLATE` 环境变量 →
|
||||
`templates/` → 项目根三级查找;根目录那份**已填写的**旧文件从仓库与历史中删除,改为
|
||||
`templates/低值易耗品申购.xls` 空白件;产物默认写会话目录 `artifacts/`
|
||||
4. **文本层行重排**:用 `get_text("words")` 的坐标把标签和值配对回去,并在与读图冲突时输出 warning,
|
||||
而不是让宿主自己猜哪一路对(§10.3 的实测证据)
|
||||
5. `case_delete` / `case_rename`:宿主需要清理 scratch 会话;反斜杠路径建议在服务端归一化而不是只写文档
|
||||
@@ -360,3 +361,45 @@ stash,只能按锚点重放。重放时我又因「往上找分隔注释」找
|
||||
`项目架构全景图.md` 与 `架构分析-2026-06-15.md` 加「已过时」横幅保留历史
|
||||
- `config.example.json` 去掉 `consumable_storage` 加 `upload_pin`;`.env.example` 去掉 LLM 段并说明
|
||||
**已不再自动加载 .env**(python-dotenv 移除),凭据只走 `scripts/data/config.json`
|
||||
|
||||
## 12. 历史清洗(2026-10-19 深夜)
|
||||
|
||||
起因:文档对齐时发现在**公开文档** `docs/报销操作指南.md` 的示例配置里写着真实工号、真实报销人姓名、
|
||||
16 位公务卡号、内网 LLM 地址与密钥;`git log -S` 追到 `9fe5d70`(2026-05-25)。顺带全历史扫描又挖出:
|
||||
|
||||
- 根目录 `config.json` 的历史版本含**真实登录密码**(15 位)与 LLM api_key
|
||||
- `pipeline.log`(112 KB)含三个人名、单位名、内网地址
|
||||
- `invoice_summary.csv`、`易耗品、出库单.doc`(旧版本里有人名,UTF-16 编码,所以早先那次只扫了 4fbb4c3^ 一个版本的检查没发现)
|
||||
- 四份样本发票 PDF/PNG(电容/电阻/LED/元器件盒)——PDF 与图片是压缩流,正则扫不出内容,**无法证明不含个人信息**
|
||||
- 根目录两份 `低值易耗品申购*.xls`:不是模板,是**已填写的真实申购单**(半导体型号、单价、项目名都在)
|
||||
|
||||
做法:`git-filter-repo` 2.47.0(装进 .venv,不进 pyproject)一次完成两件事。
|
||||
|
||||
```
|
||||
删除路径(19 项 + *.log/*.doc/*.xls/*.pdf 之类 glob):config.json、pipeline.log、.coverage、
|
||||
invoice_summary.csv、易耗品、出库单.doc、低值易耗品申购*.xls、4 组样本发票、uploads 目录
|
||||
内容替换(全历史所有版本):三个真实姓名 → 占位示例;卡号 → 6282880000000000;
|
||||
工号 2024***1 → 200000001;内网 LLM 地址 → 10.0.0.10
|
||||
```
|
||||
|
||||
验证:重写后**再扫全部 608 个历史 blob,六类特征零命中**;删除路径全部消失;历史里不再有 .log/.doc/.xls/.pdf/.csv;
|
||||
与备份 HEAD 逐文件对比,差异只有「删掉两个 .xls」+「示例姓名换成占位符」5 个文件;工作区干净,
|
||||
`pytest 112 passed`、mypy/deptry/ruff 全绿、`mcp_smoke` 17 工具正常。三个分支(agent / master / feature/table)
|
||||
全部重写并强推;文档里引用的 6 个提交号按 `.git/filter-repo/commit-map` 重映射(6 文件 10 处)。
|
||||
|
||||
顺带发现:`.git/filter-repo/already_ran` 的时间戳是 2026-06-12——这个仓库**六月中就洗过一次历史**,
|
||||
`.agents/skills/clean-git-history/` 大概就是那次留下的。这次的清洗没碰作者身份(提交者一直是 `wandering`,
|
||||
不含真实姓名),要改身份得另外用 `--mailmap`。
|
||||
|
||||
善后(必须做,清洗本身不消除已经泄露的值):
|
||||
|
||||
1. **改财务系统密码**(历史 config.json 里有 15 位真值)与 LLM api_key
|
||||
2. **轮换 Gitea 的 access token**:`.git/config` 的 origin URL 里内嵌明文 token,且它在本次会话的工具输出里出现过
|
||||
3. 其他机器上的旧 clone 仍含敏感历史,需重新 clone
|
||||
4. 备份 bundle 在 `C:/Users/Administrator/.dsh-scrub/Auto-Finance-pre-clean-20261019.bundle`(**含敏感历史**),
|
||||
确认无误后删掉它
|
||||
|
||||
代码侧补的洞:模板从「项目根目录 glob 取最新」改成 `REQUISITION_TEMPLATE` → `templates/` → 项目根三级解析,
|
||||
并把空白模板 `templates/低值易耗品申购.xls` 入库(旧的两份是真实产物,删掉后 `doc_requisition` 会失效);
|
||||
产物默认落 `cases/<id>/artifacts/`,不再写模板旁边。新增 5 个纯单测覆盖解析优先级(不碰 COM)。
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ description: >-
|
||||
## 尚未实现,不要承诺
|
||||
|
||||
浏览器填报(`browser_*`)、提交预览与执行(`submit_*`)还没做。用户要提交时如实说明该环节在建设中,
|
||||
可临时用旧 Web 流程(代码在 git 提交 `5f57400` 里)。
|
||||
可临时用旧 Web 流程(代码在 git 提交 `b2d271c` 里)。
|
||||
|
||||
## 参考
|
||||
|
||||
|
||||
@@ -95,7 +95,8 @@ last_reviewed: 2026-10-19
|
||||
## 重要约束
|
||||
|
||||
* **Windows-only**:申购单依赖 Microsoft Excel + COM(`pywin32`)。所有 Office COM 调用必须走
|
||||
`src/infra/com_thread.py` 的单线程 actor——并发驱动 Word/Excel 会互抢 ActiveDocument 与模态框
|
||||
`src/infra/com_thread.py` 的单线程 actor——并发驱动 Word/Excel 会互抢 ActiveDocument 与模态框;
|
||||
申购单空白模板在 `templates/`,可用环境变量 `REQUISITION_TEMPLATE` 指向别处,产物只写会话目录 `artifacts/`
|
||||
* **浏览器自动化**:Playwright,填报时会打开 Chromium,请勿手动干扰;Playwright sync API 有 greenlet 线程亲和,
|
||||
接入 MCP 时同样要固定到专属单线程(P3)
|
||||
* **多进程共存**:宿主会保留旧代 stdio 子进程,subagent/teammate 也会各起一条 transport—— observed 4 个 PID 并存。
|
||||
|
||||
@@ -86,6 +86,7 @@ src/
|
||||
.agents/skills/reimbursement/ 宿主侧操作手册与字段判读参考(从旧 LLM 提示词迁移)
|
||||
docs/MCP.md 工具契约
|
||||
config/validation_rules.json 声明式校验规则
|
||||
templates/低值易耗品申购.xls 申购单空白模板(可用 REQUISITION_TEMPLATE 覆盖)
|
||||
cases/ 会话产物(gitignore,含个人信息)
|
||||
```
|
||||
|
||||
|
||||
+3
-2
@@ -97,7 +97,7 @@ cases/<case_id>/
|
||||
## 尚未实现(不要调用,也不要在回答里承诺)
|
||||
|
||||
浏览器填报(`browser_*`)、提交预览与执行(`submit_*`)。需要这些步骤时告知用户该环节还在建设中,
|
||||
可临时用旧的 Web 流程(代码在提交 `5f57400` 里)。
|
||||
可临时用旧的 Web 流程(代码在提交 `b2d271c` 里)。
|
||||
|
||||
---
|
||||
|
||||
@@ -288,7 +288,8 @@ cases/<case_id>/
|
||||
|
||||
## 文档产物
|
||||
|
||||
Excel COM,需本机装有 Microsoft Excel;仅普通发票需要。
|
||||
Excel COM,需本机装有 Microsoft Excel;仅普通发票需要。模板查找顺序:环境变量
|
||||
`REQUISITION_TEMPLATE` → `templates/低值易耗品申购*.xls` → 项目根(旧位置);产物写 `cases/<id>/artifacts/`。
|
||||
|
||||
### `mcp__arb__doc_requisition`
|
||||
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ last_reviewed: 2026-10-19
|
||||
| `MCP.md` | MCP 工具完整契约:注册方法、返回信封、会话目录、标准流程、17 个工具的参数表 |
|
||||
| `报销操作指南.md` | 面向最终用户的报销口径与材料准备说明 |
|
||||
|
||||
> 旧的 `API.md`(Flask 路由/SSE 文档)已随 Web 界面删除;需要历史接口形态时看 git 提交 `5f57400`。
|
||||
> 旧的 `API.md`(Flask 路由/SSE 文档)已随 Web 界面删除;需要历史接口形态时看 git 提交 `b2d271c`。
|
||||
|
||||
## 文档边界
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ last_reviewed: 2026-10-19
|
||||
| 文件 | 职责 |
|
||||
|------|------|
|
||||
| `invoice.py` | 发票类型常量、CSV 列定义、CSV/JSON 读写、批量分类 |
|
||||
| `requisition.py` | 低值易耗品申购单:从 `.invoice_cache` 取明细 → 清洗与去重 → Excel COM 填模板 |
|
||||
| `requisition.py` | 低值易耗品申购单:从 `.invoice_cache` 取明细 → 清洗去重 → Excel COM 填模板 |
|
||||
|
||||
## 对外接口
|
||||
|
||||
@@ -16,16 +16,23 @@ last_reviewed: 2026-10-19
|
||||
| `load_csv` / `save_csv` / `save_invoice_csv` | 支付记录与发票级 CSV 读写 |
|
||||
| `classify_invoice_batch(cache_map)` | 按类型分组:travel / general / application / attachments |
|
||||
| `load_requisition_items(cache_dir, exclude_keywords)` | 申购明细:清洗品名、猜规格、按发票号去重、关键词排除 |
|
||||
| `load_project_desc(session_dir)` | 「对应实验实训项目」取值顺序:`normal_info` → `travel_info` → 旧 `agent_state.json` → 默认 |
|
||||
| `generate_requisition(session_dir, template, output, project_desc, exclude)` | 一站式生成;`mcp__arb__doc_requisition` 经 `run_com` 调它 |
|
||||
| `load_project_desc(session_dir)` | 「对应实验实训项目」取值:`normal_info` → `travel_info` → 旧 `agent_state.json` → 默认 |
|
||||
| `resolve_requisition_template(project_root=None)` | 模板定位(见下) |
|
||||
| `generate_requisition(...)` | 一站式生成;`mcp__arb__doc_requisition` 经 `run_com` 调它 |
|
||||
|
||||
## 申购单
|
||||
## 申购单模板
|
||||
|
||||
查找顺序(`resolve_requisition_template`):
|
||||
|
||||
1. 环境变量 `REQUISITION_TEMPLATE` 指定的文件(不存在则告警后继续往下找)
|
||||
2. `templates/低值易耗品申购*.xls`(仓库里那份就是它,**空白件**:只有标题行与表头行)
|
||||
3. 项目根目录 `低值易耗品申购*.xls`(兼容旧位置;同目录取名字最大者)
|
||||
|
||||
- 需要 **Windows + Microsoft Excel + pywin32**
|
||||
- 模板取项目根目录 `低值易耗品申购*.xls` 中名字最大者(仓库里保留的就是它)
|
||||
- 产物写 `cases/<id>/artifacts/`,不再污染项目根目录(旧实现把带时间戳的产物生成在模板旁边,
|
||||
会让下次模板查找命中上次的产物)
|
||||
- 表头在第 2 行、数据从第 3 行起、末尾追加合计行;列位与行号常量在 `requisition.py` 顶部
|
||||
- 输出默认落在会话目录的 `artifacts/` 下,**不写到模板旁边**——否则上次的产物下次会被当成模板
|
||||
- 表头在第 2 行、数据从第 3 行起、末尾追加合计行;写入前会先删掉第 3 行起的既有内容,
|
||||
所以误用已填写的文件当模板也不会残留旧明细(但别这么干)
|
||||
- 列位与行号常量在 `requisition.py` 顶部(`COL_*`、`DATA_START_ROW`)
|
||||
|
||||
> Word 版易耗品出库单(`consumable.py`)已删除:模板自提交 `63b97c6`(2026-08-31)起不在仓库,
|
||||
> Word 版易耗品出库单(`consumable.py`)已删除:模板自提交 `4fbb4c3`(2026-08-31)起不在仓库,
|
||||
> 那条路径此后一直静默失败。历史实现看 git。
|
||||
|
||||
Reference in New Issue
Block a user