35 KiB
最近两天 commit 纯代码审计报告(2026-10-03 23:10 定时任务)
- 仓库:
/Users/chufeng/.openclaw/sanguo_projects/sanguo_vnpy_v2(master,审计基准 HEAD =7f9b4133e5a4a104c0715d6a0849a4847d186e0c) - 时间窗:2026-10-01 23:23:14 ~ 2026-10-03 22:05:02(按任务要求取最近 48 小时,全窗口有提交,无需顺延)
- 规模:59 个提交 = 代码类 39(feat/fix/refactor/test/ops)+ 纯文档 20(docs)
- 方法:按模块分 7 簇并行只读审计(仅 git show / git diff / Read / grep,未运行测试、未安装依赖、未修改任何文件);主审对全部 5 条在役 P1 逐一亲自复读源码复核属实后才定级
- 铁律:本报告只输出处置意见,不执行任何修复。行号一律给出该提交版本行号 + 是否对 HEAD 仍有效(各发现已逐一核对后继变更)
一、总体结论
无 P0。 活跃在役发现:P1 × 5、P2 × 19、P3 × 33;另有 8 条缺陷在窗口内被后续提交自我修复(2 P1 + 4 P2 + 1 P3,修复质量经复核有效)。
三天代码整体质量高:测试与实现同提交、护栏/门禁设计有层、敏感信息纪律好(token 全走 env、QMT 密码走 DPAPI→env→内存从不落盘落 argv)。主要风险集中在两处:
- P4-3 语料漏斗(10-02 一天落地的 5 件套)是本次风险最集中的新面:崩溃窗口丢数据、
--limit假开关、--llm-cap溢出永久丢弃三条 P1 同文件(scripts/data_platform/corpus_funnel.py),且生产接线脚本未启用 token 断路——「文档承诺的护栏」与「实际存在的护栏」不一致。 - 两处"语义性静默失效":
all_weather止损的涨停观察分支被 P0-4 前视修复构造性打死(提交说明未披露);分解产物动态注册链绕过全部护栏直通 vnpy 的eval汇点(纵深防御缺口)。
另需肯定:本窗口内两笔 P1(decompose 半成功 500、manifest 缺路径炸批)均由簇内后续提交修复并钉了测试——自愈机制在正常工作。
二、活跃 P1(5 条,均已主审复核源码坐实)
P1-1 漏斗水位先行前移 + 数据延迟提交:崩溃窗口内事件与候选永久静默丢失
- commit:
65e5c02916e9597a6c4263cb697e0a4bf5bcb08d(feat(data): 漏斗主体 corpus_funnel) - 坐标:
scripts/data_platform/corpus_funnel.py:213,217,219-220(对 HEAD7f9b413仍有效);scripts/data_platform/corpus_download.py:772 - 证据(主审复读确认):
而事件/账本行要等
cd._absorb_new("events_llm", events, ledgers, recents) # L213 只进内存 DayBuffer ctx.unit_done(domain, d) # L217 wm[domain] = d # L219 水位立即写盘 _save_watermark(wm) # L220corpus_download.py:772的if self.units % FLUSH_EVERY == 0: self.commit()(FLUSH_EVERY=50)或 main 优雅出口才落盘。 - 机理:每处理一天水位立刻持久化,该天的 events_llm/events_in 行与 marker 还在内存(最多差 49 unit)。kill -9/OOM/非 WallClock/BudgetStop 的未捕获异常会跳过 commit 与
_save_pending:水位已前进 → 次日起永不再重走 → 窗口内全部词表事件与新鲜候选永久丢失。本域 append-only 永不重算,丢失即永久;stats/integrity_gate 均无字段暴露该缺口。优雅停机路径无此问题(异常→commit→remainder 回写)。 - 处置建议:
_save_watermark挪进与 commit 同一 checkpoint 边界,或每 domain-day 处理完即ctx.commit();main 加兜底except Exception落 emergency remainder 后再 rc=1 退出。
P1-2 --limit 是假开关:文档承诺「LLM 调用数上限」但全链零检查
- commit:
65e5c02916e9597a6c4263cb697e0a4bf5bcb08d - 坐标:
scripts/data_platform/corpus_funnel.py:296(argparse help),313(唯一引用点),235-238(lane 循环);对照scripts/data_platform/corpus_download.py:762-763 - 证据(主审复读确认):
Ctx.budget_exhausted()的实现是return self.limit is not None and self.stage_units >= self.limit(corpus_download.py:763),corpus_download 自己的 10 处 lane 都调用它;corpus_funnel.py 全文对budget_exhausted零引用(grep 证实),args.limit仅在 :313 构造 Ctx 时传入后再无人读。 - 机理:
corpus_funnel --limit 5会把 pending+fresh 全量串行打完(仅受--until墙钟约束),「冒烟」语义完全失效;而 marker 抑制(unit_done的if mark and self.limit is None)倒是生效——制造「没落 marker 但烧光全部 LLM 调用」的最坏冒烟形态。tests 中亦无--limit生效断言。 - 处置建议:
_llm_lane循环顶部补if ctx.budget_exhausted(): break;或删掉--limit参数。二选一,勿留假开关。
P1-3 --llm-cap 实为「逐日×逐域」截断,溢出部分永久静默丢弃
- commit:
65e5c02916e9597a6c4263cb697e0a4bf5bcb08d - 坐标:
scripts/data_platform/corpus_funnel.py:215-216(对 HEAD 仍有效) - 证据(主审复读确认):
help 文案(:298-299)宣称「每夜新鲜候选上限(默认 200)」。
fresh_cands.extend(cands[: args.llm_cap]) # L215 每日×每域截断 stats["candidates_fresh"] += len(cands[: args.llm_cap]) # L216 只统计保留部分 - 机理:截断在每日×每域粒度执行——回填/首夜全史走水位时,一夜实际可入队 200×天数×2 域(与「每夜 200」契约相去甚远,成本面);更重的是
cands[200:]尾部既不入 pending 也不进任何计数,水位前移后永远不会被第二层看到,丢弃完全不可观测。公告标题含高频信号词(合同/担保/诉讼/立案…)时单日超 200 是常态。丢的是漏斗自身覆盖面,gate 无法发现。 - 处置建议:cap 语义改「每夜总量」:入队前统一截断并记
candidates_dropped;或溢出候选追加进 funnel_pending.jsonl 次夜续。
P1-4 分解产物动态注册链零护栏直通 eval 汇点(纵深防御缺口)
- commit:
e06bf6c522639fe015b4321e7c6f35fa1c0555eb(fix(factor): D2 动态表达式注册链) - 坐标:
sanguo_factor/monthly_batch.py:61-63(1b27226 后文件未再改,对 HEAD 仍有效);汇点vnpy_v4.4.0/vnpy/alpha/dataset/utility.py:253 - 证据(主审复读确认):
汇点:
expr = params.get("expression") # yaml 最新版 params 原文 if not expr: return None register_factor(name, expr, category_for_source(...)) # 无任何 precheckother: DataProxy = eval(expression, {}, d)——globals 为空 dict 时 CPython 自动注入__builtins__,未过护栏的字符串即任意代码执行。 - 机理:resolver 只按 source 分类,对表达式本体不做
precheck_expression。当前唯一写入方 routes_pipeline 经 check_candidate 把关,但该 yaml 是运行期可变文件,任何其他写入者/手工编辑/未来旁路一旦写入未消毒字符串,下次月度批 eval 即任意代码执行。precheck 正是现成的 AST 白名单,同函数已 import factor_guard 却只用其 category_for_source。 - 处置建议:
register_factor前对 expr 跑precheck_expression(违规记 skipped_unregistered+stderr);顺带校验 source 与 derive_source(expr) 一致。另 resolver 取versions[-1]无视 effective_from/to 窗口,建议一并对齐 effective_version 纪律。
P1-5 all_weather 止损「昨日涨停打开尾盘卖出」分支被前视修复构造性打死(提交说明未披露)
- commit:
6251451a761faa2aa50d1e91d0985586bd984751(fix(strategy): P0-4 前视修复) - 坐标:
sanguo_portfolio/strategies/all_weather.py:145-159(9:05 选名单)、169-182(14:00 判板)、485-493(_limit_status)(至 HEAD 未再改,行号对 HEAD 有效) - 证据(主审复读确认):9:05 用
get_limit_status_batch(hold, T-1)筛yesterday_hl_list(is_limit_up=True);14:00stop_loss对同一批股票查同一 T-1 日期的同一个确定性日线函数(:175 → :493 → 同一get_limit_status_batch,日 bar 不可变)——结果恒为 True,else: 涨停打开,卖出(:180-182)不可达。 - 机理:修前该分支查 T 日 bar(带前视、可达);修后回测与实盘一致地永不触发。「昨日涨停打开尾盘卖出」这一风控特性在全环境实际退役,且待执行的重跑重评将把死分支行为固化进正式回测数字。提交说明只写「缺失→跳过涨停观察」,未披露分支恒死。
- 处置建议:需设计拍板——14:00 改查当日盘中实时状态(tick/最新价 vs high_limit,provider 已有 get_current_tick 雏形),或显式删除死分支并在处置档记录特性退役。当前回测语义与 docstring(:163)相悖。
三、窗口内自我修复项(8 条,修复经复核有效,无需再动)
| 原 commit | 级别 | 缺陷 | 修复 commit | 复核结论 |
|---|---|---|---|---|
4296b4f0198559655acf55380d834162c3032f55 |
P1 | building 卡二次分解撞状态矩阵 ValueError → 500 半成功(registry 已写、卡片未动) | f740999 I-1 |
HEAD:944-948 已加守卫,配套测试钉住;建议把「allowed 状态集×矩阵相容性」固化为 store 层单测 |
dbe6623e81de850aebc94766a5d00cc4820f0fe2 |
P1 | monthly_batch --manifest 缺路径 FileNotFoundError 炸批(违背 fail-soft 宣称) |
1b27226 m6 |
HEAD:112-118 已加 exists 守卫+stderr 告警,test_main_missing_manifest_failsoft 钉住;但只补了「缺路径」一态(见 P2-11/12) |
1c5f1ab53e989cc5ae8debf733d8f75cfe1baeb6 |
P2 | load_domains 只捕 OSError,坏 YAML → draft/save 双端点 500 | 1e3579b |
HEAD:54 已 except (OSError, yaml.YAMLError) |
a81e1b6af7ca3abc30e93ab5f820efbe87cc5e18 |
P2 | save 端点 sentence 无长度上限(draft 有 500 闸,不对称) | 1e3579b |
HEAD:848-850 已补,test_save_sentence_too_long_400 转绿 |
9aa104ba9fd8c1a042325feeb53838ff1bc613c0 |
P2 | 同步 time.sleep 在事件循环内阻塞 2-4 秒 | 1e3579b |
全路径已 await self._sleep;建议保留 Awaitable 类型注解防回退 |
9aa104ba9fd8c1a042325feeb53838ff1bc613c0 |
P2 | httpx.TransportError 裸逃逸穿透 502 契约 | 1e3579b |
已纳入重试链,耗尽出口 LLMError,attempts 有界 |
13f3124a4b13dcc1a5791215fd92c9b4d734141e |
P3 | 反馈轮 prompt 不带在库名单,易空耗 3 轮全灭 | f740999 M-2 |
HEAD:27-52 已带 taken 名单(截 120) |
a81e1b6(draft 先例) |
P3 | 同上 draft 端点 sentence 上限先例 | 1e3579b |
双点对称 |
max_rounds=3 专项核查结论(任务书点名项):修复完备。唯一出口 not failed or rounds >= max_rounds,LLM 调用 ≤3 次,test_loop_stops_at_max_rounds 钉住;内层 client while True 亦受 attempts/healed 双旗约束有界,无死循环路径。
四、活跃 P2(19 条)
LLM 模块簇
P2-1 「429 Retry-After」从未实现,提交说明与测试名双重失真
- commit
9aa104ba9fd8c1a042325feeb53838ff1bc613c0;sanguo_api/llm/client.py:90-93(HEAD 行号,至 HEAD 未再改);测试tests/api/test_llm_client.py:49-58 _post只返回(status_code, text),headers 全程丢弃;测试 fixture 给 Retry-After "2" 恰与固定退避_BACKOFF_SECONDS[0]=2.0重合,断言靠巧合通过。provider 要求等 30-60 秒时仍按 2/4 秒重击。- 建议:
_post带回 headers,429 解析 Retry-After(非数字回落固定退避),修正测试名。
P2-2 L5 尾逗号清洗不感知字符串,可静默改写 JSON 字符串值后当成功返回
- commit
46d76e75b7de3b945451cb62ab6a21ef45287087;sanguo_api/llm/json_utils.py:13,66(对 HEAD 有效) - 实测反例
{"s": "a, }",}被 L5 改写为{"s": "a }}"解析成功——字段值损坏且外层看到的是成功。hypothesis_decompose 链路更自动,无人审兜底。 - 建议:清洗改字符串感知状态机,或至少对 L5 救回结果打「降级解析」日志。
P2-3 robust_json_parse 对非 str 输入裸逃逸;上游 content=null 穿透 502 契约变原生 500
- commit
46d76e7(json_utils.py:57,29)+9aa104b(client.py:67-73content=None放行)→routes_pipeline.py:839-842只捕 LLMError/ValueError - openai 兼容端点空回复返回
"content": null并不罕见,此时 TypeError 直穿 FastAPI 500。 - 建议:入口
isinstance(text, str)防御;client 对 None content 直接 raise LLMError 走 strict 重试。
P2-4 「坏 YAML fail-soft」只挡语法错:合法 YAML 但形状不对仍 AttributeError→500
- commit
1e3579b64e65088e33e907aea631e4134985c85c;sanguo_api/hypothesis_card.py:53-56;爆炸半径routes_pipeline.py:834(_wizard_domains()在 try 块外) - 顶层 list/scalar 或
domains:为 list 的合法 YAML →.get/.keys()AttributeError,draft/save 双端点 500。 - 建议:
isinstance(manifest, dict)防御一行闭环 fail-soft 宣称。
pipeline 假设卡簇
P2-5 状态转移矩阵校验 SELECT→UPDATE 两步非原子,并发可绕过 graveyard 终态禁令
- commit
9389a7b9d5e5942bd5acba441492560776cdde76;sanguo_portfolio/pipeline_store.py:276-287(后未改,对 HEAD 有效) - UPDATE 不带
AND state=?守卫、无事务包裹:并发下末写者胜,可产出「building 态带 death_reason」甚至把 graveyard 迁出——D3 禁复活在竞态下不成立。同文件 graduate 端点有_GRADUATE_LOCK先例未复用。 - 建议:下沉为单条条件 UPDATE(rowcount==0 二次 SELECT 区分原因),或仿
_GRADUATE_LOCK加互斥。
P2-6 decompose「registry 落盘 + 卡片转 building」跨存储两步写不原子且无锁
- commit
4296b4f0198559655acf55380d834162c3032f55;sanguo_api/routes_pipeline.py:944-948(HEAD 仍无锁/无事务,本条在 HEAD 成立) - save_registry(yaml) 与 update_hypothesis_state(sqlite) 无共享事务;
load_registry→save_registry是无锁读-改-写。中途失败留「registry 有因子、卡片仍 queued」可重复注册;并发 decompose 同卡整文件覆盖丢更新。incubating 候选不直接涉资金,故 P2。 - 建议:短期加 graduate 同款按卡互斥;中期考虑 pending 意图行/版本号 CAS。
P2-7 反馈循环批内无表达式查重:同批「同构换皮、异名」候选双双过门一次成型
- commit
13f3124a4b13dcc1a5791215fd92c9b4d734141e;sanguo_api/hypothesis_decompose.py:130-131+routes_pipeline.py:909-916(HEAD 行号) claimed只收名字;dup_violations 的对照集library_exprs不随本批 passed 增长——防换皮门(7e93c5b 核心卖点)在同批维度被绕过,首批污染已落 registry。- 建议:循环内把已通过候选 expression 增量并入对照集,一行级改动。
factor 分解器 #84 簇
P2-8 precheck 白名单漏 JoinedStr/FormattedValue/Await/Yield:f-string/await/yield 零违规过门
- commit
62c797534aae85d418b2701c6284d2a8d0ddcd92(至今未修);sanguo_factor/factor_guard.py:56-60(HEAD 行号) - stdlib 实测
precheck("f\"{close}\"")==PASS、precheck("await cs_rank(close)")==PASS。不构成代码注入(内部节点仍被查),但非法方言拿到「合法候选」身份进注册表,直到 eval 阶段才报单因子 error,护栏「违规结构化返回」契约被击穿。f740999 补了 Tuple/List/Set 仍漏这三个。 - 建议:
ast.JoinedStr, ast.FormattedValue, ast.Await, ast.Yield, ast.YieldFrom入_BLOCKED_NODES,钉 f-string/await 拒绝测试。
P2-9 IC 正交闸可静默 no-op:「查过且干净」与「根本没查成」报告不可区分
- commit
a1caccf1b1233bbccc1d9c0f2edec639b645aa75;sanguo_factor/ic_gate.py:58-73(未改,对 HEAD 有效);接线monthly_batch.py:138-146 - 新因子 parquet 缺件(batch_eval 单因子失败时不落盘)→ 该因子整体
continue;report 无skipped_missing_values/compared_pairs字段,monthly_batch 仅 flagged 非空才打印——系统性 eval 失败呈现为绿灯。 - 建议:补计数并在
checked < len(new_names)或比对数为 0 时 stderr 显式告警。
P2-10 D5 死亡回写「卡片不存在」路径零痕迹返回 False,调用点忽略返回值
- commit
403a043b8c0ba38b6d4cac2b196a75894e5c283a;sanguo_factor/version_registry.py:151-162,240-241;根源pipeline_store.py:278-279 --pipeline-db缺省data/pipeline.db为 cwd 相对路径且 _connect 自动 CREATE 空库:从错误目录跑 CLI 转移时,因子落 graveyard 而卡片回写静默 no-op,还顺手生成空库;死假设可继续孵化新因子,无事件可审计。- 建议:False 路径显式 stderr+registry_events.jsonl 附记;
--pipeline-db绝对化或存在性预检。
P2-11 m6 manifest fail-soft:缺路径比坏 manifest 更安静,且与独立 CLI 退出码语义倒挂
- commit
1b27226ab619d18e8ef62bda1d455e9ee3b9a8a3;sanguo_factor/monthly_batch.py:112-118(对 HEAD 有效);对照data_gap_check.py:106-108 - 缺 manifest → gaps={} 完全安静(不写 data_gaps.json、不触发 gap_issue)——数据侧最需告警的场景零输出;独立 CLI data_gap_check.main 同情形 exit 1,两处契约相反。默认路径 cwd 相对,调度换目录即常驻 fail-soft 分支。
- 建议:缺 manifest 落
{"manifest_missing": true}标记件;与 CLI 退出码对齐;文档化绝对路径 env。
P2-12 manifest 存在但格式坏时月度批仍炸(fail-soft 契约只补了「缺路径」一态)
- commit
dbe6623e81de850aebc94766a5d00cc4820f0fe2;sanguo_factor/monthly_batch.py:112-114(HEAD)+data_gap_check.py:24-26,41-43 - 语法坏 → yaml.YAMLError;解析成标量/列表 →
manifest.getAttributeError——两态均无捕获,批前崩溃与 P1(已修复项)同杀伤。 - 建议:缺口比对整体 try/except(stderr 告警+gaps={} 照跑);补坏 YAML/非 dict 两态测试。P2-11/12 同根同处置,可一刀修。
factor #70 簇
P2-13 缺口单去重三重脆弱:首页 50 条上限 + 单永不关闭 + 查单失败放行,无速率上限
- commit
dbe6623;sanguo_factor/data_gap_check.py:66-82(find_open_issue),85-94(maybe_open_gap_issue)(对 HEAD 有效) - open issue 只增不减;超 50 条后目标单跌出首页,
find_open_issue静默失明,同一指纹每月重复开单;LIST 网络异常except Exception: return None后照走 open(fail-open)。全仓无任何关单代码。指纹机制本身干净(sorted 行序无关,测试钉死;月频 32bit 碰撞可忽略)。 - 建议:search API/翻页兜底;异常与「确认不存在」区分(异常时跳过 open);按指纹落本地 append-only 台账作第二道去重。
data 漏斗簇
P2-14 rc() 优先级令「墙停/token 断路 checkpoint」被单次 LLM 噪声失败覆盖成 rc=1
- commit
eb6475b1d7d0472718af896c9d0b6bb40e2b1613+ 表现层65e5c02;corpus_download.py:803-809、corpus_funnel.py:246,367(对 HEAD 有效) - 夜批出现 1 次瞬时 LLM 失败(
ctx.failed += 1不熔断继续跑)即可把正常 checkpoint 的出口 rc=3 覆盖成 1「致命」——09-19 runbook 已记录过的 corpus_download 同款坑在漏斗上复刻,监控分流失真。 - 建议:checkpoint 状态优先于噪声失败定级,或单独输出 checkpoint 标志供监控解析。
P2-15 词表否定守卫只拦「紧邻」否定:常见间隔措辞系统性漏拦,误判以 confidence=1.0 定格且无第二层纠错
- commit
8bf935b1a0349250d03dc076af1b4a4387f6e81a;scripts/data_platform/funnel_lexicon.py:44-45,55-63,79-83(对 HEAD 有效) prefix.endswith只在否定词紧贴关键词时生效:「尚未扭亏」→ earnings_pre_up/pos、「仍未增持」→ holder_increase/pos、「已终止的质押」→ pledge_new/neg——方向可能完全相反的事件以 model=lexicon、confidence=1.0 直落 events_llm,且 lexicon 命中被排除出 LLM 候选,无纠错路径。- 建议:窗口扩 3-4 字改 contains;lexicon 命中但窗口内有否定词的降级为 LLM 候选;先补「尚未/仍/不排除」负向测试。
P2-16 生产接线未启用 token 预算断路:唯一护栏只剩 --until 墙钟
- commit
e47dddd336a7c1f54a639f95a1b33d15ddf67ecd;scripts/nas_sync/run_corpus_standalone.sh:111(对 HEAD 有效) - 本簇头号特性(eb6475b token 断路)在生产命令无参数落地,叠加 P1-2(--limit 假开关)与 P1-3(逐日 cap),首夜全史回填的 token/费用实际无上界(时间有界)。runbook 宣称「token 预算断路 rc=3 次夜续」与实际不符。
- 建议:生产命令补
--token-budget,或修订 runbook/spec 文案如实声明「生产仅墙钟护栏」。
strategy 簇
P2-17 _previous_date_str 缺失时静默回落当日 T:momentum 新加的 None 守卫实际不可达,前视可静默回归
- commit
6251451(守卫新增)涉及 helperall_weather.py:629-642(旧有);momentum_timing.py:151-156 - bullet_trade 引擎首日
previous_date可能保持 None(get_trade_days 失败仅 warning、async_engine 首日不设),此时 helper 回落当日 T——panel 上界退化为回测当日收盘,恰是要根除的前视,且守卫要求 current_dt 同为 None 才触发(实际不可达)。factor_topn.py:109注释自证该回落路径真实存在;all_weather.py:632「bullet_trade context 无 previous_date 属性」注释与 0.9.2 实际相悖(陈旧注释)。 - 建议:数据上界改显式 T-1 推导(对齐 factor_topn 自算口径);fallback 分支加 warning;勘正两处陈旧注释。
qmt 灾备源簇(dbf57f2 回库 5 主件)
P2-18 模拟柜台资金账号 66639661 硬编码回库
- commit
dbf57f2fd0f9c518c8c0add766ae9c76a79c1e30;scripts/qmt_relogin/qmt_gate_common.py:14、qmt_relogin.py:41(HEAD 行号相同;回库后至 HEAD 零改动) - 经仓库内文档佐证为模拟柜台账号(余额 9999998.51、userdata_mini 模拟端),且 HEAD 全仓已扩散 32 文件(setclip_acc.py 同号在先),故定 P2 而非 P0。
- 建议:若确认永为模拟账号,新代码改读既有
BIGQMT_ACCOUNT_IDenv;若该号实际具备实盘属性或未来复用,升级 P0 并轮换/更换账号。
P2-19 探活撤单失败仍判 GREEN、exit 0:残留 live 委托仅日志 CRITICAL,进程级信号被掩盖
- commit
dbf57f2;scripts/qmt_relogin/qmt_probe_0915.py:96-103,175-179 - place() 下真实委托(0.01 买价),cancel 失败时订单仍 LIVE 但 verdict=GREEN、return 0——监控只看灯色/退出码会漏掉残留单。资金风险趋零(0.01 不可能成交+日终清算),灾备源标准定 P2。
- 建议:cancel 失败时 verdict 降 AMBER 或 exit 2,让 GREEN =「委托确认且撤单干净」。
五、活跃 P3(33 条,简式)
LLM 簇(5)
46d76e7json_utils.py:63-67 — L4/L5 修复不叠加(并行候选非累积降级);注释「尾随垃圾重截一次」未实现46d76e7json_utils.py:29 —_balanced_braces以首个{为起点,起点落在字符串内则配平错位(假阴性,仅多 502)9aa104bclient.py:67-68,115-118 — 同一响应体解析两次;每 attempt 新建 AsyncClient 无连接复用(效率)9aa104bclient.py:80-88 — 400 参数自愈为文本子串启发式且与 429/5xx 共享 attempts 预算(有界、语义混杂)7b489d1client.py:39-40,68 — want_usage 的 usage 可为空 dict,计量侧无法区分「0 token」与「上游没给」;联合返回类型不友好
pipeline 簇(3)
6. 7a89632 pipeline_store.py:227-228 — 卡 id=秒级时间戳+2 字节 hex,同秒碰撞 ~1.5e-5 → IntegrityError 500;card["id"] 通路无格式约束
7. a81e1b6 routes_pipeline.py:858 — save 端点 source 零白名单零上限,任意字符串落库永久回显
8. a81e1b6/4296b4f routes_pipeline.py:846 — 502 detail 透传上游 LLM 响应体前 200 字(可能带出上游端点/账号上下文;api_key 不泄漏已核实)
factor #84 簇(5)
9. 7e93c5b factor_guard.py:165-166,266,275 — 整树 <8 节点的交换律重排同时躲过 dup_exact 与 dup_subtree(小因子换皮漏检,靠 IC 闸兜底而 IC 闸自身有 P2-9 缺口)
10. a1caccf ic_gate.py:38-42 — 有效 corr 日数无下限:常数截面日滤除后少数日均值即可触发置疑
11. a1caccf monthly_batch.py:133-137 — origin=decomposer 新因子判定双向漂移:分解因子每月重考永不收敛;手工升版即无声退出闸视野
12. e06bf6c monthly_batch.py:38-65,70 — plan_batch「纯函数」docstring 契约被 resolver 全局注册副作用打破(跨调用/测试泄漏)
13. 62c7975 factor_guard.py:54,126 — NAME_RE $ 允许尾换行("abc\n" 过闸),公共门 API 层潜在缺陷,现调用方 strip 兜住
factor #70 簇(7)
14. dbe6623 data_gap_check.py:85-94 — 双机(NAS+VPS)同日各跑 --gap-issue 的 check-then-open 竞态可开重复单(月频+默认关,概率低)
15. f9914ca monthly_review.py:26 vs :158 — _PROMOTION_BAR=2.0 注释宣称「单一事实来源」,pre_gate_table 实为另一处硬编码 2.0(两份拷贝);负 t 侧无镜像门边带
16. 367b4cf exam_gate.py:41-49 — 缺周期跳过使判定可退化为单周期对比即 SUGGEST_PROMOTE;负 ICIR 按「序」可胜(最终人裁,实害有限)
17. 367b4cf exam_gate.py:97,100-105 — 同日重跑同候选覆盖既有 md 报告(label 不含 run_id),晋级证据链失去历史
18. d15653d config/factor_registry.yaml:108-121 — promotion_t=26.32 条目本体无 evidence_run 指针(出处只在 docs;墓园条目有此惯例)
19. d15653d composite_library.py:91-93 — 等权合成实为 12 源交集语义:任一源缺→该股当日 null,分母恒 12 不重归一(文档化已知限制,易误读为可用成员等权)
20. dbe6623 data_gap_check.py:71-72 — 内网 Gitea 地址 fallback 硬编码第二份副本(与 version_registry 同值暂无漂移)
data 漏斗簇(5)
21. 65e5c02 corpus_funnel.py:275 vs :231 — 「喂模型文本先落盘」契约与实现顺序不符(调用后才入内存缓冲,随 commit 才落盘)
22. 1ea143e integrity_gate.py:88-89,128-129 — 空窗=全绿:断供超 7 日后 L2 六项 critical 全部 vacuous pass,gate 绿不能当管道存活证据(新鲜度豁给监控是记录在案的设计决策)
23. e47dddd run_corpus_standalone.sh:112-113,123-124 — gate 1/2、funnel 0/1/3 调用侧仅回显不分流;锁让路与 checkpoint 共用 rc=3
24. 65e5c02 corpus_funnel.py:285-288,32 — _dump_raw_fail 从未被调用(死代码,让人误以为坏响应有留痕)+ Path 导入未用
25. e47dddd run_corpus_standalone.sh:101,105-107 — LLM key 经 docker run -e 传递,argv/docker inspect 短暂可见(引号处理正确、日志面无泄漏,常规实践)
strategy/data 簇(2)
26. 7f9b413 strategy_checks.py:245 — logs_stale 迁 trading_day 后 docstring 仍写「仅工作日班评」,与实际闸门语义不符
27. 434f7bc akshare_static_download.py:984-999 — margin 守卫不覆盖「feed 已越过请求日但该日块未发布」的中段缺块形态(提交说明已声明属有意边界,记录项)
qmt/docs 簇(6)
28. dbf57f2 qmt_relogin.py:174 — 启动行明文打印登录用户名入日志(密码仅打长度,处理链本身是亮点)
29. dbf57f2 qmt_gate_common.py:57,118 / qmt_relogin.py:115,144 — requirepass 正则无 None 守卫,redis.conf 漂移时 AttributeError 自爆(灾备恢复恰是配置最易漂移场景)
30. dbf57f2 qmt_relogin.py:125-130 — flush_stale_queue 对解码失败项静默 continue 后整队 delete,绕过「订单类绝不删」守卫
31. dbf57f2 qmt_gate_common.py:15,113,121 等 — 灾备源写死盘符路径;qmt_sentinel.py:90 内部域名(布局契约未文档化)
32. 22b4548 p70 计划文档 diff — 内网 Gitea IP+端口入文档(全仓 ≥15 文件已存在该 IP,增量有限);建议统一改引 env
33. 99bc801 P0-4 偏差报告 — NAS 绝对路径/91G 库坐标/实例号入审计档(无凭据无 IP,记录项)
六、敏感信息专项结论(窗口内 59 提交全扫)
- 无明文密码/token/密钥泄漏。 LLM api_key 只进 Authorization 头、中文报错只列 env 名不打值;Gitea token 只从
SANGUO_GITEA_TOKENenv 读取;QMT 登录密码走 DPAPI→env→内存,never argv/on disk;20 个 docs 提交三扫(password/token/secret/sk-/长 base64/内网坐标)18 个 CLEAN,2 个仅内网拓扑级记录(见 P3-32/33)。 - 两处值得拍板的准敏感项:模拟资金账号 66639661 硬编码(P2-18,需确认其永为模拟属性)与 LLM key 的 docker argv 可见窗口(P3-25,可改 --env-file 收敛)。
七、逐提交判定清单
代码类 39 个(●=有发现,○=CLEAN;完整 hash 前缀即可在仓内 git show 定位):
| # | hash | 类型 | 判定 |
|---|---|---|---|
| 1 | 7f9b413 |
fix(monitor) | ○ 双侧休市表镜像逐字一致+同步测试;仅 logs_stale docstring 未随迁(P3-26) |
| 2 | 1b27226 |
fix(factor) | ● m6 守卫有效但契约只补一态(P2-11) |
| 3 | dbe6623 |
feat(factor) | ● P1 已自愈+P2-12/13+P3-14/20 |
| 4 | b582b70 |
fix(factor) | ○ fixture 链式幂等重挂,真治序依赖非盖问题 |
| 5 | 367b4cf |
feat(factor) | ● P3-16/17(判定主干与「同批同 run」宣称核实为真) |
| 6 | f9914ca |
feat(factor) | ● P3-15(区间口径本身自洽) |
| 7 | d15653d |
feat(factor) | ● P3-18/19(26.32 有据,衰减告警实际由地板 2.0 主导,计划档自认) |
| 8 | b24f905 |
fix(data) | ○ 休市表经官方公告逐项核实,CI 年更为硬失败 |
| 9 | dbf57f2 |
ops(qmt) | ● P2-18/19+P3-28/29/30/31(5 主件无明文凭据,patch×2 确未回) |
| 10 | 434f7bc |
fix(data) | ● P3-27(守卫本体正确,边界已声明) |
| 11 | e47dddd |
feat(data) | ● P2-16+P3-23/25(读出口/manifest 两域无穿越面) |
| 12 | 1ea143e |
feat(data) | ● P3-22(三层门/后门约束/exit 映射本体合格) |
| 13 | 65e5c02 |
feat(data) | ● P1-1/2/3 + P3-21/24(两层分诊骨架与优雅停机路径正确) |
| 14 | 8bf935b |
feat(data) | ● P2-15(八类事件+类型去重计数正确) |
| 15 | 7b489d1 |
feat(api) | ● P3-5(「默认调用零变化」核实为真) |
| 16 | eb6475b |
feat(data) | ● P2-14(BudgetStop 机制本身稳,半途丢弃不存在) |
| 17 | f740999 |
fix(factor) | ○ 修复波六项逐一核实有效(arity 表 35 项全对照) |
| 18 | b35287f |
test(frontend) | ○ 断言与实现一致非空洞 |
| 19 | 403a043 |
feat(factor) | ● P2-10(回写主路径正确) |
| 20 | a1caccf |
feat(factor) | ● P2-9+P3-10/11(Pearson 统计主干正确) |
| 21 | 6251451 |
fix(strategy) | ● P1-5+P2-17(动量 8+全天候 2 调用点对称完整,全仓无第三处同类前视) |
| 22 | e06bf6c |
fix(factor) | ● P1-4+P3-12(无覆盖风险核实:register 重名 raise) |
| 23 | ca8673e |
refactor(strategy) | ○ 恰删四个 _ex 副本,HEAD 全仓零残留引用 |
| 24 | 4296b4f |
feat(pipeline) | ● P1 已自愈+P2-6+P3-8 |
| 25 | 13f3124 |
feat(pipeline) | ● P2-7+P3 已自愈(max_rounds=3 核实真兜住) |
| 26 | 9389a7b |
feat(pipeline) | ● P2-5(矩阵语义本身正确有测试钉) |
| 27 | 8478f23 |
fix(factor) | ○ 校准自洽(6 列和式深 8-9≤12,矛盾消除) |
| 28 | e3e8ccc |
test(frontend) | ○ stub 语义等价不掩盖真实缺陷 |
| 29 | 7d737a7 |
fix(factor) | ○ 修复最小且正确,KeyError 面完全封闭 |
| 30 | 7e93c5b |
feat(factor) | ● P3-9(同构算法主干经复刻验证正确) |
| 31 | 62c7975 |
feat(factor) | ● P2-8+P3-13(白名单主干扎实,eval 注入面封死) |
| 32 | 1e3579b |
fix(llm) | ● P2-4(六项修复本体全部核实有效) |
| 33 | 7befde0 |
feat(pipeline) | ○ 前端无 XSS 面,busy 态防双击 |
| 34 | a81e1b6 |
feat(pipeline) | ● P2 已自愈×1+P3-7/8(鉴权/503-502 分层核实为真) |
| 35 | 1c5f1ab |
feat(pipeline) | ● P2 已自愈(normalize 真同源可证幂等) |
| 36 | 7a89632 |
feat(pipeline) | ● P3-6(SQL 全参数化,CRUD 干净) |
| 37 | 9aa104b |
feat(llm) | ● P2-1/3+P2 已自愈×2+P3-3/4 |
| 38 | 46d76e7 |
feat(llm) | ● P2-2/3+P3-1/2 |
| 39 | 5fd2d84 |
feat(llm) | ○ 无 key 泄漏,chat_url 语义有测试锚定 |
纯文档 20 个:18 个 CLEAN(bf1fe98,2fdb025,d8ca4a7,56fff3d,0007f28,a3d5f3e,4cf88b4,a487192,c292dcd,03e5c8f,4e4679a,66679d2,a59a0d9,7ca6345,7ce94ad,6f4167f,780d0dc,c131ae9);2 个含内网拓扑级记录项(22b4548 P3-32、99bc801 P3-33)。
八、处置优先级建议(只提意见,不执行)
- 本周内:漏斗三连 P1-1/2/3 同文件可一刀修(checkpoint 边界统一 + limit 生效或删除 + cap 改每夜总量并记丢弃数);P1-4 在
register_factor前补一行precheck_expression。 - 需设计拍板(非纯 bug):P1-5 涨停观察分支——接实时 tick 或正式退役该特性并更新 docstring/回测口径。
- 近期排期:P2-16(生产接线补 token 断路或改文档,与 1 联动);P2-11/12 同刀修 manifest fail-soft 四态(缺路径/坏 YAML/非 dict/网络失败)并固化为测试清单——本次 fail-soft 类缺陷三度只修一态(1b27226/1e3579b/P2-16),建议立此清单防再犯。
- 排期消化:P2-5/6(状态机与 decompose 两步写的原子性)、P2-15(否定守卫窗口)、P2-1(Retry-After)、P2-9/10(闸门可观测性)、P2-13(开单去重加固)、P2-19(探活灯色语义)。
- 随手清理:P3 各项,尤其 P3-24 死代码(
_dump_raw_fail留着会误导排障)与 P3-26/29 docstring 失真。
九、方法与局限
- 7 簇并行子代理审计 + 主审对 5 条 P1 亲自复读源码复核(corpus_funnel.py/corpus_download.py Ctx/monthly_batch.py/all_weather.py/vnpy utility.py 汇点/momentum_timing.py 守卫),P2/P3 采信子代理读码证据(均含代码摘录,坐标已逐一核对后继变更)。
- 未运行任何测试(只读铁律);AST 边界类结论(P2-8、P3-9/13)经子代理用 stdlib 复刻纯函数实测,非猜测。
vnpy_v4.4.0/、vnpy_qmt_v0.3.3/、venv310/第三方/环境目录不在审计范围(eval 汇点作为外部事实引用)。- 本报告未发现需要立即阻断上线的 P0;但 P2-16 + P1-2/3 组合意味着漏斗首夜全史回填的 token 成本实际无上界,若近期要放量跑漏斗,建议先落处置建议第 1、3 条。
审计:claude_dev(ZCode 定时任务,2026-10-03 23:10 触发);报告路径:/Users/chufeng/.openclaw/sanguo_projects/sanguo_vnpy_v2/audit_20261003_recent2days.md;全程只读,未修改任何代码与文档。