Commit Graph
17 Commits
Author SHA1 Message Date
GaoYiYuan_0626 cde0c226fe 基金转换 T+1 模型:T-15/T-16/T-17 收官(842 绿 / 真库 9/9 / 转换线第 5 步完成)
T-15 D28 部分成交专项:
- sqlite +1 终态单幂等 skipped 口径裁定(ConfirmConflict 仅限读后状态才变窗口)
- 真库 confirm +3 组 19 项(E2 占用释放双向 / G2 actual_qty=0 → rejected / H2 撤单后确认)→ 102/102
- CONVERT_STRESS Barrier(2) 窄窗争批:恰 1 confirmed + 1 rejected
- 突变实证防御纵深:④可用量复核 / ⑤plan_lots / 事务内哨兵三道防线拆任一道仍收敛 rejected

T-16 D29 资金流中转:
- _insert_cash_flows 全仓唯一写入点(out/redeem 费前 + in/subscribe 净转入,remark=convert:{gid} 同事务)
- test_confirm_writes_no_cash_flow 反转为恰 2 条 + 金额对账(T-7 登记闭环)
- 真库 apply A2 组 + B 组 0 残留 → 30/30;confirm 反转断言 → 103/103
- FK 坑(core_cash_flow.fk_cf_customer 挡客户删除):5 处清理段补删

T-17 D30 share_class + A/C 互转:
- _validate_products 纯新增拦截分支:两端 share_class 非空且不同才查 allow_ac_convert(任一端=1 两向放行)
- 口径裁定 2 条(R-12 字面偏差,待用户追认):NULL 不参与 A/C 判定 / 同类走一般转换规则
- 联网核实(用户铁律):A/C 互转需管理人开通(摩根 2025-11 公告)= 开关真实载体;持有期重新起算与本仓一致
- 种子 ⑥ 段(双开对/双关对照/同类对照);sqlite +4 → 842 passed / 8 skipped;真库 accept H 组 → 43/43
- 突变:分支失效 → closed 红,还原绿

文档:开发计划 T-15~T-17 DoD 全勾 + 执行记录 · 基线 842 · TODO/MEMORY/AGENTS/交接文档 v4.5 终态(第 5 步收官 → 下一步第 6 步集成测试)
2026-09-12 13:42:49 +08:00
GaoYiYuan_0626 1a615bbbef 基金转换 T+1 模型:T-14 D27 产品舍入真正接入 + 联网核实纠偏(837 绿 / 真库 9/9 / 种子 v1.1 全 2 位)
- 接入面 4 处单点收敛:core_ro.get_share_digits(唯一回退链:规则行→core_product.share_digits→PLACES=2)· calc.in_qty 加 digits=PLACES 可选参数 · 确认段(business_type=convert)· 网关申购折算(subscribe);redeem 份额申报无折算无消费方
- 边界裁定:只接落库侧(开发计划 DoD 即边界),响应展示维持 q(D2) 收敛(2 位产品逐字节零漂移);PRD §2.5.2 展示按产品覆盖为登记开口
- 联网核实(用户铁律):主流 2 位 ✅ · 位数按各基金合同配置 ✅(南方 2012 调整公告)· 舍去 TRUNCATE 型真实存在 ✅ · 货基 2 位 ✅ · 「指数基金份额 4 位」证伪 ❌(ETF 联接/指数合同全 2 位)→ 11-seed-share-rule.sql v1.1:3 产品 9 行 4→2 + 头注重写为核实出处;「易方达 ETF 场外整数位」无证据有反证(登记开口待拍板)
- 测试 +7(830→837 零回归):calc 层 2 + confirm 段 3(回退链三层各 1 + business_type 干扰行)+ 申购段 2;4 位种子行 = D27 机制验证载体(docstring 钉明)
- 突变验证 2 组(confirm/gateway digits 改固定 2 → 各 2 红,还原零残留);真库 9/9 退出码 0(seed 重灌 42 行全 2 位生效)
- 开口 2 项待用户拍板:① PRD §2.5.3 易方达句修订 ② rounding_mode=truncate 消费接入(真实存在、T-14 范围外)
2026-09-12 12:41:20 +08:00
GaoYiYuan_0626 3bc84a093d 基金转换 T+1 模型:T-13 convert_fund 退役 + 并发面重写 + 全量门禁(830 绿 / 真库 9/9 / 紧池 100%) 2026-09-12 11:52:27 +08:00
GaoYiYuan_0626 34c7d0840d 基金转换 T+1 模型:T-10 普通申赎批次维护 + T+2 校验 + rebuild_lots
FR-C16 份额批次全生命周期 + FR-C25 T+2 可赎回 + redeem 份额申报 D26 落地普通赎回侧:

- trade_gateway:_redeem_quote 走 available_qty_with_inflight 硬校验(R-3,
  申报超可赎抛 InsufficientShares 不静默裁剪);_maintain_lots redeem 分支
  三重裁剪 = T+2 过滤 → D8 补建 → 在途占用 → 哨兵 FIFO 扣减;subscribe 落新批次
- core_ro.list_share_lots / share_lot_repository.select_for_convert 加
  available_from T+2 半开区间过滤(R-4,日历缺行降级不过滤,金额/扣减同口径)
- gateway_repository 扣批次加哨兵 remain_qty >= :q(rowcount!=1 回滚防超扣)

验证:test_share_lot +10 / test_trade_gateway +1 → 全量 844 passed / 10 skipped
(基线 834 + 11 零回归);真库 verify_convert_api 89/89(H 节提前 + H2 在途
占用拦截断言);rebuild_lots --dry-run 58 持仓 0 补建 0 写入;突防验证区分度成立
2026-09-11 21:24:32 +08:00
GaoYiYuan_0626 e04b44c44a 基金转换 T+1 模型:T-9 api 层(受理 202 + 撤单/确认/查询接口 + 网关分派 + redeem 份额申报)
三接口路径以 PRD 为准(裁定 11/12):
- app/api/convert_admin.py 新增 POST /api/simulate/trade/convert/{gid}/cancel(交易 owner 闸门)
  + POST /api/admin/convert/confirm?accept_date=(risk_officer)+ GET /api/simulate/trade/convert/{gid}(查询 scope 闸门)
- simulate.py convert 分支受理 202 + 受理回执(两类 202 分辨 accepted/processing)
- trade_gateway 分派改调 accept_convert(SUPPORTED_TRADE_TYPES 维持 2 类型)
- redeem 份额申报(D26/R-6:qty 入参,_redeem_quote = qty * T 净值 - 赎回费)
- errors.py 新增 CANCEL_NOT_ALLOWED / CONCURRENT_CONFLICT(均 409)

修正 2 处口径缺陷(测试打穿揭示,非只改测试):
- _rebuild_quote 的 out_nav 改直读 core_convert_lot_detail.nav(反推致 1.3604 -> 1.3600 漂移)
- _accept_idempotent 字段面扩展与受理回执对齐(幂等重试客户端可取到预计确认日)

验证:端到端 13 passed(T+1 两段链路重写);全量 834 passed / 10 skipped;
真库 verify_convert_api.py 88/88,存量 4 脚本零回归;3 组突变验证命中后还原
2026-09-11 20:37:45 +08:00
GaoYiYuan_0626 048f1a9e1e 基金转换 T+1 模型:T-7 确认段落地(confirm_service 三段编排 + T+1 批处理)
【新增】
- app/service/convert/confirm_service.py:confirm_one(8 步确认)+ confirm_batch
  (按业务日捞单 / 整批锁 / 串行 / 单笔容错)。关键裁定:
  · T 日净值用 get_nav_on 精确匹配,缺则 nav_pending(绝不回退旧净值);
  · 扣批次 + 2 条流水 + 转入批次 + 两端持仓 + 明细 + 受理单置 confirmed
    同处一个 Core 单库事务,状态被抢(rowcount!=1)→ 整事务回滚;
  · 引擎在事务 commit 后跑,异常不阻断已成立的交易(FR-C28);
  · 部分成交 actual=min(申请,可用),被抢部分占用自然释放(R-10)。
- app/service/convert/format.py / audit.py / engine_call.py:展示规格、审计、
  引擎调用三处共用出口抽出(受理/确认两段不再各写一份,避免口径漂移)。
- scripts/dev/verify_convert_confirm.py:真库验证 81 项断言,含 PRD §5.3.2
  示例在真库上逐字节重放(68020.00/612.18/67407.82/333.36/67074.46/34945.54/-0.0049)。

【修复 · 受理-确认接口契约缺口】
强制全转是**受理段决策**(受理时 qty 已收敛为实际全转量),确认段拿不到原始
申请量、无法复现该判定。修法:
- 受理段把 forced_full_transfer 落受理单 remark(新增 REMARK_FULL_TRANSFER);
- 确认段改为**继承受理决策、不再重判最低持有**(plan_lots 不传 min_hold_qty)
  —— 重判会因 T→T+1 可用份额变化得出与受理承诺不一致的结论(擅自扩大客户指令);
- remark 支持多标记 `;` 连接(full_transfer;partial)。
- MySQL rowcount=changed rows 陷阱:nav_pending 重试不得复用 transition_status
  的冲突判定,改为 status 未变时不迁移、返回 transitioned=False。

【其他】
- convert_service:新增 cancel_convert(T 日撤单,两道闸门)、_t1_t2_dates
  (日历边界 None 容错);受理响应改为 PRD §5.3.1 字段;convert_fund 标 Deprecated。
- convert_core_repository:ConvertApplyInput 加 convert_request_id/diff_fee/
  request_remark;_apply_convert_once 末步 _confirm_request 事务内置状态守卫。
- convert_request_repository:_end_of_day 统一闭区间语义;新增 reject()。
- 测试:新增 tests/test_convert_confirm.py(24 例);全量 827 passed / 10 skipped。
2026-09-11 19:35:37 +08:00
GaoYiYuan_0626 43cf2a1372 基金转换 T-13 后补:apply_convert 死锁 1213 服务端自动重试(用户拍板)
- 跨客户并发 InnoDB 1213 死锁由「抛给上层」改为数据访问层自动重试整个事务
  (MySQL 官方口径 Retry the entire transaction);重试次数/退避基数走
  settings(convert_deadlock_retry_max/base_ms),只重试 1213,1205 等照旧上抛
- 真库证据:8 客户并发实测触发 4 次 1213,服务端重试全部第 1 次收敛,
  外部退避兜底 0 次触发,8/8 成功、份额守恒
- sqlite 单测 +3(重试后落库/预算耗尽上抛/1205 不重试)+ 2 组突变验证命中后恢复
- 全量 739 passed/10 skipped;CONVERT_STRESS 并发 9/9;真库 apply 24/24、service 35/35 零回归
2026-09-10 20:30:30 +08:00
GaoYiYuan_0626 5e6fa06d03 基金转换 T-10:普通申赎批次维护(FR-C16)
让 core_trade 的普通申赎同步维护 core_share_lot 批次,为 convert 提供权威份额口径。

落地(改码 3 处 + 新增 2 个脚本)
- gateway_repository:新增 insert_share_lots / deduct_share_lots,各自单事务、走 rw 账号;
  只落已分配结果、不含分配逻辑,避免出现第二份 FIFO 口径
- share_lot_repository:__init__ 增可选 core_ro 入参,让 trade_gateway 复用同一份 FIFO 选批口径(D18)
- trade_gateway:新增 _nav_as_of / _maintain_lots,在落流水后、规则引擎前调用
  · subscribe:取 T 日(含)前最新净值 → qty = amount ÷ 净值(2 位 HALF_UP)→ 建批次(confirmed_at = T)
  · redeem:FIFO 扣减;无批次但有持仓 → D8 兜底补建后再扣;两者皆无 → 降级跳过
  · 整段 try 包住,任何异常只 warning,绝不阻断交易(R-c(1))
- 新增 scripts/core/rebuild_lots.py:按 core_holding 快照重建批次(L-7),与网关 D8 同调 bootstrap_lots;
  默认只补建无批次的持仓行(幂等),--force 才先删后建,--dry-run 只报告
- 新增 scripts/dev/verify_convert_lots.py:真库验证脚本(MySQL 8.0.46)

口径订正(联网查证 4 家管理人业务规则后)
- redeem 的 amount ÷ 净值 折算属本项目简化建模,不是行业标准
- 行业铁律是「金额申购、份额赎回」:投资者以份额申报,登记机构按 T 日净值算金额
  (睿远业务规则 §65 / 华泰保兴 §69 / 东方基金 §57 / 国投瑞银 §33;无一家公募支持按金额赎回)
- 派生风险:未知价法下 T 日净值当日不可得(T+1 公告),_nav_as_of 实取 T−1 净值,
  故此处算出的份额只是估算值
- 已记入 PRD §10.1 已知差异清单;trade_gateway 注释同步订正

验证
- pytest -q → 714 passed / 3 skipped(基线 697 加 17,零回归)
- R16 test_redeem_accepted_without_alert 零改动通过(由 R-c(1) 降级保住)
- 真库 20/20;T-6 24/24、T-7 35/35 复跑零回归;真库隔离数据零残留
- 突变验证 2 组:切断接线 → 精准 2 条红;关掉 D8 兜底 → 精准 2 条红(含 D18 同源断言)
2026-09-10 18:28:48 +08:00
GaoYiYuan_0626 d0097d6004 基金转换 T-9:API 模型 + 网关分派(HTTP 层 convert 走通)+ 展示位数口径修复
一、T-9 本体:HTTP 层 convert 端到端走通

- api/simulate.py:TradeRequest 三型字段分池(subscribe/redeem → product_id+amount;
  convert → from/to_product_id + qty + 可选 client_request_id)+ model_validator 分支校验;
  未知类型放行给网关抛 400(保住既有 purchase → 400 断言);model_dump(exclude_none=True);
  PROCESSING → 202;异常捕获由 except LookupError 收窄为 except NotFoundError
  (原写法把 KeyError 这类编程错误静默转成 404,实测掩盖 convert 分支真实诊断)。
- gateway/trade_gateway.py:移除 convert 显式拒绝,新增 _submit_convert 分派
  (只做参数映射 + 仓储装配);convert 不写 trade_request 审计(审计归 convert_service)。
- utils/response.py:错误体合入 exc.extra(TOO_MANY_LOTS 的 batch_count/max_lots);
  既有 ApiError 无 extra 属性 → 老错误体逐字节不变。
- utils/trace.py + main.py:正则收敛单点定义。执行期发现 trace.py 与 main.py 各有一份
  内容完全相同的白名单副本 —— S4 要防的「漂移」其实已经发生,现将常量上移 trace.py
  成公开 HEADER_ID_PATTERN(同时解决 main→simulate 反向导入成环)。

二、展示位数口径修复(执行期发现 → 联网核验 → 修复 → 文档订正)

发现:同一逻辑响应两种写法 —— 首次 "53456.95" vs 幂等重放 "53456.9500",数值相等、字符串不等。
根因不是 T-7 写错,是契约缺位:§2.5 只规定「金额/份额 2 位」,净值、费率、申请份额的
回显位数根本没定义 → 实现只能 str(Decimal) 原样出网 → 位数随数据来源漂移。

修复:convert_service 新增 _q(value, unit) + _D2/_D4 规格常量作对外唯一出口 ——
金额/份额 2 位、净值/费率/份额尾差 4 位;响应 + 审计 summary + 异常日志共用该出口;
原 _s() 全部替换。首次路径幂等(除 requested_qty/actual_qty/lot[].qty 由 4 位补齐 2 位外不变)。

依据(2026-09-10 联网核验 7 家管理人公告):金额/份额「四舍五入保留至小数点后两位」;
「申请转换份额精确到小数点后两位」;净值保留 4 位第 5 位四舍五入(中欧/国泰公告由 3 位提高至 4 位);
费率以百分比 2 位表示。已知不统一:易方达 ETF 场外份额取整数位、南方基金取截断 → 取主流口径
并记入 PRD 已知差异(未来接真实 TA 需按基金合同配置化)。

三、文档订正

- PRD → v0.9.2:§2.5 拆 2.5.1 计算精度 / 2.5.2 展示位数(新增按字段分类的规格表 + 外部依据);
  §5.3 示例 requested_qty/actual_qty/lot_breakdown[].qty 4 位 → 2 位(原示例与 §2.5
  「计算与对外展示按 2 位」自相矛盾,属漏改);字段类型约定补「位数不自由 + 两条路径须逐字节一致」。
- 架构 → v1.0.1:§1 原则 11 补「str() 前必须按 §2.5.2 量化」,无结构变更。

四、验证

- 新增 tests/test_convert_integration.py(8 条真 MySQL 端到端,CNV-TEST-/TRD-TEST- 前缀隔离):
  折算与 PRD §5.3 逐项吻合、两条流水同组、持仓与批次如实变动、明细 completed + 审计、
  幂等重试不产生第二组、跨主体 400、未知类型 400,以及
  「首次与重放逐字段逐字节相等」+「展示位数规格」两条新闸门。
- test_trade_gateway.py +17(11 条错误码映射全表参数化 · 202 · 200 透传 · 不写 trade_request 审计)。
- test_integration_risk.py:R15 处置 —— 端到端已迁入新文件,原槽位改造为
  test_invalid_type_400_and_no_new_trade_audit(改用 purchase 触发),保住「校验失败不落审计」不变量。
- pytest -q → 697 passed / 3 skipped(基线 672 +25,零回归)。
- 真库复跑:T-6 24/24 · T-7 35/35 · T-8 31/31;calc_convert_demo.py 15/15。
- 突变验证 4 组:关掉 convert 分派 → 21 条红;关掉错误体 extra 展开 → 精准 1 条;
  关掉 client_request_id 正则 → 精准 1 条;关掉 _q() 展示量化 → 2 条红
  (assert '50000.0000' == '50000' 直接复现原缺陷)。均已恢复。
2026-09-10 18:00:20 +08:00
GaoYiYuan_0626 82c9467fb7 基金转换 T-6:apply_convert 阶段一单事务(core 库唯一写入口)
新增 app/gateway/convert_core_repository.py:两条流水(redeem/subscribe,
R-b 不使用 ENUM 的 convert)+ N×条件 UPDATE 批次扣减 + 转入新批次
+ 两端 core_holding + N×计费明细,全部收口在 with engine.begin() 单事务。

实现级要点(与开发计划 §6.1 的三处差异,已回写该节执行记录):
- core_holding 改用「基于列当前值的增量 UPDATE」,入参不带持仓快照:
  MySQL 的 UPDATE 是当前读,并发两笔自然累加;用快照算绝对值会互相覆盖。
- 数值参数参与算术时写成 (:x + 0.0):实测 sqlite 在 UPDATE 算术表达式中
  不把 TEXT 绑定参数转数值(传 '120' 时 c 不变),加 +0.0 后两库一致。
- pnl_pct 拆成独立 UPDATE 重算,避开 MySQL「SET 从左到右」的顺序坑。

验证:pytest 639 passed / 3 skipped(基线 634 +5,零回归);
新增 scripts/dev/verify_convert_apply.py 真 MySQL 验证 24/24 一致,
含真并发两笔首次转入同一产品的终态断言(MySQL RR 的 gap lock 实测留痕)。
2026-09-10 16:26:42 +08:00
GaoYiYuan_0626 c5182f1910 feat(convert): 基金转换 T-0/T-0b 门禁 + T-1 数据层 + T-2/T-2b 纯函数与实算回填
T-0 / T-0b(门禁 · 2026-09-10)
- T-0:sqlite 与 MySQL 结构对齐 —— core_holding 统一为 qty/cost_amount/as_of/pnl_pct
  + PK + UNIQUE(customer_id, product_id);补 core_product_nav;新增建库自校验
  _assert_ddl_aligned()(R-g);test_db.py 增 3 条门禁用例(含反向验证门禁失效)
- T-0b:DB 账号分离(D20)—— 新增 scripts/core/00-grant.sql(三账号逐表授权);
  settings.py 增 3 组账号;db.py 改 get_engine(db, role),缓存键改为 (库名, 角色),
  账号未配置回退单账号;core_ro→ro / gateway_repository→rw / risk·session_repository→rw;
  tests/conftest.py 四处显式 role="admin"(R-e)

T-1(数据层)
- scripts/core/01-ddl.sql:新建 core_fee_rule / core_share_lot / core_convert_lot_detail;
  core_trade 加 convert_group_id + idx_convert_group;core_product 加 8 列 + fee_rate 补 COMMENT
- 新增 07-seed-fee-rule.sql(赎回费 5 档 × 14 产品,按 22 号文 §10)/ 08-seed-share-lot.sql
  (58 行持仓 → 61 行批次,Σ remain_qty 恒等于 qty)/ 09-seed-org.sql(管理人 + TA +
  申购费率 + 最低持有余额,v1.1 按「管理人全产品线」重排)
- reset.ps1 追加 07/08/09;02-mysql-agent专用.sql 追加 risk_convert_detail
- tests/_ddl.py 同步 4 表 + 新增 REQUIRED_CONVERT_TABLES 建库门禁
- 新增 scripts/dev/verify_convert_seed.py(pymysql 等价 reset 流程 + 8 条 DoD 断言,
  含断言 ⑧「费率档 ↔ product_type 匹配」,越档即 FAIL)

T-2 / T-2b(纯函数包 + 示例实算回填)
- 新增 app/service/convert/ 7 文件:__init__ / types / calc / fee / nav / lot_bootstrap / errors
  (纯函数,不查库、不碰 SQL;所有量化显式 ROUND_HALF_UP;lot_bootstrap 用 zlib.crc32
   保证 D18 跨进程同源)
- 新增 tests/test_convert_calc.py 93 用例(12 类:HALF_UP 反向自证 / 分档边界 /
  FIFO 含同 confirmed_at 兜底 / 双口径 / 强制全转与强制赎回 / PRD §5.3 全链自证 /
  纯函数零 IO 依赖断言)
- 重写 scripts/dev/calc_convert_demo.py:去掉脚本内公式副本,改为调用生产 calc.py,
  末尾与 PRD §5.3 逐项比对(不一致即退出码 1),兼作一致性门禁

验证
- pytest 609 passed / 3 skipped(516 → +93,零回归)
- verify_convert_seed.py 8/8 PASS;calc_convert_demo.py 15/15 与 PRD §5.3 一致

文档:PRD v0.9.1(费率分类修正)· 架构 §7 签名回填 / §8.3 错误码注 / §15 T-2 完成 ·
开发计划 §1.5 新增 R-h + §4.2·§4.3 执行记录 · AGENTS.md · docs/memory
2026-09-10 14:45:55 +08:00
GaoYiYuan_0626 66ec7eba08 feat: C6 FR-10 代理人行为链 RISK-008
代理人异常行为链识别(RISK-008)落地:
- 新增 agent_behavior_service:三条件证据聚合(A 诱导调仓/B AUTH_403_SCOPE 越权试探/C AUTH_403_NOT_OWNER|NOT_ASSIGNED 越权查询),按代理人维度独立出 pattern 单,payload.actor_id 指向代理人,审计仅 INSERT event_type=agent_behavior_detected。
- risk_repository 新增 list_audit_events / find_agent_behavior_alert / merge_agent_behavior_payload(同日同代理人一张单,证据并集)。
- trade_gateway.submit_trade 补 actor_id 透传(代理人发起交易归属发起人,缺省 SYSTEM);simulate 路由传入 auth.actor_id。
- chat_tools 新增 query_agent_behavior 只读 Tool(agent_id 过滤 + 客户脱敏),tool_service 补意图词与摘要。
- scripts/cron/agent_behavior_scan.py 定时扫描脚本。
- 修复 append_alert_event 序列化缺 default=str(C6 evidence 含 datetime 字段)。
- 单测 12 例(_count_induce 边界 / 三条件 / 出单去重 / payload 归属 / Tool 过滤脱敏)。
全量 pytest 482 passed 0 failed(470 基线 + 12 C6)。
2026-09-07 19:53:39 +08:00
GaoYiYuan_0626 b5fd52ef02 AL-08: 演示库重灌与种子核对对齐 main 基准——prepare_risk_demo.sql 改写 expires_at 口径(演示客户刷新为测评 90 天前/剩余 275 天,CUST-1004 保持过期演示 FM-03,替代 SUIT-008 evaluated_at+365 旧写法);演示 SOP 同步(§2 完成标志 33 客户口径+expires_at 剩余天数,A-1 预期改 SUIT_RISK_MISMATCH,A-2 改 FM-01 SUIT_AGE_CONFIRM 网点确认);网关阻断响应补全 main 契约字段(match_result/mismatch_type/requires_disclosure/needs_branch_confirm/rule_refs)+audit detail 加 block_response_code;集成测试 4 例旧口径断言更新(A-1 trace 一致性断机器码/A-1 audit JSON 断机器码/A-2 重写为 FM-01 语义/settings 退役断言)。SOP §2 脚本化全量重灌双库验证通过(AML 8 条/演示 7 行/sync 33 rows);全量 406 passed 0 failed 0 skipped(集成测试真库走 21 列新表+expires_at 数据恢复执行) 2026-09-07 17:49:39 +08:00
GaoYiYuan_0626 adf5e8013a AL-05: suitability 服务重构换核对齐 main 基准——判定内核由 SUIT-001~008 纯函数矩阵改为 core_ro.check_suitability(C×R 数据驱动);SuitabilityResult 扩 main 新字段(match_result 五值/mismatch_type 七值/requires_disclosure/needs_branch_confirm/block_response_code/rule_refs)并保留旧字段兼容层(rule_id=机器码别名/effective_level=customer_level/reasons=[reason]);check_core/cap_by_age/match_by_matrix/is_assessment_valid 删除(SUIT-006 被 FM-01 替换,SUIT-008 被 FM-03 expires_at 替换);settings.risk_assessment_valid_days 退役(.env/.env.example 注释);NotFoundError 不再抛(not_found 结构化,main 契约);写库走 build_suitability_log_row + insert_suitability_log 升级 21 列(rule_refs JSON 序列化);check_source 参数化(网关 r02_trade/risk.py manual)+actor_id 透传;网关阻断响应补 block_response_code;model 抽 compute_rule_refs 公共函数防两处漂移;测试配套:_ddl 加矩阵 25 行种子 helper、conftest fixture 灌种子+集成就位校验改 expires_at 口径、trade_gateway/risk_api fixture 补种子与 expires_at、404 两例改 200+blocked 新契约、repository 21 列断言、settings 退役断言、test_suitability 占位 skip 待 AL-07 重写。sqlite 端到端七语义+落库验证通过;剩 4 failed 均为 chat_tools/API 旧展示断言(AL-06 处理) 2026-09-07 17:34:32 +08:00
GaoYiYuan_0626 6195349dd6 feat: main 集成(路由挂载/trace 中间件/lifespan) + B7 挂账收口(引擎工厂/统一错误体/锁公共化/L3 缓存 DEL/死代码清理/处置原子事务/启动期 debug 校验, B7) 2026-09-06 20:48:50 +08:00
GaoYiYuan_0626 46a1f24870 fix: 引擎异常审计降级/审计全量输入输出/TRD-TEST 注入点(B5 评审 P1-1、P2-1~3、P3 批量) 2026-09-06 18:17:44 +08:00
GaoYiYuan_0626 2a95b65ec8 feat: 模拟交易网关(suitability 阻断→落库→引擎, convert 400, B5) 2026-09-06 18:05:44 +08:00