- core_ro 新增 get_nav_as_of(D10) / get_redeem_fee_rules / list_share_lots(S1 确定性排序) / sum_remain_qty(仅 >0) / get_holding;不动 get_latest_nav 与 list_trades_range 白名单 - 新增 share_lot_repository:core_share_lot 读侧 FIFO 贪心选批 + 汇总,排序复用 core_ro 的 ORDER BY(D18 单一副本) - 新增 tests/test_share_lot.py 15 用例;pytest 全量 624 passed / 3 skipped(基线 609,零回归) - 同步开发计划 §5.1 执行记录与交接文档 §B 状态(v1.5 / T-3 ✅ / 基线 624) Co-Authored-By: WorkBuddy <workbuddy@tencent.com>
15 KiB
2026-09-10 工作日志
本日两条线:架构改进线收尾闭环(本文主体)+ 基金转换线第 4 步开发计划待启动。
一、接手与状态核对(会话起始)
读入:docs/交接文档-基金转换.md(v1.0)· docs/memory/MEMORY.md §0 · docs/交接文档-架构改进.md(v1.1)
· docs/项目框架设计/架构设计-基金转换交易.md §15/§15.1 · docs/memory/{TODO,ITERATION}.md · AGENTS.md。
基线复核:python -m pytest -q(系统 Python 3.13.14)→ 510 passed(9.93s)。
设计资产核对:tests/_ddl.py:50-54 的 core_holding 仍为 market_value/quantity 且无 PK ——
与 T-0 描述一致,架构文档无误。
⚠️ 核对中发现的两处「文档与实况不符」(以实况为准)
037ce7e「未 push」是过期表述。 实测git ls-remote origin:refs/heads/risk-control-agent=fffb78a= 本地 HEAD;git merge-base --is-ancestor 037ce7e fffb78a→ 成立。即架构改进线全部提交(含其后 5 个文档提交)早已推送。 本地git branch -vv显示origin/risk-control-agent: gone只是本地远程跟踪引用失效,非远程分支被删。- 基金转换线 6 个设计文件全部 untracked(未纳入版本库):
docs/PRD/PRD-基金转换交易.md、docs/项目框架设计/架构设计-基金转换交易.md、基金转换-审查意见处置表.md、评审待办-风控主架构与基金转换.md、docs/交接文档-基金转换.md、scripts/dev/calc_convert_demo.py。 → 用户拍板:先 commit 入库(只 commit,不 push)。
二、架构改进线 §7.2 手工冒烟(七项,全部代跑,2026-09-10)
用户授权「七项全部代跑」。所有临时改动跑完即恢复。
第 1 项 · 无 key 启动告警 ✅ PASS
- 本机
.env的DEEPSEEK_API_KEY本就为空(实测raw_value_len = 0),故「清空」态即当前态。 uvicorn app.main:app(端口 8123)→ 1 秒就绪,/health→200 {"status":"ok","env":"development"}。- 进程存活 → 告警不阻塞启动 ✓。
- 日志命中:
DEEPSEEK_API_KEY 未配置,对话将走降级回复(前缀 (LLM 未配置:请在 .env 设置 DEEPSEEK_API_KEY 后重启)),LLM 能力不可用(app/main.py:66-72)。
第 2 项 · 恢复 key → 无告警 ✅ PASS(口径替代,已留痕)
- 替代说明:本机无真实 DeepSeek key,「恢复 key」一支改用非空占位值(
sk-smoke-placeholder-not-a-real-key)。 告警分支只判not settings.deepseek_api_key,不校验 key 有效性,故该替代足以验证条件分支。 - 改后
key_present: True→ 启动(端口 8124)→/health200 → 日志未出现该告警 ✓。 - 顺带验证 trace 中间件:响应头
x-trace-id: trc-48349abc526e4055/x-request-id: req-612a3f2acb8349d6✓。 .env已还原,key_present: False(原状)✓。
第 3 项 · 交易阻断 + 放行各一次 ✅ PASS
| 场景 | 请求(debug 头 X-Debug-Role: risk_demo / X-Debug-Actor: STAFF-DEMO) |
响应 |
|---|---|---|
| 阻断(SOP A-2) | CUST-4001 / PROD-161725 / subscribe / 20000 | blocked=true,block_response_code=SUIT_AGE_CONFIRM,needs_branch_confirm=true,rule_refs=["FM-01"] |
| 放行(SOP A-3) | CUST-3001 / PROD-510300 / subscribe / 500000 | blocked=false,triggered_rules=["RISK-001","RISK-002"],alert_ids=["ALT-20260910-7BCBBC94"] |
与 SOP 记录的预期逐字一致。 库内核验:
core_trade:阻断单TRD-20260910-C1D8AA26未落库 ✓;放行单TRD-20260910-FE545DF0已落库(confirmed, 500000.00)✓risk_suitability_log:CUST-4001is_blocked=1✓;risk_alert出suitability单ALT-20260910-652280E1(pending_review, score 90)✓audit_log:suitability_block / suitability_alert_created、trade_request / suitability_blocked(rule_id=SUIT_AGE_CONFIRM)、trade_request / trade_accepted(放行)、risk_judgement / alert_created✓
第 4 项 · 预警聚合行为不变 ✅ PASS
SOP A-4:CUST-9527 / PROD-510300 / subscribe / 1000 连发 4 笔:
| 笔次 | triggered_rules |
alert_ids |
|---|---|---|
| 1 | [] |
[] |
| 2 | [] |
[] |
| 3 | ["RISK-003"] |
["ALT-20260910-C8600425"] |
| 4 | ["RISK-003"] |
["ALT-20260910-C8600425"] ← 与第 3 笔同一张单(并入,非新建) |
库内核验:
risk_alertCUST-9527 当日pending_review单数 = 1 ✓;payload.events长度 = 2 ✓audit_log呈alert_created(1184) →alert_appended(1187)` 序列,聚合语义在审计层可证 ✓- 4 笔交易全部落库(
TRD-20260910-B66CB0D8/B39E1456/83D58A41/79EDC16E)✓
注:
risk_alert.status实际取值为pending_review(文档口头简称「pending」)。首次核库我按status='pending'查得 0 条, 系断言写错而非系统问题,修正后为 1 ✓。
第 5 项 · Redis 不可用 → 退回进程内锁 ✅ PASS(口径替代,已留痕)
- 替代说明:本机 Redis 为
redis-server.exe(PID 7716,Services 会话),无文档化启动方式、redis-server不在 PATH、sc.exe被本机安全策略拉黑,杀掉后无法保证原样拉起(且FLOW.md明示其非权威数据源)。 改用REDIS_URL=redis://127.0.0.1:6399/0(死端口):应用侧抛ConnectionError,与真宕机同一条代码路径 (redis_gateway._ensure()→ 命令异常 →locks._acquire_redis的except Exception→unavailable→ 进程内锁),且完全可逆。 - 结果:启动不被阻塞(1s,
/health200)→ 交易返回blocked=false,alert_ids=["ALT-20260910-7BCBBC94"],业务照常完成 ✓ - 日志明确出现 2 次
Redis 锁不可用,退回进程内锁:lock:agg:event:CUST-3001:2026-09-10(alert_service聚合锁)、lock:l3:CUST-3001(profile_l3L3 锁)✓ - 底层异常:
redis.exceptions.ConnectionError: Error 10061 connecting to 127.0.0.1:6399,被正确吞噬未上抛 ✓
第 6 项 · Redis 恢复 → 行为一致 ✅ PASS
redis.Redis.from_url(settings.redis_url).ping()→ True(redis://127.0.0.1:6379/0)。- 同笔交易 →
blocked=false,alert_ids=["ALT-20260910-7BCBBC94"](并入同单)✓ - 日志中
退回进程内锁命中 0 行 → 确实走 Redis 锁路径,未降级 ✓ triggered_rules由["RISK-001","RISK-002"]变为+RISK-003:CUST-3001 当日累计至第 3 笔触发频次规则, 属预期累积行为,非不一致。
第 7 项 · 调换装饰器验证 T-202 守卫变红 ✅ PASS(本项价值最高)
守用例:tests/test_audit_middleware.py::test_audit_middleware_runs_inside_trace_middleware:210。
| 步骤 | 结果 |
|---|---|
| ① 基线 | 1 passed(绿) |
② 调换 main.py 两装饰器(trace 先注册 → 变最内层;audit 后注册 → 变最外层) |
已调换,行序:trace_middleware@89 / audit_middleware_entry@117 |
| ③ 跑守卫 | 1 failed ✓ 变红 |
| ④ 失败断言原文 | AssertionError: audit 若先于 trace 执行,此处会静默为空 / assert '' @ test_audit_middleware.py:221 |
| ⑤ 还原 | sha256 前后同为 d9d7559445dffd2a4576cdc5454030d3acae5fd4c076de8daa5a35f53802510a → 字节级一致 ✓ |
| ⑥ 再跑守卫 | 1 passed(转绿)✓ |
| ⑦ 现场核对 | git status --short app/main.py 空、无残留 *.smoke.bak ✓ |
→ 守卫确实能抓住「audit 先于 trace 执行 → 全站审计静默丢 trace_id 且不报错」这一回归。设计意图达成。
三、冒烟副产物与现场恢复
3.1 集成测试失败(防护行为,非回归)
冒烟后在真 MySQL 上跑全量:507 passed / 3 failed,全部落在 tests/test_integration_risk.py:
_assert_a3_clean→CUST-3001 今日已有 confirmed 交易(影响 RISK-002 累计/RISK-003 频次口径)(我的TRD-20260910-FE545DF0)_assert_a4_clean→CUST-9527 今日已有 confirmed 交易(A-4 频次计数失真)(我的TRD-20260910-B66CB0D8)test_a7_handle_state_machine_compliance_forbidden→ 级联KeyError: 'a3_alert_id'
→ 这正是核查单⑥「演示/测试同日交叉防护」前置断言在按设计工作(交接文档已预警)。
3.2 演示库重灌(用户拍板:现在重灌)
按 docs/项目框架设计/演示SOP-风控模块.md §2 脚本化方式执行(MYSQL_PWD 传密码,避开 reset.ps1 交互 -p 卡死):
DROP DATABASE IF EXISTS jinrong_core; DROP DATABASE IF EXISTS jinrong_agent;- 依序灌 11 个 SQL:
scripts/core/00~06→表设计/01-mysql-共用底座.sql→表设计/02-mysql-agent专用.sql→scripts/agent/seed-aml-list.sql→scripts/demo/prepare_risk_demo.sql python scripts/sync/sync_advisor_rel.py
完成标志三项全部吻合:AML 名单 8 条 · prepare_risk_demo 7 行测评(expires_at 剩余 275 天)·
sync_advisor_rel upserted 33 rows。
3.3 全量复跑(用户要求「改完后再跑一次」)
510 passed, 656 warnings in 9.52s → 复绿 ✓
现场状态:.env 已还原(key 为空、REDIS_URL 为 6379)✓ · app/main.py 字节级还原且 git 无改动 ✓ · 无残留 .smoke.bak ✓。
四、回写清单
| 文档 | 改动 |
|---|---|
docs/项目框架设计/TODO-架构改进.md |
T-107 手工冒烟勾选 + 完成判定块三勾 + 状态块改「全部闭环」+ push 状态纠正 |
docs/交接文档-架构改进.md |
v1.1 → v1.2;状态块重写(push 纠正 + 两处替代口径留痕);§7.3 全勾;§10 重写为结项 |
docs/交接文档-基金转换.md |
§9「另一条线的遗留」改为已闭环,纠正 push 表述 |
docs/memory/MEMORY.md |
§0 末尾「待办两条线」改为「架构改进线已结项」+ push 纠正常见坑 |
docs/memory/TODO.md |
模块侧开放项「架构改进线 · 收尾」勾选并附七项证据摘要 |
docs/memory/ITERATION.md |
新增 2026-09-10 架构改进线收尾闭环 迭代行 |
docs/memory/2026-09-10.md |
本文件(新建) |
五、下一步
架构改进线:结项,无待办。(可选:push 后打里程碑 tag,待用户拍板)
基金转换线:第 4 步「产出开发计划」 —— 输入已齐备:
docs/项目框架设计/架构设计-基金转换交易.md §15(任务映射 T-0~T-13)+ §15.1(依赖拓扑与并行分组)+ §12(风险表);
产出落点 docs/项目框架设计/开发计划-基金转换交易.md(待创建)。
六、交接文档合并为单一入口 + 全仓指向统一(2026-09-10 晚)
6.1 用户指令与判定
- 指令:「由版本库的交接文档为主,这两个交接文档你合并成一个新的放到这次更新」+ 指向项目根
交接文档.md。 - 追加纠正:「统一一下,不是早都说过交接文档是给你 AI 接手用的吗」 ——
交接文档的定位 = AI 接手入口,所以全仓指向必须唯一,且绝不能指向过期文件,否则新会话会被误导。
(
docs/下两份留档停在 v1.0 / v1.1,不含 T-2/T-2b、609 passed、D20 实施等进度 —— 是个真实陷阱。)
6.2 落地
项目根 交接文档.md → v3.0(545 行),三线合并为单一入口:
§0 公共层(项目是什么 / 铁律与禁止事项 / 开发运行手册 / 已知坑 10 条 / 发现问题怎么办)·
§A 风控模块主线(原主干)· §B 基金转换线(含工作区最新版 v1.4)· §C 架构改进线(含工作区最新版 v1.2)。
最大价值:这两份工作区最新版从未提交,随时可能丢,现已完整固化。
全仓 10 处指向统一 → 交接文档.md §A/§B/§C:
AGENTS.md(含顶部新增「⚡ 需要接手/开工先读交接文档.md」)· docs/memory/{MEMORY,TODO,FRAMEWORK} ·
docs/PRD/PRD-架构改进与稳定性加固.md · docs/项目框架设计/{开发计划-架构改进,TODO-架构改进,开发计划-基金转换交易}.md。
两份 docs/交接文档-*.md 保留为历史留档,顶部加醒目横幅:「本文件已废弃(2026-09-10)—— 请勿据此开工,
正确入口 交接文档.md §B/§C,内容已过期,勿读」 —— 不删除(保留仓库历史),但明确失效。
未入库:交接文档.md 在 .gitignore:47 内,用户确认「不进提交」。
6.3 ⚠️ 事故:git rm 静默抹除整个 docs/(复现 2 次,已零损失恢复)
- 现象:
git rm(带不带-f均如此)删除docs/下两个中文名文件 →docs/全部 54 个文件从工作区消失, 命令返回退出码 0 不报错。 - 定位:①
ls/find/Read 三方确认真实删除;②git checkout HEAD -- docs/完整还原 54 文件(索引与 HEAD blob 完好); ③ 无自定义 hooks(core.hooksPath空);④ 同一中文路径ls完全正常 → 触发条件就是git rm本身; ⑤ 换 纯rm -f <精确路径>→ 正常。 - 损失:零内容丢失(HEAD blob 完好)。代价:本轮引用修改被连带还原 2 次(重做 3 次)。
- 纪律(已写入
交接文档.md§0.4 第 10 条 +.workbuddy/memory/MEMORY.md):- ❌ 本仓库禁止对
docs/下文件用git rm; - ✅ 删文件用纯
rm -f <精确路径>+git add -A记录删除; - ✅ 批量删除后立刻
find <dir> -type f | wc -l复核,异常立即git checkout HEAD -- <dir>。 - 根因未查明,规避即可。
- ❌ 本仓库禁止对
七、设计方法论固化为 skill + 记忆精简(2026-09-10 晚)
动机:项目记忆 MEMORY.md 与交接文档膨胀——13 问 / AIcoding 六步 / 独立审查协议 / 写计划 4 法 等项目无关的方法论每个项目都重写一遍,且挤占了项目状态信息。
落地:
- 新建用户级 skill
design-doc-selfcheck(~/.workbuddy/skills/design-doc-selfcheck/SKILL.md)—— 固化:AIcoding 六步流程 · 设计自检 13 问(含 why/翻车案例)· PRD 独立 AI 审查协议(自包含包 + 只报告不改动 + 逐条判定)· 写开发计划 4 法 · 真实翻车案例库(4 处外部事实漏网 / 分类混用 / 公式副本 / 重置伴随数据 / 方言互斥)。 - 精简项目
MEMORY.md(205 行 → ~70 行):删除已入 skill 的方法论 verbatim,只留三条线状态、git rm禁忌、交接文档定位、基金转换核心事实与业务口径、交易发起主体合规、D20 账号,并指向 skill。 - 交接文档 §B 顶部加 skill 指针:本线设计方法论已固化,避免重复维护。
效果:方法论跨项目可复用(新项目直接加载 skill);本项目记忆回到「状态 + 红线 + 口径」本职。