创建人员:dev.developer.project.secondary / infodev-2
开发事项:DEV-ANA-STOCK-VALUATION-PIPELINE-V2-20260801-001
当前审核员:dev.reviewer.project / inforev
方案性质:重型编码方案返修;一次闭环 V002 独立审核的 F1—F8。
当前状态:PENDING_FOCUSED_DESIGN_REREVIEW;审核 PASS 前禁止创建 V2 代码、测试、fixture,禁止修改 ana-dev,禁止真实联网 smoke。
前序审计:DEV-AUDIT-PROJECT-INFO-STOCK-VALUATION-PIPELINE-V2-DESIGN-20260801-001=HOLD/8。
项目管理员已通过原生交接 HANDOFF-INFOADMIN-INFODEV2-STOCK-VALUATION-V2-TAKEOVER-LEDGER-CLOSE-TERMINAL-20260801-001 完成三本 append-only 根账闭环:
dev-doc/开发事项总纲.md:709:当前 owner=dev.developer.project.secondary,reviewer=dev.reviewer.project;dev-doc/开发事项计划.md:802:V003 是唯一当前返修版本;V001、旧 ana 审核请求和 V002 审核快照均为历史;dev-doc/开发问题记录.md:362:DEV-ISSUE-ANA-STOCK-VALUATION-V2-REVIEW-SESSION-20260801-001 已因有效 project 审核员改派而关闭;dev/project-dev/stock_valuation_pipeline_v2/,测试=dev/project-dev/test/stock_valuation_pipeline_v2/,文档=dev-doc/project-doc/,审计=dev-doc/开发审计报告.md;dev/ana-dev/stock_valuation_pipeline/ 全部只读,不复制公式、校验、报告或缓存实现;旧 inbox/会话仅保留历史证据,不再形成活动阻塞。管理员另作条件单文件授权:仅在最终实现独立审核 PASS 后,本事项开发者可同步 outputs/20260730_stock_valuation_guide/股票价格合理性评估操作手册_v1.0.md;其他 outputs/ 不在写入范围。
目标是把 V1 的“人工填好 valuation_snapshot.json 后计算”升级为 ticker+as-of 端到端机械协调层:并发公开取数、可信信源停止、内容寻址缓存和公司增量基线、异常预算内降级、最小判断覆盖、固定 16 节报告、自动 QA、原子输出和从用户任务起点到提交完成的双墙钟。
必须保留 V1 --input 兼容;不输出交易指令、收益承诺或自动批准的投资结论;任何 publish_date 或 data_date 晚于 as-of 的信息都不得进入结果。
明确排除:V1 公式/schema/registry 修改,第二套估值计算核心,GUI、API、数据库、常驻服务、批处理、定时任务、付费或登录来源、验证码规避、自由搜索站点、未来信息、未披露业务事实推断。
dev/project-dev/stock_valuation_pipeline_v2/
__init__.py __main__.py cli.py telemetry.py http_client.py
cache.py providers.py acquisition.py snapshot_builder.py
judgment.py v1_bridge.py full_report.py report_qa.py workflow.py
provider_registry.json judgment_overlay.schema.json README.md
dev/project-dev/test/stock_valuation_pipeline_v2/
test_*.py
fixtures/chengchang_20260801/
dev-doc/project-doc/
股票估值端到端协调层V2.md
开发证据/DEV-ANA-STOCK-VALUATION-PIPELINE-V2-20260801-001/
V1 兼容模式:
python -m stock_valuation_pipeline_v2 --input SNAPSHOT --output-dir OUT [--force]
ticker 模式:
python -m stock_valuation_pipeline_v2 --ticker 001270.SZ --as-of 2026-08-01 `
--output-dir OUT --cache-dir CACHE [--judgment JUDGMENT.json] `
[--fixture-dir FIXTURES] [--task-start 2026-08-01T20:00:00+08:00] [--force]
--input 与 --ticker 互斥。ticker 模式必须同时给出 as-of、output-dir、cache-dir。ticker 只接受 NNNNNN.SZ|SH|BJ,别名规范化在网络前完成;as-of 不得晚于本地当前日期。fixture 模式把网络 transport 替换为显式拒绝对象,任何网络调用都使测试失败。
以仓库根为锚点,只允许加载:
dev/ana-dev/stock_valuation_pipeline/;dev/ana-dev/stock_valuation_pipeline/source_registry.json;__version__ == "1.0.0";__init__.py=257 bytes / F39479C1A7B7F40A1A71D5EDE8A287F4E701B4F1473D674F04A2E1BA1B522D29;core.py=53165 bytes / 6AB34917A8B136F684EF655995428ACB5936050E1DA36B7B2371941A3E5A5F8F;cli.py=1811 bytes / 260692D62C8983B623483E0AA29C763869E30D40952700D46C636357A7376A1E;source_registry.json=4958 bytes / 0895D4F0559A1353787059D506DF16572E6818CD847C21042FE1D1106AA854E0。桥接加载后核对 module.__file__ 位于上述只读包,函数签名逐项等于冻结合同。运行 manifest 记录实际模块路径、版本、四个 SHA-256 和 registry hash。任一不匹配产生 E_V1_CONTRACT、退出 3,并在任何写正式输出前 fail-fast;绝不以内嵌公式或复制 CLI 补偿漂移。
| 模式 | 精确调用 | 返回/用途 |
|---|---|---|
--input |
run_pipeline(snapshot_path=Path, output_dir=Path, source_registry_path=REGISTRY, force=bool) |
原样返回 V1 status;保留 GENERATED/REUSED 和 V1 三件套 |
| judgment | snapshot=load_snapshot(Path);registry=json.load(REGISTRY);results=compute_valuation(snapshot, registry) |
results 是 V2 所有估值数值章节的唯一来源;V2 不调用 V1 报告生成器 |
兼容模式复刻的仅是异常到进程语义,不复制计算:成功 stdout 为 V1 status JSON、exit 0;InputError stderr 为 {"status":"INPUT_ERROR","errors":[...]}、exit 2;OSError/json.JSONDecodeError stderr 为 {"status":"RUNTIME_ERROR","error":"..."}、exit 3;合同漂移也 exit 3,status=RUNTIME_ERROR、error_code=E_V1_CONTRACT。
测试必须同时运行直接 V1 CLI 与桥接:比较 stdout status、exit 0/2/3、GENERATED/REUSED、三件套相对文件名/bytes/SHA-256;judgment 模式将 V2 桥接的 results 对象与直接 compute_valuation(snapshot, registry) 做规范 JSON 字节相等比较。
首期不允许运行时自由换站。所有 URL 必须 HTTPS、host 精确命中 allowlist、重定向后的每一跳也重新校验。未知域名、未知 endpoint、未知方法或未登记回退在创建 socket 前拒绝。
| provider_id / version | 等级、核心性 | host、endpoint、方法 | 规范化参数、市场、日期 | 字段、单位、响应上限 | 顺序/停止 |
|---|---|---|---|---|---|
cninfo.announcement_index/1.0.0 |
A1;核心回链 | www.cninfo.com.cn/new/data/szse_stock.json GET;www.cninfo.com.cn/new/hisAnnouncement/query POST;PDF static.cninfo.com.cn/<adjunctUrl> GET |
stock list 得 orgId;form 固定 pageNum,pageSize=30,column,tabName=fulltext,plate,stock=code,orgId,category,seDate;SZ/SH,BJ 不支持即显式 gap;announcementTime<=as-of 23:59:59 |
announcementId,title,time,adjunctUrl,orgId,secCode;时间毫秒;JSON/PDF,单响应 20 MiB |
唯一公告索引;找到覆盖报告期且未被后续修订替代的 A1 即停 |
eastmoney.market/1.0.0 |
B1;价格/股本核心 | push2.eastmoney.com/api/qt/stock/get GET;push2his.eastmoney.com/api/qt/stock/kline/get GET |
secid=0.code(SZ)|1.code(SH);quote fields=f57,f58,f84,f116,f124;kline klt=101,fqt=1,beg=end=YYYYMMDD,fields1=f1..f6,fields2=f51..f61;SZ/SH;历史价取不晚于 as-of 最近交易日 |
quote f84 股、f116 元、f124 epoch 秒;kline f51日、f53收盘元/股;JSON,5 MiB |
历史收盘以 kline 为权威;quote 只补 as-of 可用股本/市值,不能把当前股本回填旧 as-of |
eastmoney.finance/1.0.0 |
B1,须 A1 ID 回链;财务核心 | datacenter-web.eastmoney.com/api/data/v1/get GET;reportName 固定 RPT_F10_FINANCE_MAINFINADATA,RPT_DMSK_FN_INCOME,RPT_DMSK_FN_BALANCE,RPT_DMSK_FN_CASHFLOW |
columns=ALL,filter=(SECUCODE="code.SZ|SH"),pageNumber,pageSize=20,sortTypes=-1,sortColumns=REPORT_DATE;记录须 NOTICE_DATE<=as-of 且 REPORT_DATE<=as-of |
收入 TOTAL_OPERATE_INCOME,归母 PARENT_NETPROFIT,扣非 DEDUCT_PARENT_NETPROFIT;现金 MONETARYFUNDS;资产/负债/权益;经营现金 NETCASH_OPERATE,资本开支 CONSTRUCT_LONG_ASSET;金额原始元、无缩放;JSON 20 MiB |
四张表均只取满足 as-of 的最新所需期间;字段必须链接同报告期 CNInfo A1,否则该字段 gap/核心阻断 |
eastmoney.forecast_summary/1.0.0 |
B2;非核心 | datacenter-web.eastmoney.com/api/data/v1/get GET,reportName=RPT_WEB_RESPREDICT |
filter=(SECURITY_CODE="code"), page 1/50;记录 REPORT_DATE/UPDATE_DATE<=as-of |
RATING_ORG_NUM、年度 EPS/利润汇总字段;原始元/股或元,按响应定义且不猜缩放;JSON 10 MiB |
预测第 1 个来源;取得可用汇总即不重复请求汇总 |
eastmoney.forecast_detail/1.0.0 |
B2;非核心 | emweb.eastmoney.com/PC_HSF10/ProfitForecast/Index GET |
code=SZ001270|SHxxxxxx,type=web;只解析固定表头“机构/报告日期/年度/EPS或净利润”;明细发布日期不得晚于 as-of |
UTF-8 HTML;机构名、报告日期、预测年度、EPS/净利润;5 MiB | 预测第 2 且最后来源;只为可见明细。解析不到即一个 coverage gap,不再搜索第三站 |
财务数值只在响应字段存在、可解析、币种/单位明确时采用;缺失不得填 0。公告索引仅提供 A1 身份与链接,不从标题猜财务值。市场 f124 为 0/缺失时不得作为日期,历史价日期以 kline f51 为准。所有 adapter 保存原始字段路径、解析版本、发布/数据日期和单位换算表达式。
实现后才可创建 fixtures/chengchang_20260801/。fixture_manifest.json 固定以下规范请求键到响应文件;测试不得由被测 V2 生成 expected:
| data kind | request | fixture response |
|---|---|---|
| stock identity | CNInfo stock list GET | cninfo_stock_list_success.json |
| A1 index | CNInfo announcements POST page 1 | cninfo_announcements_success.json |
| market quote | Eastmoney quote GET | eastmoney_market_quote_success.json |
| historical close | Eastmoney kline GET, beg/end=20260731 |
eastmoney_market_kline_success.json |
| finance main/income/balance/cashflow | 四个固定 reportName GET | eastmoney_finance_{main,income,balance,cashflow}_success.json |
| forecast summary | RPT_WEB_RESPREDICT GET |
eastmoney_forecast_summary_success.json |
| forecast detail | emweb fixed GET | eastmoney_forecast_detail_success.html |
每个 provider 另有最小 empty、http_404、http_500、schema_drift、future_record fixture;HTTP fixture 的状态和 headers 放在 manifest,不伪装为 200 body。forecast summary=4 家、可见 detail=3 家,expected 只能生成一个 W_FORECAST_COVERAGE gap。
机械网络阶段开始时以 time.monotonic() 形成唯一 network_deadline = network_started_mono + 90.0。每个请求、DNS/连接、响应头、分块读取、退避、重试以及 forecast 二次来源都调用同一个 remaining 函数;连接/读/总超时分别取固定上限与剩余预算的较小值。remaining<=0 后不得创建请求或重试。
最多 4 worker。调用方不用 with ThreadPoolExecutor(...) 的隐含等待;显式 shutdown(wait=False,cancel_futures=True),provider transport 必须协作检查 deadline,socket 超时也裁剪到 deadline。已在途任务须在同一 deadline+冻结调度容差内返回;不得再叠加 20 秒读超时。容差固定为 max(0.5s, 测试环境调度分位上限),正式验收上限 91.0 秒。
只对连接重置、超时、5xx 最多重试 2 次;4xx、schema/解析、as-of 错误不重试。退避序列 0.25/0.75 秒,实际 sleep=min(backoff,remaining)。每次请求记录 provider、request_id、started/finished、remaining_before/after、attempt、bytes、HTTP、cache、semantic status、deadline cause;阶段记录 budget start/deadline/end。
离线桩覆盖四 worker 同启、截止前 50ms 启动、阻塞读取、5xx+退避、shutdown,断言不晚于冻结容差且截止后请求计数不增长。
布局:
CACHE/blobs/sha256/<first2>/<sha256>.bin
CACHE/raw-index/<provider>/<fingerprint>/<run_id>.json
CACHE/reusable/<provider>/<fingerprint>.json
CACHE/companies/<ticker>/baselines/<as_of>-<data_hash>.json
CACHE/companies/<ticker>/current.json
fingerprint 前像为 UTF-8 RFC8785 等价规范 JSON(键排序、无多余空白、数字/布尔规范化),字段固定:schema_version,provider_id,adapter_version,method,canonical_scheme_host_path,sorted_query,canonical_body_sha256,ticker,as_of,data_kind,fixture_identity|null,再取 SHA-256。query 重复键保持值数组原序;body 先按 content-type 规范化。fixture_identity=fixture_manifest_sha256:response_id,绝不与真实请求碰撞。
raw blob 可归档成功或失败响应。raw-index 分别记录 transport_complete、HTTP、content_type、bytes、blob_hash、parse/schema/as_of 状态和 provider semantic status。complete=true 只表示归档写完整,不代表可复用。
reusable 索引必须同时满足:transport_complete、登记 HTTP 2xx、允许 content-type、bytes<=上限、blob hash 复核、adapter 版本相同、parse/schema PASS、as-of PASS、semantic status=OK。404/5xx/超时/空数据/schema drift/GAP/BLOCKED 只在本次运行去重;允许负缓存 TTL 固定 60 秒且不得跨 as-of/adapter,也不得写 reusable。篡改时保留 raw 证据、废弃 logical index 并重取。
baseline schema 固定包含 schema_version=1,adapter_bundle_version,ticker,baseline_as_of,created_at,watermark{announcement_time,report_date,market_date,forecast_date},provider_results,field_lineage{field:[source_id,raw_hash]},source_hashes,data_hash。data_hash 的前像排除自身和 created_at,包含其余规范 JSON。只以临时文件+os.replace 提交;同 ticker 加锁并在 replace 前重新读取 current,解决并发竞争。
选择规则:只复用 baseline_as_of<=requested_as_of 且 source hashes 可验证的最近基线;较新基线绝不回跑较旧 as-of。动态模块局部刷新失败时,可保留未过期、日期不晚于 requested as-of、来源哈希仍有效的旧字段并显式 gap;不得把新价格/股本回填旧日期。核心采集未完成不更新 current。并发较旧运行不得覆盖较新 current;相同 as-of 以确定的 data_hash 字典序作幂等选择并保留两个不可变 baseline。
无 judgment:完成 data_snapshot.json、snapshot_build_report.json、来源/原始哈希、基线、16 节数据就绪报告、QA、gaps、runtime 和 manifest;终态固定 DATA_READY_NEEDS_JUDGMENT。不创建 valuation_snapshot.json 或 valuation_results.json,所有需判断章节写“GAP:需要人工判断覆盖层”,不输出方向性价格区间或评价。
有 judgment:schema 只允许 normalization.adjustments、valuation.scenarios/reverse_pe_multiples/exit_pe_multiples/holding_period、analysis 的业务摘要/模型/交叉验证/风险/触发器/边界。禁止写价格、股本、法定收入/利润、报表日期、来源日期、A1 ID/URL/hash;递归发现保护键或覆盖后数据哈希改变即 E_JUDGMENT_CONFLICT。合并后由 V1 load_snapshot 与 compute_valuation 计算;报告数字只读取 V1 results,不重新算 PE/PB/PS/情景/反向 PE/持有期。
任何记录必须同时满足 publish_date<=as-of、data_date<=as-of。无明确 publish_date 的财务/预测记录不得用于核心值;修订公告按 A1 ID/标题/日期建立替代链,as-of 前的最后有效版本才可用。发现未来记录产生 E_ASOF_VIOLATION 并阻断受影响核心字段,不得降成普通 warning。
同一数值取得 A1 原文或可核对 A1 ID 的结构化记录,且公司、期间、币种、单位、口径、修订状态明确,勾稽/数量级合理,即停止继续查询。forecast 只查上述两个登记来源;汇总 4/明细 3 形成一个 gap 后立即停止。
章节顺序固定:1 结论摘要;2 市场和资本结构;3 信源优先级;4 业务及利润来源;5 历史盈利;6 TTM 与归一化;7 机构预期;8 利润质量与现金流;9 模型选择;10 三情景;11 反向隐含条件;12 交叉验证;13 持有期测试;14 风险与触发器;15 复评清单;16 数据局限和复算摘要。
QA 硬门禁:标题齐全且唯一、Markdown fence/表列完整、无 TODO/TBD/待计算/NaN/Infinity;本地产物链接存在;核心字段有 source_id/A1/raw hash 且日期安全;报告数字与 data snapshot 或 V1 results 规范值一致;judgment 不改保护字段;无 judgment 无方向结论;不含“买入、卖出、加仓、减仓”等交易指令或收益承诺;manifest 中每个正式文件的 bytes/hash 可复算。外部 URL 可达性仅 warning,不改写既有结果。
stdout 仅一行规范 JSON:schema_version,status,run_id,output_dir,manifest_path,receipt_path,task_wall_seconds,process_wall_seconds,gap_count,error_code|null;进度写 stderr/runtime.log。
| 状态 | exit | 正式目录必有 | 可有 | 禁止/manifest |
|---|---|---|---|---|
COMPLETE |
0 | data snapshot、build report、valuation snapshot/results、16节报告、QA、gaps、sources、runtime、manifest | provider diagnostics | manifest status 同名、complete=true |
COMPLETE_WITH_GAPS |
0 | 同 COMPLETE 且 gaps 非空 | 非核心缺口 | 核心缺失禁止;complete=true |
DATA_READY_NEEDS_JUDGMENT |
0 | data snapshot、build report、16节报告、QA、gaps、sources、runtime、manifest | provider diagnostics | 禁止 valuation snapshot/results 和方向结论;manifest status 同名、complete=true |
BLOCKED |
4 | 无正式目录;OUT.failed-RUN/failure.json,runtime.log,runtime_metrics.json |
已形成诊断/原始哈希引用 | 禁止 complete manifest/receipt;failure complete=false |
FAILED |
5 | 无正式目录;同上失败包 | 诊断 | 禁止 complete manifest/receipt;failure complete=false |
输入合同错误在网络前 exit 2,不创建正式或失败目录;V1 兼容模式严格使用第 5 节 0/2/3。ticker 模式内部合同错误归 FAILED/5,核心数据/A1不足归 BLOCKED/4。预期的 DATA_READY 不是伪 COMPLETE,但属于可消费成功数据终态。
在网络前以 lstat 检查 output、staging、backup、receipt、所有 .failed-* 冲突;普通文件、符号链接、junction/reparse point 或不明类型一律拒绝。cache 可单独存在但也拒绝链接/reparse。
absent 路径:ABSENT -> STAGING_OWNED -> STAGING_COMPLETE(manifest last) -> OUTPUT_INSTALLED(rename) -> RECEIPT_WRITTEN。force 路径:先完整创建 staging;OLD_OUTPUT -> BACKUP_OWNED(rename1) -> NEW_OUTPUT_INSTALLED(rename2) -> RECEIPT_WRITTEN -> BACKUP_REMOVED。
提交边界捕获 BaseException。若旧目录已移到 backup 且新目录尚未成功就位,先把 backup 恢复到 output;恢复失败时保留 backup 并在 failure 证据记录双异常,绝不删除。若新目录已就位,正式真值是新目录;backup 清理失败只留 warning/backup,不撤销新结果。清理异常不得替换原 KeyboardInterrupt/SystemExit;以异常链保存。只有新目录和 receipt 均成功后才对外宣告成功;receipt 失败时 force 模式恢复旧目录,新 staging/新 output 改名为 failed。
注入点固定:mkdir、每个 write/replace、manifest write、rename1、rename2、restore、receipt、backup cleanup。逐点断言旧输出全树 hash、正式目录唯一、staging/backup/failed 归属、无伪 complete manifest、原异常类型。
process_start_wall 用带时区 datetime.now().astimezone(),duration/预算全部用 monotonic。--task-start 必须是带时区 ISO-8601,解析后不得晚于 process_start;保留原字符串、规范 UTC、source=arg|process_start,缺省等于 process_start。未来值/无时区在网络前 exit 2。
正式包内 runtime_metrics.json 在 manifest 前冻结,包含 task_start,process_start,commit_ready_at,task_wall_seconds,process_wall_seconds,wall_scope=through_commit_ready,以及阶段和 provider telemetry;两个 wall 字段均非负且 task>=process(允许 1ms 舍入容差)。manifest 哈希该文件。
目录 rename 完成后不改写包内文件,而在同级写 OUT.commit-receipt.json:schema_version,run_id,output_path,manifest_sha256,commit_ready_at,commit_finished_at,task_wall_seconds,process_wall_seconds,wall_scope=through_commit_finished。它是最终总墙钟权威记录;stdout 必须复制 receipt 的两个最终 wall 和 receipt path。receipt 以临时文件 fsync+replace 写入;其 hash/bytes 写 stdout,不回写 manifest。正常、data-ready、blocked、failed、force rollback 测试双墙钟、阶段之和上界、receipt/manifest 绑定;失败包 runtime 的 wall_scope=through_failure_recorded,无 receipt。
User-Agent 固定、禁止 cookie/auth、禁止跨 host 重定向、日志移除 query 中潜在敏感值;响应按 bytes 上限流式终止。报告明确“研究与复算材料,不构成交易指令”,但不以免责声明替代数据/结论 QA。不输出任何自动买卖动作。
只读基线固定:
outputs/20260801_chengchang_technology_valuation/valuation_snapshot.json=10585 bytes / 4C27EE81A670BFA8BBD1E2DFB03A9730F6940D7A340D410D232585C57598A138;outputs/20260801_chengchang_technology_valuation/generated/valuation_results.json=9766 bytes / 27671D42A75C82125B893B3374E27497E33B929BB1AFEFA61A5D3370BC446559;normalization、valuation 和允许的 analysis 字段人工摘取;剔除 analysis.executive_conclusion 中的既有价格/方向文字;文件 hash 在创建后单独登记,不由 V2 运行生成;关键 expected 以 Decimal 字符串比较,绝对容差 1e-8(完整规范 results 仍要求字节等价):
| 指标 | expected |
|---|---|
| market cap | 19077995236.56 |
| TTM revenue | 416511774.73 |
| TTM attributable | 132018113.77 |
| TTM deduct / normalized profit | 118174918.34 |
| PB | 12.22659092842983667773303996 |
| PS | 45.80421585662767464686795987 |
| base price low/high | 32.40910757830167747066477256 / 41.96688331621399852114525189 |
| optimistic high | 66.95294679349747740945716487 |
| reverse PE 50 profit | 381559904.7312 |
| required exit price | 152.48767265546425000 |
forecast expected=summary_count=4,detail_count=3,gap_count_by_id.W_FORECAST_COVERAGE=1,禁止为了第四家无限取数。
L0:全包 compile/import、JSON/schema/registry、V1 指纹/函数签名。
L1:每个 provider 成功/空/4xx/5xx/schema drift/future;未知域名网络前拒绝;90 秒四 worker 阻塞桩;cache 404/5xx/负 TTL/篡改/adapter 变化;较新 baseline 回跑旧 as-of、局部失败、并发提交;judgment 禁写;16 节/交易词/数值 QA。
L2:铖昌有/无 judgment、冷/热缓存;有 judgment 与冻结 V1 results 比较,无 judgment 为 DATA_READY 且无伪结论;冷运行<5秒,热缓存<2秒。
L3:force 每个注入点、KeyboardInterrupt/SystemExit、恢复/cleanup 双失败;断言旧树 hash、唯一正式目录、manifest/receipt 真值。
L4:真实网络按第 20 节;不把外站故障伪装成功。
V1 10/10 固定入口:python -m unittest dev/ana-dev/test/stock_valuation_pipeline/test_pipeline.py -v;测试文件=7231 bytes / C1ECD2A8C8C0C9131C3E93B1E384616508314CB2843571D169876CA155D171CD。长城 V1 fixture=dev/ana-dev/test/stock_valuation_pipeline/fixtures/greatwall_example.json=7142 bytes / 06AB6A7C45C2E43F71654C616F15A826B21E468C4BA72AFB0B253C9DD89FACD8。直接 V1 与 V2 bridge 对该 fixture 分别运行无 force、复跑、force 和输入错误,按第 5 节比较。
fixture 冷运行以新 cache/OUT 计 <5.0s;热运行复用同 cache、新 OUT <2.0s;均报告 process/task wall。真实网络机械阶段硬门禁 <=91.0s,目标 <90s;报告每 provider/request 和 cache telemetry。性能测试只比较同机、同 fixture、同输出模式,不能以 V1 毫秒计算时间冒充端到端总墙钟。
PASS 后首选且固定 001270.SZ / 2026-08-01。使用独立目录:
python -m stock_valuation_pipeline_v2 --ticker 001270.SZ --as-of 2026-08-01 `
--cache-dir dev/tmp/valuation-v2-smoke/cache --output-dir dev/tmp/valuation-v2-smoke/cold `
--task-start 2026-08-01T00:00:00+08:00
python -m stock_valuation_pipeline_v2 --ticker 001270.SZ --as-of 2026-08-01 `
--cache-dir dev/tmp/valuation-v2-smoke/cache --output-dir dev/tmp/valuation-v2-smoke/warm `
--task-start 2026-08-01T00:00:00+08:00
唯一换股条件:登记的交易所/行情 provider 明确返回证券不存在,或 as-of 前后无历史收盘且可证明停牌;一般超时、5xx、解析漂移、财务/预测缺口不得换股。满足条件时唯一备用为 000001.SZ / 2026-08-01,保留原失败证据并用同样两条隔离命令。
证据必须保存:两次命令、exit、stdout/stderr、runtime/receipt、request indexes、raw hashes、provider/gap、A1 document IDs/links、价格/股本/市值/财务期间/预测日期、cold→warm cache 命中和 baseline diff、network deadline/end、是否<=91秒。真实数值可变化,但来源身份、日期、单位、预算、复用和缺口真值不可省略。本节只冻结验收,不在方案 PASS 前授权联网。
实现证据写入 project 文档路径,列代码/测试/registry/fixture bytes+SHA-256、全部命令和 exit、V1 10/10、fixture expected、冷/热性能、真实 smoke、失败注入、无关改动隔离。工具说明写 dev-doc/project-doc/股票估值端到端协调层V2.md 与包 README。实现审计 PASS 后,才依管理员条件授权同步原操作手册单文件;审核员在 dev-doc/开发审计报告.md 形成独立结论。
| Finding | 本版闭环 |
|---|---|
| F1 | 第1节引用管理员三账 closure 和唯一 V003 权属 |
| F2 | 第5节冻结 V1 路径/hash/签名/registry/异常/一致性测试 |
| F3 | 第6—7节冻结五个 adapter、allowlist、字段/日期/单位/fixtures/停止 |
| F4 | 第8、18—20节冻结单调 deadline、协作取消、容差和阻塞测试 |
| F5 | 第9节冻结 fingerprint、raw/reusable、负 TTL、baseline 并发/as-of |
| F6 | 第14节冻结 absent/force BaseException 状态机和全点注入 |
| F7 | 第13、15节冻结状态/产物/exit/stdout、task-start、receipt 双墙钟 |
| F8 | 第7、17—20节冻结基线 hash、request map、expected、V1/真实 smoke 命令和证据 |
V003 只提交现有 dev.reviewer.project 做限定方案复审。只有审核明确 PASS,开发者才能创建 V2 代码、测试和 fixture;之后依次执行实现、离线测试、fixture 性能、真实 smoke、文档与实现独立审核。若复审仍 HOLD,只返修阻断项,不绕过门禁,不修改 ana-dev。