docs: 清理过期计划文档并补全 work-log 与开发/用户文档
- 删除已落地的 improvement-roadmap、superpowers 计划与 ui-mockups 参考稿,删除早期 work-log(2026-05-06~08) - 新增 2026-05-23 起的 work-log 与 attachment-association-background-job、reimbursement-draft-action-branching 等开发文档及用户文档 - docker-compose(.full).yml 微调服务配置
@@ -42,7 +42,7 @@ services:
|
|||||||
- >
|
- >
|
||||||
apt-get update &&
|
apt-get update &&
|
||||||
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends
|
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends
|
||||||
python3 python3-pip python3-venv fontconfig openssh-server poppler-data &&
|
python3 python3-pip python3-venv fontconfig openssh-server poppler-data mupdf-tools &&
|
||||||
if ! fc-match 'Noto Sans CJK SC' | grep -qi 'Noto'; then if ! timeout "${CJK_FONT_INSTALL_TIMEOUT_SECONDS:-45}" sh -lc 'DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends fonts-noto-cjk fonts-noto-cjk-extra'; then printf '%s\n' '[WARN] CJK font installation timed out or failed; continuing startup without blocking the app.'; fi; fi &&
|
if ! fc-match 'Noto Sans CJK SC' | grep -qi 'Noto'; then if ! timeout "${CJK_FONT_INSTALL_TIMEOUT_SECONDS:-45}" sh -lc 'DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends fonts-noto-cjk fonts-noto-cjk-extra'; then printf '%s\n' '[WARN] CJK font installation timed out or failed; continuing startup without blocking the app.'; fi; fi &&
|
||||||
printf '%s\n'
|
printf '%s\n'
|
||||||
'<?xml version="1.0"?>'
|
'<?xml version="1.0"?>'
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ services:
|
|||||||
- >
|
- >
|
||||||
apt-get update &&
|
apt-get update &&
|
||||||
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends
|
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends
|
||||||
python3 python3-pip python3-venv fontconfig openssh-server poppler-data &&
|
python3 python3-pip python3-venv fontconfig openssh-server poppler-data mupdf-tools &&
|
||||||
if ! fc-match 'Noto Sans CJK SC' | grep -qi 'Noto'; then if ! timeout "${CJK_FONT_INSTALL_TIMEOUT_SECONDS:-45}" sh -lc 'DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends fonts-noto-cjk fonts-noto-cjk-extra'; then printf '%s\n' '[WARN] CJK font installation timed out or failed; continuing startup without blocking the app.'; fi; fi &&
|
if ! fc-match 'Noto Sans CJK SC' | grep -qi 'Noto'; then if ! timeout "${CJK_FONT_INSTALL_TIMEOUT_SECONDS:-45}" sh -lc 'DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends fonts-noto-cjk fonts-noto-cjk-extra'; then printf '%s\n' '[WARN] CJK font installation timed out or failed; continuing startup without blocking the app.'; fi; fi &&
|
||||||
printf '%s\n'
|
printf '%s\n'
|
||||||
'<?xml version="1.0"?>'
|
'<?xml version="1.0"?>'
|
||||||
|
|||||||
@@ -1,572 +0,0 @@
|
|||||||
# X-Financial 改进路线图
|
|
||||||
|
|
||||||
> 本文档基于 2026-06-18 对代码库的算法层、业务层、工程层综合评估生成。
|
|
||||||
> 每项改进都附有文件路径佐证,便于后续定位和追踪。
|
|
||||||
> 维护规则:状态变更请在对应章节同步更新;新增改进项追加到对应优先级末尾。
|
|
||||||
|
|
||||||
## 状态约定
|
|
||||||
|
|
||||||
| 标记 | 含义 |
|
|
||||||
|---|---|
|
|
||||||
| ⏳ | 待启动 |
|
|
||||||
| 🔄 | 进行中 |
|
|
||||||
| ✅ | 已完成 |
|
|
||||||
| ⏸️ | 暂缓(需说明原因) |
|
|
||||||
| ❌ | 取消(需说明原因) |
|
|
||||||
|
|
||||||
## 优先级矩阵
|
|
||||||
|
|
||||||
| 优先级 | 编号 | 标题 | 状态 |
|
|
||||||
|---|---|---|---|
|
|
||||||
| 🔴 P0 安全 | B2 | HTTP Header 权限漏洞 | ⏳ |
|
|
||||||
| 🔴 P0 业务核心 | B1 | 审批流转交/加签/撤回/会签 | ⏳ |
|
|
||||||
| 🔴 P0 共识 | B10 | 800 行硬约束破防 | ⏳ |
|
|
||||||
| 🟠 P1 算法 | A1 | 风险评分权重自适应 | ⏳ |
|
|
||||||
| 🟠 P1 算法 | A4 | LLM 票据分类 + 字段置信度 | ⏳ |
|
|
||||||
| 🟠 P1 算法 | A7 | LLM 幻觉检测 | ⏳ |
|
|
||||||
| 🟠 P1 业务 | B6 | 规则覆盖不均衡 | ⏳ |
|
|
||||||
| 🟡 P2 业务 | B3 | 申请/报销拆表 | ⏳ |
|
|
||||||
| 🟡 P2 业务 | B4 | 可配置审批矩阵 | ⏳ |
|
|
||||||
| 🟡 P2 算法 | A2 | 异常检测自适应阈值 | ⏳ |
|
|
||||||
| 🟢 P3 算法 | A3 | 多模型异常检测集成 | ⏳ |
|
|
||||||
| 🟢 P3 算法 | A5 | 票据分类持续学习 | ⏳ |
|
|
||||||
| 🟢 P3 算法 | A6 | Prompt 模板集中管理 | ⏳ |
|
|
||||||
| 🟢 P3 算法 | A8 | 规则冗余建模 | ⏳ |
|
|
||||||
| 🟢 P3 算法 | A9 | 行为画像 fairness 保护 | ⏳ |
|
|
||||||
| 🟢 P3 业务 | B5 | 预算跨期/跨科边界 | ⏳ |
|
|
||||||
| 🟢 P3 业务 | B7 | 审计日志防篡改 | ⏳ |
|
|
||||||
| 🟢 P3 业务 | B8 | 审批 SLA 监控 | ⏳ |
|
|
||||||
| 🟢 P3 业务 | B9 | 支付与凭证对接 | ⏳ |
|
|
||||||
| 🟢 P3 算法 | A10 | 算法模块 800 行拆分 | ⏳ |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 一、算法层面改进
|
|
||||||
|
|
||||||
### A1. 风险评分权重自适应调优 ⏳
|
|
||||||
|
|
||||||
**优先级**:🟠 P1
|
|
||||||
|
|
||||||
**证据**:
|
|
||||||
- `server/src/app/algorithem/risk_graph/engine.py:457-465`
|
|
||||||
- `server/src/app/services/risk_rule_scoring.py:16-23`
|
|
||||||
|
|
||||||
**当前实现**:
|
|
||||||
```python
|
|
||||||
risk_score = 0.35*S_rule + 0.25*S_anomaly + 0.20*S_graph + 0.15*S_policy + 0.05*S_history
|
|
||||||
```
|
|
||||||
五维权重和六因子权重均为硬编码常量,无法反映规则有效性差异。
|
|
||||||
|
|
||||||
**问题**:
|
|
||||||
- 已有 `RiskObservationFeedback` 表收集人工反馈,但反馈数据**未反向更新权重**
|
|
||||||
- 不同费用类型(差旅/招待/通信)的合理权重差异大,目前一刀切
|
|
||||||
|
|
||||||
**改进方向**:
|
|
||||||
- 按费用类型分组的权重向量
|
|
||||||
- 定期基于反馈数据做 logistic regression / Bayesian 更新
|
|
||||||
- 权重变更需版本化、可回滚
|
|
||||||
|
|
||||||
**验收标准**:
|
|
||||||
- [ ] 权重从配置/数据库读取,不再硬编码
|
|
||||||
- [ ] 反馈数据能触发权重自动调整
|
|
||||||
- [ ] 不同费用类型可配置独立权重
|
|
||||||
- [ ] 调整过程有日志和效果对比
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### A2. 金额异常检测自适应阈值 ⏳
|
|
||||||
|
|
||||||
**优先级**:🟡 P2
|
|
||||||
|
|
||||||
**证据**:`server/src/app/algorithem/risk_graph/engine.py:221-261`
|
|
||||||
|
|
||||||
**当前实现**:固定分档阈值 `1.0x→0, 1.25x→30, 1.5x→55, 2.0x→75, 3.0x→95`
|
|
||||||
|
|
||||||
**问题**:
|
|
||||||
- 通信费(小额高频)和差旅(大额低频)的"1.5x"含义完全不同
|
|
||||||
- peer p75 在新部门/新费用类型时样本稀疏
|
|
||||||
- 已识别 `peer_baseline_insufficient` 不确定性,但无冷启动方案
|
|
||||||
|
|
||||||
**改进方向**:
|
|
||||||
- 改为自适应分位数(基于历史数据动态计算)
|
|
||||||
- 按 `(费用类型 × 部门层级)` 分组维护基线
|
|
||||||
- 冷启动:全局基线 + 小样本置信度折扣
|
|
||||||
|
|
||||||
**验收标准**:
|
|
||||||
- [ ] 阈值按业务维度分组,不再全局统一
|
|
||||||
- [ ] 新部门/新费用类型有冷启动策略
|
|
||||||
- [ ] 基线样本不足时有降级机制
|
|
||||||
- [ ] 增加单元测试覆盖冷启动场景
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### A3. 多模型异常检测集成策略 ⏳
|
|
||||||
|
|
||||||
**优先级**:🟢 P3
|
|
||||||
|
|
||||||
**证据**:`server/src/app/algorithem/risk_graph/anomaly_models.py`
|
|
||||||
|
|
||||||
**当前实现**:5 个模型独立输出(`robust_statistics / isolation_proxy / local_outlier / temporal_jump / periodic_deviation`),无集成。
|
|
||||||
|
|
||||||
**问题**:
|
|
||||||
- 多模型同时报警时聚合规则未定义
|
|
||||||
- 单模型 vs 多模型共识的严重度差异未体现
|
|
||||||
- 模型间冲突无裁决机制
|
|
||||||
|
|
||||||
**改进方向**:
|
|
||||||
- 引入 `AnomalyEnsembler` 集成层
|
|
||||||
- 输出 `consensus_score` + `model_disagreement_flag`
|
|
||||||
- 高风险图谱评分区分"单点异常"和"多维共识异常"
|
|
||||||
|
|
||||||
**验收标准**:
|
|
||||||
- [ ] 实现集成层并接入 engine.py
|
|
||||||
- [ ] 集成结果包含共识度指标
|
|
||||||
- [ ] 单元测试覆盖各种模型组合情况
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### A4. LLM 票据分类与字段置信度 ⏳
|
|
||||||
|
|
||||||
**优先级**:🟠 P1
|
|
||||||
|
|
||||||
**证据**:
|
|
||||||
- `server/src/app/services/document_intelligence.py:143-153`(`_classify_with_model` 当前 `return None`)
|
|
||||||
- `server/src/app/services/document_intelligence.py:20-37`(字段抽取全正则)
|
|
||||||
|
|
||||||
**问题**:
|
|
||||||
- 规则层单点支撑,非标准票据格式失效
|
|
||||||
- 无字段级置信度评分,无法判断哪些抽取值需要人工复核
|
|
||||||
- LLM 分类合并策略代码已存在但未启用
|
|
||||||
|
|
||||||
**改进方向**:
|
|
||||||
1. 启用 LLM 分类层(合并逻辑可直接复用)
|
|
||||||
2. 字段抽取增加置信度:`{field: {value, confidence, source}}`
|
|
||||||
3. 低置信度字段(< 0.7)自动标记"需人工核对"
|
|
||||||
|
|
||||||
**验收标准**:
|
|
||||||
- [ ] LLM 分类层启用并通过对比测试
|
|
||||||
- [ ] 每个抽取字段附带置信度评分
|
|
||||||
- [ ] 低置信度字段触发人工复核标记
|
|
||||||
- [ ] 提供准确率回归测试集
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### A5. 票据分类持续学习 ⏳
|
|
||||||
|
|
||||||
**优先级**:🟢 P3
|
|
||||||
|
|
||||||
**证据**:`server/src/app/services/document_intelligence_rules.py:120`(`score_bias` 硬编码)
|
|
||||||
|
|
||||||
**问题**:新票种(ETC 电子票、滴滴行程单新模板)需开发改代码才能识别。
|
|
||||||
|
|
||||||
**改进方向**:
|
|
||||||
- 分类规则做成可配置 + 可学习
|
|
||||||
- 管理员上传样本自动更新关键词权重
|
|
||||||
- 基于历史已分类票据做 TF-IDF 训练
|
|
||||||
|
|
||||||
**验收标准**:
|
|
||||||
- [ ] 后台提供分类规则管理界面
|
|
||||||
- [ ] 新票种可通过样本上传识别
|
|
||||||
- [ ] 历史数据可训练关键词权重
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### A6. Prompt 模板集中管理 ⏳
|
|
||||||
|
|
||||||
**优先级**:🟢 P3
|
|
||||||
|
|
||||||
**证据**:
|
|
||||||
- `server/src/app/services/ontology_extraction.py`
|
|
||||||
- `server/src/app/services/ontology_detection.py`
|
|
||||||
- `server/src/app/services/risk_rule_generation.py`
|
|
||||||
- `server/src/app/services/user_agent_response.py`
|
|
||||||
- `server/src/app/services/user_agent_application.py`
|
|
||||||
- `server/src/app/services/user_agent_review_core.py`
|
|
||||||
- `server/src/app/services/knowledge_rag.py:214`(查询重写硬编码在方法内)
|
|
||||||
|
|
||||||
**问题**:
|
|
||||||
- Prompt 散落在 12+ 文件,无版本化、无回滚、无 A/B 测试
|
|
||||||
- 相同意图的 prompt 在不同 service 中重复
|
|
||||||
|
|
||||||
**改进方向**:
|
|
||||||
- 建立 `prompts/` 集中目录 + `PromptRegistry`
|
|
||||||
- 按 `(意图, 版本)` 管理
|
|
||||||
- 支持灰度发布和效果对比
|
|
||||||
|
|
||||||
**验收标准**:
|
|
||||||
- [ ] 所有 prompt 迁移到集中目录
|
|
||||||
- [ ] 支持版本化与回滚
|
|
||||||
- [ ] 提供 A/B 测试接口
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### A7. LLM 幻觉检测与事实校验 ⏳
|
|
||||||
|
|
||||||
**优先级**:🟠 P1
|
|
||||||
|
|
||||||
**证据**:当前系统缺少 LLM 输出的显式幻觉检测。本体解析有 `confidence` 门禁,但生成的解释文本、规则建议、对话回复无校验。
|
|
||||||
|
|
||||||
**问题**:
|
|
||||||
- LLM 可能编造不存在的政策条款、错误金额阈值、虚构审批人
|
|
||||||
- 风险图谱解释文本幻觉会误导审批人
|
|
||||||
- 唯一兜底是 `data_quality_gate`,仅管输入数据质量
|
|
||||||
|
|
||||||
**改进方向**:
|
|
||||||
- 关键输出(金额、政策条款、规则编号)做 grounded check:LLM 输出后用规则引擎反向校验
|
|
||||||
- 对话回复中的具体数字、日期强制引用证据片段(RAG 引用)
|
|
||||||
|
|
||||||
**验收标准**:
|
|
||||||
- [ ] 关键数值字段有反向校验机制
|
|
||||||
- [ ] 对话回复中的事实声明可追溯到证据
|
|
||||||
- [ ] 校验失败时有明确降级策略
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### A8. 规则冗余/相关性建模 ⏳
|
|
||||||
|
|
||||||
**优先级**:🟢 P3
|
|
||||||
|
|
||||||
**证据**:`server/src/app/services/risk_rule_scoring.py`(多规则命中简单求和/max)
|
|
||||||
|
|
||||||
**问题**:相关规则同时命中时分数被夸大。如 `preapproval_absent` 和 `date_outside_trip` 可能高度相关。
|
|
||||||
|
|
||||||
**改进方向**:引入规则相关矩阵,对相关规则命中分数做去冗余折扣。
|
|
||||||
|
|
||||||
**验收标准**:
|
|
||||||
- [ ] 建立规则相关矩阵
|
|
||||||
- [ ] 命中聚合时考虑冗余
|
|
||||||
- [ ] 测试验证去冗余效果
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### A9. 行为画像 fairness 保护 ⏳
|
|
||||||
|
|
||||||
**优先级**:🟢 P3
|
|
||||||
|
|
||||||
**证据**:`server/src/app/algorithem/employee_behavior_profile.py:345`(`evaluate_weighted_profile` / `calculate_review_priority_score`)
|
|
||||||
|
|
||||||
**问题**:行为画像影响审核优先级,若基于受保护属性(性别/年龄)产生系统性偏差,会构成隐性歧视。
|
|
||||||
|
|
||||||
**改进方向**:
|
|
||||||
- 增加 fairness audit 接口(按人群分组统计风险分布)
|
|
||||||
- 评分特征显式排除受保护属性
|
|
||||||
- 定期输出偏差报告
|
|
||||||
|
|
||||||
**验收标准**:
|
|
||||||
- [ ] 评分特征清单明确排除受保护属性
|
|
||||||
- [ ] 提供 fairness audit API
|
|
||||||
- [ ] 定期偏差报告生成
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### A10. 算法模块 800 行拆分 ⏳
|
|
||||||
|
|
||||||
**优先级**:🟢 P3(与 B10 同源,单独追踪算法模块进度)
|
|
||||||
|
|
||||||
**证据**:
|
|
||||||
- `server/src/app/algorithem/employee_behavior_profile_tag_rules.py`: **812 行** 🔴
|
|
||||||
- `server/src/app/algorithem/risk_graph/engine.py`: **794 行** 🟡 临界
|
|
||||||
|
|
||||||
**改进方向**:
|
|
||||||
- `employee_behavior_profile_tag_rules.py` 按标签类别拆分(差旅类 / 招待类 / 办公类)
|
|
||||||
- `engine.py` 的 5 个评分维度(rule/anomaly/graph/policy/history)拆为 5 个独立打分器
|
|
||||||
|
|
||||||
**验收标准**:
|
|
||||||
- [ ] 所有算法文件 ≤ 800 行
|
|
||||||
- [ ] 拆分前后行为等价(单元测试通过)
|
|
||||||
- [ ] 拆分后职责边界清晰
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 二、业务层面改进
|
|
||||||
|
|
||||||
### B1. 审批流转交/加签/撤回/会签 ⏳
|
|
||||||
|
|
||||||
**优先级**:🔴 P0
|
|
||||||
|
|
||||||
**证据**:
|
|
||||||
- `server/src/app/services/expense_claim_workflow_constants.py`(仅 11 行固定阶段)
|
|
||||||
- `server/src/app/services/expense_claim_approval_flow.py:28`(`approve_claim` 串行硬编码)
|
|
||||||
- 转交/加签/撤回代码中**不存在**
|
|
||||||
|
|
||||||
**问题**:
|
|
||||||
- 费控系统核心能力缺失
|
|
||||||
- 现实中领导出差无法审批是常态
|
|
||||||
- 无并行审批(会签),多人审批只能串行
|
|
||||||
- 审批节点调整需改代码
|
|
||||||
|
|
||||||
**改进方向**:
|
|
||||||
- 引入审批矩阵:`费用类型 × 金额区间 × 部门` → 审批节点列表
|
|
||||||
- 支持节点动作:`{approve, reject, return, transfer, countersign, withdraw, add_approver}`
|
|
||||||
- 短期优先实现"转交"和"撤回"两个最常用动作
|
|
||||||
|
|
||||||
**验收标准**:
|
|
||||||
- [ ] 支持转交(审批人转给他人)
|
|
||||||
- [ ] 支持撤回(提交人在审批中撤回)
|
|
||||||
- [ ] 支持加签(临时增加审批节点)
|
|
||||||
- [ ] 支持会签(多节点并行)
|
|
||||||
- [ ] 审批矩阵可后台配置
|
|
||||||
- [ ] 关键操作有审计日志
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### B2. HTTP Header 权限漏洞修复 ⏳
|
|
||||||
|
|
||||||
**优先级**:🔴 P0(安全)
|
|
||||||
|
|
||||||
**证据**:`server/src/app/api/deps.py:33-213`,通过 `X-Auth-Username / X-Auth-Role-Codes / X-Auth-Is-Admin` 等请求头识别身份。
|
|
||||||
|
|
||||||
**问题**:
|
|
||||||
- **任何人只要在请求头加 `X-Auth-Is-Admin: true` 就能获得管理员权限**
|
|
||||||
- 没有 token、没有签名、没有任何校验
|
|
||||||
- 足以让所有费控规则形同虚设
|
|
||||||
|
|
||||||
**改进方向**:
|
|
||||||
- 引入真正的身份认证(JWT 或 session cookie)
|
|
||||||
- 角色信息从服务端 session/token 获取,**绝不信任客户端传来的角色声明**
|
|
||||||
- 短期方案:前置网关(nginx)剥离这些头并注入真实身份
|
|
||||||
|
|
||||||
**验收标准**:
|
|
||||||
- [ ] 客户端无法通过伪造 Header 越权
|
|
||||||
- [ ] 所有角色信息来自服务端校验
|
|
||||||
- [ ] 现有 API 行为兼容(不破坏调用方)
|
|
||||||
- [ ] 安全测试覆盖权限边界
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### B3. 申请单与报销单拆表 ⏳
|
|
||||||
|
|
||||||
**优先级**:🟡 P2
|
|
||||||
|
|
||||||
**证据**:
|
|
||||||
- `server/src/app/models/financial_record.py`:`ExpenseClaim` 通过 `expense_type` 后缀 + `claim_no` 前缀区分
|
|
||||||
- `server/src/app/models/reimbursement.py`:`ReimbursementRequest` 几乎废弃(service 仅 54 行 CRUD)
|
|
||||||
|
|
||||||
**问题**:
|
|
||||||
- 查询复杂度高,每个查询都要带 `expense_type IN (...)` 过滤
|
|
||||||
- 字段冗余(申请单无发票字段但表里有)
|
|
||||||
- 业务语义混乱("claim"分不清是申请还是报销)
|
|
||||||
- 索引难优化
|
|
||||||
|
|
||||||
**改进方向**(需决策):
|
|
||||||
- 方案 A(保守):保留单表,增加 `claim_kind` 字段(`application` / `reimbursement`)显式区分
|
|
||||||
- 方案 B(彻底):拆分为 `ExpenseApplication` + `ExpenseReimbursement` 两张表,通过 `application_id` 外键关联
|
|
||||||
- **涉及数据迁移,需用户确认方案**
|
|
||||||
|
|
||||||
**验收标准**:
|
|
||||||
- [ ] 方案决策完成
|
|
||||||
- [ ] 数据迁移脚本可重入、可回滚
|
|
||||||
- [ ] 迁移前后数据等价校验
|
|
||||||
- [ ] 现有 API 行为兼容或平滑升级
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### B4. 可配置审批矩阵 ⏳
|
|
||||||
|
|
||||||
**优先级**:🟡 P2
|
|
||||||
|
|
||||||
**证据**:`server/src/app/services/expense_claim_approval_routing.py`(`_APPLICATION_BUDGET_REVIEW_USAGE_THRESHOLD = 90%` 等阈值硬编码)
|
|
||||||
|
|
||||||
**问题**:什么金额走什么审批、什么情况要预算管理者介入,全部硬编码。不同公司/部门差异大,无法运维配置。
|
|
||||||
|
|
||||||
**改进方向**:建立审批矩阵配置表:
|
|
||||||
```
|
|
||||||
approval_matrix(expense_type, amount_range, department_level, risk_level)
|
|
||||||
→ [approver_roles, parallel_or_serial, sla_hours]
|
|
||||||
```
|
|
||||||
管理员后台维护,系统按矩阵动态生成审批流。
|
|
||||||
|
|
||||||
**验收标准**:
|
|
||||||
- [ ] 审批矩阵可后台配置
|
|
||||||
- [ ] 系统按矩阵动态生成审批流
|
|
||||||
- [ ] 配置变更有版本和审计
|
|
||||||
- [ ] 矩阵未命中时有合理默认值
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### B5. 预算管控跨期/跨科边界 ⏳
|
|
||||||
|
|
||||||
**优先级**:🟢 P3
|
|
||||||
|
|
||||||
**证据**:
|
|
||||||
- `server/src/app/services/budget.py`(780 行)
|
|
||||||
- `server/src/app/services/expense_claim_budget_flow.py`(112 行)
|
|
||||||
- 预算占用/释放/核销/转移已实现,但边界场景验证不足
|
|
||||||
|
|
||||||
**潜在漏洞**:
|
|
||||||
- 跨财年结转:去年冻结的预算今年初未释放
|
|
||||||
- 跨期占用:Q1 提交的申请 Q2 才审批,占用的是哪个季度?
|
|
||||||
- 跨科目调剂:差旅预算不够能否临时挪用办公预算?
|
|
||||||
- 无对应单元测试
|
|
||||||
|
|
||||||
**改进方向**:
|
|
||||||
- 增加预算状态周期性对账任务(每日扫描 orphan reservation)
|
|
||||||
- 跨期策略明确化(默认跟随申请提交期,可配置)
|
|
||||||
- 补充跨期/跨科目单元测试
|
|
||||||
|
|
||||||
**验收标准**:
|
|
||||||
- [ ] 跨期/跨科目边界单元测试覆盖
|
|
||||||
- [ ] 周期性对账任务上线
|
|
||||||
- [ ] orphan reservation 自动清理
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### B6. 规则覆盖不均衡补齐 ⏳
|
|
||||||
|
|
||||||
**优先级**:🟠 P1
|
|
||||||
|
|
||||||
**证据**:`server/rules/risk-rules/` 38 条规则分布:
|
|
||||||
- 差旅(travel):13 条
|
|
||||||
- 预算(budget):13 条
|
|
||||||
- 申请(application):5 条
|
|
||||||
- 报销(reimbursement):7 条
|
|
||||||
- 标准(standard):5 条
|
|
||||||
|
|
||||||
**问题**:
|
|
||||||
- **招待费、市场推广、培训费、福利费、软件服务费几乎没有专门规则**
|
|
||||||
- 缺少供应商关联方交易、连号发票重复报销、跨年度重复报销检测
|
|
||||||
- 这些恰是真实费控场景最易出问题的领域
|
|
||||||
|
|
||||||
**改进方向**:
|
|
||||||
1. 招待费规则(参与人数缺失、人均超标、同城招待、节假日招待)
|
|
||||||
2. 供应商风险规则(同一供应商高频、关联方、工商信息异常)
|
|
||||||
3. 重复报销检测(发票号哈希去重、跨期扫描)
|
|
||||||
|
|
||||||
**验收标准**:
|
|
||||||
- [ ] 招待费规则集(≥5 条)
|
|
||||||
- [ ] 供应商风险规则集(≥3 条)
|
|
||||||
- [ ] 重复报销检测规则(≥2 条)
|
|
||||||
- [ ] 每条新规则有对应单元测试
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### B7. 审计日志防篡改 ⏳
|
|
||||||
|
|
||||||
**优先级**:🟢 P3
|
|
||||||
|
|
||||||
**证据**:
|
|
||||||
- `server/src/app/models/audit_log.py`
|
|
||||||
- `server/src/app/services/audit.py`(72 行)
|
|
||||||
- before/after JSON 快照完整,但**无 hash chain 或数字签名**
|
|
||||||
|
|
||||||
**问题**:数据库管理员(或有 DB 写权限的人)可静默篡改审计日志。
|
|
||||||
|
|
||||||
**改进方向**:
|
|
||||||
- 每条日志附加 `prev_hash + current_hash = sha256(prev_hash + payload)`
|
|
||||||
- 定期锚定到外部存证(区块链 / 公证处 / WORM 存储)
|
|
||||||
|
|
||||||
**验收标准**:
|
|
||||||
- [ ] 审计日志实现 hash chain
|
|
||||||
- [ ] 篡改可被检测
|
|
||||||
- [ ] 外部存证机制(至少文档化)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### B8. 审批 SLA 与时效监控 ⏳
|
|
||||||
|
|
||||||
**优先级**:🟢 P3
|
|
||||||
|
|
||||||
**证据**:审批节点无超时提醒代码。
|
|
||||||
|
|
||||||
**问题**:单据卡在某领导处一周无人管,系统无感知。
|
|
||||||
|
|
||||||
**改进方向**:
|
|
||||||
- 每个审批节点配置 SLA(如 24h/48h)
|
|
||||||
- 后台定时任务扫描超时单据
|
|
||||||
- 自动催办 / 升级到上级 / 转交
|
|
||||||
|
|
||||||
**验收标准**:
|
|
||||||
- [ ] SLA 可配置
|
|
||||||
- [ ] 超时自动催办
|
|
||||||
- [ ] 超时升级机制
|
|
||||||
- [ ] SLA 报表可查
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### B9. 支付与凭证对接 ⏳
|
|
||||||
|
|
||||||
**优先级**:🟢 P3(业务延伸方向)
|
|
||||||
|
|
||||||
**证据**:状态机到 `paid` 就结束,无银企直连、无会计凭证生成。
|
|
||||||
|
|
||||||
**问题**:报销审批通过后仍需财务人工付款、手工录凭证,未形成完整闭环。
|
|
||||||
|
|
||||||
**改进方向**:
|
|
||||||
- 银企直连(用友 / 金蝶 / 远光 API)
|
|
||||||
- 自动生成会计凭证(借:管理费用-差旅,贷:银行存款/应付职工薪酬)
|
|
||||||
|
|
||||||
**验收标准**:
|
|
||||||
- [ ] 至少接入一个财务系统
|
|
||||||
- [ ] 凭证自动生成
|
|
||||||
- [ ] 支付状态回传
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### B10. 800 行硬约束拆分(业务模块) ⏳
|
|
||||||
|
|
||||||
**优先级**:🔴 P0
|
|
||||||
|
|
||||||
**证据**:services/ 下 ≥ 800 行的文件,共 **20 个**:
|
|
||||||
|
|
||||||
| 文件 | 行数 | 超标幅度 |
|
|
||||||
|---|---|---|
|
|
||||||
| `services/user_agent_application.py` | 1451 | +81% |
|
|
||||||
| `services/risk_rule_template_executor.py` | 1164 | +45% |
|
|
||||||
| `services/expense_claim_draft_flow.py` | 1064 | +33% |
|
|
||||||
| `services/expense_claims.py` | 1042 | +30% |
|
|
||||||
| `services/receipt_folder.py` | 1034 | +29% |
|
|
||||||
| `services/steward_planner.py` | 935 | +17% |
|
|
||||||
| `api/v1/endpoints/agent_assets.py` | 925 | +16% |
|
|
||||||
| `services/orchestrator_execution.py` | 900 | +12.5% |
|
|
||||||
| `services/finance_dashboard.py` | 884 | +10.5% |
|
|
||||||
| `services/knowledge_rag.py` | 877 | +9.6% |
|
|
||||||
| `services/settings.py` | 873 | +9.1% |
|
|
||||||
| `services/agent_assets.py` | 856 | +7% |
|
|
||||||
| `services/employee.py` | 850 | +6.25% |
|
|
||||||
| `services/employee_behavior_profile_service.py` | 823 | +2.9% |
|
|
||||||
| `services/risk_rule_generation.py` | 821 | +2.6% |
|
|
||||||
| `services/agent_foundation_asset_topup.py` | 809 | +1.1% |
|
|
||||||
| `services/ontology_extraction.py` | 808 | +1% |
|
|
||||||
| `services/demo_company_simulation_seed.py` | 805 | +0.6% |
|
|
||||||
| `services/knowledge.py` | 800 | 临界 |
|
|
||||||
| 另约 20 个文件在 700-800 行区间 | | 🟡 |
|
|
||||||
|
|
||||||
**前端超大文件**:
|
|
||||||
|
|
||||||
| 文件 | 行数 |
|
|
||||||
|---|---|
|
|
||||||
| `web/src/views/scripts/TravelReimbursementCreateView.js` | 4066 🔴🔴 |
|
|
||||||
| `web/src/views/scripts/TravelRequestDetailView.js` | 2861 🔴🔴 |
|
|
||||||
| `web/src/views/scripts/useTravelReimbursementSubmitComposer.js` | 2173 🔴🔴 |
|
|
||||||
| `web/src/composables/useRequests.js` | 1799 🔴 |
|
|
||||||
| `web/src/views/scripts/travelReimbursementReviewModel.js` | 1662 🔴 |
|
|
||||||
| 多个 `.vue` 文件 | 800-1130 🔴 |
|
|
||||||
|
|
||||||
**改进方向**:
|
|
||||||
- 按 AGENTS.md 既定的拆分原则(编排 / 状态 / 持久化 / 权限 / 文件存储 / OCR / 规则审核 / 响应构建 / 序列化)逐个拆
|
|
||||||
- 优先 Top 5:`user_agent_application` / `risk_rule_template_executor` / `expense_claim_draft_flow` / `expense_claims` / `receipt_folder`
|
|
||||||
- 每次拆分配套定向测试
|
|
||||||
|
|
||||||
**验收标准**:
|
|
||||||
- [ ] 所有类/文件 ≤ 800 行
|
|
||||||
- [ ] 拆分前后行为等价(测试通过)
|
|
||||||
- [ ] 拆分后职责边界清晰
|
|
||||||
- [ ] CI 中加入行数检查(防止回潮)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 三、推进原则
|
|
||||||
|
|
||||||
1. **P0 优先**:B2(安全)、B1(核心能力)、B10(共识)必须先行。
|
|
||||||
2. **算法优化在 P0 落地后做**:再准的算法也会被权限漏洞和流程缺失抵消。
|
|
||||||
3. **小步快跑**:每项改进拆成可独立验证的子任务,配套测试。
|
|
||||||
4. **不破坏既有协议**:对外 API 尽量稳定,内部实现先拆。
|
|
||||||
5. **800 行约束**:所有改动前后检查受影响类行数,CI 加入行数门禁。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 四、变更日志
|
|
||||||
|
|
||||||
| 日期 | 变更 | 操作人 |
|
|
||||||
|---|---|---|
|
|
||||||
| 2026-06-18 | 路线图初始版本,基于代码库全量评估生成 | Sisyphus |
|
|
||||||
@@ -1,177 +0,0 @@
|
|||||||
# Steward Application Reimbursement State Implementation Plan
|
|
||||||
|
|
||||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
||||||
|
|
||||||
**Goal:** Build a persistent ontology-bound steward state for travel application and travel reimbursement flows.
|
|
||||||
|
|
||||||
**Architecture:** Keep the existing steward planning UI and assistant delegation flow. Add a backend state layer that stores `steward_state` in `AgentConversation.state_json`, merges LLM/rule output as patches, and rejects fields outside the ontology registry before downstream services consume them.
|
|
||||||
|
|
||||||
**Tech Stack:** FastAPI, SQLAlchemy JSON state, Pydantic schemas, pytest in Docker `x-financial-main:/app`, Vue/Vite frontend.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 1: Backend State Contract
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `server/src/app/schemas/steward.py`
|
|
||||||
- Create: `server/src/app/services/steward_flow_state.py`
|
|
||||||
- Test: `server/tests/test_steward_flow_state.py`
|
|
||||||
|
|
||||||
- [ ] **Step 1: Write failing tests**
|
|
||||||
|
|
||||||
```python
|
|
||||||
def test_state_merge_keeps_application_and_reimbursement_flows():
|
|
||||||
service = StewardFlowStateService()
|
|
||||||
state = service.merge_state(
|
|
||||||
{},
|
|
||||||
StewardFlowStatePatch(
|
|
||||||
active_flow="travel_application",
|
|
||||||
flow_id="travel_application",
|
|
||||||
intent="travel_application_create",
|
|
||||||
fields={"expense_type": "travel", "location": "上海"},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
state = service.merge_state(
|
|
||||||
state,
|
|
||||||
StewardFlowStatePatch(
|
|
||||||
active_flow="travel_reimbursement",
|
|
||||||
flow_id="travel_reimbursement",
|
|
||||||
intent="travel_reimbursement_draft",
|
|
||||||
fields={"amount": "708", "invoice_no": "NO-1"},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
assert state["flows"]["travel_application"]["fields"]["location"] == "上海"
|
|
||||||
assert state["flows"]["travel_reimbursement"]["fields"]["amount"] == "708"
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
def test_state_merge_filters_non_ontology_fields():
|
|
||||||
service = StewardFlowStateService()
|
|
||||||
state = service.merge_state(
|
|
||||||
{},
|
|
||||||
StewardFlowStatePatch(
|
|
||||||
active_flow="travel_application",
|
|
||||||
flow_id="travel_application",
|
|
||||||
intent="travel_application_create",
|
|
||||||
fields={"location": "上海", "invented_field": "x"},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
assert state["flows"]["travel_application"]["fields"] == {"location": "上海"}
|
|
||||||
```
|
|
||||||
|
|
||||||
- [ ] **Step 2: Run red tests**
|
|
||||||
|
|
||||||
Run:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker exec -w /app -e SERVER_VENV_DIR=/tmp/x-financial-server-venv x-financial-main /tmp/x-financial-server-venv/bin/pytest -q server/tests/test_steward_flow_state.py
|
|
||||||
```
|
|
||||||
|
|
||||||
Expected: fail because `steward_flow_state.py` does not exist.
|
|
||||||
|
|
||||||
- [ ] **Step 3: Implement minimal state service**
|
|
||||||
|
|
||||||
Create `StewardFlowStatePatch`, `StewardFlowStateService.merge_state`, ontology field filtering, and event append logic.
|
|
||||||
|
|
||||||
- [ ] **Step 4: Run green tests**
|
|
||||||
|
|
||||||
Run the same pytest command and expect pass.
|
|
||||||
|
|
||||||
### Task 2: Steward Plan Persistence
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `server/src/app/schemas/steward.py`
|
|
||||||
- Modify: `server/src/app/api/v1/endpoints/steward.py`
|
|
||||||
- Modify: `server/src/app/services/agent_conversations.py`
|
|
||||||
- Test: `server/tests/test_steward_planner.py`
|
|
||||||
|
|
||||||
- [ ] **Step 1: Write failing API/service test**
|
|
||||||
|
|
||||||
Add a test proving `/steward/plans` response contains `conversation_id` and `steward_state` when `context_json.session_type = steward`, and the state contains two flows when the input contains one application and one reimbursement task.
|
|
||||||
|
|
||||||
- [ ] **Step 2: Run red test**
|
|
||||||
|
|
||||||
Run:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker exec -w /app -e SERVER_VENV_DIR=/tmp/x-financial-server-venv x-financial-main /tmp/x-financial-server-venv/bin/pytest -q server/tests/test_steward_planner.py
|
|
||||||
```
|
|
||||||
|
|
||||||
- [ ] **Step 3: Implement conversation state persistence**
|
|
||||||
|
|
||||||
Add `conversation_id` and `steward_state` fields to response schemas, persist state through `AgentConversationService`, and merge planner tasks into `steward_state`.
|
|
||||||
|
|
||||||
- [ ] **Step 4: Run green test**
|
|
||||||
|
|
||||||
Run the same pytest command and expect pass.
|
|
||||||
|
|
||||||
### Task 3: Runtime Decision Reads Persistent State
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `server/src/app/services/steward_runtime_decision_agent.py`
|
|
||||||
- Test: `server/tests/test_steward_runtime_decision_agent.py`
|
|
||||||
|
|
||||||
- [ ] **Step 1: Write failing test**
|
|
||||||
|
|
||||||
Add a test proving runtime decision uses `context_json.conversation_state.steward_state` when `runtime_state` is empty.
|
|
||||||
|
|
||||||
- [ ] **Step 2: Implement minimal fallback hydration**
|
|
||||||
|
|
||||||
Normalize runtime state by merging request runtime state with persisted steward state.
|
|
||||||
|
|
||||||
- [ ] **Step 3: Run green test**
|
|
||||||
|
|
||||||
Run:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker exec -w /app -e SERVER_VENV_DIR=/tmp/x-financial-server-venv x-financial-main /tmp/x-financial-server-venv/bin/pytest -q server/tests/test_steward_runtime_decision_agent.py
|
|
||||||
```
|
|
||||||
|
|
||||||
### Task 4: Frontend State Carry
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `web/src/views/scripts/stewardPlanModel.js`
|
|
||||||
- Modify: `web/src/views/scripts/TravelReimbursementCreateView.js`
|
|
||||||
- Modify: `web/src/views/scripts/useTravelReimbursementSessionState.js`
|
|
||||||
|
|
||||||
- [ ] **Step 1: Preserve steward state from backend responses**
|
|
||||||
|
|
||||||
Normalize `conversation_id` and `steward_state` from plan/runtime responses into the local session model.
|
|
||||||
|
|
||||||
- [ ] **Step 2: Send steward state in later requests**
|
|
||||||
|
|
||||||
Include the current `steward_state` under `context_json` for plan and runtime decision calls.
|
|
||||||
|
|
||||||
- [ ] **Step 3: Build frontend**
|
|
||||||
|
|
||||||
Run:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker exec -w /app/web x-financial-main npm run build
|
|
||||||
```
|
|
||||||
|
|
||||||
Expected: build succeeds.
|
|
||||||
|
|
||||||
### Task 5: Final Verification
|
|
||||||
|
|
||||||
- [ ] **Step 1: Run backend steward tests**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker exec -w /app -e SERVER_VENV_DIR=/tmp/x-financial-server-venv x-financial-main /tmp/x-financial-server-venv/bin/pytest -q server/tests/test_steward_flow_state.py server/tests/test_steward_planner.py server/tests/test_steward_runtime_decision_agent.py server/tests/test_steward_slot_decision_agent.py
|
|
||||||
```
|
|
||||||
|
|
||||||
- [ ] **Step 2: Run frontend build**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker exec -w /app/web x-financial-main npm run build
|
|
||||||
```
|
|
||||||
|
|
||||||
- [ ] **Step 3: Report workspace status**
|
|
||||||
|
|
||||||
Run:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git status --short
|
|
||||||
```
|
|
||||||
@@ -1,159 +0,0 @@
|
|||||||
# Refactor Under 800 Lines Implementation Plan
|
|
||||||
|
|
||||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
||||||
|
|
||||||
**Goal:** Keep every Python class and every frontend core component/module under 800 lines, while deleting proven dead code and reducing avoidable runtime overhead.
|
|
||||||
|
|
||||||
**Architecture:** Add automated code-size guardrails first, then split oversized units by existing responsibility boundaries. Preserve public APIs wherever possible, move private helpers into focused modules, and delete code only after usage checks or tests prove it is not needed.
|
|
||||||
|
|
||||||
**Tech Stack:** Vue single-file components, Vite/Node test runner, Python/FastAPI service layer, pytest inside Docker container `x-financial-main`.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 1: Guardrails
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Create: `web/tests/code-size-limits.test.mjs`
|
|
||||||
- Create: `server/tests/test_code_size_limits.py`
|
|
||||||
|
|
||||||
- [x] **Step 1: Add frontend source-unit limit test**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
node --test web/tests/code-size-limits.test.mjs
|
|
||||||
```
|
|
||||||
|
|
||||||
Expected current result: FAIL, listing oversized files in `web/src/components`, `web/src/composables`, `web/src/utils`, and `web/src/views`.
|
|
||||||
|
|
||||||
- [x] **Step 2: Add backend class limit test**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker exec -w /app -e SERVER_VENV_DIR=/tmp/x-financial-server-venv x-financial-main /tmp/x-financial-server-venv/bin/pytest -q server/tests/test_code_size_limits.py
|
|
||||||
```
|
|
||||||
|
|
||||||
Expected current result: FAIL, listing Python classes over 800 lines.
|
|
||||||
|
|
||||||
|
|
||||||
### Task 2: Backend Python Class Split
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `server/src/app/services/user_agent_application.py`
|
|
||||||
- Modify: `server/src/app/services/risk_rule_template_executor.py`
|
|
||||||
- Modify: `server/src/app/services/steward_planner.py`
|
|
||||||
- Modify: `server/src/app/services/receipt_folder.py`
|
|
||||||
- Modify: `server/src/app/services/expense_claim_draft_flow.py`
|
|
||||||
- Modify: `server/src/app/services/expense_claims.py`
|
|
||||||
- Modify: `server/src/app/services/orchestrator_execution.py`
|
|
||||||
- Modify: `server/src/app/services/finance_dashboard.py`
|
|
||||||
- Modify: `server/src/app/services/agent_assets.py`
|
|
||||||
- Create focused helper or mixin files under `server/src/app/services/`
|
|
||||||
|
|
||||||
- [ ] **Step 1: Split low-risk helper groups first**
|
|
||||||
|
|
||||||
Move private formatting, parsing, label, and serialization methods into helper mixins or helper modules. Keep original public classes and method names stable.
|
|
||||||
|
|
||||||
- [ ] **Step 2: Split domain-heavy groups**
|
|
||||||
|
|
||||||
Move larger responsibility groups into named mixins:
|
|
||||||
|
|
||||||
```text
|
|
||||||
UserAgentApplicationMixin
|
|
||||||
├── application fact resolution
|
|
||||||
├── application persistence
|
|
||||||
└── application duplicate/detail helpers
|
|
||||||
|
|
||||||
RiskRuleTemplateExecutor
|
|
||||||
├── condition evaluators
|
|
||||||
├── value resolvers
|
|
||||||
└── date/window parsing
|
|
||||||
|
|
||||||
ReceiptFolderService
|
|
||||||
├── storage/meta helpers
|
|
||||||
├── editable field resolution
|
|
||||||
└── train ticket extraction
|
|
||||||
```
|
|
||||||
|
|
||||||
- [ ] **Step 3: Verify backend class limit**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker exec -w /app -e SERVER_VENV_DIR=/tmp/x-financial-server-venv x-financial-main /tmp/x-financial-server-venv/bin/pytest -q server/tests/test_code_size_limits.py
|
|
||||||
```
|
|
||||||
|
|
||||||
Expected final result: PASS.
|
|
||||||
|
|
||||||
- [ ] **Step 4: Run targeted backend regression tests**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker exec -w /app -e SERVER_VENV_DIR=/tmp/x-financial-server-venv x-financial-main /tmp/x-financial-server-venv/bin/pytest -q server/tests/test_user_agent_service.py server/tests/test_expense_claim_service.py server/tests/test_steward_planner.py server/tests/test_risk_rule_generation.py server/tests/test_agent_asset_service.py server/tests/test_reimbursement_endpoints.py
|
|
||||||
```
|
|
||||||
|
|
||||||
Expected final result: PASS or a documented pre-existing failure with evidence.
|
|
||||||
|
|
||||||
|
|
||||||
### Task 3: Frontend Source Unit Split
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `web/src/components/business/PersonalWorkbenchAiMode.vue`
|
|
||||||
- Modify: `web/src/views/scripts/TravelReimbursementCreateView.js`
|
|
||||||
- Modify: `web/src/views/scripts/TravelRequestDetailView.js`
|
|
||||||
- Modify: `web/src/views/scripts/useTravelReimbursementSubmitComposer.js`
|
|
||||||
- Modify remaining files reported by `web/tests/code-size-limits.test.mjs`
|
|
||||||
- Create focused modules beside the existing owners under `web/src/views/scripts/`, `web/src/components/`, `web/src/composables/`, and `web/src/utils/`
|
|
||||||
|
|
||||||
- [ ] **Step 1: Split pure helpers before stateful runtime code**
|
|
||||||
|
|
||||||
Extract pure formatting, payload normalization, label mapping, row building, and text rendering helpers. This reduces file size without changing component state ownership.
|
|
||||||
|
|
||||||
- [ ] **Step 2: Split composables and child components**
|
|
||||||
|
|
||||||
For Vue files, move stable repeated UI blocks into child components only when props/events are clear. For script modules, move independent computed builders and action helpers into colocated modules.
|
|
||||||
|
|
||||||
- [ ] **Step 3: Remove proven redundant frontend code**
|
|
||||||
|
|
||||||
Use `rg` to confirm an export, class, helper, CSS hook, or branch is unused before deleting it. If a usage is dynamic, keep it unless a regression test proves it is dead.
|
|
||||||
|
|
||||||
- [ ] **Step 4: Verify frontend source limit**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
node --test web/tests/code-size-limits.test.mjs
|
|
||||||
```
|
|
||||||
|
|
||||||
Expected final result: PASS.
|
|
||||||
|
|
||||||
- [ ] **Step 5: Run targeted frontend regression tests**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
node --test web/tests/workbench-ai-mode-switch.test.mjs web/tests/expense-application-fast-preview.test.mjs web/tests/expense-profile-detail-modal.test.mjs web/tests/finance-dashboard-ranking.test.mjs
|
|
||||||
npm --prefix web run build
|
|
||||||
```
|
|
||||||
|
|
||||||
Expected final result: PASS.
|
|
||||||
|
|
||||||
|
|
||||||
### Task 4: Performance And Cleanup Pass
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify only files already touched by Tasks 2 and 3 unless a usage check proves a separate dead module can be removed.
|
|
||||||
|
|
||||||
- [ ] **Step 1: Remove repeated computation inside hot paths**
|
|
||||||
|
|
||||||
Cache local computed values inside functions, avoid repeated JSON/string/date parsing loops, and prefer early returns for blocked states.
|
|
||||||
|
|
||||||
- [ ] **Step 2: Delete redundant private helpers**
|
|
||||||
|
|
||||||
Delete helpers only when all of these checks are true:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
rg "helperName" server web
|
|
||||||
node --test affected-web-test.mjs
|
|
||||||
docker exec -w /app -e SERVER_VENV_DIR=/tmp/x-financial-server-venv x-financial-main /tmp/x-financial-server-venv/bin/pytest -q affected_server_test.py
|
|
||||||
```
|
|
||||||
|
|
||||||
- [ ] **Step 3: Final verification**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
node --test web/tests/code-size-limits.test.mjs
|
|
||||||
docker exec -w /app -e SERVER_VENV_DIR=/tmp/x-financial-server-venv x-financial-main /tmp/x-financial-server-venv/bin/pytest -q server/tests/test_code_size_limits.py
|
|
||||||
npm --prefix web run build
|
|
||||||
```
|
|
||||||
|
|
||||||
Expected final result: PASS.
|
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
# 附件自动关联后台任务实施计划
|
||||||
|
|
||||||
|
## 目标
|
||||||
|
|
||||||
|
把小财管家 AI 模式里的附件关联从前端会话内存任务改为后端可查询后台任务,保证用户退出或刷新当前会话后,附件关联仍能继续完成并可恢复状态。
|
||||||
|
|
||||||
|
## 执行清单
|
||||||
|
|
||||||
|
- [x] 定位当前断链根因:前端依赖 `File` 对象和内存 `Map`。
|
||||||
|
- [x] 确认票据夹已有 `receipt_id`、源文件和关联状态能力。
|
||||||
|
- [x] 落开发方案文档。
|
||||||
|
- [x] 实现后端任务 schema 和内存任务池。
|
||||||
|
- [x] 实现后端任务 API。
|
||||||
|
- [x] 实现后端票据夹源文件归集到报销单明细。
|
||||||
|
- [x] 增加后端测试。
|
||||||
|
- [x] 实现前端任务创建、轮询和恢复。
|
||||||
|
- [x] 增加前端测试断言。
|
||||||
|
- [x] 执行容器后端定向测试。
|
||||||
|
- [x] 执行前端定向测试和构建。
|
||||||
|
|
||||||
|
## 验证结果
|
||||||
|
|
||||||
|
- 后端定向测试:`6 passed`
|
||||||
|
- 前端定向测试:`12 passed`
|
||||||
|
- 前端构建:通过,保留既有 chunk size warning。
|
||||||
|
- 运行时检查:新任务查询路由已加载,未知任务返回“附件关联任务不存在或已失效。”
|
||||||
|
|
||||||
|
## 关键决策
|
||||||
|
|
||||||
|
- 第一版使用后端内存任务池和 FastAPI `BackgroundTasks`,解决前端会话断链。
|
||||||
|
- 第一版不新增数据库任务表,服务重启后的任务恢复作为后续增强。
|
||||||
|
- 前端消息只保存 `job_id`、状态和票据引用,不再保存附件原件。
|
||||||
@@ -1,410 +0,0 @@
|
|||||||
# X-Financial Duplicate Code Refactor Plan
|
|
||||||
|
|
||||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development or superpowers:executing-plans for multi-task execution. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
||||||
|
|
||||||
**Goal:** Reduce duplicated business logic, renderer helpers, protocol constants, and test fixtures without changing existing behavior.
|
|
||||||
|
|
||||||
**Architecture:** Start with low-risk pure helpers, then move toward business contract consolidation. Each round must add or preserve regression tests before production code changes, and backend validation must run inside `x-financial-main`.
|
|
||||||
|
|
||||||
**Tech Stack:** Vue 3, Vite, Node test runner, FastAPI, SQLAlchemy, pytest, Docker Compose.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Scope
|
|
||||||
|
|
||||||
This document records the duplicate-code audit from 2026-06-23 and defines a staged cleanup path. The first implementation slice is intentionally small: extract shared frontend conversation rendering helpers used by `markdown.js` and `aiConversationHtmlRenderer.js`.
|
|
||||||
|
|
||||||
The following areas are in scope:
|
|
||||||
|
|
||||||
- Frontend AI markdown / HTML trusted block normalization.
|
|
||||||
- Frontend reimbursement review panel model duplication.
|
|
||||||
- Workbench AI composer / attachment strip duplication.
|
|
||||||
- Backend application gate, fact extraction, amount/date/location parsing.
|
|
||||||
- Backend platform risk context helper duplication.
|
|
||||||
- Cross-layer status, expense type, document type, and risk-level taxonomy drift.
|
|
||||||
- Test helper duplication for DB sessions, FastAPI client overrides, and OCR fakes.
|
|
||||||
|
|
||||||
The following areas are out of scope for the first implementation slice:
|
|
||||||
|
|
||||||
- Changing application submission behavior.
|
|
||||||
- Changing reimbursement association decision flow.
|
|
||||||
- Changing API response shapes.
|
|
||||||
- Editing unrelated notification top bar changes already present in the worktree.
|
|
||||||
|
|
||||||
## Findings
|
|
||||||
|
|
||||||
### P0: Frontend Trusted HTML And Conversation Text Helpers
|
|
||||||
|
|
||||||
`web/src/utils/markdown.js` and `web/src/utils/aiConversationHtmlRenderer.js` both implement:
|
|
||||||
|
|
||||||
- `ALLOWED_COLON_HEADING_TITLES`
|
|
||||||
- `BUSINESS_FIELD_LABELS`
|
|
||||||
- `TRUSTED_HTML_ALLOWED_TAGS`
|
|
||||||
- `TRUSTED_HTML_ALLOWED_ATTRS`
|
|
||||||
- `splitColonHeadingLine`
|
|
||||||
- `normalizeBusinessFieldLine`
|
|
||||||
- `hasOnlyTrustedHtmlTags`
|
|
||||||
- `sanitizeTrustedHtmlBlock`
|
|
||||||
- `extractTrustedHtmlBlocks`
|
|
||||||
- `restoreTrustedHtmlBlocks`
|
|
||||||
|
|
||||||
Plan:
|
|
||||||
|
|
||||||
- [x] Create `web/src/utils/conversationTrustedHtml.js`.
|
|
||||||
- [x] Move trusted HTML sanitizing and business-line normalization into the helper.
|
|
||||||
- [x] Keep renderer-specific output differences in each renderer.
|
|
||||||
- [x] Verify both markdown and AI conversation renderers still preserve valid trusted document cards and reject unsafe trusted HTML.
|
|
||||||
|
|
||||||
Expected benefit:
|
|
||||||
|
|
||||||
- One XSS whitelist.
|
|
||||||
- One business field normalization rule.
|
|
||||||
- Less drift between AI workbench and reimbursement assistant rendering.
|
|
||||||
|
|
||||||
### P0: Reimbursement Review Panel Model Duplication
|
|
||||||
|
|
||||||
`web/src/views/scripts/travelReimbursementCreateReviewModel.js` and `web/src/views/scripts/travelReimbursementReviewPanelModel.js` duplicate review scope, fact cards, risk item mapping, risk conversation text, and message cleanup.
|
|
||||||
|
|
||||||
Plan:
|
|
||||||
|
|
||||||
- [x] Choose `travelReimbursementReviewPanelModel.js` as the shared model.
|
|
||||||
- [x] Convert create-view imports to the shared model, or make the create-view module a thin compatibility re-export.
|
|
||||||
- [x] Add behavior tests for exported review helpers before deleting duplicate code.
|
|
||||||
|
|
||||||
Expected benefit:
|
|
||||||
|
|
||||||
- One risk item mapping.
|
|
||||||
- One review fact card model.
|
|
||||||
- Lower risk when changing reimbursement review copy or drawer behavior.
|
|
||||||
|
|
||||||
### P0: Workbench AI Composer And File Strip Template Duplication
|
|
||||||
|
|
||||||
`web/src/components/business/PersonalWorkbenchAiMode.template.html` keeps two near-identical composer forms and two near-identical selected-file strips for the welcome and inline conversation states. `web/src/components/business/workbench-ai/WorkbenchAiComposer.vue` and `web/src/components/business/workbench-ai/WorkbenchAiFileStrip.vue` already exist, but the main template still duplicates the markup.
|
|
||||||
|
|
||||||
Plan:
|
|
||||||
|
|
||||||
- [x] Reuse `WorkbenchAiComposer.vue` for both welcome and inline composer surfaces.
|
|
||||||
- [x] Reuse `WorkbenchAiFileStrip.vue` for both welcome and inline selected-file strips.
|
|
||||||
- [x] Keep the parent runtime API stable by passing a proxied runtime object into shared components.
|
|
||||||
- [x] Preserve OCR state display in the shared file-strip component.
|
|
||||||
- [x] Keep input focus behavior by exposing an explicit assistant input ref setter.
|
|
||||||
|
|
||||||
Expected benefit:
|
|
||||||
|
|
||||||
- One composer markup surface.
|
|
||||||
- One selected-file/OCR badge markup surface.
|
|
||||||
- Lower maintenance cost when upload, date picker, lock state, or send-button behavior changes.
|
|
||||||
|
|
||||||
### P1: Application Gate And Fact Extraction
|
|
||||||
|
|
||||||
Backend application flow repeats checks across `user_agent_application.py`, `steward_planner.py`, `orchestrator.py`, `ontology_detection.py`, and `ontology_extraction.py`.
|
|
||||||
|
|
||||||
Plan:
|
|
||||||
|
|
||||||
- [ ] Extract application intent / context gate helpers.
|
|
||||||
- [ ] Extract application fact resolver for date, location, reason, amount, transport, and expense type.
|
|
||||||
- [ ] Route UserAgent, StewardPlanner, and Orchestrator through the same helpers.
|
|
||||||
- [ ] Preserve existing application vs reimbursement stage boundaries.
|
|
||||||
|
|
||||||
Expected benefit:
|
|
||||||
|
|
||||||
- Fewer mismatches between button actions and text-input actions.
|
|
||||||
- Less chance of direct submit re-entering slow `/orchestrator/run` paths.
|
|
||||||
- More consistent missing-field prompts.
|
|
||||||
|
|
||||||
### P1: Backend Parsing And Risk Context Utilities
|
|
||||||
|
|
||||||
Several backend modules repeat city extraction, document field lookup, item-id dedupe, Decimal conversion, endpoint normalization, and JSON error parsing.
|
|
||||||
|
|
||||||
Plan:
|
|
||||||
|
|
||||||
- [ ] Extract platform risk context helpers for item-id and document field utilities.
|
|
||||||
- [ ] Reuse existing amount utilities before adding new regex parsing.
|
|
||||||
- [ ] Share model connectivity URL/header/error helpers between RAG runtime and connectivity checks.
|
|
||||||
- [ ] Cache sorted travel-policy city names per policy snapshot.
|
|
||||||
|
|
||||||
Expected benefit:
|
|
||||||
|
|
||||||
- Less CPU churn in repeated risk/OCR loops.
|
|
||||||
- Fewer provider connectivity behavior differences.
|
|
||||||
- Easier review of platform-risk regressions.
|
|
||||||
|
|
||||||
### P1: Cross-Layer Taxonomy And Protocol Constants
|
|
||||||
|
|
||||||
Status labels, expense types, document types, risk levels, API paths, and snake_case/camelCase mappings are repeated across backend schemas, frontend services, and tests.
|
|
||||||
|
|
||||||
Plan:
|
|
||||||
|
|
||||||
- [ ] Establish read-only contract baseline from OpenAPI export.
|
|
||||||
- [ ] Export status / approval-stage registry to frontend constants.
|
|
||||||
- [ ] Consolidate expense type, document type, and risk-level taxonomy.
|
|
||||||
- [ ] Move high-churn API path and payload builders into shared frontend test helpers.
|
|
||||||
|
|
||||||
Expected benefit:
|
|
||||||
|
|
||||||
- Fewer display inconsistencies.
|
|
||||||
- Easier API evolution.
|
|
||||||
- Less brittle source-string tests.
|
|
||||||
|
|
||||||
### P2: Test Fixture Duplication
|
|
||||||
|
|
||||||
`server/tests` repeatedly defines `build_session`, `build_session_factory`, `override_db`, `build_client`, and OCR fake functions.
|
|
||||||
|
|
||||||
Plan:
|
|
||||||
|
|
||||||
- [ ] Add backend test fixtures in `server/tests/conftest.py`.
|
|
||||||
- [ ] Move OCR fake builders into a small test helper.
|
|
||||||
- [ ] Migrate tests in batches, one behavior area at a time.
|
|
||||||
|
|
||||||
Expected benefit:
|
|
||||||
|
|
||||||
- Less boilerplate in large test files.
|
|
||||||
- Easier targeted regression coverage before service refactors.
|
|
||||||
|
|
||||||
## First Slice Execution Plan
|
|
||||||
|
|
||||||
### Task 1: Lock Shared Renderer Helper Behavior
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
|
|
||||||
- Create: `web/tests/conversation-trusted-html.test.mjs`
|
|
||||||
- Create: `web/src/utils/conversationTrustedHtml.js`
|
|
||||||
- Modify: `web/src/utils/markdown.js`
|
|
||||||
- Modify: `web/src/utils/aiConversationHtmlRenderer.js`
|
|
||||||
|
|
||||||
Steps:
|
|
||||||
|
|
||||||
- [x] Add a failing Node test that imports `conversationTrustedHtml.js`.
|
|
||||||
- [x] Assert valid trusted document-card HTML is preserved through placeholder extraction and restore.
|
|
||||||
- [x] Assert unsafe tags, event handlers, and non-document hrefs are rejected.
|
|
||||||
- [x] Assert colon headings and business field lines normalize outside fenced code blocks.
|
|
||||||
- [x] Run the new test and confirm it fails because the helper does not exist.
|
|
||||||
- [x] Implement the helper with pure functions only.
|
|
||||||
- [x] Refactor both renderers to use the helper.
|
|
||||||
- [x] Run targeted renderer tests.
|
|
||||||
- [x] Run `npm --prefix web run build`.
|
|
||||||
|
|
||||||
Validation commands:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
node --test web/tests/conversation-trusted-html.test.mjs
|
|
||||||
node --test web/tests/ai-conversation-html-renderer.test.mjs web/tests/travel-reimbursement-review-drawer-switch.test.mjs
|
|
||||||
npm --prefix web run build
|
|
||||||
```
|
|
||||||
|
|
||||||
## Third Slice Execution Plan
|
|
||||||
|
|
||||||
### Task 3: Reuse Workbench AI Composer Components
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
|
|
||||||
- Create: `web/tests/workbench-ai-composer-components.test.mjs`
|
|
||||||
- Modify: `web/src/components/business/PersonalWorkbenchAiMode.vue`
|
|
||||||
- Modify: `web/src/components/business/PersonalWorkbenchAiMode.template.html`
|
|
||||||
- Modify: `web/src/components/business/workbench-ai/WorkbenchAiFileStrip.vue`
|
|
||||||
- Modify: `web/src/composables/workbenchAiMode/usePersonalWorkbenchAiMode.js`
|
|
||||||
|
|
||||||
Steps:
|
|
||||||
|
|
||||||
- [x] Add a failing Node test that expects the main template to use `WorkbenchAiComposer` and `WorkbenchAiFileStrip`.
|
|
||||||
- [x] Assert the shared file strip preserves OCR state badges.
|
|
||||||
- [x] Assert the runtime exposes an input ref setter for the shared composer.
|
|
||||||
- [x] Run the new test and confirm it fails on the duplicated template.
|
|
||||||
- [x] Pass a proxied runtime object from `PersonalWorkbenchAiMode.vue` into shared components.
|
|
||||||
- [x] Replace duplicate composer and file-strip markup in the external template.
|
|
||||||
- [x] Add OCR badge markup to `WorkbenchAiFileStrip.vue`.
|
|
||||||
- [x] Run targeted workbench AI tests.
|
|
||||||
- [x] Run `npm --prefix web run build`.
|
|
||||||
|
|
||||||
Validation commands:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
node --test web/tests/workbench-ai-composer-components.test.mjs
|
|
||||||
node --test web/tests/workbench-ai-composer-components.test.mjs web/tests/workbench-ai-mode-switch.test.mjs web/tests/workbench-ai-mode-expense-scene-action.test.mjs
|
|
||||||
npm --prefix web run build
|
|
||||||
```
|
|
||||||
|
|
||||||
## Remaining Execution Plan
|
|
||||||
|
|
||||||
The remaining work is intentionally split into bounded slices. Each slice extracts shared code without changing user-facing flow, API response shape, or submission semantics.
|
|
||||||
|
|
||||||
### Task 4: Frontend Application Gate Helpers
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
|
|
||||||
- Create: `web/src/composables/workbenchAiMode/workbenchAiApplicationGateModel.js`
|
|
||||||
- Create: `web/tests/workbench-ai-application-gate-model.test.mjs`
|
|
||||||
- Modify: `web/src/composables/workbenchAiMode/usePersonalWorkbenchAiMode.js`
|
|
||||||
- Modify: `web/src/composables/workbenchAiMode/useWorkbenchAiApplicationPreviewFlow.js`
|
|
||||||
|
|
||||||
Steps:
|
|
||||||
|
|
||||||
- [x] Add a failing Node test for reimbursement creation intent, submit/save text action resolution, and orphan preview detection.
|
|
||||||
- [x] Move pure gate predicates into `workbenchAiApplicationGateModel.js`.
|
|
||||||
- [x] Replace inline copies in personal workbench and application-preview flow.
|
|
||||||
- [x] Run targeted workbench AI application tests.
|
|
||||||
|
|
||||||
Validation commands:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
node --test web/tests/workbench-ai-application-gate-model.test.mjs
|
|
||||||
node --test web/tests/workbench-ai-application-gate-model.test.mjs web/tests/workbench-ai-mode-switch.test.mjs web/tests/workbench-ai-action-router.test.mjs
|
|
||||||
```
|
|
||||||
|
|
||||||
### Task 5: Backend Application Fact Resolver
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
|
|
||||||
- Create: `server/src/app/services/application_fact_resolver.py`
|
|
||||||
- Create: `server/tests/test_application_fact_resolver.py`
|
|
||||||
- Modify: `server/src/app/services/steward_planner.py`
|
|
||||||
|
|
||||||
Steps:
|
|
||||||
|
|
||||||
- [x] Add failing pytest coverage for time, location, reason, transport, and task-type inference.
|
|
||||||
- [x] Extract pure resolver helpers that preserve existing planner output.
|
|
||||||
- [x] Route `StewardPlannerService` extraction wrappers through the resolver.
|
|
||||||
- [x] Run targeted planner/fact tests inside the active app container.
|
|
||||||
|
|
||||||
Validation commands:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker exec -w /app -e SERVER_VENV_DIR=/tmp/x-financial-server-venv x-financial-main /tmp/x-financial-server-venv/bin/pytest -q server/tests/test_application_fact_resolver.py server/tests/test_steward_planner.py
|
|
||||||
```
|
|
||||||
|
|
||||||
### Task 6: Backend Platform Risk Context Utilities
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
|
|
||||||
- Modify: `server/src/app/services/expense_claim_platform_context_tools.py`
|
|
||||||
- Create: `server/tests/test_expense_claim_platform_context_tools.py`
|
|
||||||
- Modify: `server/src/app/services/expense_claim_platform_route_risk.py`
|
|
||||||
- Modify: `server/src/app/services/expense_claim_platform_risk.py`
|
|
||||||
|
|
||||||
Steps:
|
|
||||||
|
|
||||||
- [x] Add failing pytest coverage for context city extraction, item-id dedupe, and text-value dedupe helpers.
|
|
||||||
- [x] Add pure helper functions in `expense_claim_platform_context_tools.py`.
|
|
||||||
- [x] Route route-risk and platform-risk consumers through the shared helpers.
|
|
||||||
- [x] Run targeted platform-risk tests inside the active app container.
|
|
||||||
|
|
||||||
Validation commands:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker exec -w /app -e SERVER_VENV_DIR=/tmp/x-financial-server-venv x-financial-main /tmp/x-financial-server-venv/bin/pytest -q server/tests/test_expense_claim_platform_context_tools.py server/tests/test_expense_claim_platform_risk_stage.py
|
|
||||||
```
|
|
||||||
|
|
||||||
### Task 7: Frontend Protocol Constants And Test Helpers
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
|
|
||||||
- Create: `web/src/constants/documentProtocol.js`
|
|
||||||
- Create: `web/tests/helpers/sourceSurface.mjs`
|
|
||||||
- Create: `web/tests/document-protocol-constants.test.mjs`
|
|
||||||
- Modify: `web/src/composables/workbenchAiMode/workbenchAiApplicationPreviewModel.js`
|
|
||||||
- Migrate one high-churn source-surface test to the helper.
|
|
||||||
|
|
||||||
Steps:
|
|
||||||
|
|
||||||
- [x] Add failing Node tests for status labels, document type constants, and reusable source-surface loading.
|
|
||||||
- [x] Move duplicated status labels into `documentProtocol.js`.
|
|
||||||
- [x] Reuse constants in application-preview model and request/document-center model code.
|
|
||||||
- [x] Migrate one source-surface test helper to reduce brittle boilerplate.
|
|
||||||
|
|
||||||
Validation commands:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
node --test web/tests/document-protocol-constants.test.mjs web/tests/workbench-ai-mode-switch.test.mjs
|
|
||||||
```
|
|
||||||
|
|
||||||
### Task 8: Backend Test Fixture Consolidation
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
|
|
||||||
- Create: `server/src/app/test_helpers/db.py`
|
|
||||||
- Create: `server/src/app/test_helpers/__init__.py`
|
|
||||||
- Create: `server/tests/test_db_test_helpers.py`
|
|
||||||
- Modify: `server/tests/test_expense_claim_platform_risk_stage.py`
|
|
||||||
|
|
||||||
Steps:
|
|
||||||
|
|
||||||
- [x] Identify an existing small test file with duplicated session/client/OCR helpers.
|
|
||||||
- [x] Add shared DB helper while preserving its current behavior.
|
|
||||||
- [x] Migrate one test file only.
|
|
||||||
- [x] Run the migrated test plus adjacent coverage inside the active app container.
|
|
||||||
|
|
||||||
Validation commands:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker exec -w /app -e SERVER_VENV_DIR=/tmp/x-financial-server-venv x-financial-main /tmp/x-financial-server-venv/bin/pytest -q server/tests/test_db_test_helpers.py server/tests/test_expense_claim_platform_risk_stage.py
|
|
||||||
```
|
|
||||||
|
|
||||||
### Task 9: Steward Planner Module Split
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
|
|
||||||
- Create: `server/src/app/services/steward_planner_shared.py`
|
|
||||||
- Create: `server/src/app/services/steward_planner_fallback.py`
|
|
||||||
- Create: `server/src/app/services/steward_planner_extraction.py`
|
|
||||||
- Modify: `server/src/app/services/steward_planner.py`
|
|
||||||
|
|
||||||
Steps:
|
|
||||||
|
|
||||||
- [x] Move shared constants and `PlannedTaskDraft` into a shared planner module.
|
|
||||||
- [x] Move off-topic, pending-flow, and rule-fallback planning into `steward_planner_fallback.py`.
|
|
||||||
- [x] Move task extraction, ontology normalization, attachment grouping, and summary helpers into `steward_planner_extraction.py`.
|
|
||||||
- [x] Keep `steward_planner.py` as the service orchestration entrypoint.
|
|
||||||
- [x] Run planner/fact resolver tests inside the active app container.
|
|
||||||
|
|
||||||
Validation commands:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker exec -w /app -e SERVER_VENV_DIR=/tmp/x-financial-server-venv x-financial-main /tmp/x-financial-server-venv/bin/pytest -q server/tests/test_application_fact_resolver.py server/tests/test_steward_planner.py
|
|
||||||
```
|
|
||||||
|
|
||||||
### Task 10: App Shell Dynamic Business Chunk Loading
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
|
|
||||||
- Create: `web/src/views/scripts/appShellAsyncViews.js`
|
|
||||||
- Create: `web/src/components/shared/AppViewLoadingState.vue`
|
|
||||||
- Create: `web/src/components/shared/AppModalLoadingState.vue`
|
|
||||||
- Modify: `web/src/views/AppShellRouteView.vue`
|
|
||||||
- Modify: `web/src/components/layout/SidebarRail.vue`
|
|
||||||
- Modify: `web/src/components/layout/AiSidebarRail.vue`
|
|
||||||
- Modify: `web/tests/app-shell-route-loading.test.mjs`
|
|
||||||
- Modify: `web/tests/ai-sidebar-rail-mode.test.mjs`
|
|
||||||
|
|
||||||
Steps:
|
|
||||||
|
|
||||||
- [x] Keep top-level shell routes eager so login/setup/app layout does not blank during route navigation.
|
|
||||||
- [x] Move heavy business views behind `defineAsyncComponent` loaders.
|
|
||||||
- [x] Add an in-workarea loading state for slow business chunks.
|
|
||||||
- [x] Add a modal loading state for the smart reimbursement assistant chunk.
|
|
||||||
- [x] Preload likely next views on sidebar hover/focus and during browser idle time.
|
|
||||||
- [x] Preserve existing Vite manual vendor chunks, including `vendor-echarts`.
|
|
||||||
- [x] Run targeted frontend tests and production build.
|
|
||||||
|
|
||||||
Validation commands:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
node --test web/tests/app-shell-route-loading.test.mjs web/tests/ai-sidebar-rail-mode.test.mjs web/tests/sidebar-document-unread-dot.test.mjs web/tests/workbench-ai-mode-switch.test.mjs web/tests/workbench-ai-reimbursement-association-gate.test.mjs web/tests/travel-reimbursement-review-drawer-switch.test.mjs web/tests/documents-center-status-filter.test.mjs
|
|
||||||
npm --prefix web run build
|
|
||||||
```
|
|
||||||
|
|
||||||
Result:
|
|
||||||
|
|
||||||
- App shell entry chunk after split: `index-vWyUfHfm.js` 223.75 kB, gzip 74.11 kB.
|
|
||||||
- Large `vendor-echarts` chunk remains isolated at 598.67 kB, gzip 204.84 kB; it is no longer part of the app-shell entry chunk.
|
|
||||||
- Build still reports the existing Rollup `#__PURE__` annotation warnings from Element Plus / VueUse.
|
|
||||||
|
|
||||||
## Guardrails
|
|
||||||
|
|
||||||
- Do not touch unrelated dirty files.
|
|
||||||
- Do not change renderer output intentionally in this slice.
|
|
||||||
- Do not move backend logic until frontend helper extraction is green.
|
|
||||||
- Backend tests must run through Docker:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker exec -w /app -e SERVER_VENV_DIR=/tmp/x-financial-server-venv x-financial-main /tmp/x-financial-server-venv/bin/pytest -q <path>
|
|
||||||
```
|
|
||||||
|
Before Width: | Height: | Size: 148 KiB |
@@ -0,0 +1,144 @@
|
|||||||
|
# 附件自动关联后台任务方案
|
||||||
|
|
||||||
|
## 背景
|
||||||
|
|
||||||
|
小财管家 AI 模式里,用户上传票据后会先做 OCR。当前附件自动关联报销草稿的后半段仍依赖前端会话内存:
|
||||||
|
|
||||||
|
- 前端保留浏览器里的 `File` 对象。
|
||||||
|
- 前端在当前会话里完成草稿匹配。
|
||||||
|
- 用户点击“确认自动关联”后,再用这些 `File` 上传到报销单明细。
|
||||||
|
|
||||||
|
这会带来一个核心问题:用户发送消息后,如果刷新页面、切换会话或退出当前会话,浏览器内存里的附件原件会丢失,历史消息中的关联动作就无法继续执行。
|
||||||
|
|
||||||
|
票据夹已经能持久化 OCR 结果和源文件,并且 OCR 返回里已经带有 `receipt_id`。所以正式方案应该把“附件关联”从前端内存任务调整为后端可查询任务。
|
||||||
|
|
||||||
|
## 目标
|
||||||
|
|
||||||
|
1. 用户一上传附件即触发 OCR,附件卡片显示“识别中”,识别完成后显示“当前附件已识别”。
|
||||||
|
2. 用户点击发送后,前端不再依赖 `File` 原件做后续归集,而是把 OCR 产生的 `receipt_id` 提交给后端。
|
||||||
|
3. 后端创建附件关联任务,并在后台继续匹配、复制票据夹源文件、关联报销单明细。
|
||||||
|
4. 用户退出或刷新当前会话后,前端可通过保存下来的 `job_id` 查询任务状态并更新消息。
|
||||||
|
5. 如果匹配失败、置信度不足或找不到可编辑草稿,系统给出清晰提示,引导用户补充说明、上传附件或新建草稿。
|
||||||
|
|
||||||
|
## 非目标
|
||||||
|
|
||||||
|
第一版不承诺后端服务进程重启后任务状态仍可恢复。
|
||||||
|
|
||||||
|
本次实现使用轻量内存任务池,解决“用户离开前端会话导致连接断开”的问题。后续如果要做到服务重启、横向扩容、任务审计都可恢复,再新增数据库任务表。
|
||||||
|
|
||||||
|
## 核心流程
|
||||||
|
|
||||||
|
```text
|
||||||
|
用户上传票据
|
||||||
|
→ 前端立即调用 OCR
|
||||||
|
→ OCR 写入票据夹并返回 receipt_id
|
||||||
|
→ 附件卡片显示“当前附件已识别”
|
||||||
|
→ 用户点击发送
|
||||||
|
→ 前端 POST 创建附件关联任务
|
||||||
|
→ 后端后台任务继续运行
|
||||||
|
→ 前端轮询 job_id
|
||||||
|
→ 成功:消息显示已关联,并刷新报销单详情
|
||||||
|
→ 失败:消息显示失败原因和下一步动作
|
||||||
|
```
|
||||||
|
|
||||||
|
## 后端设计
|
||||||
|
|
||||||
|
### API
|
||||||
|
|
||||||
|
新增接口:
|
||||||
|
|
||||||
|
- `POST /api/v1/reimbursements/attachment-association-jobs`
|
||||||
|
- `GET /api/v1/reimbursements/attachment-association-jobs/{job_id}`
|
||||||
|
|
||||||
|
创建任务请求只传持久化引用,不传浏览器文件:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"receipt_ids": ["receipt-1", "receipt-2"],
|
||||||
|
"prompt": "请帮我处理已上传的附件。",
|
||||||
|
"conversation_id": "inline-xxx"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
状态返回:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"job_id": "job-xxx",
|
||||||
|
"status": "running",
|
||||||
|
"message": "正在匹配可关联的报销草稿...",
|
||||||
|
"receipt_ids": ["receipt-1", "receipt-2"],
|
||||||
|
"claim_id": "",
|
||||||
|
"claim_no": "",
|
||||||
|
"uploaded_count": 0,
|
||||||
|
"skipped_count": 0,
|
||||||
|
"error": ""
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
状态枚举:
|
||||||
|
|
||||||
|
- `queued`:任务已创建,等待后台执行。
|
||||||
|
- `running`:正在匹配和归集。
|
||||||
|
- `succeeded`:已完成自动归集。
|
||||||
|
- `failed`:无法自动完成,返回可读错误。
|
||||||
|
|
||||||
|
### 任务执行
|
||||||
|
|
||||||
|
后端任务执行步骤:
|
||||||
|
|
||||||
|
1. 按 `receipt_ids` 读取票据夹明细和源文件。
|
||||||
|
2. 从票据 OCR 文本、结构化字段、日期、城市提取匹配信号。
|
||||||
|
3. 查询当前用户可见且可编辑的报销草稿,排除申请单和已归档单据。
|
||||||
|
4. 对候选草稿按日期、城市、事由、草稿状态评分。
|
||||||
|
5. 置信度足够时选择目标草稿。
|
||||||
|
6. 为每份票据找到可用费用明细,没有合适明细时创建空明细。
|
||||||
|
7. 从票据夹源文件复制到报销单附件目录,并沿用 `source_receipt_id` 回填 OCR 信息。
|
||||||
|
8. 更新票据夹状态为 `linked`。
|
||||||
|
9. 写入任务最终状态。
|
||||||
|
|
||||||
|
## 前端设计
|
||||||
|
|
||||||
|
### 会话消息
|
||||||
|
|
||||||
|
AI 消息需要持久化 `attachmentAssociationJob`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"jobId": "job-xxx",
|
||||||
|
"status": "running",
|
||||||
|
"receiptIds": ["receipt-1", "receipt-2"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
这样历史会话恢复后,不再需要浏览器里的 `File` 对象,只要消息里仍有 `jobId`,就可以继续查询后端状态。
|
||||||
|
|
||||||
|
### 发送行为
|
||||||
|
|
||||||
|
当用户上传附件并点击发送:
|
||||||
|
|
||||||
|
1. 前端确认 OCR 已完成。
|
||||||
|
2. 从 OCR 结果里提取 `receipt_id`。
|
||||||
|
3. 创建后端任务。
|
||||||
|
4. 立即持久化带 `job_id` 的 pending 消息。
|
||||||
|
5. 页面仍打开时轮询任务状态。
|
||||||
|
6. 页面恢复或打开历史会话时,对未完成任务继续轮询。
|
||||||
|
|
||||||
|
## 异常处理
|
||||||
|
|
||||||
|
- 未完成 OCR:禁止发送,提示“附件 OCR 识别中,请稍等,识别完成后再继续对话。”
|
||||||
|
- OCR 失败:禁止发送,提示“请先移除识别失败的附件或重新上传。”
|
||||||
|
- 没有 `receipt_id`:提示“当前附件没有持久化票据记录,请重新上传后再试。”
|
||||||
|
- 没有可编辑草稿:任务失败,提示用户先新建或选择草稿。
|
||||||
|
- 多个候选置信度接近:第一版不自动归集,提示补充说明或手动选择。
|
||||||
|
- 服务重启导致内存任务丢失:返回任务不存在,前端提示“后台任务状态已失效,请重新发送附件关联请求。”
|
||||||
|
|
||||||
|
## 验收标准
|
||||||
|
|
||||||
|
1. 上传附件后必须先进入 OCR 识别中状态,识别完成前不能发送对话。
|
||||||
|
2. 发送附件关联请求后,前端能收到并保存 `job_id`。
|
||||||
|
3. 用户离开当前会话后,后端任务仍会继续执行。
|
||||||
|
4. 用户回到历史会话后,前端可以根据 `job_id` 查询并更新最终状态。
|
||||||
|
5. 成功后报销单明细出现附件,票据夹状态变为已关联。
|
||||||
|
6. 找不到草稿、低置信度、源文件缺失时,消息能给出明确原因。
|
||||||
|
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
# 附件自动关联后台任务 TODO
|
||||||
|
|
||||||
|
- [x] 梳理当前前端内存任务断链原因。
|
||||||
|
- [x] 明确第一版边界:页面/会话退出可恢复,服务进程重启暂不承诺恢复。
|
||||||
|
- [x] 新增后端任务 schema。
|
||||||
|
- [x] 新增后端后台任务服务。
|
||||||
|
- [x] 新增任务创建和查询接口。
|
||||||
|
- [x] 补后端任务测试。
|
||||||
|
- [x] 新增前端任务 service。
|
||||||
|
- [x] 调整 AI 模式附件关联流程为创建后端任务。
|
||||||
|
- [x] 持久化消息里的 `attachmentAssociationJob`。
|
||||||
|
- [x] 历史会话恢复时继续轮询未完成任务。
|
||||||
|
- [x] 更新前端源码断言测试。
|
||||||
|
- [x] 容器内运行后端定向测试。
|
||||||
|
- [x] 运行前端定向测试和构建。
|
||||||
|
|
||||||
|
## 验证记录
|
||||||
|
|
||||||
|
- `docker exec -w /app -e SERVER_VENV_DIR=/tmp/x-financial-server-venv x-financial-local-linux /tmp/x-financial-server-venv/bin/pytest -q server/tests/test_attachment_association_jobs.py server/tests/test_ocr_endpoints.py server/tests/test_reimbursement_endpoints.py::test_claim_item_attachment_upload_preview_and_delete server/tests/test_openapi_schema.py`
|
||||||
|
- `node --test web/tests/workbench-ai-mode-switch.test.mjs web/tests/ai-attachment-association-model.test.mjs`
|
||||||
|
- `npm --prefix web run build`
|
||||||
|
- 已重启 `x-financial-local-linux`,并确认 `/api/v1/reimbursements/attachment-association-jobs/not-exist` 返回自定义任务失效提示。
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
# 报销草稿分支动作收口 概念文档
|
||||||
|
|
||||||
|
更新时间:2026-06-23
|
||||||
|
|
||||||
|
## 功能一句话
|
||||||
|
|
||||||
|
当用户发起报销且系统命中可继续的报销草稿时,只提供“查看草稿、继续关联草稿、独立新建报销单”三个明确入口,让用户能看详情、补附件/说明,或确认另起一张新草稿。
|
||||||
|
|
||||||
|
## 背景与问题
|
||||||
|
|
||||||
|
- 当前现状:AI 工作台和报销助手在“我要报销”后会先查询可继续报销草稿;命中草稿时,当前按钮把“继续草稿”和“打开详情”混在一起,并把跳过草稿描述成“关联申请单新建报销单”。
|
||||||
|
- 用户痛点:按钮语义不清,用户无法判断点击“继续草稿”是打开详情、继续补附件,还是进入申请单关联。
|
||||||
|
- 业务影响:报销草稿与新建报销单的路径混杂,容易造成重复草稿、附件归集错误或用户误以为已继续处理。
|
||||||
|
- 为什么现在需要做:截图中的草稿分支是报销入口的第一屏决策,需要先把按钮数量、文案和后续状态固定下来,再继续开发。
|
||||||
|
|
||||||
|
## 目标与非目标
|
||||||
|
|
||||||
|
### 目标
|
||||||
|
|
||||||
|
- [G1] 命中可继续报销草稿时,快捷按钮固定为三个:查看草稿、继续关联草稿、独立新建报销单。
|
||||||
|
- [G2] “查看草稿”只负责跳转详情页,不承担继续上传或新建逻辑。
|
||||||
|
- [G3] “继续关联草稿”只负责把当前会话切到“等待上传附件或补充说明”的状态,并锁定目标草稿。
|
||||||
|
- [G4] “独立新建报销单”先提示用户确认是否新建草稿单据,再进入新草稿创建流程。
|
||||||
|
|
||||||
|
### 非目标
|
||||||
|
|
||||||
|
- [NG1] 本轮不改后端草稿保存、附件 OCR、风险审核和审批流规则。
|
||||||
|
- [NG2] 本轮不改变申请单关联命中时的“选择申请单 / 单独新建报销单”逻辑。
|
||||||
|
- [NG3] 本轮不重做报销助手整体 UI,只收口草稿命中态的按钮和动作流。
|
||||||
|
|
||||||
|
## 用户与场景
|
||||||
|
|
||||||
|
- 目标用户:普通员工在个人工作台 AI 模式或报销助手中发起报销。
|
||||||
|
- 使用入口:快捷操作“发起报销”、输入“我要报销 / 发起报销 / 新建报销”。
|
||||||
|
- 核心场景:
|
||||||
|
1. 系统查到可继续报销草稿,展示草稿卡片和三个按钮。
|
||||||
|
2. 用户点击“查看草稿”,打开对应单据详情页。
|
||||||
|
3. 用户点击“继续关联草稿”,系统提示上传相关附件或补充说明。
|
||||||
|
4. 用户点击“独立新建报销单”,系统询问是否新建草稿单据。
|
||||||
|
- 异常场景:
|
||||||
|
- 草稿缺少 `claim_id` 时,“查看草稿”和“继续关联草稿”不能提交无目标动作。
|
||||||
|
- 历史会话里的旧动作仍可兼容处理,不影响新生成提示。
|
||||||
|
|
||||||
|
## 功能能力
|
||||||
|
|
||||||
|
- [C1] 输入能力:读取报销草稿候选单据,识别 `claim_id`、`claim_no`、状态、金额、时间和事由。
|
||||||
|
- [C2] 处理能力:将草稿命中态动作拆成查看、继续关联、独立新建三条互斥分支。
|
||||||
|
- [C3] 输出能力:输出固定三按钮,并在点击后生成明确的用户回显和助手提示。
|
||||||
|
- [C4] 状态与权限:继续关联时记录目标草稿,后续上传附件或补充说明应围绕该草稿继续。
|
||||||
|
- [C5] 边界与降级:保留旧 `skip_reimbursement_draft_check` 动作兼容,避免历史会话按钮失效。
|
||||||
|
|
||||||
|
## 方案设计
|
||||||
|
|
||||||
|
### 前端
|
||||||
|
|
||||||
|
- 页面/组件:
|
||||||
|
- `travelReimbursementAssociationGateModel.js` 负责生成草稿命中态文案和三个动作。
|
||||||
|
- `useWorkbenchAiActionRouter.js` 负责个人工作台 AI 模式的动作分流。
|
||||||
|
- `useWorkbenchAiExpenseFlow.js` 负责个人工作台中的继续关联提示和独立新建确认提示。
|
||||||
|
- `useTravelReimbursementSuggestedActions.js` 负责报销助手页面中的相同动作分流。
|
||||||
|
- 交互状态:
|
||||||
|
- 查看草稿:沿用 `open_application_detail`,只跳转详情。
|
||||||
|
- 继续关联草稿:新增动作类型,点击后提示“请上传相关附件,或补充说明”,并记录目标草稿。
|
||||||
|
- 独立新建报销单:新增动作类型,点击后提示“是否新建草稿单据”,确认后进入现有单独新建流程。
|
||||||
|
- 展示规则:
|
||||||
|
- 草稿命中态只显示三个按钮,不再出现“继续草稿”或“不用草稿,关联申请单新建报销单”。
|
||||||
|
- 按钮文案携带草稿编号,方便用户辨认目标。
|
||||||
|
- 降级处理:
|
||||||
|
- 历史旧动作仍走原有分支。
|
||||||
|
- 缺少草稿 ID 时给出 toast,不继续进入无目标关联。
|
||||||
|
|
||||||
|
### 后端
|
||||||
|
|
||||||
|
- 接口/服务:当前不新增接口。
|
||||||
|
- 权限与校验:沿用现有详情页与草稿操作权限。
|
||||||
|
- 持久化:当前不改后端持久化结构。
|
||||||
|
- 降级处理:后续上传附件或保存草稿仍使用现有 orchestrator 与附件归集能力。
|
||||||
|
|
||||||
|
### 算法与规则
|
||||||
|
|
||||||
|
- 输入:已筛选出的报销草稿候选。
|
||||||
|
- 流程:按更新时间排序后取首个草稿作为三按钮默认目标;草稿卡片仍展示候选详情。
|
||||||
|
- 输出:三个动作对象及后续提示文案。
|
||||||
|
- 解释:本轮不是匹配算法改造,只是草稿命中后的动作语义收口。
|
||||||
|
|
||||||
|
### 数据与契约
|
||||||
|
|
||||||
|
- 核心字段:`claim_id`、`claim_no`、`original_message`、`draft_claim_id`、`selected_claim_no`。
|
||||||
|
- 状态枚举:新增前端动作类型 `continue_reimbursement_draft_association`、`create_standalone_reimbursement_draft`、`cancel_standalone_reimbursement_draft`。
|
||||||
|
- 兼容策略:保留 `open_application_detail` 和旧跳过动作分支。
|
||||||
|
- 版本/审计:通过前端测试锁定动作数量、文案和路由行为。
|
||||||
|
|
||||||
|
## 算法与公式
|
||||||
|
|
||||||
|
当前功能不涉及显式数学公式。
|
||||||
|
|
||||||
|
## 测试方案
|
||||||
|
|
||||||
|
后端:
|
||||||
|
|
||||||
|
- 当前不新增后端测试;本轮没有修改后端服务或接口。
|
||||||
|
|
||||||
|
前端:
|
||||||
|
|
||||||
|
- 扩展 `workbench-ai-reimbursement-association-gate.test.mjs`,验证草稿命中态只输出三个动作和新文案。
|
||||||
|
- 扩展 `workbench-ai-action-router.test.mjs`,验证继续关联、独立新建确认的路由行为。
|
||||||
|
- 扩展 `travel-reimbursement-guided-flow.test.mjs` 或既有报销助手动作测试,验证旧报销助手使用相同动作语义。
|
||||||
|
|
||||||
|
集成:
|
||||||
|
|
||||||
|
- 运行相关 Node 测试,确认 AI 工作台和报销助手入口没有回退到旧按钮。
|
||||||
|
|
||||||
|
手工验证:
|
||||||
|
|
||||||
|
- 在个人工作台 AI 模式输入“我要报销”,命中草稿后检查按钮数量和点击行为。
|
||||||
|
|
||||||
|
## 指标与验收
|
||||||
|
|
||||||
|
- [A1] 功能验收:草稿命中态固定显示三个按钮,且第一个按钮跳详情,第二个按钮提示上传附件/说明,第三个按钮提示是否新建草稿单据。
|
||||||
|
- [A2] 性能指标:不增加额外接口查询;仍复用一次单据列表查询。
|
||||||
|
- [A3] 质量指标:定向前端测试通过,旧动作兼容测试不失效。
|
||||||
|
- [A4] 安全/权限指标:不绕过详情页和草稿操作原有权限。
|
||||||
|
- [A5] 可观测性:对话消息中能看到用户选择了哪个分支。
|
||||||
|
|
||||||
|
## 风险与开放问题
|
||||||
|
|
||||||
|
- 风险:多个草稿同时命中时,三个按钮默认指向最新草稿;用户如需其他草稿,可先通过卡片查看信息后进入详情页处理。
|
||||||
|
- 风险:全量 `code-size-limits` 当前仍会被既有 `TopBar.vue:824` 阻断;本轮新增和修改的文件均已控制在 800 行内。
|
||||||
|
- 已处理依赖:复用现有详情页跳转、报销场景选择和草稿保存链路。
|
||||||
|
- 待确认:后续是否要在草稿卡片内为每张草稿提供独立按钮;本轮先按截图中的三按钮入口收口。
|
||||||
|
- 降级策略:旧历史会话按钮保持可点击,不强制迁移旧消息。
|
||||||
|
|
||||||
|
## 本轮实现记录
|
||||||
|
|
||||||
|
- 2026-06-23:先落本文档和 TODO,再按测试驱动修改前端草稿分支动作。
|
||||||
|
- 2026-06-23:新增 `travelReimbursementDraftBranchModel.js` 承载草稿三分支动作,避免继续放大 `travelReimbursementAssociationGateModel.js`。
|
||||||
|
- 2026-06-23:个人工作台和报销助手页面均已接入“继续关联草稿”和“独立新建报销单”的后续提示。
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
# 报销草稿分支动作收口 开发 TODO
|
||||||
|
|
||||||
|
更新时间:2026-06-23
|
||||||
|
|
||||||
|
## 使用规则
|
||||||
|
|
||||||
|
- 每个 TODO 必须对应 `CONCEPT.md` 中的目标、能力、方案或验收点。
|
||||||
|
- 只有完成并验证后,才能把 `[ ]` 改成 `[x]`。
|
||||||
|
- 勾选时在任务后补充简短证据,例如文件、接口、命令或验证结果。
|
||||||
|
- 如果需求发生变化,先更新 `CONCEPT.md`,再调整本 TODO。
|
||||||
|
|
||||||
|
## 1. 调研与边界
|
||||||
|
|
||||||
|
- [x] [CONCEPT: 背景与问题] 阅读相关页面、动作模型和测试,确认当前“继续草稿”实际走详情打开,“不用草稿”走申请单关联。
|
||||||
|
证据:`travelReimbursementAssociationGateModel.js`、`useWorkbenchAiActionRouter.js`、`useWorkbenchAiExpenseFlow.js`、`workbench-ai-reimbursement-association-gate.test.mjs`。
|
||||||
|
- [x] [CONCEPT: 目标与非目标] 确认本轮只改草稿命中态按钮与点击流,不改后端草稿保存和风险审核。
|
||||||
|
证据:`CONCEPT.md` 的目标与非目标章节。
|
||||||
|
- [x] [CONCEPT: 风险与开放问题] 标记多草稿命中时默认指向最新草稿,历史旧动作保留兼容。
|
||||||
|
证据:`CONCEPT.md` 的风险与开放问题章节。
|
||||||
|
|
||||||
|
## 2. 契约与设计
|
||||||
|
|
||||||
|
- [x] [CONCEPT: 功能能力] 定义三个动作分支:查看草稿、继续关联草稿、独立新建报销单。
|
||||||
|
证据:`CONCEPT.md` 的功能能力和方案设计章节。
|
||||||
|
- [x] [CONCEPT: 方案设计] 明确个人工作台 AI 模式与报销助手页面共用动作模型,但分别在各自 action router 中处理点击。
|
||||||
|
证据:`CONCEPT.md` 的前端方案设计章节。
|
||||||
|
- [x] [CONCEPT: 算法与公式] 明确本轮不涉及显式数学公式。
|
||||||
|
证据:`CONCEPT.md` 的算法与公式章节。
|
||||||
|
- [x] [CONCEPT: 指标与验收] 把验收标准拆成按钮数量、按钮文案、点击后提示和旧动作兼容。
|
||||||
|
证据:`CONCEPT.md` 的指标与验收章节。
|
||||||
|
|
||||||
|
## 3. 后端实现
|
||||||
|
|
||||||
|
- [x] [CONCEPT: 后端] 本轮不新增后端 schema、service、endpoint、权限和持久化逻辑。
|
||||||
|
证据:`CONCEPT.md` 明确当前不新增接口。
|
||||||
|
- [x] [CONCEPT: 数据与契约] 后端响应结构不变,新增内容仅为前端动作类型。
|
||||||
|
证据:`CONCEPT.md` 的数据与契约章节。
|
||||||
|
|
||||||
|
## 4. 算法/规则实现
|
||||||
|
|
||||||
|
- [x] [CONCEPT: 算法与规则] 本轮不改候选单据筛选算法,只改命中后的动作分支。
|
||||||
|
证据:`CONCEPT.md` 的算法与规则章节。
|
||||||
|
- [x] [CONCEPT: 功能能力] 明确旧动作保留兼容,不删除历史会话能力。
|
||||||
|
证据:`CONCEPT.md` 的边界与降级说明。
|
||||||
|
|
||||||
|
## 5. 前端实现
|
||||||
|
|
||||||
|
- [x] [CONCEPT: 前端] 在草稿分支模型中新增动作类型和三按钮生成逻辑。
|
||||||
|
证据:`travelReimbursementDraftBranchModel.js` 定义 `CONTINUE_REIMBURSEMENT_DRAFT_ACTION`、`CREATE_STANDALONE_REIMBURSEMENT_DRAFT_ACTION` 和三按钮构造;`travelReimbursementAssociationGateModel.js` re-export 保持兼容。
|
||||||
|
- [x] [CONCEPT: 前端] 在个人工作台 AI 模式中处理继续关联草稿、独立新建确认和取消新建。
|
||||||
|
证据:`useWorkbenchAiActionRouter.js` 分流新动作;`useWorkbenchAiExpenseFlow.js` 追加上传附件/说明提示和新建草稿确认提示。
|
||||||
|
- [x] [CONCEPT: 前端] 在报销助手页面中处理同一批新动作,保持与工作台一致。
|
||||||
|
证据:`useTravelReimbursementSuggestedActions.js` 接入继续关联、独立新建确认和取消新建;`TravelReimbursementCreateView.js` 传入 `draftClaimId` 与 `composerUploadIntent`。
|
||||||
|
- [x] [CONCEPT: 前端] 保留旧动作兼容,不破坏历史会话按钮。
|
||||||
|
证据:`SKIP_REIMBURSEMENT_DRAFT_CHECK_ACTION` 和 `SKIP_REQUIRED_APPLICATION_LINK_ACTION` 仍由原路径处理;相关旧链路测试通过。
|
||||||
|
|
||||||
|
## 6. 测试与验证
|
||||||
|
|
||||||
|
- [x] [CONCEPT: 测试方案] 先补充失败的前端单元测试,覆盖三按钮生成和路由行为。
|
||||||
|
证据:RED 阶段 `workbench-ai-reimbursement-association-gate.test.mjs` 和 `workbench-ai-action-router.test.mjs` 因缺少 `CONTINUE_REIMBURSEMENT_DRAFT_ACTION` 导出失败。
|
||||||
|
- [x] [CONCEPT: 测试方案] 实现后运行定向前端测试,记录通过结果。
|
||||||
|
证据:`node --test web/tests/workbench-ai-reimbursement-association-gate.test.mjs`、`node --test web/tests/workbench-ai-action-router.test.mjs`、`node --test web/tests/travel-reimbursement-guided-flow.test.mjs`、`node --test web/tests/travel-reimbursement-review-drawer-switch.test.mjs`、`node --test web/tests/expense-attachment-draft-selection.test.mjs`、`node --test web/tests/attachment-association-confirmation.test.mjs` 均通过。
|
||||||
|
- [x] [CONCEPT: 指标与验收] 回看验收点,确认没有旧文案继续出现在新草稿命中态。
|
||||||
|
证据:`workbench-ai-reimbursement-association-gate.test.mjs` 断言新草稿命中态有且仅有三个动作,并不再出现“跳过草稿后再关联申请单”。
|
||||||
|
|
||||||
|
## 7. 文档收尾
|
||||||
|
|
||||||
|
- [x] [CONCEPT: 指标与验收] 实现完成后更新本 TODO 的证据。
|
||||||
|
证据:本 TODO 已回填实现文件和测试命令。
|
||||||
|
- [x] [CONCEPT: 风险与开放问题] 根据实现结果更新剩余风险。
|
||||||
|
证据:`CONCEPT.md` 已记录全量 `code-size-limits` 仍被既有 `TopBar.vue:824` 阻断;本轮文件行数为 `travelReimbursementAssociationGateModel.js:714`、`travelReimbursementDraftBranchModel.js:143`。
|
||||||
|
- [x] [CONCEPT: 功能一句话] 确认最终实现没有偏离原始目标。
|
||||||
|
证据:新草稿命中态固定为查看草稿、继续关联草稿、独立新建报销单三个入口。
|
||||||
490
document/development/自我进化学习闭环/CONCEPT.md
Normal file
@@ -0,0 +1,490 @@
|
|||||||
|
# X-Financial 自我进化学习闭环方案
|
||||||
|
|
||||||
|
更新日期:2026-06-23
|
||||||
|
|
||||||
|
## 功能一句话
|
||||||
|
|
||||||
|
把 X-Financial 从“规则 + 图谱 + Agent 的智能费控系统”升级为“可持续学习的费控智能体平台”:先通过反馈、回放和影子运行让分析能力变强,再把稳定结论沉淀为可审核、可测试、可回滚的规则、参数和知识资产。
|
||||||
|
|
||||||
|
## 背景与问题
|
||||||
|
|
||||||
|
当前系统已经具备费用申请、报销、审批、规则中心、知识库、小财管家、数字员工、风险观察、员工画像和财务行为图谱。现有能力已经不是单一算法,而是由多类算法共同形成判断:
|
||||||
|
|
||||||
|
- 规则引擎负责执行已上线的制度口径和风险 DSL。
|
||||||
|
- 风控图谱负责识别重复票据、拆单、高频、跨部门聚集、同组偏离等风险信号。
|
||||||
|
- 员工画像和申请人画像负责建立同组基线、流程质量和历史行为特征。
|
||||||
|
- 知识库负责制度检索、引用和政策解释。
|
||||||
|
- Agent 编排负责意图识别、流程确认、工具调用和可视化交互。
|
||||||
|
|
||||||
|
但如果这些模块只各自运行,系统仍然只是“更自动化的费控工具”。要变成自我进化系统,必须解决几个核心问题:
|
||||||
|
|
||||||
|
- 每次命中风险后,系统是否知道人工最终确认、驳回、误报还是漏报。
|
||||||
|
- 新规则、新阈值、新权重上线前,是否能用历史样本回放验证。
|
||||||
|
- 系统是否能从反复出现的人工反馈中形成候选规则或候选参数。
|
||||||
|
- 知识库制度变更后,是否能定位受影响的规则、流程和问答。
|
||||||
|
- Agent 回答错误或流程误判后,是否能沉淀为可复盘样本,而不是只改一处文案。
|
||||||
|
|
||||||
|
因此,自我进化不是让大模型直接改生产代码或发布规则,而是建立一条受控学习链路:
|
||||||
|
|
||||||
|
```text
|
||||||
|
运行数据
|
||||||
|
-> 人工反馈 / 审批结果 / 用户纠错
|
||||||
|
-> 标签样本与回放集
|
||||||
|
-> 分析能力校准
|
||||||
|
-> 候选规则 / 候选参数 / 候选知识修订
|
||||||
|
-> 影子运行与历史回放
|
||||||
|
-> 人审发布
|
||||||
|
-> 上线后持续监控
|
||||||
|
```
|
||||||
|
|
||||||
|
## 核心判断
|
||||||
|
|
||||||
|
学习闭环同时让两类能力变强,但顺序不同。
|
||||||
|
|
||||||
|
第一层是分析变强。
|
||||||
|
|
||||||
|
分析变强指系统越来越知道:
|
||||||
|
|
||||||
|
- 哪些风险信号真的值得阻断。
|
||||||
|
- 哪些风险只适合提醒或补充说明。
|
||||||
|
- 哪些规则在某些部门、费用类型、职级或场景下误报率高。
|
||||||
|
- 哪些历史相似单据最终被退回、确认或通过。
|
||||||
|
- 哪些同组基线更适合当前单据,而不是简单使用全局均值。
|
||||||
|
|
||||||
|
这一层优先影响风险分、置信度、推荐动作、抽检策略、自动化模式和解释质量。
|
||||||
|
|
||||||
|
第二层是规则变强。
|
||||||
|
|
||||||
|
规则变强指当某类分析结论被足够多的反馈和回放证明稳定后,再沉淀为正式规则、规则修订、例外条件或阈值配置。规则变强必须经过测试和审核,不能由模型直接上线。
|
||||||
|
|
||||||
|
推荐顺序是:
|
||||||
|
|
||||||
|
```text
|
||||||
|
分析先学习
|
||||||
|
-> 形成候选结论
|
||||||
|
-> 回放证明有效
|
||||||
|
-> 人审沉淀为规则或参数
|
||||||
|
-> 规则上线后继续接受反馈
|
||||||
|
```
|
||||||
|
|
||||||
|
这样可以避免系统过早把偶然反馈固化为生产规则。
|
||||||
|
|
||||||
|
## 目标与非目标
|
||||||
|
|
||||||
|
### 目标
|
||||||
|
|
||||||
|
- 建立统一的学习闭环总纲,串联风险观察、规则反馈、Agent 反馈、审批结果、回放评测和规则中心。
|
||||||
|
- 明确“分析进化”和“规则进化”的边界。
|
||||||
|
- 让风险分、置信度、推荐动作、抽检策略和自动化模式具备反馈校准依据。
|
||||||
|
- 让候选规则、候选参数和候选知识修订进入待审核流程,而不是自动生效。
|
||||||
|
- 通过历史回放、影子运行和灰度发布降低自我进化风险。
|
||||||
|
- 为后续实现算法评估中心、反馈样本池和候选规则工厂提供架构依据。
|
||||||
|
|
||||||
|
### 非目标
|
||||||
|
|
||||||
|
- 不让大模型直接修改生产规则、生产数据或核心代码。
|
||||||
|
- 不让系统绕过财务、风控或管理员审核自动发布规则。
|
||||||
|
- 不把员工画像作为惩罚标签;画像只服务于风险解释、排序和复核辅助。
|
||||||
|
- 不把所有学习结果都固化为规则;低置信反馈只进入分析校准和样本池。
|
||||||
|
- 不在第一阶段引入复杂机器学习训练平台,优先把样本、标签、回放和门控做稳。
|
||||||
|
|
||||||
|
## 现有基础
|
||||||
|
|
||||||
|
### 风控图谱
|
||||||
|
|
||||||
|
`evaluate_financial_risk_graph()` 已经把单据、员工、部门、费用类型、地点、票据和本体解析合成风险图谱,并输出贡献分、证据、风险等级、置信度、采样策略和决策 trace。
|
||||||
|
|
||||||
|
当前贡献分包括:
|
||||||
|
|
||||||
|
- `S_rule`:规则信号。
|
||||||
|
- `S_anomaly`:同组金额异常。
|
||||||
|
- `S_graph`:图谱异常。
|
||||||
|
- `S_policy`:制度关联。
|
||||||
|
- `S_history`:历史反馈。
|
||||||
|
|
||||||
|
这说明系统已经具备“分析可解释”和“反馈可进入评分”的基础。
|
||||||
|
|
||||||
|
### 规则中心
|
||||||
|
|
||||||
|
风险规则已经支持自然语言生成 JSON 风险规则、DSL 校验、风险评分、样例测试、真实场景试运行、测试报告确认、审核发布、反馈记录和修订版本。
|
||||||
|
|
||||||
|
这说明系统已经具备“规则可生成、可测试、可审核、可发布”的基础。
|
||||||
|
|
||||||
|
### 风险观察反馈池
|
||||||
|
|
||||||
|
`RiskObservation` 和 `RiskObservationFeedback` 已经能记录风险观察、反馈状态、反馈历史、算法版本和证据数据。
|
||||||
|
|
||||||
|
这说明系统已经有学习闭环的核心样本载体。
|
||||||
|
|
||||||
|
### 回放评测雏形
|
||||||
|
|
||||||
|
`AlgorithmReplayCase` 和 `AlgorithmReplaySet` 已经定义了历史单据、本体版本、规则版本、算法版本和反馈标签的回放契约。
|
||||||
|
|
||||||
|
这说明系统已经具备把历史风险观察转为评测样本的基础。
|
||||||
|
|
||||||
|
### 数字员工
|
||||||
|
|
||||||
|
数字员工已有风险图谱巡检、员工画像扫描、反馈样本积累、算法回放评估等任务概念。
|
||||||
|
|
||||||
|
这说明后台定时分析能力可以成为学习闭环的执行入口。
|
||||||
|
|
||||||
|
## 学习对象分层
|
||||||
|
|
||||||
|
### L1. 交互与意图学习
|
||||||
|
|
||||||
|
学习对象:
|
||||||
|
|
||||||
|
- 用户是否选择了正确流程。
|
||||||
|
- 小财管家是否误判申请 / 报销。
|
||||||
|
- 直接提交、保存草稿、附件关联、关联申请单等动作是否被用户纠正。
|
||||||
|
|
||||||
|
可进化内容:
|
||||||
|
|
||||||
|
- 意图识别提示词。
|
||||||
|
- 澄清问题策略。
|
||||||
|
- 流程确认门控。
|
||||||
|
- 推荐动作排序。
|
||||||
|
- 前端快捷动作默认项。
|
||||||
|
|
||||||
|
禁止直接进化内容:
|
||||||
|
|
||||||
|
- 不根据单次对话自动修改规则中心。
|
||||||
|
- 不把用户一句话纠错直接变成生产规则。
|
||||||
|
|
||||||
|
### L2. 风险分析学习
|
||||||
|
|
||||||
|
学习对象:
|
||||||
|
|
||||||
|
- 风险观察是否被人工确认。
|
||||||
|
- 命中后是否被退回、补件、通过、忽略。
|
||||||
|
- 哪些风险信号误报率高。
|
||||||
|
- 哪些风险在相似场景下总是漏报。
|
||||||
|
|
||||||
|
可进化内容:
|
||||||
|
|
||||||
|
- 风险分权重。
|
||||||
|
- 置信度计算。
|
||||||
|
- 自动化模式门槛。
|
||||||
|
- 抽检和回放采样策略。
|
||||||
|
- 同组基线选择策略。
|
||||||
|
- 风险解释优先级。
|
||||||
|
|
||||||
|
禁止直接进化内容:
|
||||||
|
|
||||||
|
- 不让系统自动把高风险改成阻断。
|
||||||
|
- 不让模型直接替代人工确认违规。
|
||||||
|
|
||||||
|
### L3. 规则学习
|
||||||
|
|
||||||
|
学习对象:
|
||||||
|
|
||||||
|
- 多次确认的风险观察。
|
||||||
|
- 反复出现的漏判反馈。
|
||||||
|
- 规则测试中的真实场景命中差异。
|
||||||
|
- 制度变更引起的规则失配。
|
||||||
|
|
||||||
|
可进化内容:
|
||||||
|
|
||||||
|
- 候选规则。
|
||||||
|
- 规则修订草稿。
|
||||||
|
- 例外条件。
|
||||||
|
- 阈值建议。
|
||||||
|
- 规则适用范围。
|
||||||
|
|
||||||
|
必须经过:
|
||||||
|
|
||||||
|
- 样例测试。
|
||||||
|
- 真实场景试运行。
|
||||||
|
- 回放评测。
|
||||||
|
- 人工审核。
|
||||||
|
- 灰度或发布确认。
|
||||||
|
|
||||||
|
### L4. 知识学习
|
||||||
|
|
||||||
|
学习对象:
|
||||||
|
|
||||||
|
- 知识库问答命中错误。
|
||||||
|
- 制度引用缺口。
|
||||||
|
- 规则和制度条款不一致。
|
||||||
|
- 用户追问中反复出现的政策盲点。
|
||||||
|
|
||||||
|
可进化内容:
|
||||||
|
|
||||||
|
- 知识文档结构化摘要。
|
||||||
|
- 制度条款引用。
|
||||||
|
- 问答检索关键词。
|
||||||
|
- 规则与制度条款绑定。
|
||||||
|
|
||||||
|
禁止直接进化内容:
|
||||||
|
|
||||||
|
- 不让模型编造制度。
|
||||||
|
- 不让模型用未审核知识覆盖正式制度。
|
||||||
|
|
||||||
|
## 闭环架构
|
||||||
|
|
||||||
|
### 1. 事件采集层
|
||||||
|
|
||||||
|
统一采集以下事件:
|
||||||
|
|
||||||
|
- 风险观察生成。
|
||||||
|
- 规则命中和未命中。
|
||||||
|
- 审批通过、退回、驳回、补件。
|
||||||
|
- 风控人员反馈确认、误报、漏报、不清楚。
|
||||||
|
- 用户对 Agent 回答的低分反馈。
|
||||||
|
- 规则测试、试运行和发布结果。
|
||||||
|
- 知识库检索命中和无结果。
|
||||||
|
|
||||||
|
每个事件都应绑定:
|
||||||
|
|
||||||
|
- 业务对象:申请单、报销单、票据、员工、部门、规则。
|
||||||
|
- 版本信息:算法版本、规则版本、本体版本、知识版本。
|
||||||
|
- 执行上下文:run_id、conversation_id、task_id。
|
||||||
|
- 处理结果:人工动作、审批状态、反馈标签。
|
||||||
|
|
||||||
|
### 2. 标签与样本层
|
||||||
|
|
||||||
|
将原始事件转为标准标签:
|
||||||
|
|
||||||
|
- `confirmed`:风险被确认。
|
||||||
|
- `false_positive`:误报。
|
||||||
|
- `false_negative`:漏报。
|
||||||
|
- `unclear`:证据不足。
|
||||||
|
- `over_blocked`:阻断过度。
|
||||||
|
- `manual_override`:人工覆盖系统建议。
|
||||||
|
- `policy_changed`:制度变化导致旧判断失效。
|
||||||
|
|
||||||
|
同时形成三类样本池:
|
||||||
|
|
||||||
|
- 分析校准样本:用于调整风险分、置信度和推荐动作。
|
||||||
|
- 回放评测样本:用于新算法、新规则、新权重上线前验证。
|
||||||
|
- 规则候选样本:用于生成或修订规则草稿。
|
||||||
|
|
||||||
|
### 3. 离线评估层
|
||||||
|
|
||||||
|
定期对候选算法、候选规则、候选参数运行回放。
|
||||||
|
|
||||||
|
关键指标:
|
||||||
|
|
||||||
|
- 确认率:命中后被人工确认的比例。
|
||||||
|
- 误报率:命中后被标记误报的比例。
|
||||||
|
- 漏报率:人工发现风险但系统未命中的比例。
|
||||||
|
- 阻断准确率:阻断动作最终被确认合理的比例。
|
||||||
|
- 人工负担:进入人工复核的单据比例。
|
||||||
|
- 解释完整率:风险观察是否包含规则、证据、基线和相似案例。
|
||||||
|
- 数据质量通过率:字段完整性、票据 OCR、申请关联等基础数据质量。
|
||||||
|
|
||||||
|
### 4. 候选生成层
|
||||||
|
|
||||||
|
系统只能生成候选,不直接生效。
|
||||||
|
|
||||||
|
候选类型:
|
||||||
|
|
||||||
|
- 候选规则:来自反复确认的风险观察或漏判样本。
|
||||||
|
- 候选规则修订:来自误报较高的规则反馈。
|
||||||
|
- 候选参数:来自权重、阈值、置信度、自动化门槛的评估结果。
|
||||||
|
- 候选知识修订:来自制度引用缺口或知识问答低分反馈。
|
||||||
|
|
||||||
|
每个候选必须包含:
|
||||||
|
|
||||||
|
- 来源样本。
|
||||||
|
- 触发原因。
|
||||||
|
- 预期改善指标。
|
||||||
|
- 可能副作用。
|
||||||
|
- 回放结果。
|
||||||
|
- 推荐发布方式。
|
||||||
|
|
||||||
|
### 5. 发布门控层
|
||||||
|
|
||||||
|
发布顺序:
|
||||||
|
|
||||||
|
```text
|
||||||
|
候选
|
||||||
|
-> 样例测试
|
||||||
|
-> 历史回放
|
||||||
|
-> 影子运行
|
||||||
|
-> 人工审核
|
||||||
|
-> 灰度启用
|
||||||
|
-> 全量发布
|
||||||
|
-> 上线后监控
|
||||||
|
```
|
||||||
|
|
||||||
|
影子运行期间,新规则或新参数只记录“如果启用会发生什么”,不影响真实审批。
|
||||||
|
|
||||||
|
灰度启用期间,只对指定部门、费用类型或测试公司生效。
|
||||||
|
|
||||||
|
全量发布后,必须持续监控误报、漏报、阻断和人工覆盖。
|
||||||
|
|
||||||
|
## 数据与版本要求
|
||||||
|
|
||||||
|
每条学习样本至少保留:
|
||||||
|
|
||||||
|
- `sample_id`
|
||||||
|
- `sample_type`
|
||||||
|
- `subject_type`
|
||||||
|
- `subject_id`
|
||||||
|
- `business_stage`
|
||||||
|
- `risk_signal`
|
||||||
|
- `rule_code`
|
||||||
|
- `algorithm_version`
|
||||||
|
- `rule_version`
|
||||||
|
- `ontology_version`
|
||||||
|
- `knowledge_version`
|
||||||
|
- `input_snapshot`
|
||||||
|
- `decision_trace`
|
||||||
|
- `expected_label`
|
||||||
|
- `actual_label`
|
||||||
|
- `feedback_source`
|
||||||
|
- `feedback_actor`
|
||||||
|
- `created_at`
|
||||||
|
|
||||||
|
每次算法或规则评估至少保留:
|
||||||
|
|
||||||
|
- `evaluation_id`
|
||||||
|
- `candidate_type`
|
||||||
|
- `candidate_version`
|
||||||
|
- `baseline_version`
|
||||||
|
- `replay_set_id`
|
||||||
|
- `sample_count`
|
||||||
|
- `metrics_before`
|
||||||
|
- `metrics_after`
|
||||||
|
- `regression_cases`
|
||||||
|
- `approval_status`
|
||||||
|
|
||||||
|
## 推荐实施路径
|
||||||
|
|
||||||
|
### 第一阶段:补齐评估地基
|
||||||
|
|
||||||
|
目标是让系统知道自己判断得好不好。
|
||||||
|
|
||||||
|
- 统一风险观察反馈标签。
|
||||||
|
- 把审批结果、退回原因、补件动作写入风险样本池。
|
||||||
|
- 将 Agent 低分反馈归因到意图识别、流程路由、知识问答、规则解释、附件处理等类别。
|
||||||
|
- 建立回放集生成任务,把风险观察和反馈状态转成评测样本。
|
||||||
|
- 在数字员工工作记录中展示反馈样本摘要和回放评估摘要。
|
||||||
|
|
||||||
|
### 第二阶段:分析进化
|
||||||
|
|
||||||
|
目标是先让判断更稳。
|
||||||
|
|
||||||
|
- 将风险图谱权重、置信度门槛、自动化模式门槛迁移到版本化配置。
|
||||||
|
- 基于反馈样本计算规则、风险信号、费用类型、部门维度的误报率和确认率。
|
||||||
|
- 对高误报规则降低默认动作等级,对高确认规则提高抽检优先级。
|
||||||
|
- 增强同组基线选择,优先使用部门、职级、费用类型、供应商等可解释维度。
|
||||||
|
- 引入影子参数评估,只记录差异,不直接影响生产。
|
||||||
|
|
||||||
|
### 第三阶段:规则进化
|
||||||
|
|
||||||
|
目标是把稳定结论沉淀为规则资产。
|
||||||
|
|
||||||
|
- 从 confirmed 和 false_negative 样本中生成候选规则。
|
||||||
|
- 从 false_positive 样本中生成候选例外条件或适用范围收缩建议。
|
||||||
|
- 候选规则自动进入规则中心草稿,不自动发布。
|
||||||
|
- 草稿必须完成样例测试、真实场景试运行和测试报告确认。
|
||||||
|
- 已上线规则只能通过修订版本替换。
|
||||||
|
|
||||||
|
### 第四阶段:知识进化
|
||||||
|
|
||||||
|
目标是让制度、规则和问答保持一致。
|
||||||
|
|
||||||
|
- 对知识库无结果、低分反馈和制度引用缺口做聚类。
|
||||||
|
- 自动生成知识修订建议或制度引用补充建议。
|
||||||
|
- 标记受影响规则和问答范围。
|
||||||
|
- 由制度管理员确认后再更新知识库或规则引用。
|
||||||
|
|
||||||
|
### 第五阶段:灰度自进化
|
||||||
|
|
||||||
|
目标是在受控范围内逐步提高自动化程度。
|
||||||
|
|
||||||
|
- 为低风险、高置信、高证据完整度场景开放自动提醒或自动补件建议。
|
||||||
|
- 为高风险场景继续保持人工复核或阻断确认。
|
||||||
|
- 每个自动化动作都必须可解释、可撤回、可追踪。
|
||||||
|
- 自动化范围随反馈质量逐步扩大。
|
||||||
|
|
||||||
|
## 产品边界
|
||||||
|
|
||||||
|
自我进化系统里,人和系统的职责要明确。
|
||||||
|
|
||||||
|
系统负责:
|
||||||
|
|
||||||
|
- 发现模式。
|
||||||
|
- 聚合证据。
|
||||||
|
- 生成候选。
|
||||||
|
- 运行回放。
|
||||||
|
- 计算指标。
|
||||||
|
- 提醒风险。
|
||||||
|
- 记录全链路证据。
|
||||||
|
|
||||||
|
人负责:
|
||||||
|
|
||||||
|
- 确认制度口径。
|
||||||
|
- 审核规则发布。
|
||||||
|
- 判断复杂业务例外。
|
||||||
|
- 决定阻断、退回或放行。
|
||||||
|
- 对候选改进做最终确认。
|
||||||
|
|
||||||
|
大模型负责:
|
||||||
|
|
||||||
|
- 语义理解。
|
||||||
|
- 候选规则草稿。
|
||||||
|
- 解释生成。
|
||||||
|
- 知识摘要。
|
||||||
|
- 反馈归因辅助。
|
||||||
|
|
||||||
|
大模型不负责:
|
||||||
|
|
||||||
|
- 最终违规判定。
|
||||||
|
- 自动发布规则。
|
||||||
|
- 自动修改生产代码。
|
||||||
|
- 绕过审核执行高风险动作。
|
||||||
|
|
||||||
|
## 验收指标
|
||||||
|
|
||||||
|
第一阶段验收:
|
||||||
|
|
||||||
|
- 风险观察反馈、规则反馈、Agent 反馈能统一进入样本池。
|
||||||
|
- 回放集能按算法版本、规则版本、本体版本构建。
|
||||||
|
- 风险看板能展示确认率、误报率、反馈样本数和待回放样本数。
|
||||||
|
|
||||||
|
第二阶段验收:
|
||||||
|
|
||||||
|
- 风险分、置信度和自动化动作的调整都有反馈证据。
|
||||||
|
- 新参数可以影子运行并产生差异报告。
|
||||||
|
- 高误报规则能被识别并生成修订建议。
|
||||||
|
|
||||||
|
第三阶段验收:
|
||||||
|
|
||||||
|
- 系统能从反馈样本生成候选规则或候选修订。
|
||||||
|
- 候选规则能进入规则中心草稿。
|
||||||
|
- 候选规则必须通过测试报告确认后才允许发布。
|
||||||
|
|
||||||
|
第四阶段验收:
|
||||||
|
|
||||||
|
- 知识问答低分反馈能定位到知识缺口。
|
||||||
|
- 制度变更能提示受影响规则和问答范围。
|
||||||
|
- 知识修订必须保留来源和审核记录。
|
||||||
|
|
||||||
|
## 风险与防护
|
||||||
|
|
||||||
|
- 反馈噪音:单次反馈不能直接改规则或参数,必须聚合后进入候选。
|
||||||
|
- 误报固化:规则上线前必须跑历史回放和影子运行。
|
||||||
|
- 模型幻觉:所有制度、规则和风险结论必须绑定来源证据。
|
||||||
|
- 自动化越权:阻断、退回、发布规则等高风险动作必须人工确认。
|
||||||
|
- 数据漂移:长期监控样本量、字段缺失率、费用分布和 OCR 质量。
|
||||||
|
- 版本混乱:算法、规则、本体、知识和回放集必须带版本号。
|
||||||
|
|
||||||
|
## 与现有文档关系
|
||||||
|
|
||||||
|
- `document/development/hermes-risk-graph-algorithm/CONCEPT.md`:负责风险图谱算法和风险观察模型。
|
||||||
|
- `document/development/risk-rule-explainable-flow/CONCEPT.md`:负责风险规则 DSL、解释、测试和发布流程。
|
||||||
|
- `document/development/数字员工能力库扩展/CONCEPT.md`:负责数字员工技能边界和后台分析任务。
|
||||||
|
- 本文档负责把上述能力串成“自我进化学习闭环”的总体路线。
|
||||||
|
|
||||||
|
## 结论
|
||||||
|
|
||||||
|
X-Financial 的自我进化应先让分析变强,再让规则变强。
|
||||||
|
|
||||||
|
分析变强是低风险、高收益的第一步:它通过反馈、回放和影子运行持续校准风险分、置信度、动作建议和解释质量。
|
||||||
|
|
||||||
|
规则变强是第二步:只有当分析结论经过足够样本验证后,才沉淀为正式规则、规则修订或参数版本,并通过测试、人审和灰度发布进入生产。
|
||||||
|
|
||||||
|
最终目标不是“系统自己随便改规则”,而是形成一条可审计、可回放、可控发布的学习链路,让系统越用越懂企业自己的财务控制口径。
|
||||||
3
document/user/example.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
user1: caoxiaozhu@xf.com / 123456
|
||||||
|
User2: xiangwanhong@xf.com / 123456
|
||||||
|
Admin: admin/ admin
|
||||||
BIN
document/user/出差/2月20 武汉-上海.pdf
Normal file
BIN
document/user/出差/2月21日,上海-深圳.png
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
document/user/出差/2月22日,深圳-上海.png
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
BIN
document/user/出差/2月23 上海-武汉.pdf
Normal file
BIN
document/user/出差/82956c41-db2f-4768-bba5-21181bd4706c.png
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
document/user/出差/KTV 招待客户.png
Normal file
|
After Width: | Height: | Size: 183 KiB |
BIN
document/user/出差/住宿费1.png
Normal file
|
After Width: | Height: | Size: 266 KiB |
BIN
document/user/出差/住宿费2.png
Normal file
|
After Width: | Height: | Size: 206 KiB |
BIN
document/user/出差/住宿费3.png
Normal file
|
After Width: | Height: | Size: 209 KiB |
BIN
document/user/出差/洗脚城 招待客户.png
Normal file
|
After Width: | Height: | Size: 172 KiB |
BIN
document/user/出差/的士1.jpg
Normal file
|
After Width: | Height: | Size: 138 KiB |
BIN
document/user/出差/的士2.jpg
Normal file
|
After Width: | Height: | Size: 135 KiB |
BIN
document/user/出差/的士3.jpg
Normal file
|
After Width: | Height: | Size: 149 KiB |
BIN
document/user/出差/酒店1.jpg
Normal file
|
After Width: | Height: | Size: 133 KiB |
BIN
document/user/出差/酒店2.jpg
Normal file
|
After Width: | Height: | Size: 153 KiB |
BIN
document/user/出差/酒店3.jpg
Normal file
|
After Width: | Height: | Size: 150 KiB |
BIN
document/user/出差/酒店(招待客户).png
Normal file
|
After Width: | Height: | Size: 296 KiB |
@@ -1,18 +0,0 @@
|
|||||||
# Work Log - 2026-05-06
|
|
||||||
|
|
||||||
## 今日工作
|
|
||||||
|
|
||||||
### 下午
|
|
||||||
- **修复了 Windows Git Bash 启动脚本报错问题**
|
|
||||||
- 问题:虚拟环境指向不存在的 python3
|
|
||||||
- 解决:添加检测函数,无效则重建
|
|
||||||
|
|
||||||
- **创建了 work-log 技能**
|
|
||||||
- 自动记录工作日志
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# 待处理
|
|
||||||
|
|
||||||
- [ ] 安装 PostgreSQL
|
|
||||||
- [ ] 创建 x_financial 数据库
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
# Work Log - 2026-05-07
|
|
||||||
|
|
||||||
## 今日工作
|
|
||||||
|
|
||||||
- **提交 c00db75** (11:50)
|
|
||||||
- feat: add employee management, backend health check, and UI improvements
|
|
||||||
- 完成了员工管理模块(后端 + 前端)
|
|
||||||
- 添加了后端健康检查
|
|
||||||
- 整理了 UI 资源
|
|
||||||
|
|
||||||
- **提交 2d56bc2** (13:48)
|
|
||||||
- feat: enhance employee CRUD with search, filters, and security module
|
|
||||||
- 增强了员工搜索和筛选功能
|
|
||||||
- 添加了安全模块(security.py)
|
|
||||||
- 添加了单元测试
|
|
||||||
|
|
||||||
- **提交 b8ba0ea** (14:32)
|
|
||||||
- feat: add auth module with login and access control
|
|
||||||
- 为系统实现了完整的登录认证功能
|
|
||||||
- 后端使用 FastAPI 搭建了 auth 服务,支持管理员密钥验证
|
|
||||||
- 前端对接了登录接口,实现了 Token 存储和自动登录逻辑
|
|
||||||
- 设计并实现了基于角色的访问控制(RBAC),区分超级管理员和普通员工
|
|
||||||
|
|
||||||
- **提交 e8f3d97** (15:18)
|
|
||||||
- feat: add settings page with navigation and access control updates
|
|
||||||
- 搭建了系统设置页面,支持管理员配置系统参数
|
|
||||||
- 优化了侧边栏导航交互,增加了收起/展开的流畅动画
|
|
||||||
- 将访问控制规则统一收敛到 accessControl.js,避免散落各处
|
|
||||||
- 统一了 useSystemState 和 useNavigation 两个 composable 的职责
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# 待处理
|
|
||||||
|
|
||||||
- [ ] 安装 PostgreSQL
|
|
||||||
- [ ] 创建 x_financial 数据库
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
# Work Log - 2026-05-08
|
|
||||||
|
|
||||||
## 今日工作
|
|
||||||
|
|
||||||
- **提交 adda87a** (08:56)
|
|
||||||
- feat: add system settings with model connectivity and encrypted storage
|
|
||||||
- 为系统设置页面新增了配置管理功能,支持管理员修改 AI 模型连接参数
|
|
||||||
- 引入加密存储方案(secret_box.py),对敏感配置(如 API Key)使用对称加密保护
|
|
||||||
- 后端新增 settings 端点、repository 层和 service 层,实现配置的增删改查
|
|
||||||
- 新增 model_connectivity.py 服务,支持测试 AI 模型连接是否正常
|
|
||||||
- 前端设置页面大幅重构,增加了模型配置表单和连接测试功能
|
|
||||||
- 新增数据库表 system_setting 和 system_setting_secret 存储配置和加密值
|
|
||||||
- 编写了 settings 相关的单元测试,确保配置持久化和服务逻辑正确
|
|
||||||
|
|
||||||
- **提交 c5486dd** (10:52)
|
|
||||||
- feat: 启用后端自动启动与 Setup 引导流程增强
|
|
||||||
- 启用了后端自动启动功能,用户访问前端时后端自动拉起,无需手动启动 server
|
|
||||||
- 增强了 Setup 引导流程,新增后端启动进度追踪,分 5 步展示(config → deps → server → health → done)
|
|
||||||
- 网络绑定从 127.0.0.1 扩展到 0.0.0.0,支持远程浏览器访问部署的系統
|
|
||||||
- API URL 动态化,通过 localStorage 持久化配置,支持运行时修改
|
|
||||||
- 新增后端启动探针(probe),自动检测后端就绪状态后才允许浏览器继续操作
|
|
||||||
- Setup 表单智能判断浏览器 host,将本地地址自动转换为 0.0.0.0 供远程访问
|
|
||||||
|
|
||||||
- **提交 8656866** (11:14)
|
|
||||||
- feat: 重构模型配置存储与 API Key 加密管理
|
|
||||||
- 新增 SystemModelSetting 模型(slot 为 PK),支持 main/backup/vlm/embedding 四个模型槽位配置
|
|
||||||
- 废弃旧的加密存储方案,改用更规范的数据库表存储加密的 API Key
|
|
||||||
- 兼容旧版 admin secret 格式,将历史密码记录迁移到标准 scrypt 哈希格式
|
|
||||||
- 前端 API URL 智能解析,当后端配置为回环地址但浏览器非回环时,自动使用浏览器 host 访问
|
|
||||||
- 改进 API Key 输入体验,聚焦时自动清除遮罩显示,并提示已从数据库加载密钥
|
|
||||||
17
document/work-log/2026-05-23.md
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# 2026-05-23 工作日志
|
||||||
|
|
||||||
|
## 远端依据
|
||||||
|
|
||||||
|
- 分支:`origin/main`
|
||||||
|
- 提交:`575f093`
|
||||||
|
|
||||||
|
## 工作内容
|
||||||
|
|
||||||
|
- 新增风险规则生成引擎,支持从知识、规则资产和业务上下文中生成风险规则草案。
|
||||||
|
- 增强知识图谱可视化能力,补充知识摄取日志图谱节点、证据和运行信息展示。
|
||||||
|
- 扩展审计页、日志详情页和归档中心交互,便于追踪规则生成、知识索引和报销会话链路。
|
||||||
|
- 补充风险规则生成、知识摄取日志、报销引导流程等测试覆盖。
|
||||||
|
|
||||||
|
## 提交记录
|
||||||
|
|
||||||
|
- `575f093` feat: 新增风险规则生成引擎与知识图谱可视化
|
||||||
18
document/work-log/2026-05-24.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# 2026-05-24 工作日志
|
||||||
|
|
||||||
|
## 远端依据
|
||||||
|
|
||||||
|
- 分支:`origin/main`
|
||||||
|
- 提交:`50b1c3f`
|
||||||
|
|
||||||
|
## 工作内容
|
||||||
|
|
||||||
|
- 增强规则资产管理能力,引入规则测试、规则流图和运行时调试相关页面能力。
|
||||||
|
- 新增 Hermes Agent 相关架构、数据库、风险扫描、报销报告和部署说明文档。
|
||||||
|
- 扩展 Hermes 配置、报告、风险扫描、调度等后端模型和服务。
|
||||||
|
- 新增文档中心页面与时间工具,优化审计页、日志页、设置页和导航交互。
|
||||||
|
- 清理旧风险规则文件,并补充知识解析、RAG、规则生成和用户代理服务测试。
|
||||||
|
|
||||||
|
## 提交记录
|
||||||
|
|
||||||
|
- `50b1c3f` feat: 增强规则资产管理与审计页面运行时调试
|
||||||
18
document/work-log/2026-05-25.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# 2026-05-25 工作日志
|
||||||
|
|
||||||
|
## 远端依据
|
||||||
|
|
||||||
|
- 分支:`origin/main`
|
||||||
|
- 提交:`d0e946c`
|
||||||
|
|
||||||
|
## 工作内容
|
||||||
|
|
||||||
|
- 完善文档中心和报销申请链路,新增首页参考稿并优化侧边栏结构。
|
||||||
|
- 抽取用户代理申请服务,增强报销单、申请单、本体识别和编排流程。
|
||||||
|
- 强化文档中心未读状态、侧边栏入口、详情提醒和申请预填能力。
|
||||||
|
- 优化报销创建页、差旅详情页和小财管家会话状态。
|
||||||
|
- 补充文档中心、申请提交确认、助手建议动作、侧边栏折叠等测试。
|
||||||
|
|
||||||
|
## 提交记录
|
||||||
|
|
||||||
|
- `d0e946c` feat: 完善文档中心与报销申请交互及侧边栏重构
|
||||||
20
document/work-log/2026-05-26.md
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# 2026-05-26 工作日志
|
||||||
|
|
||||||
|
## 远端依据
|
||||||
|
|
||||||
|
- 分支:`origin/main`
|
||||||
|
- 提交:`0e861d8` 至 `df49103`
|
||||||
|
|
||||||
|
## 工作内容
|
||||||
|
|
||||||
|
- 增强风险规则生成引擎和预算中心页面,打通预算中心本体、风险规则评分和预算后端服务。
|
||||||
|
- 新增差旅风险规则库,补充预算实体、预算服务、预算图表和预算中心视图。
|
||||||
|
- 完善预算中心图表展示、确认对话框和费用管控交互。
|
||||||
|
- 扩展规则资产、员工、报销申请、审批和预算相关测试,覆盖新引擎与预算链路。
|
||||||
|
|
||||||
|
## 提交记录
|
||||||
|
|
||||||
|
- `0e861d8` feat: 增强风险规则生成引擎与预算中心页面
|
||||||
|
- `e1e515e` feat: 新增预算中心本体与风险规则评分回填
|
||||||
|
- `e7bef08` feat: 新增预算后端服务与差旅风险规则库
|
||||||
|
- `df49103` feat: 完善预算中心图表与确认对话框交互
|
||||||
22
document/work-log/2026-05-27.md
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# 2026-05-27 工作日志
|
||||||
|
|
||||||
|
## 远端依据
|
||||||
|
|
||||||
|
- 分支:`origin/main`
|
||||||
|
- 提交:`2dcc721` 至 `d4d5d40`
|
||||||
|
|
||||||
|
## 工作内容
|
||||||
|
|
||||||
|
- 重构全局 UI 主题皮肤与样式模块,统一页面视觉基线。
|
||||||
|
- 优化报销创建页面样式和洞察面板交互,提升申请与报销过程的可读性。
|
||||||
|
- 新增预算助手报告组件,补强预算报告、报销交互细节和申请关联能力。
|
||||||
|
- 完善审批退回流程与报销申请关联逻辑。
|
||||||
|
- 新增预算费控模型和报销审批流引擎,为后续动态审批与预算分析打基础。
|
||||||
|
|
||||||
|
## 提交记录
|
||||||
|
|
||||||
|
- `2dcc721` style: 全局 UI 主题皮肤重构与样式模块化
|
||||||
|
- `b1a9c8a` fix: 优化报销创建页面样式与洞察面板交互
|
||||||
|
- `7d32eae` feat: 新增预算助手报告组件并优化报销交互细节
|
||||||
|
- `cbb98f4` feat: 完善审批退回流程与报销申请关联
|
||||||
|
- `d4d5d40` feat: 新增预算费控模型与报销审批流引擎
|
||||||
21
document/work-log/2026-05-28.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# 2026-05-28 工作日志
|
||||||
|
|
||||||
|
## 远端依据
|
||||||
|
|
||||||
|
- 分支:`origin/main`
|
||||||
|
- 提交:`04cd6d0` 至 `064eeb6`
|
||||||
|
|
||||||
|
## 工作内容
|
||||||
|
|
||||||
|
- 重构工作台首页,新增数字员工管理页面和员工行为画像算法。
|
||||||
|
- 引入费用风险标签体系、员工画像标签分页和 ECharts 统一图表能力。
|
||||||
|
- 在列表详情页面引入共享 shell,并逐步拆分审计列表、详情和模型逻辑。
|
||||||
|
- 备份列表详情 shell 重构前工作区,降低大规模 UI 抽取风险。
|
||||||
|
|
||||||
|
## 提交记录
|
||||||
|
|
||||||
|
- `04cd6d0` feat: 新增数字员工管理页面与工作台首页重构
|
||||||
|
- `8a4a777` feat: 新增员工行为画像算法与费用风险标签体系
|
||||||
|
- `e384318` feat: 引入 ECharts 统一图表并完善员工画像标签分页
|
||||||
|
- `b383244` chore: backup workspace before list detail shell refactor
|
||||||
|
- `064eeb6` refactor(ui): introduce shared list detail shells
|
||||||
21
document/work-log/2026-05-29.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# 2026-05-29 工作日志
|
||||||
|
|
||||||
|
## 远端依据
|
||||||
|
|
||||||
|
- 分支:`origin/main`
|
||||||
|
- 提交:`99e9079` 至 `4c59941`
|
||||||
|
|
||||||
|
## 工作内容
|
||||||
|
|
||||||
|
- 拆分审计列表详情流程和模型,复用共享列表 shell,降低重复 UI 结构。
|
||||||
|
- 完成共享 shell 与加载状态收口,统一页面加载、空态和列表体验。
|
||||||
|
- 统一后端分页查询接口与前端服务层适配。
|
||||||
|
- 新增票据夹模块,优化 OCR、员工画像和票据相关服务。
|
||||||
|
|
||||||
|
## 提交记录
|
||||||
|
|
||||||
|
- `99e9079` refactor(audit): split list detail flows
|
||||||
|
- `64cc76c` refactor(audit): reuse list shells and split models
|
||||||
|
- `e080105` feat(ui): finalize shared shells and loading states
|
||||||
|
- `678f64d` feat: 统一后端分页查询与前端服务层适配
|
||||||
|
- `4c59941` feat: 新增票据夹模块并优化 OCR 与员工画像服务
|
||||||
18
document/work-log/2026-05-30.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# 2026-05-30 工作日志
|
||||||
|
|
||||||
|
## 远端依据
|
||||||
|
|
||||||
|
- 分支:`origin/main`
|
||||||
|
- 提交:`7989f3a`
|
||||||
|
|
||||||
|
## 工作内容
|
||||||
|
|
||||||
|
- 新增风险图谱算法能力,围绕风险节点、关系和来源构建设计与实现文档。
|
||||||
|
- 扩展系统仪表盘和操作反馈体系,提升风险与业务操作的可解释性。
|
||||||
|
- 增强规则资产、风险规则模拟、员工、申请和审批相关服务。
|
||||||
|
- 更新前端预算中心、审计、工作台、差旅申请和详情页等模块。
|
||||||
|
- 补充文档、测试和运行资产,支撑风险图谱与仪表盘演示。
|
||||||
|
|
||||||
|
## 提交记录
|
||||||
|
|
||||||
|
- `7989f3a` feat: 新增风险图谱算法与系统仪表盘及操作反馈体系
|
||||||
18
document/work-log/2026-06-01.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# 2026-06-01 工作日志
|
||||||
|
|
||||||
|
## 远端依据
|
||||||
|
|
||||||
|
- 分支:`origin/main`
|
||||||
|
- 提交:`92444e7`
|
||||||
|
|
||||||
|
## 工作内容
|
||||||
|
|
||||||
|
- 扩展风险规则体系,增强规则生成、规则执行、复合规则和本体字段治理能力。
|
||||||
|
- 新增审批动态路由能力,补强申请审批、报销审批和流程转派场景。
|
||||||
|
- 推进预算中心列表化改造,配套更新预算、审计、文档中心和工作台页面。
|
||||||
|
- 更新项目协作规范、环境配置和规则表资产。
|
||||||
|
- 补充风险规则、本体、审批、文档中心和申请流程相关测试。
|
||||||
|
|
||||||
|
## 提交记录
|
||||||
|
|
||||||
|
- `92444e7` feat: 扩展风险规则体系、审批动态路由与预算中心列表化改造
|
||||||
18
document/work-log/2026-06-02.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# 2026-06-02 工作日志
|
||||||
|
|
||||||
|
## 远端依据
|
||||||
|
|
||||||
|
- 分支:`origin/main`
|
||||||
|
- 提交:`ca691f3` 至 `0c74b4a`
|
||||||
|
|
||||||
|
## 工作内容
|
||||||
|
|
||||||
|
- 优化差旅报销预审流程和个人工作台 UI 体系,增强申请、报销和智能助手联动。
|
||||||
|
- 重构财务看板口径,补充半年模拟数据和报销状态注册表。
|
||||||
|
- 扩展财务看板、风险看板、员工画像、工作台、差旅详情和申请创建页面。
|
||||||
|
- 补充模拟数据、状态口径、看板展示和报销流程相关测试。
|
||||||
|
|
||||||
|
## 提交记录
|
||||||
|
|
||||||
|
- `ca691f3` feat: 优化差旅报销预审流程与个人工作台 UI 体系
|
||||||
|
- `0c74b4a` feat: 财务看板口径重构与半年模拟数据及报销状态注册表
|
||||||
49
document/work-log/2026-06-03.md
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
# 2026-06-03 工作日志
|
||||||
|
|
||||||
|
## 远端依据
|
||||||
|
|
||||||
|
- 分支:`origin/main`
|
||||||
|
- 提交:`faa39e6` 至 `87da5df`
|
||||||
|
|
||||||
|
## 工作内容
|
||||||
|
|
||||||
|
- 建设数字员工财务报告体系、定时提醒和看板快照调度能力。
|
||||||
|
- 优化风险看板、数字员工看板、预算与风险卡片、共享加载态和仪表盘展示。
|
||||||
|
- 完善工作台费用进度、费用统计详情弹窗、分布图、画像雷达和个人工作台标签展示。
|
||||||
|
- 推进本体字段治理和风险规则模板执行器重构。
|
||||||
|
- 优化申请与报销流程,包括申请关联限制、交通方式显式要求、手工明细入口收口和管理员工作台权限。
|
||||||
|
- 完善文档中心未读状态、铃铛通知、排序、全部已读和顶部通知持久化。
|
||||||
|
- 细化风险可见性和审核人风险提示,修复规则标准调整后的风险说明保留问题。
|
||||||
|
|
||||||
|
## 提交记录
|
||||||
|
|
||||||
|
- `faa39e6` test(dashboard): cover shared loading overlay
|
||||||
|
- `d060f89` style(dashboard): reuse shared loading overlay
|
||||||
|
- `0d6327a` feat(dashboard): polish risk and digital employee boards
|
||||||
|
- `15006a0` feat: 数字员工财务报告体系与定时提醒及看板快照调度
|
||||||
|
- `27dd2f0` feat(dashboard): reorganize budget and risk cards
|
||||||
|
- `6fc5e66` feat(workbench): show progress update time first
|
||||||
|
- `3130c42` feat(workbench): separate stale progress items
|
||||||
|
- `20cb60e` feat(workbench): add expense stats detail modal
|
||||||
|
- `31052d0` feat(workbench): keep progress detail return context
|
||||||
|
- `74d488a` fix(workbench): center progress expense type
|
||||||
|
- `18d716b` feat(workbench): show expense distribution as donut chart
|
||||||
|
- `e12b140` fix(workbench): show single expense distribution chart
|
||||||
|
- `34457f9` feat: 本体字段治理与风险规则模板执行器重构
|
||||||
|
- `8887cf5` fix(workbench): stretch profile tag card
|
||||||
|
- `04f0951` fix: restrict application linking for reimbursement drafts
|
||||||
|
- `59d3bf0` fix(auth): keep admin out of personal workbench
|
||||||
|
- `9219854` fix: require explicit transport mode for applications
|
||||||
|
- `513ff90` fix: remove manual expense detail add action
|
||||||
|
- `4717ee6` fix(documents): refine unread badges and mark all read
|
||||||
|
- `8c2f301` fix(documents): sort newest rows first
|
||||||
|
- `c73178b` fix(documents): move unread notice into bell
|
||||||
|
- `95956af` fix(notifications): refine bell notification center
|
||||||
|
- `9c24a85` fix(workbench): remount expense stats chart on reopen
|
||||||
|
- `67b81a1` fix(workbench): replay profile radar animation
|
||||||
|
- `8e24775` fix: handle risk explanation standard adjustment
|
||||||
|
- `cb36d78` fix: 优化顶部导航栏布局与工作台摘要展示并清理旧票据数据
|
||||||
|
- `0f8bc40` fix: preserve reviewer risk notice after standard adjustment
|
||||||
|
- `b9826a1` fix: keep adjusted risks visible to reviewers
|
||||||
|
- `75d5c17` feat(workbench): persist topbar notification state
|
||||||
|
- `87da5df` feat: 风险可见性控制与差旅详情页交互优化
|
||||||
18
document/work-log/2026-06-04.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# 2026-06-04 工作日志
|
||||||
|
|
||||||
|
## 远端依据
|
||||||
|
|
||||||
|
- 分支:`origin/main`
|
||||||
|
- 提交:`1cbf3fe` 至 `f60ceba`
|
||||||
|
|
||||||
|
## 工作内容
|
||||||
|
|
||||||
|
- 增强报销预审会话状态管理,优化工作台与报销创建页交互。
|
||||||
|
- 完善小财管家意图规划、管家计划和报销提交编排。
|
||||||
|
- 扩展用户代理、编排器、差旅报销会话、提交组合器和申请预填相关能力。
|
||||||
|
- 补充小财管家计划、报销预审、提交编排和工作台交互测试。
|
||||||
|
|
||||||
|
## 提交记录
|
||||||
|
|
||||||
|
- `1cbf3fe` feat: 报销预审会话状态管理与工作台交互增强
|
||||||
|
- `f60ceba` feat: 小财管家意图规划与报销提交编排增强
|
||||||
18
document/work-log/2026-06-06.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# 2026-06-06 工作日志
|
||||||
|
|
||||||
|
## 远端依据
|
||||||
|
|
||||||
|
- 分支:`origin/main`
|
||||||
|
- 提交:`e124e4b`
|
||||||
|
|
||||||
|
## 工作内容
|
||||||
|
|
||||||
|
- 重构报销审批流,贯通小财管家计划、报销预审、申请提交和审批链路。
|
||||||
|
- 扩展管家计划流式接口、报销单服务、申请草稿、风险提示和上下文工具。
|
||||||
|
- 优化工作台 AI 模式、差旅报销创建页、申请详情页和文档中心交互。
|
||||||
|
- 更新 Docker、环境配置和忽略规则,配合新流程运行。
|
||||||
|
- 补充大量后端、前端和端到端测试,覆盖审批流、预算分析、申请确认和工作台入口。
|
||||||
|
|
||||||
|
## 提交记录
|
||||||
|
|
||||||
|
- `e124e4b` feat: 报销审批流重构与管家计划全链路贯通
|
||||||
18
document/work-log/2026-06-09.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# 2026-06-09 工作日志
|
||||||
|
|
||||||
|
## 远端依据
|
||||||
|
|
||||||
|
- 分支:`origin/main`
|
||||||
|
- 提交:`25724c3`
|
||||||
|
|
||||||
|
## 工作内容
|
||||||
|
|
||||||
|
- 同步报销流程和工作台近期改动,继续完善申请、报销、风险建议与工作台协同。
|
||||||
|
- 调整 Docker、GPU、Postgres 和环境配置,适配本地与容器化运行。
|
||||||
|
- 补充移动端相关资源和前端页面改动。
|
||||||
|
- 更新服务端报销、员工、本体、规则、用户代理和审批链路实现。
|
||||||
|
- 扩展工作台、申请详情、报销创建、审计和文档中心相关测试。
|
||||||
|
|
||||||
|
## 提交记录
|
||||||
|
|
||||||
|
- `25724c3` feat: 同步报销流程与工作台改动
|
||||||
15
document/work-log/2026-06-12.md
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# 2026-06-12 工作日志
|
||||||
|
|
||||||
|
## 远端依据
|
||||||
|
|
||||||
|
- 分支:`origin/main`
|
||||||
|
- 提交:`336fee9`
|
||||||
|
|
||||||
|
## 工作内容
|
||||||
|
|
||||||
|
- 更新仓库忽略规则,将 `.superpowers` 工具缓存目录排除出版本管理。
|
||||||
|
- 降低本地代理工具缓存误入库风险。
|
||||||
|
|
||||||
|
## 提交记录
|
||||||
|
|
||||||
|
- `336fee9` chore: 忽略 .superpowers 工具缓存目录
|
||||||
17
document/work-log/2026-06-13.md
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# 2026-06-13 工作日志
|
||||||
|
|
||||||
|
## 远端依据
|
||||||
|
|
||||||
|
- 分支:`origin/main`
|
||||||
|
- 提交:`8b952c9`
|
||||||
|
|
||||||
|
## 工作内容
|
||||||
|
|
||||||
|
- 拆分差旅报销创建工作流,降低单页脚本和流程模型复杂度。
|
||||||
|
- 抽取差旅报销草稿、提示动作、附件、会话状态和提交组合等前端逻辑。
|
||||||
|
- 强化报销创建页的可维护性,为后续 AI 工作台与报销流程复用做准备。
|
||||||
|
- 补充报销创建、会话状态、建议动作和附件流程测试。
|
||||||
|
|
||||||
|
## 提交记录
|
||||||
|
|
||||||
|
- `8b952c9` refactor(travel): split reimbursement create workflow
|
||||||
19
document/work-log/2026-06-15.md
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# 2026-06-15 工作日志
|
||||||
|
|
||||||
|
## 远端依据
|
||||||
|
|
||||||
|
- 分支:`origin/main`
|
||||||
|
- 提交:`5747e85` 至 `9f7b8b4`
|
||||||
|
|
||||||
|
## 工作内容
|
||||||
|
|
||||||
|
- 恢复上传阶段规则中心复核,确保附件上传时的风险识别链路有效。
|
||||||
|
- 修正报销明细和风险建议对齐问题,让风险提示能对应到具体费用行。
|
||||||
|
- 细化差旅报销小财管家流程,覆盖申请、报销、计划、回显和提交流程。
|
||||||
|
- 更新规则表、后端服务、前端工作台和差旅报销创建页,补齐流程测试。
|
||||||
|
|
||||||
|
## 提交记录
|
||||||
|
|
||||||
|
- `5747e85` fix(risk): restore upload-time rule center review
|
||||||
|
- `7927417` fix(claim): align risk advice with expense rows
|
||||||
|
- `9f7b8b4` Refine travel reimbursement steward flow
|
||||||
26
document/work-log/2026-06-17.md
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# 2026-06-17 工作日志
|
||||||
|
|
||||||
|
## 远端依据
|
||||||
|
|
||||||
|
- 分支:`origin/main`
|
||||||
|
- 提交:`470f343` 至 `b8915a2`
|
||||||
|
|
||||||
|
## 工作内容
|
||||||
|
|
||||||
|
- 收窄差旅路线风险指标,减少误报并统一风险标记口径。
|
||||||
|
- 调整 Web 端口配置,补充工具临时目录忽略规则。
|
||||||
|
- 重构报销审批流,优化差旅详情、风险建议卡片和文档中心交互。
|
||||||
|
- 更新财务差旅与通信费用规则表。
|
||||||
|
- 同步报销审批流和预算分析测试。
|
||||||
|
- 归档用户报销票据附件,清理运行资产边界。
|
||||||
|
|
||||||
|
## 提交记录
|
||||||
|
|
||||||
|
- `470f343` fix(expense): narrow travel route risk indicators
|
||||||
|
- `0d525fa` chore: 忽略 .codex-temp 工具临时目录
|
||||||
|
- `09a66c7` chore: 将 web 端口由 5173 调整为 5273
|
||||||
|
- `1f4681f` feat(claim): 重构报销审批流并收敛风险标记
|
||||||
|
- `a3e5295` feat(rules): 更新财务差旅与通信费用规则表
|
||||||
|
- `0fac8b6` feat(web): 优化差旅详情、风险建议卡片与文档中心交互
|
||||||
|
- `4199feb` test: 同步报销审批流与预算分析测试
|
||||||
|
- `b8915a2` chore(storage): 归档用户报销票据附件
|
||||||
32
document/work-log/2026-06-18.md
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
# 2026-06-18 工作日志
|
||||||
|
|
||||||
|
## 远端依据
|
||||||
|
|
||||||
|
- 分支:`origin/main`
|
||||||
|
- 提交:`cce19e4` 至 `4d04f4e`
|
||||||
|
|
||||||
|
## 工作内容
|
||||||
|
|
||||||
|
- 完善 Steward 业务无关输入拦截,支持 `off_topic` 计划、前端引导话术和场景细分。
|
||||||
|
- 增强服务端启动 bootstrap、缓存预热和登录目录并发幂等控制。
|
||||||
|
- 仅放行财务业务相关问题的信号校验,强化业务边界。
|
||||||
|
- 更新差旅、通信等财务规则表,并清理用户历史报销票据附件。
|
||||||
|
- 优化工作台 AI 模式、差旅/风险建议交互、用户消息气泡和引用图标。
|
||||||
|
- 新增 X-Financial 改进路线图,补充未来改进方向。
|
||||||
|
- 更新忽略规则,避免 `.env`、`.nezha`、`.omo` 等本地或敏感配置入库。
|
||||||
|
|
||||||
|
## 提交记录
|
||||||
|
|
||||||
|
- `cce19e4` feat(steward): 拦截业务无关输入返回 off_topic 计划
|
||||||
|
- `4343253` feat(steward): 前端支持 off_topic 与引导话术
|
||||||
|
- `c28e99b` chore(gitignore): 忽略 .nezha/ 与 .omo/ 本地工具目录
|
||||||
|
- `38653fa` chore(storage): 清理用户历史报销票据附件
|
||||||
|
- `35372c6` feat(rules): 更新差旅与通信费用等财务规则表
|
||||||
|
- `59ba76c` feat(startup): 服务端启动 bootstrap 与缓存预热
|
||||||
|
- `3f17619` fix(auth): 登录目录就绪幂等化与并发控制
|
||||||
|
- `127d603` feat(ontology): 仅放行财务业务相关问题的信号校验
|
||||||
|
- `a6674a1` feat(steward): off_topic 场景细分与引导回复
|
||||||
|
- `0cde1f8` feat(web): 工作台 AI 模式与差旅/风险建议交互优化
|
||||||
|
- `a2f67af` docs: 新增 X-Financial 改进路线图
|
||||||
|
- `3131112` style(web): 调整 AI 模式用户消息气泡布局与引用图标
|
||||||
|
- `4d04f4e` chore(gitignore): 忽略 .env 防止敏感配置入库
|
||||||
27
document/work-log/2026-06-20.md
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# 2026-06-20 工作日志
|
||||||
|
|
||||||
|
## 远端依据
|
||||||
|
|
||||||
|
- 分支:`origin/main`
|
||||||
|
- 提交:`3d69f85` 至 `3b74a33`
|
||||||
|
|
||||||
|
## 工作内容
|
||||||
|
|
||||||
|
- 细化申请单阶段风险可见性并更新规则表。
|
||||||
|
- 拆分工作台 AI 模式报销预审和文档查询模型。
|
||||||
|
- 新增申请核对预览快速建单接口,并统一平台管理员判定。
|
||||||
|
- 接入 AI 工作台申请预览动作,支持申请单草稿保存和删除权限统一。
|
||||||
|
- 将单号规则收紧为 `A/R/D + 8 位` 紧凑格式,并适配后端测试。
|
||||||
|
- 增强 AI 工作台会话、文档卡片渲染和 AI 文档查询卡片。
|
||||||
|
|
||||||
|
## 提交记录
|
||||||
|
|
||||||
|
- `3d69f85` feat(risk): 申请单阶段风险可见性细化与规则表更新
|
||||||
|
- `304bbe1` feat(web): 工作台 AI 模式报销预审与文档查询模型拆分
|
||||||
|
- `729d833` feat(server): 新增申请核对预览快速建单接口与平台管理员判定统一
|
||||||
|
- `96c2e10` feat(web): 统一平台管理员判定与 AI 工作台申请预览动作接入
|
||||||
|
- `47c6a4b` refactor(server): 单号规则收紧为 A/R/D+8 位紧凑格式
|
||||||
|
- `81e990a` feat(server): 申请单支持草稿保存并统一删除权限口径
|
||||||
|
- `0cda750` feat(web): AI 工作台会话与文档卡片渲染增强
|
||||||
|
- `8158716` test(server): 适配 A/R/D 紧凑单号格式
|
||||||
|
- `3b74a33` feat(web): AI 文档查询卡片重构与单号判定统一
|
||||||
24
document/work-log/2026-06-21.md
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# 2026-06-21 工作日志
|
||||||
|
|
||||||
|
## 远端依据
|
||||||
|
|
||||||
|
- 分支:`origin/main`
|
||||||
|
- 提交:`8b34954` 至 `08a4fa3`
|
||||||
|
|
||||||
|
## 工作内容
|
||||||
|
|
||||||
|
- 增强 AI 文档详情引用解析和查询卡片展示。
|
||||||
|
- 优化差旅申请详情进度 viewer、审批信息、加载态和领导意见事件样式。
|
||||||
|
- 移除顶栏 AI 快捷操作区,让非首页顶栏更收敛。
|
||||||
|
- 优化 OCR 处理:PDF 文本层可用时跳过 worker 调用,并补装 `poppler-data`。
|
||||||
|
- 将 AI 工作台附件改为卡片化展示,支持单项移除并适配卡片样式与交互。
|
||||||
|
|
||||||
|
## 提交记录
|
||||||
|
|
||||||
|
- `8b34954` feat(web): AI 文档详情引用解析与查询卡片增强
|
||||||
|
- `24b5b71` feat(web): 差旅申请详情进度 viewer 与审批/加载态组件增强
|
||||||
|
- `1986b0d` style(web): 移除顶栏 AI 快捷操作区并优化差旅领导意见事件样式
|
||||||
|
- `88e91a5` feat(ocr): PDF 文本层可用时跳过 worker 调用并补装 poppler-data
|
||||||
|
- `669d22e` feat(web): 差旅领导意见事件结构化与申请审批信息增强
|
||||||
|
- `d660a96` feat(web): AI 工作台附件改为卡片化展示并支持单项移除
|
||||||
|
- `08a4fa3` style(web): AI 工作台附件卡片样式与交互适配
|
||||||
28
document/work-log/2026-06-22.md
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# 2026-06-22 工作日志
|
||||||
|
|
||||||
|
## 远端依据
|
||||||
|
|
||||||
|
- 分支:`origin/main`
|
||||||
|
- 提交:`6d33ba5` 至 `bc743ad`
|
||||||
|
|
||||||
|
## 工作内容
|
||||||
|
|
||||||
|
- 执行 800 行源码限制重构,拆分服务、组件、composable、工具函数和测试辅助模块。
|
||||||
|
- 拆分 Docker 主应用编排和完整本地栈,补充 Docker 说明、重构计划和 UI 参考图。
|
||||||
|
- 更新差旅、交通、通信等财务规则表。
|
||||||
|
- 恢复差旅详情子组件样式。
|
||||||
|
- 扩展报销单输出工号/邮箱,并支持申请人邮箱前缀匹配。
|
||||||
|
- 新增报销单关联申请单门控和草稿检测流程。
|
||||||
|
- 增强申请单预览编辑器和报销流程细节。
|
||||||
|
|
||||||
|
## 提交记录
|
||||||
|
|
||||||
|
- `6d33ba5` refactor: enforce 800 line source limits
|
||||||
|
- `607e127` chore(docker): 拆分主应用编排与完整本地栈
|
||||||
|
- `e42deda` docs: 同步 Docker 编排说明并补充重构计划与 UI 参考
|
||||||
|
- `103f225` chore(rules): 更新差旅/交通/通信等财务规则表
|
||||||
|
- `1b04ee1` fix(web): restore travel detail child component styles
|
||||||
|
- `aa965da` feat(server): 报销单输出工号/邮箱并扩展申请人邮箱前缀匹配
|
||||||
|
- `ba444a5` feat(web): 报销单新增关联申请单门控与草稿检测流程
|
||||||
|
- `ded8b39` feat(web): 申请单预览编辑器增强与报销流程细节适配
|
||||||
|
- `bc743ad` chore(rules): 更新公司通信费报销规则表
|
||||||
28
document/work-log/2026-06-23.md
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# 2026-06-23 工作日志
|
||||||
|
|
||||||
|
## 远端依据
|
||||||
|
|
||||||
|
- 分支:`origin/main`
|
||||||
|
- 提交:`84a8998` 至 `73966b3`
|
||||||
|
|
||||||
|
## 工作内容
|
||||||
|
|
||||||
|
- 新增票据文件夹资产缓存和统一文档预览生成,完善 OCR、票据夹和附件分析链路。
|
||||||
|
- 前端接入票据夹资产缓存,完善 AI 工作台附件流程、智能入口识别和草稿附件选择。
|
||||||
|
- 统一 `WEB_PORT` 回退到 `5173`,并让烟雾检查支持开关。
|
||||||
|
- 更新交通、通信、差旅、出差等财务规则表。
|
||||||
|
- 重构通知中心列表行布局和时间标签格式。
|
||||||
|
- 移除误跟踪的 `expense_claims` 运行时票据文件。
|
||||||
|
- 修复孤儿申请预览消息,触发重新生成可编辑表格。
|
||||||
|
- 合并财务工作流模块,抽取申请事实解析、Steward 计划拆分、可信 HTML、加载状态和文档协议常量。
|
||||||
|
|
||||||
|
## 提交记录
|
||||||
|
|
||||||
|
- `84a8998` feat(server): 票据文件夹资产缓存与文档预览统一生成
|
||||||
|
- `e725b7f` feat(web): 票据夹资产缓存接入与 AI 工作台附件流程完善
|
||||||
|
- `dc4cad2` chore(env): WEB_PORT 统一回退为 5173 并烟雾检查改为可开关
|
||||||
|
- `0122f3b` chore(rules): 更新交通/通信/差旅/出差等财务规则表
|
||||||
|
- `8094333` style(web): 通知中心列表行布局重构与时间标签格式化
|
||||||
|
- `f17098a` chore(repo): 移除误跟踪的 expense_claims 运行时票据文件
|
||||||
|
- `1f40ce3` fix(web): 孤儿申请预览消息触发重新生成可编辑表格
|
||||||
|
- `73966b3` refactor: consolidate finance workflow modules
|
||||||
138
document/work-log/2026-06-24.md
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
# 2026-06-24 工作日志
|
||||||
|
|
||||||
|
## 当日工作内容
|
||||||
|
|
||||||
|
- 09:41:我开始为 X-Financial 补一个专门写修改日志的项目级 Skill,目标是让后续每次 bugfix、新功能、重构或配置/文档修改之后,都能留下有时间、有操作、有判断的增量记录。
|
||||||
|
- 修改:新增 `agent-change-log` Skill,约定触发场景、每日日志位置、三段式结构、TODO 勾选规则和拟人化记录方式。
|
||||||
|
- 修改:新增 Skill 展示元数据,方便后续通过 `$agent-change-log` 识别和调用。
|
||||||
|
- 修改:准备把 `AGENTS.md` 接上强触发规则,避免后续代理只记得“写代码”而忘了“写修改记录”。
|
||||||
|
- 操作:沿用既有 `document/work-log/YYYY-MM-DD.md` 日志目录,不另起一套新路径,避免历史记录分裂。
|
||||||
|
- 验证:09:42 已补做结构检查,见下一条记录。
|
||||||
|
- 影响:后续修改会从“最终总结”升级为“过程可追踪”,当天工作内容、遗留问题和 TODO 会随着每轮修改持续增长。
|
||||||
|
|
||||||
|
- 09:42:我按刚写好的 `agent-change-log` 规则做了第一次自检,并把验证结果回填到当天日志里。
|
||||||
|
- 操作:运行 `git diff --check` 检查本轮涉及文件的空白问题。
|
||||||
|
- 操作:用 `rg` 检查 Skill frontmatter、`AGENTS.md` 触发规则,以及日志中的 `当日工作内容`、`遗留问题`、`TODO` 三个固定标题。
|
||||||
|
- 验证:`git diff --check` 无输出,说明补丁没有空白错误;`rg` 能命中 `agent-change-log`、日志路径和三段式标题。
|
||||||
|
- 影响:这个日志 Skill 已经有了可执行的触发条件、固定记录位置和第一次样例记录,后续修改可以直接照这个格式增量追加。
|
||||||
|
|
||||||
|
- 09:43:我继续检查了新 Skill 的版本管理可见性,确认它已经落在本机项目目录,但默认会被 `.gitignore` 忽略。
|
||||||
|
- 操作:运行 `git check-ignore -v` 检查 `.codex/skills/agent-change-log/SKILL.md` 和 `agents/openai.yaml` 的忽略来源。
|
||||||
|
- 验证:命中 `.gitignore:10:.codex/`,说明普通 `git status` 不会显示这个新 Skill;`ls` 已确认两个文件真实存在。
|
||||||
|
- 影响:本机后续可以使用这个 Skill,但如果要把它随仓库交付,需要后续显式调整忽略规则或强制加入版本管理。
|
||||||
|
|
||||||
|
- 09:44:我收紧了 `.gitignore` 规则,让新建的 `agent-change-log` Skill 能进入普通版本管理视野,同时继续保护 `.codex` 下其他本地状态。
|
||||||
|
- 修改:把 `.codex/` 改成 `.codex/*`,再只放行 `.codex/skills/agent-change-log/**`。
|
||||||
|
- 操作:保留 `.codex` 其他内容默认忽略,避免把本地运行缓存、临时状态或其他未审查 Skill 一起暴露出来。
|
||||||
|
- 验证:`git status --short` 已能看到 `agent-change-log` 的两个新增文件;`git diff --check` 仍然无输出。
|
||||||
|
- 影响:后续提交这个 Skill 时不需要强制添加,普通 `git status` 就能看到相关文件。
|
||||||
|
|
||||||
|
- 10:01:我按你的补充要求,把“先拉取/检查 Git,分析其他智能体提交”纳入 `agent-change-log` 的硬流程。
|
||||||
|
- Git 提交检查:已运行 `git fetch --all --prune`;`HEAD..origin/main` 未发现 upstream 新提交。当前本地 `main` 显示 ahead 1,后续在 10:02 单独补充分析本地 ahead 提交。
|
||||||
|
- 修改:更新 `agent-change-log`,新增 `Required Git Check`,要求写日志前执行 `git fetch --all --prune`、`git status -sb`、上游分支识别和 `git log HEAD..@{u}`。
|
||||||
|
- 修改:更新 Skill 展示提示,把 upstream commit check 也列入触发场景。
|
||||||
|
- 修改:更新 `AGENTS.md`,明确每次日志更新前先做 Git 拉取检查;工作区干净且只落后上游时可 `git pull --ff-only`,脏工作区或可能冲突时只 fetch 并记录风险。
|
||||||
|
- 操作:没有在当前脏工作区执行自动 merge/rebase,避免把其他大量未提交改动和远端提交混在一起。
|
||||||
|
- 验证:`rg` 已命中 `Required Git Check`、`git fetch --all --prune`、`HEAD..@{u}` 和 `git pull --ff-only`;`git diff --check` 无输出。
|
||||||
|
- 影响:后续日志会同时记录“我改了什么”和“其他智能体已经提交了什么”,不会只盯着本地 diff。
|
||||||
|
|
||||||
|
- 10:02:我把本地 ahead 提交也纳入日志 Skill,因为当前仓库已经出现 `origin/main..HEAD` 的本地提交。
|
||||||
|
- Git 提交检查:`origin/main..HEAD` 发现 `9321260 chore(skills): add git checkpoint commit loop`,提交时间为 2026-06-24 09:47:05,内容包括新增 `git-checkpoint-commit` Skill、展示元数据、`checkpoint_commit.py` 脚本,并调整 `.gitignore`。
|
||||||
|
- 修改:更新 `agent-change-log`,要求同时检查 `HEAD..@{u}` 和 `@{u}..HEAD`,分别识别 upstream 新提交和本地 ahead 新提交。
|
||||||
|
- 修改:更新 `AGENTS.md`,把本地 ahead 提交也纳入“其他智能体提交摘要”的记录范围。
|
||||||
|
- 操作:用 `git show --stat` 和 `git show --name-only` 查看 `9321260` 的文件清单与提交信息,没有改写该提交。
|
||||||
|
- 验证:`rg` 已命中 `@{u}..HEAD`、`本地 ahead` 和 `9321260`;`git diff --check` 无输出。
|
||||||
|
- 影响:后续即使其他智能体只做了本地 commit、还没 push,也会被日志 Skill 捕捉并分析。
|
||||||
|
|
||||||
|
- 10:21:自动记录 `9321260` 提交后的工作日志。(auto-log:9321260)
|
||||||
|
- Git 提交检查:fetch 失败:error: cannot open '.git/FETCH_HEAD': Operation not permitted;upstream `origin/main`;upstream 新提交:未发现;本地 ahead 提交:9321260 (HEAD -> main) chore(skills): add git checkpoint commit loop。
|
||||||
|
- 修改:最近提交为 `9321260 chore(skills): add git checkpoint commit loop`。
|
||||||
|
- 操作:manual 验证自动日志脚本 触发 `tools/agent-change-log/update_change_log.py`,自动读取 Git 状态并写入当天日志。
|
||||||
|
- 验证:自动脚本只记录提交和 Git 状态,不替代业务测试;业务验证仍以本次任务实际运行结果为准。
|
||||||
|
- 影响:提交后即使执行代理忘记手动写日志,也会留下最低限度的时间、提交和分支状态记录。
|
||||||
|
|
||||||
|
- 10:21:我排查了“修改 bug 或新增功能后不会自动写日志”的根因,并补上可执行自动化入口。
|
||||||
|
- Git 提交检查:当前权限下 `git fetch --all --prune` 会失败,错误是 `.git/FETCH_HEAD` 不允许写入;`origin/main..HEAD` 仍显示本地 ahead 提交 `9321260`。
|
||||||
|
- 修改:新增 `tools/agent-change-log/update_change_log.py`,用于自动生成并追加当天工作日志,包含 Git 双向提交检查、最近提交摘要、重复提交去重和 fetch 失败遗留问题记录。
|
||||||
|
- 修改:新增 `.githooks/post-commit`,提交后调用日志脚本,作为真正的自动触发点。
|
||||||
|
- 修改:新增 `tools/agent-change-log/install_post_commit_hook.sh` 和 `README.md`,说明如何把版本化 hook 安装到本地 `.git/hooks/post-commit`。
|
||||||
|
- 修改:更新 `AGENTS.md`,明确 Skill/AGENTS 只是规则,自动触发必须安装 post-commit hook;如果当前环境无法写 `.git`,必须如实记录限制。
|
||||||
|
- 操作:尝试执行 `tools/agent-change-log/install_post_commit_hook.sh`,当前沙箱返回 `mkdir: .git/hooks: Operation not permitted`,所以本轮不能实际安装本地 hook。
|
||||||
|
- 验证:`update_change_log.py --dry-run --no-fetch` 能输出日志条目;默认 dry-run 能捕获 fetch 权限错误并输出遗留问题;真实运行脚本已成功追加 10:21 的 `auto-log:9321260` 记录。
|
||||||
|
- 影响:现在仓库里已经有可执行自动日志链路;等环境允许写 `.git` 后,安装 hook 即可实现“提交后自动写日志”。未提交的普通文件变更仍无法由 Git 自动判断,需要代理在任务结束前主动调用日志 Skill。
|
||||||
|
|
||||||
|
- 10:24:我修正了 PDF 票据 OCR 的转图链路,避免“预览图丢中文但仍继续 OCR”的假成功。
|
||||||
|
- Git 提交检查:`git fetch --all --prune` 失败,错误是 `.git/FETCH_HEAD: Operation not permitted`;`git status -sb` 显示当前 `main...origin/main [ahead 1]`;`HEAD..@{u}` 未输出 upstream 新提交;`@{u}..HEAD` 显示本地 ahead 提交 `9321260 chore(skills): add git checkpoint commit loop`。
|
||||||
|
- 修改:`document_preview.py` 把 PDF 渲染器标识升级为 `pdf-raster-cjk-safe-v3`,新增 `render_pdf_pages()`,按 `pdftoppm -> mutool -> gs -> pdftocairo` 尝试生成 PNG;遇到 `Missing language pack`、`Unknown font tag`、`No font in show` 这类会丢中文的输出时,不再接受该 PNG。
|
||||||
|
- 修改:`ocr.py` 删除“PDF 文本层可用就直接构建识别结果”的分支,PDF 现在必须先转图片,再进入 Paddle OCR worker;文本层仅作为后续纠错/兜底材料,不再绕过图片 OCR。
|
||||||
|
- 修改:`docker-compose.yml`、`docker-compose.full.yml`、`bootstrap_paddleocr_mobile.sh`、`bootstrap_paddleocr_gpu.sh` 增加 `mupdf-tools`,让容器里有 `mutool` 作为中文安全转图 fallback。
|
||||||
|
- 修改:`test_ocr_service.py` 增加回归测试,覆盖运行时依赖包含 `mupdf-tools`、Poppler 字体映射失败时尝试下一个渲染器、坏转图不再调用 OCR worker、以及 PDF 文本层可用时仍必须调用 OCR worker。
|
||||||
|
- 操作:执行 `python3 -m py_compile`、`git diff --check` 和 `rg` 残留检查;尝试按项目规范执行容器内定向 pytest。
|
||||||
|
- 验证:`py_compile`、`git diff --check`、残留搜索均通过;容器 pytest 未能执行,原因是当前 Codex 进程访问 Docker socket 被拒绝:`permission denied while trying to connect to the docker API at unix:///Users/caoxiaozhu/.docker/run/docker.sock`。
|
||||||
|
- 影响:后续 PDF 票据如果第一轮转图丢中文,会自动切换渲染器;如果所有渲染器都不可用,会明确失败并提示转图问题,而不是把缺中文的坏图送进 OCR。
|
||||||
|
|
||||||
|
- 10:28:我确认 10:06 上传的票据夹记录当前仍是 PDF 预览,并修正 OCR 文本层纠错会清空 PNG 预览的问题。
|
||||||
|
- Git 提交检查:`git fetch --all --prune` 失败,错误是 `.git/FETCH_HEAD: Operation not permitted`;当前 `main...origin/main [ahead 1]`;`HEAD..@{u}` 未输出 upstream 新提交;`@{u}..HEAD` 仍显示本地 ahead 提交 `9321260 chore(skills): add git checkpoint commit loop`。
|
||||||
|
- 发现:`server/storage/receipt_folder/caoxiaozhu_xf.com/f0dd9b4a-f7b7-4784-ade7-4e31b71f0b12/meta.json` 中 `preview_kind=pdf`、`preview_media_type=application/pdf`,前端 `ReceiptFolderView.vue` 因此走 `<iframe>` 而不是 `<img>`。
|
||||||
|
- 根因:`OcrService._finalize_document()` 里旧逻辑在 PDF 文本层参与纠错且 OCR 文本占位符比例较高时,会主动把 `preview_kind` 和 `preview_data_url` 清空;票据夹保存时拿不到 `data:image/png`,只能回退到原 PDF 预览。
|
||||||
|
- 修改:删除这段清空 PNG 预览的旧保护逻辑;转图阶段已经负责识别坏 PNG,文本层纠错不再影响预览资产类型。
|
||||||
|
- 操作:执行 `python3 -m py_compile server/src/app/services/ocr.py server/tests/test_ocr_service.py`、`git diff --check` 和 `rg` 残留检查。
|
||||||
|
- 验证:语法检查、空白检查和残留搜索均通过;容器 pytest 仍因 Docker socket 权限无法执行。
|
||||||
|
- 影响:后续 PDF OCR 结果即使使用文本层修正字段,也会保留 OCR 转图得到的 PNG 预览,票据夹应写入 `preview_kind=image`、`preview_media_type=image/png`。
|
||||||
|
|
||||||
|
- 10:32:我继续排查“重新上传仍是 PDF 识别”的原因,确认最新 10:29 上传命中了旧 OCR 结果,并修正 OCR 内存缓存失效条件。
|
||||||
|
- Git 提交检查:`git fetch --all --prune` 失败,错误是 `.git/FETCH_HEAD: Operation not permitted`;当前 `main...origin/main [ahead 1]`;`HEAD..@{u}` 未输出 upstream 新提交;`@{u}..HEAD` 仍显示本地 ahead 提交 `9321260 chore(skills): add git checkpoint commit loop`。
|
||||||
|
- 发现:最新两条票据夹记录 `e9e3c0be-...`、`9ecee0d8-...` 上传时间为 10:29,但仍是 `preview_kind=pdf`、`ocr_line_count=0`,`ocr_text` 仍是只有英文和数字的旧坏结果。
|
||||||
|
- 根因:`OcrService._build_cache_key()` 只使用 OCR 语言、设备、模型和文件 digest,没有包含 PDF 转图/识别管线版本;同一 PDF 重新上传时可能复用旧的内存缓存,导致新转图逻辑没有机会执行。
|
||||||
|
- 修改:新增 `OCR_RESULT_CACHE_PIPELINE_VERSION`,把当前 PDF 渲染器标识 `DocumentPreviewAssets.PDF_RENDERER_ID` 和 `no-pdf-direct` 策略写入 OCR cache key。
|
||||||
|
- 修改:`test_ocr_service.py` 增加 `test_ocr_cache_key_includes_pdf_render_pipeline_version`,防止以后改转图管线但继续吃旧缓存。
|
||||||
|
- 操作:执行 `python3 -m py_compile server/src/app/services/ocr.py server/tests/test_ocr_service.py`、`git diff --check` 和 `rg` 检查;尝试执行容器内定向 pytest。
|
||||||
|
- 验证:本地语法检查、空白检查和残留搜索通过;容器 pytest 仍因 Docker socket 权限被拒绝,未能执行。
|
||||||
|
- 影响:后端加载新代码后,同一 PDF 会因为 cache key 变化重新进入 PDF 转 PNG + Paddle OCR 流程,而不是复用旧的 PDF fallback/坏识别结果。
|
||||||
|
|
||||||
|
- 10:40:我修正了 AI 工作台附件预览弹窗在左侧侧边栏存在时视觉不居中的问题。
|
||||||
|
- Git 提交检查:`git fetch --all --prune` 失败,错误是 `.git/FETCH_HEAD: Operation not permitted`;当前 `main...origin/main [ahead 1]`;基于本地 ref,`HEAD..@{u}` 未输出 upstream 新提交;`@{u}..HEAD` 仍显示本地 ahead 提交 `9321260 chore(skills): add git checkpoint commit loop`。
|
||||||
|
- 修改:`workbench-ai-file-preview-dialog.css` 将预览遮罩改成“侧边栏占位列 + 主内容列”的网格布局,弹窗固定落在第二列并居中;同时保留折叠侧栏变量和 900px 以下移动端单列布局。
|
||||||
|
- 修改:`workbench-ai-composer-components.test.mjs` 增加回归断言,锁定附件预览必须按主内容区域居中,而不是按整个 viewport 居中。
|
||||||
|
- 操作:检查本地 `5173` 可达,返回 `HTTP/1.1 200 OK`;检查项目没有现成 Playwright/Puppeteer 依赖,未新增依赖。
|
||||||
|
- 验证:`node --test web/tests/workbench-ai-composer-components.test.mjs` 通过 8/8;`npm --prefix web run build` 构建通过;`git diff --check` 无输出。
|
||||||
|
- 影响:用户点击附件打开预览时,弹窗会避开左侧 AI 工作台侧边栏,在右侧主工作区内居中展示,截图里的“偏左/不居中”观感会收敛。
|
||||||
|
|
||||||
|
- 10:41:我补修了票据夹 PDF 保存阶段的预览持久化,避免 OCR 后仍把源 PDF 当成附件预览展示。
|
||||||
|
- Git 提交检查:`git fetch --all --prune` 失败,错误是 `error: cannot open '.git/FETCH_HEAD': Operation not permitted`;当前 `main...origin/main [ahead 1]`;基于本地 ref,`HEAD..@{u}` 未输出 upstream 新提交;`@{u}..HEAD` 显示本地 ahead 提交 `9321260 chore(skills): add git checkpoint commit loop`。
|
||||||
|
- 修改:`receipt_folder.py` 在 `document.preview_data_url` 缺失且源文件是 `application/pdf` 时,保存阶段立即调用 `DocumentPreviewAssets.render_pdf_first_page()` 生成 `preview.png`,并把 `preview_kind`、`preview_media_type`、`preview_rendered_with` 写成图片预览元数据;只有渲染异常时才回退到源 PDF 预览。
|
||||||
|
- 修改:`test_receipt_folder_service.py` 新增 `test_receipt_folder_pdf_save_eagerly_renders_image_preview`,覆盖 PDF OCR 结果没有内嵌预览图时,票据夹仍应主动生成图片预览的场景。
|
||||||
|
- 操作:读取当前票据夹存储里的两条 PDF meta,确认旧记录存在 `preview_kind=pdf`、`preview_media_type=application/pdf` 且没有 `preview.png`,这与前端显示 PDF 预览的问题一致。
|
||||||
|
- 验证:`python3 -m py_compile server/src/app/services/receipt_folder.py server/tests/test_receipt_folder_service.py` 通过;宿主机缺少 pytest 和后端依赖,容器 pytest 又因 Docker socket 权限被拒绝,暂未完成项目要求的容器定向测试。
|
||||||
|
- 影响:后续新上传或重新 OCR 保存的 PDF 票据会优先拥有 PNG 图片预览,前端票据夹预览应走 `<img>` 体验;既有已经写成 PDF fallback 的旧 meta 还需要单独刷新。
|
||||||
|
|
||||||
|
## 遗留问题
|
||||||
|
|
||||||
|
- 09:41:当前 Skill 是新建在项目级 `.codex/skills` 目录里,本轮可以通过文件检查验证结构,但是否被未来会话自动加载还依赖 Codex 对项目 Skill 的刷新机制。建议后续新开会话或下一次任务时确认 Skill 列表是否出现 `agent-change-log`。
|
||||||
|
- 09:43:`.codex/` 曾被 `.gitignore` 整体忽略,新建的 `agent-change-log` 默认不会进入普通提交范围;09:44 已改成只放行该 Skill。建议后续如果还新增其他项目 Skill,也按同样方式逐个显式放行,别一次性开放整个 `.codex`。
|
||||||
|
- 10:01:当前工作区已有大量未提交改动,且本地 `main` ahead 1。建议后续如果真的发现 upstream 新提交,先用 fetch 和 `HEAD..@{u}` 写日志;只有在工作区干净、可快进时再执行 `git pull --ff-only`,避免把其他智能体提交和本地半成品混到一起。
|
||||||
|
- 10:02:本地 ahead 提交也可能来自其他智能体,不能只看 upstream behind。建议后续日志固定同时记录 `HEAD..@{u}` 和 `@{u}..HEAD` 两个方向。
|
||||||
|
- 10:21:自动日志触发时发现 fetch 未成功:失败:error: cannot open '.git/FETCH_HEAD': Operation not permitted。建议后续在有 Git 写权限和网络权限的环境里重新执行拉取检查。
|
||||||
|
- 10:21:当前环境不能写 `.git/hooks`,所以 post-commit hook 模板已经入库,但尚未安装到本 checkout。建议在有 `.git` 写权限的环境执行 `tools/agent-change-log/install_post_commit_hook.sh`。
|
||||||
|
- 10:24:本轮未能在容器内执行 pytest,也未能实际确认容器是否已安装 `mupdf-tools`。建议在 Docker 权限恢复后重建/重启 `x-financial-main`,执行定向 OCR 测试,并在 5173 用真实 PDF 票据确认预览图和 OCR 字段都保留中文。
|
||||||
|
- 10:28:10:06 那条既有票据记录已经写成 PDF fallback,代码修复不会自动改写旧 meta。建议重新上传一次同一 PDF,或在容器权限恢复后触发票据重识别/重建预览,确认新记录变为 PNG 预览。
|
||||||
|
- 10:32:最新 10:29 上传仍然写成 PDF,说明运行中的后端可能还没加载最新代码,或本轮上传发生在缓存版本修复之前。建议重启后端/重建容器后再重新上传,确认 OCR cache key 已包含 `pdf-image-ocr:`。
|
||||||
|
- 10:40:本轮可以确认 5173 服务可达、结构测试和生产构建通过,但当前环境没有可调用的浏览器自动化插件,项目也没有现成 Playwright/Puppeteer 依赖,所以未生成真实页面截图。建议在具备浏览器自动化的环境回放一次附件预览,确认主内容区居中效果。
|
||||||
|
- 10:41:票据夹 PDF 保存阶段已补主动生成图片预览,但当前沙箱不能访问 Docker socket,无法运行容器内 pytest,也无法刷新已有 PDF 票据的旧 meta。建议 Docker 权限恢复后先跑定向测试,再对旧记录触发 `resolve_preview` 或重识别来补 `preview.png`。
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
|
||||||
|
- [x] ~~检查 `agent-change-log` 的 frontmatter、触发描述和日志模板是否完整。~~(完成于 09:42,证据:`rg` 命中 frontmatter、日志路径和三段式标题;`git diff --check` 无输出)
|
||||||
|
- [x] ~~将 `AGENTS.md` 接入“每次修改后调用日志 Skill”的项目级规则。~~(完成于 09:42,证据:`AGENTS.md` 已新增 `变更日志 Skill 规范`)
|
||||||
|
- [x] ~~如果需要把 `agent-change-log` 随仓库提交,确认是调整 `.gitignore` 放行还是用强制添加方式纳入版本管理。~~(完成于 09:44,证据:`.gitignore` 已只放行 `.codex/skills/agent-change-log/**`)
|
||||||
|
- [x] ~~把 Git 拉取检查和其他智能体 upstream 提交分析纳入 `agent-change-log`。~~(完成于 10:01,证据:Skill 已新增 `Required Git Check`,`AGENTS.md` 已要求日志前运行 `git fetch --all --prune` 和 `git log HEAD..@{u}`)
|
||||||
|
- [x] ~~把本地 ahead 提交也纳入 `agent-change-log` 的提交分析范围。~~(完成于 10:02,证据:Skill 和 `AGENTS.md` 已新增 `git log @{u}..HEAD`,并记录 `9321260` 本地 ahead 提交)
|
||||||
|
- [x] ~~补上提交后自动写日志的可执行脚本和 hook 模板。~~(完成于 10:21,证据:`update_change_log.py` dry-run 与真实写入成功,`.githooks/post-commit` 已新增)
|
||||||
|
- [ ] 在有 `.git` 写权限的环境执行 `tools/agent-change-log/install_post_commit_hook.sh`,让提交后自动写日志真正启用。(来源:10:21 当前沙箱安装失败)
|
||||||
|
- [ ] 在后续每次 bugfix、新功能、重构或配置/文档修改后,调用 `agent-change-log` 并增量更新当天日志。(来源:09:41 用户要求)
|
||||||
|
- [ ] 重建/重启 `x-financial-main`,确认容器内存在 `mutool`,并执行 OCR 定向 pytest。(来源:10:24 PDF 中文转图链路修复)
|
||||||
|
- [ ] 在 5173 真页重新上传/预览火车票 PDF,确认预览 PNG 不再丢中文,OCR 字段不再出现“乘车人/站点”等中文缺失或错位。(来源:10:24 PDF 中文转图链路修复)
|
||||||
|
- [ ] 重新上传 10:06 同款 PDF 或触发该票据重识别,确认新的 `meta.json` 写入 `preview_kind=image` 和 `preview_media_type=image/png`。(来源:10:28 PNG 预览保留修复)
|
||||||
|
- [ ] 后端加载缓存版本修复后,重新上传同一 PDF,确认不会再命中旧 OCR 缓存,`ocr_line_count` 和 PNG 预览都来自新转图流程。(来源:10:32 OCR cache key 修复)
|
||||||
|
- [ ] 在有浏览器自动化能力的环境回放 AI 工作台附件预览弹窗,截图确认弹窗按侧边栏右侧主内容区居中。(来源:10:40 附件预览弹窗布局修复)
|
||||||
|
- [ ] Docker 权限恢复后运行票据夹 PDF 预览定向测试,并刷新已有 `preview_kind=pdf` 的旧票据 meta。(来源:10:41 PDF 保存阶段主动生成图片预览修复)
|
||||||