wandering
|
5dda126e21
|
feat(upload): 建会话即给这一单的手机直链,收件器地址改为显式配置
用户选了 B 方案。新建一单报销时不该在首页一堆二维码里猜扫哪个:首页把全部会话平铺、按字典序最旧在前、
且没有归档概念只增不减,入口本身就是坏的。现在 case_create 直接返回 upload_url。
- src/config.py 新增可选字段 upload_base_url(环境变量 UPLOAD_BASE_URL;留空才退回探测)
- src/cases.py:upload_page_url() 优先用配置;新增 CaseStore.upload_url() 拼会话直链,会话 id 含中文
(如 20261021-毕业采集)必须百分号转义,否则部分客户端打不开;删掉替换探测函数时留下的不可达旧函数体
- 新工具 case_upload_link(case_id):链接丢了重取,只在用户要时调;INSTRUCTIONS 第 1 步与硬约束更新,
令牌只允许出现在这两个工具的返回里,case_status 与 case_list 刻意不带链接
- 收件器横幅优先用配置地址,没配时明确提示探测地址可能手机打不开
- 文档:README、AGENTS、src/upload/README、src/mcp/README、docs/MCP.md 标准流程、操作指南 7.5、
scripts/data/README、config.example.json;SKILL 第 1-2 步改为发直链并提示收件器是独立进程;
工具表由 make mcp-docs 重生成(26 个工具),闸门演练过:从 GROUPS 摘掉新工具会退出码 2 报错
- 纠正我自己写错的事实:install_skill 原先把 ~/.agents/skills 写死成本机启用,而来源开关会变
(本机今早 08:11 就翻回 ~/.dsh/skills)。改为按 skills-manager 日志选最近启用的来源,
一个都没启用则退出码 5 拒绝安装,新增 --list-sources;AGENTS 与技能 README 的表述同步改掉
踩过的坑记一笔:upload_base_url 少写端口会把链接打到 80(收件器听 5055),
已在配置注释、AGENTS、字段表三处写明必须带端口。
测试:tests/test_upload_link.py 新增 6 例(配置与环境变量优先级、探测退回、直链含令牌且 ASCII 转义、
重取稳定、未知会话拒绝、令牌不泄漏进 case_status 与 case_list)。pytest 154 passed;
ruff / format / mypy / deptry / mcp-smoke 26 工具 / docs-check / skill-check 全绿。
端到端实测:拿生成的直链访问真实运行中的收件器返回 200 且页面是上传页。
仍用 --no-verify 提交并手跑等价检查。
|
2026-10-21 10:05:33 +08:00 |
|
wandering
|
821822a408
|
docs: 全面体检并更新文档,工具参考改为从运行时 schema 生成
先体检再动手:44 个 Markdown,相对链接 0 处失效,逐份分辨「现状文档」与「历史记录」。
历史记录(error-experience/*、架构分析、已过时的全景图)保留原貌只加指路,不重写。
- 新增 scripts/gen_mcp_docs.py:起 stdio 子进程 list_tools 后整段重生成 docs/MCP.md 的「工具参考」
(291 行 / 25 个工具,占这份文档四分之三,手工维护必漂)。--check 漂移退出码 1,--diff 打印差异;
GROUPS 是刻意闸门——加了工具没登记就报错,防止「有工具没文档」。接进 make mcp-docs / docs-check
与 tasks.py 同名任务
- 生成时抓到两处真实漂移:invoice_type 线上是 string/null 且默认 null,文档手写成 null/string 无默认;
case_list 无参数在旧文档里写成一句散文。现已与线上一字不差
- 过期说法清理:src/README 的「browser_* 与 submit_* 尚未实现」(browser 早已联机验通、submit 定案不做);
tests/README 的「当前 107 例」(现 148)与缺 test_mcp_browser.py 一行、「Playwright 填报不进单测」
(现在选择器分支/状态判定/错误路径有单测,只有真实页面需要联机);.agents/README 的「Cursor Agent」;
plans/README 里还写着「提交加确认 token」;scripts/data/README 表格有一行跑到正文后面
- 工程实践指南里把已删除的 CLI 入口当例子:mypy src/main.py、make run、python src/main.py 全部改为现状
(mypy src / 唯一入口 python -m src.mcp.server),并补上「任务必须透传退出码」这条本轮踩到的坑
- README:「还没做完」重写为「边界与未完事项」——把刻意不做(提交、submit_* 整类、删除、撤回)与
真的未完(科目/项目/人员固定取第 N 行,待业务口径)分开写;开发命令补 mcp-docs / docs-check / skill-install
- 操作指南:7.3 经济科目与项目从「要改就改索引」改成「已知限制,等口径,填报后务必人工核对」;
相关命令补齐新目标;MCP.md 标准流程补上填报与「到此为止,提交由人」两步,并改掉与新纪律矛盾的
「把截图报给用户」表述
- AGENTS:命令表加两行;测试段给出改工具后的固定顺序(mcp-smoke → mcp-docs → 重连宿主);提交纪律
补「make check 之外还有 docs-check / skill-check 两道专项门禁」;截图产物改标注为排查证据
- install_skill.py:拿不到主目录时退出码改 4,别和「漂移」的 1 混成一类
- 已核对:submit_execute / src/main.py 在文档里的残留都是禁止性表述或「已删除」清单项,不是现状描述
验证:ruff / format --check / mypy src / deptry / pytest 148 passed / mcp-smoke 25 工具 /
docs-check 与 skill-check 均退出码 0。--no-verify 提交并手跑等价检查。
|
2026-10-20 23:12:46 +08:00 |
|
wandering
|
6e00ddc37e
|
docs+chore: 定案——submit_* 整类不做,填报完把单据编号交给用户即可
接上一条定案继续收紧:用户不需要提交前预览("我自己去系统就行了,也不需要给我看")。
能力边界停在 browser_fill / browser_page_state。
- 清掉随之变死的代码:cases.py 的 previewed 阶段与 submit_preview.json 读取(没有任何东西会再生成它),
case_reset(scope=all) 的清理列表同步去掉;阶段链回到五档 empty→extracted→matched→info_ready→docs_ready。
仍遵循"阶段由产物推导":推不出的一律不写
- INSTRUCTIONS 改为:把单据编号与会话目录告诉用户即可,不必逐张呈报截图。截图仍然生成——它是这一轮
抓出附件静默假成功的证据,定位是排查用,不是给用户的报告
- SKILL 补一句纪律:提交错了要写情况说明,宁可停在填完,也不替用户按任何不可逆的按钮
- 文档:docs/MCP.md(目录树去掉 submit_preview.json、说明段改为整类否决)、README、浏览器包 README、
src/mcp/tools/browser.py 模块说明、方案文档 §17 记录定案与连带清理
验证:pytest 148 passed;ruff / format / mypy / deptry 全绿;mcp_smoke 25 工具,INSTRUCTIONS 2199 字节。
仍用 --no-verify 提交并手跑等价检查。
|
2026-10-20 21:49:17 +08:00 |
|
wandering
|
2e2519632a
|
docs+chore: 定案——提交永远由人类执行,删掉 submit_execute 的全部规划
用户明确否决代提交工具。这不是「还没做」,是能力边界,所以凡是把它写成「待实现」的地方都改了,
免得以后有人以为补个实现就齐活。
- server.py INSTRUCTIONS 改成硬约束:本项目不提供也不计划提供点提交的工具;删除(#delete)、
撤回同理。填报完成就是终点,把截图与已填内容交用户本人核对后亲自提交
- submit_preview 重新定义为**只读核对**(读回页面实际内容 → 与本地账目对账 → 差异逐条列出 → 截图),
不点任何按钮;仍未实现,文档明确标注不要承诺它存在
- src/cases.py 删掉 submitted 阶段与 meta.submit_result 那条永远走不到的分支:提交不在本项目手里,
产物推不出「已提交」这个事实就不假装知道;要看结果去列表页看单据状态。previewed 保留
(它对应真会落盘的只读产物 submit_preview.json)
- 文案:browser.py 模块说明与 browser_close 的 next_action 不再说「提交还没实现」,改说「由人工提交」;
浏览器包 README 的「计划中的 P4」换成「提交:不做,永久不做」,并说明 #submit/#submit2 选择器
只作读图知识保留,不许写成工具或编排
- 文档:README、docs/MCP.md(新增「提交:不做,永久不做」一节)、操作指南(数据流标注到此为止、
提交小节标明工具不提供该动作)、SKILL 的提交段改为永久约束;方案文档 §16 记录定案与理由,
并把早期把 submit_execute 列为待办的 4 处改为删除线 + 指向 §16
验证:pytest 148 passed;ruff / format --check / mypy src / deptry 全绿;mcp_smoke 25 工具,
INSTRUCTIONS 2224 字节。--no-verify 提交并手跑等价检查。
|
2026-10-20 21:00:48 +08:00 |
|
wandering
|
ceefe3c4eb
|
feat(mcp): P3 联机验证通过,新增 browser_open_form 断点续填,修 4 个联机才暴露的真 bug
联机跑通 open→login→new_form→fill(basic)→page_state→close:财务系统真的落库(单据编号 202610020850,
basic 页点「下一步」即保存)。据此补上续填能力并把测试草稿清理干净(删除前后截图 + 复查 0 命中)。
- 新增第 25 个工具 browser_open_form:列表页 #seacher 定位 → 唯一命中 → 行内单选 → #update 修改,
读回 #EXPENEXPLAIN 证明数据还在;preview_only 只定位不点开并回显 bill_no/state/amount;
命中多张直接拒绝并回 candidates,不替用户猜单据
- 修 4 个真 bug(都是单元测试看不见的):
1) navigate_to_reimburse 单点硬等 5 秒偶发超时 → 全程轮询 + 失败带页面文字与截图;
并查明直达报销 URL 不建立会话(会被踢「长时间未操作,请重新登录!」),门户点击链是必经
2) actor.close_all 用 atexit 注册无效:concurrent.futures.thread 的钩子走 threading._register_atexit,
比 atexit 早跑,executor 已 shutdown → close 提交不进去。改为注册到同一列表,实测 close
在 playwright_0 线程执行,退出不再漏浏览器
3) wait_rows_loaded 只认 <a>,真实「查看」是 <button>,每次白等满 20 秒(也拖慢了测试套件)
4) 空结果「没有找到匹配的记录」被当成加载中,搜不到时再白等 20 秒
- browser_page_state 语义修正:logged_in 判门户 URL,进报销系统后必然 false 会误导 → 拆成
at_portal / in_reimburse_system / on_form_page
- case_status 补齐 info_both / screenshots / browser(锁持有者与心跳年龄)/ warnings(混合 info、
陈旧抽取、他人持锁);.browser.lock 文件名由 cases.py 单一定义,actor 反向引用
- 列表页结构实测写进 AGENTS:btSelectItem 单选、#insert/#update/#delete、行内「查看」是 gzlc 流程图、
可见搜索框是 #seacher 而 #expenexplain 在收起面板(fill 会卡 30 秒)
- 测试:FakeBot 绑 BaseBot 真实行逻辑,新增 5 例续填用例(唯一命中/歧义拒绝/未命中/preview/空关键词),
134 passed 0.36s;文档 docs/MCP.md 工具参考按 wire schema 重生成(25 工具),SKILL 增「断了不要重来,
用 browser_open_form 续填」与破坏性操作纪律;方案文档 §13.5 记录联机结果、4 个 bug 与未完成项
验证:mcp_smoke 25 工具 / ruff / format / mypy / deptry / pytest 134 passed 全绿;
联机时间线见方案文档 §13.5。仍用 --no-verify 提交并手跑等价检查(原因见 AGENTS 提交纪律)。
|
2026-10-20 10:44:57 +08:00 |
|
wandering
|
1725244faf
|
feat(mcp): 浏览器分步填报 P3——7 个 browser 工具 + 单线程 actor + 磁盘锁
填报从「一把梭」变成分步:Agent 可以开浏览器、登录、建单、按步填、看页面、关,每步有截图,
中途失败不必从头重来。提交不在本步——提交不可逆,留给 P4 的 submit_preview/submit_execute。
- src/infra/browser/actor.py(新):Playwright 单线程 actor(sync API 的 greenlet 线程亲和要求所有
调用回到创建线程)+ 会话注册表 + cases/<id>/.browser.lock(PID/started_at/heartbeat/url,
心跳 180 秒过期才允许接管;锁文件损坏按无锁处理;atexit 尽力关浏览器)。与 COM actor 分开。
- base.py:login_portal 拆成 submit_login + wait_for_portal(返回布尔不抛异常),新增 portal_reached/
human_required;_screenshot 支持 screenshot_dir 并按 001-步骤名.png 编号、返回路径、失败只告警
- src/mcp/tools/browser.py(新):browser_open/login/new_form/fill/steps/page_state/close,工具 17 → 24
· need_human 用 ok:true + logged_in:false 返回(扫码不是失败,避免宿主当错误重试或另开窗口)
· 步骤顺序硬约束,跳步拒绝并用 next_action 指回该补的一步;步骤报错回传 detail.screenshot
· browser_close 明确不提交不存草稿;travel 五步、normal 四步(无 subsidy)
- tests/test_mcp_browser.py(新,17 例,FakeBot/FakePage 不起浏览器):锁四种情形、need_human 分支与
截图落点、重复登录幂等、未打开时各工具拒绝、类型推断与两 info 并存时拒猜、未登录拒建单、跳步拦截、
步骤推进与 remaining、未知步骤、报错截图、close 释放会话与锁、open 复用、steps 两种流程
- 文档:docs/MCP.md 工具段按 wire schema 重生成(24 工具);AGENTS/SKILL/操作指南/README/浏览器 README
同步分步流程、锁与心跳、有头默认、提交必须交人工;方案文档 §13 记录实现、取舍与未完成项
验证:
- 联机跑通 open(3.1s 起有头 Chromium)→ 锁写入(pid/heartbeat)→ page_state(about:blank,
001-state.png 4721 字节)→ 重复 open 复用(already_open=true,不多开窗)→ close(锁释放、注册表清空)
- 登录与填报的联机验证需要用户在场(SSO 可能扫码),本轮未做
- 门禁:ruff / format --check / mypy src / deptry / pytest 129 passed / mcp_smoke 24 工具
instructions 2109 字节。仍用 --no-verify 提交并手跑等价检查(原因见 AGENTS 提交纪律)。
|
2026-10-20 00:46:23 +08:00 |
|
wandering
|
d3728bfe51
|
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,这个仓库六月中已洗过一次历史
|
2026-10-19 23:57:49 +08:00 |
|
wandering
|
e1acf2de84
|
docs: 文档全面对齐 MCP 架构,并脱敏公开操作指南
接口与入门:
- 新增 docs/MCP.md:注册方法(DSH patch + 通用 client)、返回信封、会话目录布局、标准流程、
硬约束与未实现清单;工具参考段由**运行时 input_schema 自动生成**,与代码同源不会漂移
- 删除 docs/API.md(856 行 Flask 路由/SSE 文档,描述的端点已不存在)
- 重写根 README.md:为什么放弃自带前端、职责分工表、快速开始、注册配置、流程链、结构与风险
- 重写 AGENTS.md:命令表换成 mcp/mcp-smoke/upload;mypy 目标改 src;新增「提交纪律」
(pre-commit 的 stash 窗口会回滚未暂存改动)、COM 与 Playwright 线程约束、多进程共存提醒
包文档:src/README.md 与各包 README 按现状重写;新增 src/mcp/README.md(写工具的规矩、
宿主侧四个坑)与 src/upload/README.md(路由表与安全边界);tests/scripts/config 三处索引更新。
提示词迁移:src/infra/llm/ 整个删除,三份系统提示词迁到 .agents/skills/reimbursement/references/
(invoice-fields / travel-info-fields / normal-info-fields),删掉 can_submit 与 suggestion
(save_info 也会主动剥离),「严格只输出 JSON」改为「交给对应工具落盘」;新增 SKILL.md 作为
宿主侧操作纪律(已被 DSH 热加载为 reimbursement 技能)。
作废处理:删除 .agents/docs/guides/系统事件流全景图.md(SSE 与 file_events/agent_events 通道已整体
移除,现在没有任何事件流);给项目架构全景图与架构分析-2026-06-15 加「已过时」横幅保留历史;
config.example.json 去 consumable_storage 加 upload_pin;.env.example 去 LLM 段并说明已不再自动加载 .env。
安全:docs/报销操作指南.md 的示例配置里原来写着**真实姓名、16 位公务卡号、内网 LLM 地址与工号**
(自 9fe5d70/2026-05-25 起在版本历史里),本次全部换成占位符。历史清洗与令牌轮换另议。
门禁(改动含 src/infra/llm 删除,故重跑全部门禁):
ruff check PASS | ruff format --check PASS(42) | mypy src PASS(34) | deptry PASS(36) |
pytest 107 passed | scripts/mcp_smoke.py PASS(17 工具 / instructions 1449 字节 / case_list ok)
申购单在依赖清理后另已实机复测:2.4s 生成,产物单元格读回正确。
|
2026-10-19 22:40:06 +08:00 |
|