# CHANGELOG 格式遵循 Keep a Changelog,并采用语义化版本。 ## [2.1.0] - 2026-10-10 把已有的数据和计算展示出来:回测带图和指数对照,个股页看 K 线,持仓能体检,按名称和拼音搜股票,报告里的推断分档、口径错位有提示;六阶段个股研究支持港股、美股;首页先看指数、自选和持仓盈亏(开盘时价格自动刷新),再往下是对话;左侧栏目从 16 个收成 8 个一级,新增「产业研究」给 20 个板块配分步研究提示词;个股深挖、自选与持仓各合成一页。 2.0.0 没有单独发布,下面 2.0.0 条目里的改动随本版一起发布;从 v1.2.0 升级请两条都看。 ### 新增 - **首页先看自己的股票**:首页最上面是大盘与全球指数(上证指数、沪深300、深证成指、创业板指,道琼斯、纳斯达克综合,恒生指数、恒生科技), 接着是「我的自选」(现价、涨跌幅,先列 10 只、可展开)和「我的持仓」(现价、市值、持仓盈亏的金额和百分比、当日盈亏),再往下才是对话和功能目录。 持仓的股数和成本由交易流水重放,盈亏按现价算;合计按人民币、港元、美元分开,不换汇相加,只算拿到现价的,一只都没拿到(包括行情还没回来时)显示「—」不显示 0。 当日盈亏 =(现价 − 昨收)× 股数,「当日」是这份行情所属的交易日:先看行情自带的成交日期(节假日里停在节前那天),再和按当地时间推的最近一个工作日 (周末、开盘前算上一个工作日,美东按夏令时 / 冬令时切换)比,取更早的那天;这只股票当日有买卖或送转时不算,原因写在那一行的「—」下面(合计下面不另外提示几只没算进来:小概率,提示反而让人困惑), 迁移来的期初持仓不算当日买入;现价 0 当作没取到;流水里有数据不对、没参与计算的,和持仓页一样提示。行情还在取的那几只显示「正在取现价」,不提前报「没取到」。 自选和持仓在交易时段、页面在前台时约每 3 秒取一次现价;指数在三地任一开盘且页面在前台时每 15 秒取一次,四个 A 股指数哪个没取到就显示「—」并写明,八个全空时说没取到; 港股的交易时段算到 16:10(收盘竞价),收市价也刷得到(自选页同样受益)。上一次没回来不叠加,切回页面立刻补一次,休市时不刷。 隐私模式遮金额、不遮百分比。这部分只读:不开始研究、不调模型、不改台账。 - 批量行情 `tx_quotes_batch` 每只多给一条 `quote_time`:腾讯的成交时间,交易所当地时间、原样(A 股 20261009110653 / 港股 2026/10/09 10:51:51 / 美股 2026-10-08 16:00:01)。 - **产业研究**:原来的「板块中心」改名「产业研究」并单独成一级,列出全部 20 个板块(新增 PCB),不再只列已核实环节的几个。每个板块配一组分步研究提示词: 第 1 步让 AI 先读资料库里和这个板块相关的研报,再找今年和去年的公开行业研报(年份按当天日期生成,不写死);之后一步产出一页。光互联、HBM、人形机器人、PCB 四个板块用各自的栏目,其余用通用五栏(总览、技术路线、产业链与价值量、全球格局、确定性地图)。提示词只讲产业:每个数字要求写来源和年份,查不到写「未查到」, 公司只按在产业链里的位置描述,不涉及估值和买卖;提示词里举的数字只作参考,以 AI 查到的资料为准。每一步可以复制,也可以「发给 Agent」。 板块内容由使用者自己的 AI 产出,产品不预先填写。 - **「问 Agent」接收页面填进来的文字**:产业研究的「发给 Agent」把这一步的提示词填进右上角输入框并打开面板,不替用户发送;换页后才收到的不填进别的页面。 输入框里没发出去的字按页面记,换页不显示上一页的;输入框按内容撑高,最多 8 行。 - **回测图表与指数对照**:回测页在报告下方画 4 张图(累计收益对基准、水下回撤、月度收益热力图、年度收益柱),图里的数直接取自回测工具, 不另算一份。基准改为指数:A 股沪深300指数、美股标普500 ETF(SPY)、港股盈富基金(02800.HK,跟踪恒生指数); 取不到时退回所测标的自身的等权买入持有,并在披露里写明。逐日序列只给界面画图,不进 AI 上下文;图只在当次会话显示,归档里保留年度收益与回撤段附表。 - **回测数值指标补到 43 项**:新增年化波动、最长回撤、持仓时间占比、最好 / 最差日月年、正收益月份占比、偏度峰度、VaR / CVaR、Ulcer 指数、 期望收益、SQN、费用占初始资金比例等,只用 pandas 计算;没有定义的值显示「未定义」,不显示 0。另附月度 / 年度收益表与最深 5 段回撤。 - **回测扣费前后对照**:每次回测在同一份数据上把费用和滑点都设为零、同一套信号再跑一遍,报告和图表下方并排给实际与不计成本两列 (总收益、年化、最大回撤、夏普、成交笔数),并写明成本吃掉总收益和年化各多少个百分点、成交记录里实际扣了多少费用(滑点在成交价里,不算进费用)。 不计成本那次只用来量成本,页面写明现实里做不到零成本;重跑失败或仍扣了费用时不给对照,主结果照常。实测(2021–2025): 茅台 RSI 均值回归实际 17.0%、不计成本 25.6%,成本吃掉 8.6 个百分点;腾讯均线交叉 −13.6% 对 −8.0%,吃掉 5.6 个百分点; 苹果均线交叉吃掉 2.0 个百分点(美股零佣金,全是滑点)。每次回测多 5–13 秒。 - **稳健性检验与参数敏感度**:默认输出夏普的重抽样置信区间、把净值切段分别看的分段检验;两参数的内置策略在邻近参数上重跑一张网格 (均线 7×7),页面写明「不代表最优参数,也不代表未来表现」,不标最优格子。 - **个股页 K 线**:K 线 + 5/10/20/60 日收盘价均线 + 成交量,日 / 周 / 月三档,A 股可切换前复权 / 后复权 / 不复权(腾讯不复权价按新浪复权因子换算), 港美股走 Yahoo;红涨绿跌,不画买卖点;北交所暂不支持,会直接提示。 - **持仓体检**:按币种分别算集中度、年化波动、最大回撤、单日 95% VaR / ES、每只的风险贡献、两两相关性和行业暴露(A 股按申万一级,港美股按 GICS 一级); 提醒线由使用者自己设,超线时在持仓页顶部提示;只给数字,不出综合分,缺数据的进缺口。 港美股的行业来自东财公司资料:港股直接给 GICS 四级路径,取第一段;美股只给最细的那一级名字,按一张对照表对回 11 个一级行业。 这张表 2026-10-09 用东财港股的 166 种 GICS 路径生成,美股出现过的 156 种行业名里 150 种能唯一对上,另 6 种 REIT 细分按 GICS 2023 版手工归类(抵押 REIT 在金融,其余在房地产)。 每个行业下面列出是哪几只,港美股另带东财的细分行业名(「英伟达·半导体产品」);东财没有公司资料、或资料里一个行业都没写的(ETF、基金多是这样,东财分不出来就不硬判)单独归「没有行业资料」, 和「行业未取到」「ETF / 基金」一样不算进单一行业提醒线;写了行业但对不回一级的写进缺口,不猜。 - **历史情景回放**:持仓页体检下面新增一张卡片,按现在的持仓比例把几段历史大跌期重放一遍:A 股 5 段(2015 年 6–8 月、2016 年初熔断、2018 年、2020 年 3 月、2021–2024 年)、港股 4 段、美股 4 段,每段的起止取对照指数(沪深300指数 / 盈富基金 / SPY)这段时间收盘的最高点和最低点。每段给组合涨跌、期间最大回撤、最差单日和同期对照,点开看走势图(两条线从 0% 起步)和每只的占比、涨跌、贡献;「按现在的市值约」的金额过隐私遮挡。按币种分开回放、不换汇。当时还没上市、没有价格、到结束还在停牌的进缺口,不当 0,权重只在有价格的几只之间分;有价格的不到这一组市值一半时不给组合数字,只列各只的涨跌;停牌的日子按停牌前的收盘价算,停了几天写明。A 股用 baostock 前复权日线(回到 2015 年),港美股用 Yahoo 日线(约 10 年,更早的时期写「取不到」,港美股 ETF 也走这条);A 股的 ETF、指数、可转债这一版取不到这么早的价格,进缺口。要逐只取十几年的日线,所以点「开始回放」才跑,同一组持仓半小时内记住结果。「问 Agent」带上回放结果(只给百分比和覆盖,不给金额;持仓变了以后旧结果不再带)。新工具 `replay`(`backtest.scenario_replay`),不需要模型。 - **按名称、拼音或代码搜股票**:个股研究、多空辩论、我的持仓共用一个搜索框(「gzmt」「茅台」「600519」都能找到); 自选股支持粘贴一串代码、中文名或拼音首字母批量添加,有歧义的会列出候选让你选。搜索接口不通时退回只认代码,并给出提示。 - **隐私模式**:右上角一键把金额、股数、成本价显示成 ••••(百分比照常),持仓、研究记录、资料导入预览和对话里都生效(自选股页本来就不显示金额),方便录屏截图; 只遮屏幕显示,不影响计算和发给 AI 的内容;对话按措辞识别,个别说法可能遮不到。 - **推断四档可信度**:研究报告「推断」里每条标一档——已披露证实 / 有依据的推断 / 未核实线索 / 被反证;除「未核实线索」外都要写出 证据或计算编号。研究宪法、研究技能与报告阶段校验同步,旧的高 / 中 / 低写法会被校验拦下。 - **口径提示**:编排器按本次证据确定性核对四件事——同一计算是否混用币种、TTM 与单季计算的期末是否一致、按 A 股定期报告披露期限财报是否已是最新一期、 扣非 × 4 年化是否被季节性放大或压低(最新单季比前三季平均高或低三成以上),查到的写在报告开头。只提示、不改变研究状态。 - **MCP 接口说明**:连接时附使用说明,7 个只读工具带只读标注,出错时写明能不能原样重试、下一步怎么做;README 新增 「在 Claude Code / Codex / Cursor 里调用 VR」一节。 - **定时提醒与收件箱**:新栏目「提醒」。程序开着时,A 股交易日收盘后自动整理「收盘摘要」(15:40:指数、涨停 / 炸板 / 跌停、最高连板、 行业资金流前三、龙虎榜上榜只数)和「自选变化」(16:15:自选涨跌、A 股自选新公告标题),放进收件箱;时刻可改可关。周末不联网直接跳过, 节假日按交易日历跳过,日历取不到时当天不运行并在收件箱说明;关机或没开程序时不运行,当天再打开会补跑一次;失败隔 10 分钟重试,三次后在收件箱说明。 推送可选系统通知(macOS / Linux)和飞书、企业微信、钉钉群机器人(只认三家官方地址,支持飞书签名校验与钉钉加签),带静默时段、24 小时去重和每任务冷却; 机器人地址与密钥存本机(权限 0600),接口只回打码后的地址,报错里抹掉地址和密钥。手动「立即运行」照常推送,但不计入去重和冷却、不保存进度; 远程模式下推送里的链接用对外地址;企业微信群机器人没有签名密钥这一项,填了会提示不用填;运行中途程序被关掉的任务显示为没正常结束。 核心层只提供通用的调度与推送,交易日判断和摘要内容在金融层注册。 - **事件日历**:新栏目「事件日历」。自选和持仓未来 7 / 30 / 90 天的事件排成一条时间轴,每条带来源:A 股定期报告预约披露日(过了日子还没披露的单独列)、 限售解禁(只写实际解禁股数)、除权除息(每 10 股派息与送转);美股财报日(Nasdaq,预估日单独标出);台账里的裁决点到期、论点复核日、待办到期放进同一条时间轴, 已过期未处理的置顶;宏观日历可选。港股和 A 股的基金 / 债券没有对应来源,如实写没查;A 股最多查 30 只(持有优先);取不到的来源列在「没查到的」,不当成没有事件。 取数结果最多沿用 6 小时,每条注明取数时间;「过了日子还没披露」只在取数时已经过了预约日才算。 核心层新增通用的「视图」登记口(`GET /view/`),日历在金融层注册。 - **判据到期回看**:事件日历页上方列出到期没判的裁决点和证伪条件,每条附写下以来的公司公告标题(A 股,来源只给最近 30 条,看不全时写明;最多沿用 2 小时内取的,注明取数时间); 用户对照后自己标记兑现 / 没兑现(证伪条件为到期没触发 / 触发了)或不再跟踪,可写一句依据、可改回待判。判过的累积成回看表,只数兑现了多少,不算涨跌和胜率。 新增定时任务「判据到期」(16:30,交易日运行,周末到期的下一个交易日提醒,同一条只提醒一次,改了到期日会在新日子再提醒)。 台账判据新增可选字段「判定日」「判定说明」;个股研究页判据和论点的状态改为中文显示(原来显示 pending / met 等英文值)。 - **报告新旧版对比**:个股研究打开报告时,可以从同一家公司的其他研究里另选一次来比较(默认上一次;只列同市场、未失败、同为正式或同为测试的研究)。 关键数据沿用原来的证据对齐,分变了 / 新增 / 消失,两侧各带证据编号,大金额写成「亿 / 万」,公告标题单独折叠;报告按章节逐行比,证据和计算编号忽略不计, 点开一节看哪几行不一样。只有一次研究时写明「还没有可比较的第二次」,不显示成没有变化;某一次没有通过校验的报告时只比关键数据。取代原来只能看最近两次的「该公司最近两次研究的变化」卡片。 可比较的研究从最近 500 次里找;另一次的报告这次没取到时单独说明,不当成那次没通过校验。 - **对话来源面板**:Agent 回答下面的「本轮工具记录」改为「本轮来源」,按条列出取了什么数据(端点中文名、标的、来源、取数时间、条数,只取到一部分或用的快照会注明)、 读了哪些网页和搜索结果(附链接)、引用了哪份研报的第几页,重复的合并计数,没成功的单独列出;这一轮一次都没查时写明「没有来源可以核对」。 核心层的受控工具执行记录新增可选的来源字段,各字段限长,链接只保留 http(s) 且去掉账号密码;搜索关键词和网页标题也过一遍产出红线,命中的关键词隐去、标题只留地址。 - **对话数字核对**:首页对话(普通对话、Agent、模型直连)的回答逐个核对数字出处——你发的消息与页面内容、召回的资料、本轮取到的数据和网页、此前的对话, 或回答里写出、算对、运算数也有出处的算式。找不到的只把那个数字连同单位换成「(略※)」,末尾注明几处,不整段拒答。按写出的单位换算(写「亿」才乘 1 亿、写「%」才按比例比), 容差按写到的那一位;取数结果里带单位字段的数(如 `"value": 18234.56, "unit": "亿元"`)按那个单位换算后也算出处。 日期、钟点、年份、编号、资料引用、闭合且装着代码的代码块、时间窗口、括号里的参数组,以及金融层登记的指数名和均线 / 交易日窗口不核对; 年份样子的整数后面跟着元 / 亿元 / 点、「35.2x」这种倍数,以及没闭合或装着数据的代码块照常核对;写明「假设」的那一小句算举例。 提示词同步告诉模型会核对。辩论、翻译等内部任务不核对。 - **候选池**:新栏目「候选池」。在自选、持仓或 8 个指数(沪深300、中证A500 / 500 / 1000 / 2000、上证50、科创50、创业板指)的成分股里, 按市盈率(TTM)、市净率、总市值、当天成交额、换手率的区间和「排除 ST / 停牌」逐只核对,每条写明满足 / 不满足 / 缺数据和实际的值; 分三组、按代码排列,不排名、不打分,「全部满足」只表示过了用户设的条件。腾讯把空值写成 0,所以市盈率、市净率、总市值的 0 记为缺数据; 开盘前全都(或几乎全都)没有成交时,停牌、成交额、换手率这三条记为缺数据。成分从中证 / 国证官网的成分文件读全表(读不到时只核对来源列出的前 30 只并写明), 行情每 50 只一批;「重新取行情」不重取成分文件。没取到的写进缺口,不算不满足。东财选股接口实测能通但不用:它在服务器上筛完只回符合的,看不到哪一条缺数据。 个股研究页支持 `?symbol=` 带入代码(只填好、显示走势,不自动开始研究;带进来时名称搜索不再自己弹出下拉框)。 - **异动接近度**:自选股页新增一张卡片,A 股自选逐只算离交易所「异常波动 / 严重异常波动」标准还有多远:3 日、10 日、30 日累计偏离 (前复权日 K 的区间涨跌幅减去基准指数同期涨跌幅,不是每天的偏离值相加)对照标准,10 日内同向异常波动次数;达到后从次一交易日重新算, 停牌的从复牌日重新算,新股上市初期没有涨跌幅限制的几天不算; 基准指数缺某天数据时,那天和紧接着的一天都不算(那一天的指数涨跌跨了两天,对不上)。停牌的股票写它最后一个交易日达到,不写成「今天」。标准按沪深北交易所 2026 年修订的交易规则(2026-07-06 起施行),逐条核对官网原文; 推算的触发日用九阳股份、紫竹高科 2026 年 9–10 月的异常波动公告核对过。离标准不到一半的收起;北交所(腾讯 K 线不支持)、基金债券、B 股、港美股不算, 沪深主板换手率那一条日 K 里没有换手率不算,都写明。只看离标准多远,不判断方向,以交易所公告为准。「问 Agent」带上这张表;「自选变化」提醒附上离标准七成以上的。 - **涨停分档**:每日复盘页新增一张卡片,复盘那天的涨停股按东财行业归类,和前两个交易日(从上证A股指数日 K 找)比,按只数分四档: 连续集中 / 今天集中 / 零散 / 单只,列出连板数和同花顺题材标签。每个行业另写「最高板」(连板数最多的那只,一样多时首封早的在前)和「梯队」(几只首板、几只 2 板……), 看这个行业是只有一只高标,还是一层层有跟上来的;排序按固定规则,不是推荐。前两个交易日的池没取到时写明分不出是不是连续,不当成 0;过去日子的池是那天收盘前取的会重取。 复盘提示词按分档顺序写板块部分,小标题不超过 25 个字、术语第一次出现写全、不用渲染词。板块内龙头集中度没做:要板块成分和市值全表,东财列表接口 2026-09 起取不到。 - **财报前瞻与复盘**:个股研究页 K 线下新增一张卡片(A 股 / 港股 / 美股)。下一份财报:A 股取东财预约披露日(改过期、预约日已过还没披露都写明),港美股取 Yahoo(标明估计日期还是公司公布的日期)。 一致预期:A 股是同花顺全年每股收益(写明是全年的;年份跟下一期走,下一期预约日还没公布时按已披露的最新一期推),港美股是 Yahoo 本季每股收益和营收均值,另给最高 ÷ 最低看分歧;A 股有下一期业绩预告时列出。 过去几次财报:按发布时刻认反应日(盘前 / 盘中当天、盘后次日;A 股只有正式披露日、没有发布时刻,定期报告晚上发的正式日期是次日,按正式披露日当天算,界面写「正式披露」),涨跌 = 复权收盘 ÷ 前一交易日收盘 − 1,含当天大盘;同一天的合并算一次; 和此前最多 4 次的平均绝对涨跌对照。实际 vs 预期:A 股用季报累计归母净利对照当期业绩预告区间(落在哪一边、比中点偏多少),港美股用实际每股收益对照一致预期。 计算库 0.4.0 新增 `earnings_reaction` / `earnings_surprise`,卡片上的数都由它算。没有扣大盘、没做营收和毛利率趋势;北交所不算涨跌(腾讯 K 线不支持);港美股只有 Yahoo 给的最近 4 个季度; Yahoo 发布时刻是当地 0 点的当作时刻不明、不算涨跌。只描述过去,不预测、不出目标价。「问 Agent」带上这张卡片。 - **事件回看**:个股研究页财报卡下面新增一张卡片(只有 A 股个股)。选一类公告——业绩预告、重要股东增持、重要股东减持(东财),列出这只股票历史上每一次公告前 5 个交易日到后 20 个交易日、相对沪深300指数的累计超额收益(每天的涨跌减去指数当天的涨跌再累加),第 0 天是公告日(不是交易日的取之后第一个交易日)。按「事件前 5 日 / 第 0–1 日 / 第 0–5 日 / 第 0–20 日」四档给平均、中位数、上涨占比,画平均和中位的累计路径;业绩预告按东财给的预告类型字面分向好(预增、略增、扭亏、减亏)和向差(预减、略减、首亏、增亏)两组,续盈 / 续亏 / 不确定不归组,和「全部」次数一样的组不重复列。 - **事件回看扩到港股、美股**:港股、美股个股也显示这张卡,事件类型是「业绩公布」。港股按港交所披露易的末期 / 中期 / 季度业绩公告,带香港发布时间,16:00 收市后发的从下一个交易日算第 0 天(平安夜、除夕这类半日市午后发的仍算当天,结果里写明),对照盈富基金(02800.HK,跟踪恒生指数);美股按 SEC 8-K 里的业绩公布(Item 2.02),填了 SEC 联系方式走 SEC 官方全文检索、没填走东财转载(见下一条),用美东提交日当第 0 天(多数公司收市后发,主要看「第 0–1 日」),对照 SPY。新增 3 个端点:零鉴权的 `hkex_results_dates`、`us_earnings_8k_dates`,和要 SEC 联系方式的 `sec_earnings_8k_dates`(注册表 171 个、35 层,可用 168 个)。局限照实写在结果里:港美股日线只能取到约 10 年前,更早的事件不算;外国公司(ADR)用 6-K 报业绩,取不到;没填 SEC 联系方式时,大银行这类申报特别多的只翻最近 30 页(每页 100 份),更早的业绩申报没取到,结果里提示可以去填;美股一次要半分钟上下。港美股的股东增减持这一版没做。 同一天的几条预告(净利润、扣非等)或几位股东的公告算一次,按归母净利润那条定类型;窗口里有停牌的照列、不进平均;最近的还没满 20 个交易日的只进已有的几档;相隔不到 26 个交易日、窗口重叠的标出来;少于 8 次不给平均、不画路径,只列逐次结果;事件前凑不够 6 个交易日的(还没上市、沪深300 2005 年 4 月才有)进缺口。股票用 baostock 前复权日线,沪深300是价格指数、不含分红。没有这类公告的直接写「没查到」;公告明细最多取 5000 条,取满了写进缺口。盘中沪深300已经有今天这根、股票日线收盘后才有时,只算到股票最后一个价格那天并写明,不把今天当成停牌日。 2026-10-09 实测 5 只股票:业绩预告最早到 2004 年、每只 1–66 条,股东增减持最早到 2009 年、每只 7–47 条;回购、机构调研、龙虎榜、限售解禁后来也加上了,见「事件回看加四类 A 股事件」。ETF、北交所、港美股不支持,会直接说明。点「开始回看」才跑,同一只、同一类半小时内记住结果;「问 Agent」带上各档统计和最近 6 次(只有百分比)。新工具 `events`(`backtest.event_study`),不需要模型。 - **事件回看加四类 A 股事件**:回购方案、机构调研、龙虎榜上榜、限售解禁。回购按方案第一次公告的日子算(东财「首次公告日」,和巨潮公告核对过),不是实际买入的日子;机构调研按调研记录的公告日算(接待日通常早几天,那几天外界还不知道),东财只保留近一年左右;龙虎榜收盘后才公布,第 0 天从上榜日之后的第一个交易日算起,上榜当天的大涨大跌落在「事件前 5 日」,同一天因几条理由上榜算一次,按每条理由的席位净额都为正 / 都为负分净买入、净卖出两组(有正有负不归组;「3 日累计偏离」这类理由的净额是几天合计,几条分别写、不相加);限售解禁按实际可上市流通股数占总股本 ≥ 1% / 不到 1% 分两组(占比没写的不归组),已经排期、还没到的批次单独列在卡片最上面,只列日期和规模、不算涨跌。逐次表的日期列按类型改叫首次公告日 / 上榜日 / 解禁日;类型按钮窄屏换行。 现有端点各缺一样(`share_buyback` 没有首次公告日、`em_dragon_tiger` 默认只看近 30 天、`em_lockup_expiry` 历史只取 15 条),所以新增 3 个东财个股历史端点 `em_buyback_history`、`em_dragon_tiger_history`、`em_lockup_history`(注册表 179 个、35 层,可用 176 个),走上游同一套严格翻页:中途出错、回了别的股票、出现重复行都抛错;不取东财自编的「成功率」,也不取解禁表里历史批次和未来批次分母对不上的「占流通股比例」。2026-10-09 实测中际旭创:回购 5 次、机构调研 9 次、龙虎榜 39 个上榜日(2012 年刚上市那几天凑不齐事件前的价格,进缺口)、限售解禁 15 次;中芯国际另列出 2027-06-23 一批已排期的解禁。回购和机构调研次数常常不到 8 次,这时只列逐次结果。 - **回测新增 RSRS 择时模板**:回测可选的内置规则从三种变成四种。RSRS(阻力支撑相对强度)按光大证券 2017 年公开研报的公式自己写、没有搬任何仓库的代码:每天用最近 n 天(默认 18)的最高价对最低价做最小二乘回归取斜率,再算斜率在最近 m 个(默认 600)读数里的标准分,高于阈值(默认 0.7)目标权重为 1、低于负阈值为 0、中间保留前值;只做了基础标准分,研报的 R² 修正版和右偏版没做。 前 n+m-1 根日线只用来算指标、不持有,运行期守卫把这段算进样本:能持有的不够口径最低要求(波段 240 根、长线 480 根)就拒绝并写明还差多少根,单只票不够的点名。报告口径写明方法出处、研报参数是在沪深300指数 2005–2017 年上定的、预热期不持有而对照基准持有、第一个读数在哪天,平仓记录少于 10 条时写明结论说明不了有效还是无效(合成一条,强制披露最坏情况正好是 12 条上限)。参数敏感度网格是回归天数 × 阈值,标准化窗口不动,阈值轴最高到 3(和参数上限一致);网格的中文轴名补上。只用于历史回测,不给当天的读数。 最低价连续几天不变时斜率记为无定义:滚动方差有累积的浮点误差,常数序列算出来不是 0,按「方差大于 0」判会得出 ±4.8 这样的假读数,改成看这几天最低价有没有变动。2026-10-09 茅台实测:2019–2025 波段第一个读数在 2021-07-16、18 条平仓记录,49 格参数网格全部跑完;2023–2025 波段被拒(还差 130 根);标准化窗口改成 250 后能跑,8 条平仓记录,报告写明结论不可靠。 - **研究分享卡**:个股研究报告通过校验后,标题旁多一个「分享卡」按钮,可下载竖版 1080×1920(手机)或横版 1920×1080 的 PNG,也能复制成文字。卡片只放四样: 事实原值(股价、总市值、市盈率(TTM)、市净率取最新一天,营业收入、归母净利润取最新报告期累计,一致预期每股收益取研究那一年、按北京时间定年份;各带日期和来源, 同一期几个来源的值不同就并列,最多 3 个,图上放 2 个;几个来源给出同一个值时来源都列出)、数量(证据 / 来源 / 计算 / 阶段 / 来源冲突,取不到写「—」不写 0)、数据缺口(只写哪一项和哪类缺口,同名的合成一行并数清几处, 名称用数据源注册表的中文名,模型写的原因句不上卡,原因看报告「数据缺口」一节)、一句声明加出处。不放报告里的判断、可信度、评分和目标价;公司名和缺口名过一遍产出红线, 命中的不上卡。测试场景和没做完的研究在卡上醒目标出;报告没通过校验不出卡(后端同样拒绝)。新视图 `share_card`。 - **数据补洞:13 个新端点**(注册表 163 个、35 层,可用 160 个;新增「G13 公司资料」层),每个都先联网实测再登记,健康检查全部正常: 港股 `em_southbound_flow` 南向资金每日成交(百万港元,与港交所披露核对过)、`em_southbound_holding` 个股南向持股、`em_hk_dividend` 派息历史(方案原文,不解析成数字); `ah_premium_a` / `ah_premium_h` AH 溢价(A 价、H 价、港元兑人民币三个原值和各自时间都留证,不是两地上市的写明「源里没有对应股票」,不算失败); 港美股 `em_global_profile` 公司资料(行业 / 上市板块 / 上市日 / 员工 / 简介,源文本净化后截断)、`yahoo_events` 分红与拆合股历史、 `baidu_valuation_global` 估值历史(市盈率 TTM / 市净率 / 总市值近一年日序列,另存一份 CSV,可直接交给 `percentile_rank` 算历史分位;源在周末节假日延续上一日值,周末已剔除); A 股 `em_top10_holders` / `em_top10_free_holders` 十大股东与十大流通股东、`em_main_business` 主营构成(按行业 / 产品 / 地区)、`em_suspensions` 当日停复牌名单; 美国 `fred_us_macro` 宏观历史序列(FRED 免 key 的 CSV:CPI、核心 CPI、核心 PCE、失业率、非农、联邦基金利率、实际 GDP 等 12 个系列,单位逐个对照 FRED 系列页;版权受限的系列不收)。 十大流通股东进 risk 阶段、主营构成进 profile 阶段(都是可选);港美股研究阶段计划在后面的港美股六阶段一项里再定。 - **港股、美股六阶段研究**:个股研究页、Deep 研究和 MCP / 接口都能对港股(5 位代码,如 00700)和美股(如 AAPL)启动六阶段研究;MCP / 接口调用港美股必须传 `market`。 口径按市场调整:开头先核对公司身份(腾讯报价与东财公司资料两个来源的公司名比对,对不上必须写进缺口,编排器独立复核); 财务只用 `global_financials_pit`(东财港美股主要指标,按「公告日 ≤ 研究日」筛过),季度 / 全年 / 年初至今累计分开标,近四季合计与同比由累计值推 (适合苹果这种 9 月截止的财年和只发半年报的港股),累计值逐项照抄证据、截止期必须是本次取到的最新一期;东财三表与 `yahoo_financials` 没有按公告日筛,只能并列展示、不进计算。 估值时股价 / 市值与利润币种不同(如腾讯港元报价、人民币列报)必须传汇率,汇率只能照抄 `fx_rates` 证据(值和单位都核对);一致预期取 Yahoo 当前财年 T 与 T+1 (前瞻增速 1 年、分歧度看 T+1);报价参考日按美股标普 500、港股恒生指数;市盈率历史分位用百度 PE TTM 近三年序列;PEG 与消化情景用财报算的 PE TTM。 港美股不披露扣非,扣非市盈率一格写「未获取」;单季环比本版不算;ADR 与本地股的换股比例不核对,报告里写明。 报告开头的口径提示、分享卡(「起..止」报告期按截止日取最新、当前财年跟一致预期走、亿美元 / 亿港元)和报告数字核对(HK:00700、(00700) 这类港股代码不当成数字)同步支持港美股。 - **美股业绩日期可改用 SEC 官方数据**:「接入 AI」页新增「美股官方数据(选填)」,填英文姓名和邮箱——SEC 要求每个访问者在请求里留下联系方式,不留一律拒绝;产品不替用户编一个,也不冒充浏览器。填了以后,事件回看的美股业绩日期改用 SEC EDGAR 全文检索(`sec_earnings_8k_dates`,按申报自带的 items 只留 2.02,更正版 8-K/A 不算),摩根大通这类大银行也能取全(2026-10-09 实测摩根大通 2015 年以来 47 份,和把 8-K 全部翻完再筛的结果逐份一致;之前用东财一份都取不到);已有的 6 个 SEC 端点(申报列表、XBRL 财务、全文检索等)也能用了。SEC 这次没取到时自动退回东财并写明原因;没填照旧用东财,东财翻不完时提示可以去填。 联系方式只存在数据目录的 `sec-contact.json`(只有自己可读),只交给声明了它的端点和工具(垂类工具新增 `authEnv` 声明,和端点的 `auth_env` 同一回事;没声明的工具拿不到),放进发往 SEC 的请求头;页面只显示打码后的样子(如「Z*** S*** z***@example.com」),只收可打印的英文字符(请求头里不会出现换行);环境变量 `VRA_SEC_CONTACT` 设了以它为准、页面不能改(按同一口径整理和校验,格式不对当没填,报错里不带填的内容);远程访问模式下页面不能改。错误信息里出现填的联系方式会整串遮掉。每次取数现读,保存后不用重启。 - **港美股研究用的 5 个新端点**(注册表 168 个、35 层,可用 165 个):`global_quote_ref` 港美股报价 + 基准指数(报价日 / 参考交易日 / 交易时段 / 僵尸报价判定)、 `fx_rates` 汇率(美元 / 港元兑人民币、美元兑港元)、`global_financials_pit` 按公告日过滤的关键财务、`yahoo_consensus` 年度一致预期(EPS 均值 / 最低 / 最高 / 分析师数 / 营收,按财报币种标单位)、 `baidu_pe_history_3y` 百度 PE TTM 近三年日序列。均已联网实测,健康检查全部正常。 - **复盘页用的 5 个新端点**(注册表 176 个、35 层,可用 173 个),都先联网实测再登记:`em_market_breadth` 全市场涨跌分布(涨停到跌停 23 档)+ 沪深京三所涨跌家数与成交额(只给当天); `em_market_trend` 8 条主要指数(上证、深证成指、创业板指、科创50、沪深300、中证500、中证1000、北证50)的 5 / 20 / 60 / 250 日和年初至今涨跌、20 / 60 / 250 日均线、250 日内最高 / 最低收盘和离最高点多远, 加沪深两市成交额(上证指数 + 深证综指的成交额)近 60 日和 20 / 60 日均值(可传 `end` 截到某一天;当天还没收盘时另给不含今天的均值);`em_market_margin` 全市场两融余额逐日序列与融资净买入(T 日数据 T+1 才发布); `sina_board_flow` 新浪板块资金流、`sina_turnover_rank` 新浪沪深京 A 股成交额榜,作为东财两个榜单取不到时的备源,字段名和说明都写明是新浪口径。 - **持仓改为交易流水**:「我的持仓」改记一笔笔流水——期初持仓、买入、卖出、现金分红、送转拆股,按日期重放出当前持仓、已实现盈亏和分红; 成本法可在先进先出和移动加权平均之间切换。数据不对的流水(卖超、缺价格、送转比例不对等)逐条写原因,不参与计算。 各币种分别合计,另给一行按当前汇率(腾讯外汇,写明日期和汇率)折合的人民币参考,缺汇率时写明没算。候选池「我的持仓」、判据回看、事件日历改读重放出来的持仓。 - **旧持仓自动转成流水**:原来一只一条的持有记录,打开持仓页时自动转成「期初持仓」流水,数量和成本照旧。转之前先把台账文件复制到 `ledger/持仓迁移备份-日期/`(附恢复说明),流水写好并回读确认后才删旧记录;中途断掉重跑不会重复。同一代码已经有自己记的流水时不自动转, 列出来让你选「按它补一笔期初持仓」或删掉;没写建立日期的按迁移当天记,并在备注里写明。 - **持仓收益率**:持仓页新增收益率卡,按币种分开给时间加权收益(看所选的票本身走得怎么样)和资金加权收益(XIRR,看这些钱实际赚了多少), 不满一年只给区间值、不给年化,附累计收益走势。A 股用不复权价、按流水里的送转换算股数;港美股用拆股已调整价、按流水里的送转拆股还原成当时的价格; A 股价格出现像除权的断崖而前后没记送转时给提醒。期初持仓按当天收盘价计入、成本只用于算盈亏;取不到价格的整只不算、列进缺口,不拿成本价或 0 凑市值。 区间从第一笔投入算;流水比能取到的价格(约 5 年)还早时,从能取到价格那天按收盘价计入并写明;那之前就已卖光的不取价、不算,写明几只;新股上市前那几天按成交价计市值并写明。只给数字,不和指数比输赢。 - **从表格批量导入流水**:持仓页「记一笔」下面新增「批量导入流水(CSV / 复制粘贴)」,可以选 CSV 文件,或从表格软件直接复制粘贴; 在本机按列名解析,不发给 AI。常见券商导出的列名(成交日期、业务名称、证券代码、成交数量、成交价格、手续费等)和类型写法(证券买入、红利入账等)都认, GBK 编码的中文 CSV 也能读;Excel 工作簿(.xlsx)提示另存为 CSV。每行和手动「记一笔」过同一套检查,不对的写原因;1–5 位纯数字代码一律拒 (表格软件常把 000001 存成 1、00700 存成 700,分不清 A 股还是港股),负数不取绝对值。检查后先预览:和已记的流水一样的默认不勾, 写进去以后会卖超的写明,已记的流水会因为这批变成算不了的也提前列出。勾选的行一次写入,**要么全写、要么全不写**,写之前先把台账备份到 `ledger/持仓导入备份-日期/`。一次最多 1000 行; 有「填入格式示例」可以照着改;隐私模式下输入框和预览里的数字都遮住。 - **Windows / macOS 免安装包**:Releases 里提供 Windows x64、Apple 芯片 Mac、Intel Mac 三个压缩包,自带 Node 24 和 Python 3.12(官方发布文件,写死 SHA256 校验), 解压后双击 `Start-VibeResearch` 启动,不用装 Node、Python、Git。需要 64 位 Windows 10 或 macOS 14 及以上(旧版 macOS 启动时直接说明);只在本机打开,不开放局域网。 数据放在包文件夹的 `.local`,升级时整个复制到新文件夹。包没有代码签名,第一次打开的放行方法写在包里的 `README-portable.txt` 和 README。打 tag 时由 GitHub Actions 在三个平台各构建一次,在没有系统 Node / Python 的环境里启动、打开页面、跑体检, 三个平台都通过才挂到 Release;每个包附 `.sha256`。 - **新版提示**:每天查一次 GitHub 上的最新正式版本(请求只带当前版本号,没查成隔一小时再试),有新版时页面顶部提示一行,按免安装包 / 源码安装分别说明升级做法; 可以「这个版本不再提示」,在「接入 AI」页关掉、恢复或现在检查;环境变量 `VRA_UPDATE_CHECK=0` 完全不联网。查失败时不打扰,原因显示在设置页。 - **防篡改核对**:每次研究结束(成功或出错都算)、每次在软件里保存或删除台账记录(研究笔记、交易流水、自选、判据等),都在数据目录的 `audit/chain.jsonl` 里追加一条登记: 记下内容的指纹(SHA-256),每条再带上上一条的指纹,连成一条链。「研究记录」页最下面点「核对」逐个重算——研究的报告、证据、计算、阶段结果、取数记录和原始文件,以及台账每一条记录—— 和登记时不一样的、登记过但现在不见了的、还没登记的分开列出,研究写明是哪几个文件改了、多了、少了;登记簿本身哪一行被改、删、插过也会指出。 报告附录和证据查看器也算内容(直接给人看,查看器里嵌着报告)。"和登记时不一样"多半是绕开软件改的,但当时登记没写上也会这样显示,页面两种可能都写明。 功能上线前就有的点「补登」;确实是自己改过或删掉的,要另点「按现在的内容重新登记」或「确认这些已经不在了」才不再报,原来的登记仍留在链上。 登记簿和数据在同一个文件夹,能改数据的人也能把整份登记簿重写,页面如实写明这一点,并给出「链头」(最后一条的序号和指纹):复制到别处保存,以后粘回来比一下就能发现。 核对只读;登记写不进去时不拦原来的保存或研究,下次核对报「还没登记」。过程日志 `events.jsonl` 不算内容(收尾后还会追加)。 登记簿或它所在的文件夹是符号链接时拒绝读写。极少数情况下(上一个写登记的程序意外退出、两个程序同时接手)两条登记可能撞上同一个序号,核对会把它报成「接不上」——宁可多报,不会漏报。 新接口 `GET /audit`、`POST /audit/register`、`POST /audit/check-head`。 - **各次研究过程对比**:个股研究打开报告时,点「对比」把同一家公司最近几次研究并排(最多 8 次,当前这次一定在;同市场、同为正式或同为测试、已经结束的,失败和取消的也列): 哪家 Agent(订阅档写明模型由本机登录决定、CLI 没有回报)、取数范围、总用时和 Agent 干活的时间、资料齐全的阶段(分母是这次要跑的阶段,中途停下的没跑到的也算)、一次就过校验的阶段、 报告里引了证据或计算编号的那些行数字对不对得上(没引编号的行不核对)、 取到和实际引用的证据、引用的计算、写出的缺口、跨来源对不上的证据、触到产出红线、收尾时被拦回补做、取数脚本成功 / 部分 / 失败。换一家 Agent 再研究同一只股票,就能比较不同 Agent 的研究过程。 只比研究过程,不比结论对错,也不比收益;不打总分、不排名次、不按好坏上色(缺口写得多可能只是更老实)。读不到的显示「—」,不当成 0;阶段结果文件坏了,引用和缺口整体给「—」,不只数其余阶段。 取数范围不同、有的只跑了部分阶段、都是同一家 Agent、有中途停下的时,表格上方先说明。只读,不重新跑校验。新接口 `GET /runs//compare`。 - **请另一家 Agent 也研究这只、对比存进研究记录、本周对比周报**:「各次研究过程对比」点了「对比」以后,下面列出本机已登录的订阅 Agent(Codex / Claude Code / WorkBuddy), 每家一个按钮,写明表里已有它几次。点了先确认,再用那家的订阅、沿用这次的取数范围研究同一只股票——只这一次用它,不改「接入 AI」里存的设置; 页面上方已有一次研究在跑时按钮不能点;本机没有已登录的订阅 Agent 时指去「接入 AI」。跑完回来点「重新对比」就能并排看。 对比表可以「存入沉淀」(研究记录新增「研究对比」分类),存的是同一张表,连同表格上方的说明和各行怎么读。 研究归档旁新增「本周对比周报」:近 7 天开始、已经结束、被至少两家不同 Agent 研究过的股票(测试运行不算),各自的对比汇成一份存进研究记录; 每只只列本周那几次,一份最多 10 只,超出的和没对比出来的写明;一只都没有时不存空周报。只存本机,不发到任何地方。 2026-10-09 在本机真跑过:腾讯控股已有两次 Claude Code 订阅研究(港美股硬测试的真实运行),点按钮请 Codex 订阅研究同一只,15 分 31 秒跑完, 对比表三列并排(用时、引用的证据、收尾时被拦回补做各不相同);存入沉淀和本周对比周报都存进了研究记录,内容就是卡片上那张表。 - **自选和持仓的表格能排序**:自选总览、首页「我的持仓」、持仓页「持仓明细」点表头排序(再点一下反过来,第三下恢复原来的顺序),选的排序记在本机浏览器里。 现价、成本价、市值、盈亏金额、已实现、分红这类列先按人民币、港元、美元分块再排,不同币种不比大小;数量、涨跌幅、盈亏% 直接比。 首页持仓表的格子是两行的,按下面那行的百分比排(「现价」按今天的涨跌幅,「持仓盈亏」按收益率)。取不到的值不论升序降序都排最后,值一样的保持原来的先后。 持仓另有「调整顺序」:每行出现上移 / 下移,自己排先后,首页和持仓页共用一份,只记在这台电脑的浏览器里;新买的跟在最后。正按某列排着时点「调整顺序」,从眼前的先后开始挪。 自选在台账里本来就不记先后,所以自选只做表头排序。 隐私模式下,被遮住的列(数量、成本价、市值、盈亏金额、已实现、分红,首页是市值和当日盈亏)不能点排序:金额虽然显示成 ••••,行的先后却会透露哪只仓位最重、亏得最多。 记着的排序正好是这些列时先不用,关掉隐私模式又回来;现价、涨跌幅、盈亏% 照常排。 - **自选总览整行可点,下面接 K 线**:点一行,自选总览下面的走势卡换成这只的日 / 周 / 月 K 线,右上角「个股页」去看财报和事件回看。 名称是一个按钮,键盘 Tab 到它按回车 / 空格也能选,读屏会念出选中了哪只。 没点过默认第一行;行情完整取过一次后定住,按涨跌排着时每次刷新不会换图,按行情排着时行情回来之前先不画(不然先画一只、行情一到又换一只);点移除不会顺带换图。 走势卡换股票时,新的还没取回来就不显示上一只的图,不再出现新名字配旧图(个股页同样受益)。 - **持仓明细的「已实现」「分红」是 0 时显示 0**,原来显示「—」,和「取不到」混在一起,排序时却又当 0 排。 ### 变更 - **删掉 8 个和在用源重复的数据端点**(注册表 179 → 171 个、35 层,可用 176 → 168 个):港美股实时报价 `tx_us_quote` `sina_us_quote` `tx_hk_quote` `sina_hk_quote` `em_global_quote` (界面和六阶段研究用的都是 `global_quote_ref`)、百度日 K `baidu_kline_ma`(A 股日 K 用 `fetch_kline` / `bs_kline_qfq`)、新浪研报 `sina_reports`(研报用 `em_reports`)、 深交所交易日历 `szse_trading_calendar`(交易日历用 `fetch_trade_calendar`)。对应的取数函数和映射一并删掉;上游生成文件 `astock_ported.py` 照原样不动。 前端没有页面调用、还在用 `em_global_quote` 的 `api.globalStock` 一起删掉。问财两个端点、期货 / 可转债等产品主线以外的品种照旧保留;README、官网、`CATALOG.md`、`UPSTREAM.md` 的数字跟着改。 清点经过见仓库外的 `数据源清点-2026-10-10.md`。 - **删掉默认停用的通达信 K 线 / 五档 / 逐笔 3 个端点**(注册表 171 → 168 个,全部可用):2026-09 起服务器不再给这三类数据(上游 #52),K 线用 `tx_kline` / `tdx_daily_package`、逐笔用 `tx_ticks`、 实时价用 `tx_quote`(买卖五档本来就取不到,删了也不少什么)。通达信财务快照和 F10 照旧可用,选服验活只按财务命令验。 - **前端删掉没有页面调用的取数函数**:估值、分位、财报、研报、两融、大宗、股东户数、分红、资金流、A 股指数、行业排行、大盘概览、短线情绪、成交额榜、港股现金流、龙虎榜、解禁、板块、热门概念、 互动问答和一个连通检查,共 21 个,连同只给它们用的类型和小工具函数;另删掉没有页面引用的 `EarningsSnapshot` 组件。`api.ts` 1545 → 约 790 行。对应的数据源都还在,Agent 和研究流程照常取。 - **界面换成「静默数据台」样式**:底色从深蓝黑换成中性石墨(浅色是浅灰白),主色仍是橙色;去掉玻璃渐变、背景光晕和发光字,每块数据一个方框(面板底色 + 1 px 线框、圆角 8 px), 面板顶上一条 34 px 标题条。整体收紧:顶栏 64 → 44 px,侧栏 228 → 216 px、行高收紧,页面标题 18 px,表格用统一的紧凑样式(表头 11 px、单元格上下 6 px、行间一条线、数字等宽)。 首页指数八格放在一个面板里用细线分格,自选和持仓各一个带标题条的面板,三个币种的合计放在一张各列对齐的小表里。左侧栏目照旧默认展开显示文字,底部一个按钮可以收起成图标; 红涨绿跌不变;报错文字和横条仍用红色,没另换颜色。对比度按 WCAG 核过:深色正文 14.7、次要文字约 7.9、橙色 5.8、涨 5.1、跌 7.0;浅色次要文字 6.8、橙色 6.3(选中页签的橙字 4.9)、涨 4.8(面板上)。「问 Agent」按钮去掉投影。首页对话区的暖色样式没动。 README 截图按新样式重拍,旧截图删掉。2026-10-10 又在单独的演示工作区补拍了 10 个功能页(每日复盘、个股深挖、六阶段研究报告、产业研究、资讯雷达、产业信号、持仓、事件日历、候选池、接入 AI), 首页换成带示例自选和持仓的版本,中英文 README 用两列表格展示;示例数据都标了「示例」,研究报告用 10-08 开发验证跑完的那份原样展示(截图说明在 `assets/screenshots/2026-10-10/README.md`)。 - **左侧栏目收成 8 个一级**:原来 16 个栏目平铺,现在是首页、每日复盘、产业资讯、产业研究、研究工具、我的股票、资料库、接入 AI。有几个页面的收成二级: 产业资讯(资讯雷达、产业信号)、产业研究(20 个板块直接列在二级里,每个配一个图标,如人形机器人是机器人、AI 算力是芯片;点「产业研究」本身是全部板块一览,顶栏显示当前板块名)、 研究工具(个股深挖、多空辩论、回测、候选池)、我的股票(自选与持仓、事件日历、提醒)、资料库(我的研报、研究记录); 接入 AI 固定在侧栏底部。点一级栏目的名字进它的第一个页面(产业研究进总览),旁边的实心三角展开或收起二级(收起时朝下、展开后朝上),展开状态记在本机;没手动展开或收起过的组,当前页面在里面时自动展开,收起时一级栏目照样高亮, 提醒有未读时一级栏目也显示数字。侧栏收成图标时,点有二级的图标在旁边弹出二级列表(Esc 关闭,焦点回到图标)。资讯雷达、产业信号原来在侧栏里的 子项去掉,只在页面里切换。首页功能目录改成和一级栏目同名的分组。下文写的「个股研究页」「自选股页」「持仓页」现在的位置见下面几条。 - **个股深挖**:「个股研究」改名「个股深挖」。页头先选一只股票(A 股、港股、美股),下面分两个分页:「概览」直接显示 K 线、财报前瞻与复盘、事件回看 (原来要点「看走势」才出来);「深度研究」是原来的六阶段研究,研究归档默认只列这只股票,可以切到全部。选股票只是打开这只,不会自动开始研究; 切走分页时正在跑的研究照常进行,分页上转圈提示。A 股页头有「多空辩论」按钮,带着这只股票去多空辩论页。 - **多空辩论**:仍是单独一页,放在研究工具下。原来只能填 6 位代码,现在用同一个搜索框(名称、拼音、代码都行,只列 A 股),辩论进行中不能换股票; 打开的是港股、美股时写明只支持 A 股,并给去个股深挖的链接。 - **自选与持仓**:「自选股」和「我的持仓」合成一页,分「自选」「持仓」两个分页,记住上次看的分页。自选里已经持有的标「持有」,两个分页里点股票名都进个股深挖。 持仓的收益表现、交易流水、持仓体检、历史回放从上下一长串改成页面下方的分页;「记一笔 / 导入」收进页头按钮,还没有任何流水时自动展开。 - **每日复盘重做:打开就看市场处在什么状态**。原来是几张零散的表,最下面的板块资金流和成交额榜从 2026-09-22 起一直是空的(东财列表接口取不到,页面也没说原因)。 现在从上到下是:市场状态八格(涨跌家数、两市成交额对 20 / 60 日均值、涨停 / 跌停 / 封板率、最高连板、昨日涨停今天的平均涨跌、站上 20 / 60 / 250 日线的指数个数、两融余额 5 日变化、沪深300 市盈率与股息率对 10 年国债)→ 主要指数与全球市场 → Agent 复盘 → 短线情绪(涨跌分布图与三所家数、赚钱效应与亏钱效应、晋级率与连板股明细、涨停分档)→ 中长线(指数多周期涨跌与均线位置表、成交额 60 日柱图和均值线、两融走势、股债收益率差)→ 资金去了哪(行业资金净流入 / 流出、成交额前 20、龙虎榜净买卖)。赚钱效应、晋级率由昨日涨停池和今天的涨停池逐只对出来,算法写在卡片上。 交易时段默认看今天(收盘前数字还会变,成交额那根标灰、不和整天的均值比,改和截至上一个交易日的均值对照),可以切到上一个交易日看完整的一天;切换由后端按交易日历判断,不按本机时间猜。 板块资金流、成交额榜取不到时自动换新浪,卡片上写明是新浪口径(新浪约 48 个行业、净额 = 流入 − 流出,和东财主力净额不能互相比);新浪也取不到时两个原因都写出来。每块标自己的数据日, 只给当天的三个来源在看上一个交易日时标「此刻快照」;没取到的块写原因,不显示成 0。「偏强」「活跃」这类标签按写死的阈值算,规则写在标签上,不预测涨跌、不出买卖点。 「让 Agent 复盘」发给模型的页面摘要同步:每块带读法、备用来源、缺口,盘中写明成交额还没收完。复盘页去掉了自选股表(首页已有),搜索框也随之去掉。 核心层的界面查询新增两样通用能力:块可以声明一个备用端点(主源失败或抛错才换,只取到一部分不换;不许和注入上下文、用户参数同用);页面可以声明看法(`mode`,金融层注册了 `live`)。 - **旧地址照样能打开**:/watchlist、/portfolio 跳到自选与持仓对应的分页,/stock-data 跳到个股深挖,开发中出现过的个股页多空辩论分页(`?tab=debate`)跳到多空辩论页,原来带的 `?symbol=` 等参数照带。 收盘提醒里「自选变化」的链接改成新地址;以前存下的提醒点开也能跳过去。 - **取消「开启Agent」开关和普通对话**:接入订阅或模型 API 后,AI 一律可以按问题需要联网搜索、读取网页、取数和计算,不再有只凭模型自身知识回答、不查数据的模式。 侧栏和设置页的开关、首页「普通对话 · Agent 已关闭」一并去掉;对话提示词改为不需要新数据的问题(解释概念、梳理思路、翻译)直接回答。 旧版本浏览器里存下的开关状态读取时忽略、不改写。模型 API 需要支持工具调用(function calling)。接口调用方仍可传 `executionMode: "direct"`,后端行为不变; 这时的报错改为说明 executionMode 要用 agent,不再提已经不存在的开关。 - `yahoo_financials` 改走 Yahoo 财务时间序列接口:原来的 quoteSummary 财报模块对多数股票已经不返回数据。现在给收入、毛利、营业利润、净利润、 稀释每股收益、EBITDA、经营现金流、资本开支、自由现金流和总资产、总负债、股东权益、现金、总债务,可选全年 / 单季 / 近四季;金额按报告币种(港股公司常以人民币列报,单位写「人民币元」),源给 0 就记 0。 - Yahoo 关键指标与分析师预期不再输出分析师目标价和逐家升降级(评级分布作为机构聚合篇数保留);原始响应照常落盘存证。 - 事件日历和候选池的「没取到」写明来源和原因(如「csindex 超时」):取数器把原因写在信封的 errors 里,此前没有读出来。 - 回测 Agent 的工具能力说明写明基准、图表不是参数而是每次都有,多只标的一次运行合成等权组合;此前 Agent 会误以为不能和指数比、不能画图。 - 启动脚本新增 `--prebuilt`(Windows `-Prebuilt`):用打包好的页面启动,不跑开发服务器;Windows 另加 `-NoOpen` 不自动开浏览器。 - 体检扫描本机文件时跳过产品根目录下的 `runtime/`(免安装包自带的 Node / Python,文件上万);别处同名目录照扫。 - 回测工具说明里给出敏感度矩阵的行列方向;页面上的占比不再把 99.5% 四舍五入成 100%。 - MCP 工具说明与报错里的「大脑」改为「模型」;没设后台默认 AI 时,报错指向 `provider.profile` / `VRA_PROVIDER`。 - 回测里没有平仓交易时的胜率、净值没有波动(如全程空仓)时的夏普和信息比率改为「未定义」,不再写成 0;分段检验里空仓的那一段同样处理。 - 同一次回测里取不到的指数或标的不再在敏感度网格的每一格重取(此前每格都要再等一次超时,可能拖垮整次回测)。 - 搜索框改了输入、新结果还没回来时按回车,不再选中上一个词的候选(自选页此前会直接存进去)。 - 年度收益的「不完整」标记按起止日期判断(1 月中开始、12 月上旬结束的年份也会标出);持仓体检里没有复权因子的 A 股标的(如部分 ETF)单独注明用的是不复权价。 - MCP 报错指引不再建议传 `overwrite=true` 覆盖已用过的研究编号(服务端一律拒绝),改为换一个编号或不传让服务自动生成。 - 计算库版本 0.3.2 → 0.4.0:只新增财报两个函数,已有函数的结果不变。计算编号里含版本号,所以同样的输入升级后会得到新编号;用旧版本做的硬测试夹具会按原规则被拒,要重录。 - 计算库版本 0.4.0 → 0.5.0:金额单位支持美元 / 港元;两个金额币种不同必须传汇率(`fx_rate` + `fx_unit`),不给就报错、不猜;`forward_pe` 可选核对股价与 EPS 的单位; 新增 `fx_convert`、`ttm_from_ytd`、`ttm_yoy_from_ytd`。已有函数在原来的输入下结果不变(原有计算库测试全部照旧通过);计算编号同样随版本变化。 - 研究检查收紧(A 股同样适用):估值等下游计算按口径引用的上游(A 股的最新单季扣非、近四季归母、近四季同比;港美股的累计值推近四季与同比), 必须登记在所属阶段(财务)的计算清单里——只有登记的计算才会被逐项核对。以前可以另造一条只引一项证据、数字自己编的上游计算绕过核对。 不带口径的上游(如 PEG 用的前瞻增速)不受影响:AI 用最低 / 最高预测另算的情景版本照常可用。2026-10-08 三家(Claude Code、Codex、WorkBuddy)的 9 次真实 A 股运行按新规则复核,没有一处被误拦。 - 港美股回测起点早于约 10 年前时直接报错并写明最早能取到哪天:此前会落到 Yahoo 的 `range=max`,它给的是**月线**,回测拿月线当日线跑完、结果看着正常。现在取回的 Yahoo 行情一律核对粒度,不是日线(或没写粒度)就中止。 - baostock 翻页失败(会话被挤掉等)只改错误码、不抛异常,此前会拿着前 2000 行当完整序列用(长区间 K 线、估值历史、交易日历、公司资料都可能被截断);现在翻页失败直接报错,写明只取到几行。取下一页时网络异常更隐蔽:SDK 只打印一行、错误码不变,现在读完还停在满页(2000 行)也按翻页失败报错,正好 2000 行、下一页回空的照常返回。 - 研究页对港股、美股多一道确认:查不到公司名不开始;不是从下拉选的字母代码,先显示要研究的是哪家公司,再按一次「开始」才启动(md、ba 这类拼音本身也是美股代码)。 - 文字跟上现状:官网去掉「普通对话 / 按需开启 Agent」和 Agent 开关的说法,端点数 147 → 176,六阶段研究写成 A 股、港股、美股(多空辩论仍只做 A 股), 首页写成先看指数、自选和持仓,8 张功能卡对应 8 个一级栏目,截图换成 2026-10-10 演示工作区拍的新图(示例自选与持仓,旧的 4 张 v1 截图删除)。 README 的已知限制写明港美股六阶段研究已用 Claude Code 订阅真跑过硬测试;回测「净值没有波动」的提示和情景回放的说明不再出现「空仓」「加减仓」这类词; 回测目录的第三方归属说明补上 v2.1 对上游文件(指标、校验、引擎、对照、风险 X 光)的改动和新写的文件,去掉过时的测试条数。 ### 修复 - **Windows 上 Codex 越界或取消时报错原因不对**:Codex 已经自己退出后,taskkill 找不到它,原来会报「进程树退出未确认」而不是「策略违规」或「已取消」。现在 Windows 上直接子进程已退出就按正常退出的同一判据收尾。发版前的跨平台 CI 发现;同一次还修了一条在 Linux 上把临时路径拼错的测试。 - **Windows 检出后 6 条界面测试失败**:`.gitattributes` 只给脚本定了换行符,其余文件在 Windows 上检出成 CRLF,按 `\n` 比对源码的测试整批红。现在文本文件默认 LF,`.cmd` 仍是 CRLF;仓库里的文件本来就是 LF,内容没有变化。 - **第四轮代码审计(2026-10-10,Codex gpt-6.1-sol 与 Opus 5.5 各审一轮,范围相同)**:Codex 报 23 条,Opus 报 11 条,两边重合 4 条,去重后 30 条。 修了 29 条;首页「当日盈亏」只合计部分持仓的提示(两边都报了)按 Simon 的决定不改。 Opus 另列 9 条待核实:百度总市值单位、下载按钮两条核实后修了,其余记为已知项(见审计记录)。 - **合规与安全**: - 缩略引用链接(正文写 `[仓]`、别处写 `[仓]: 网址`)渲染出来是「建仓」,原来绕得过合规检查;明确的个股涨跌预测原来也放行(历史涨跌、经营预期不拦)。 - AI 回答、报告、要点里的 Markdown 图片原来会自动加载外部地址,网页里藏的指令能借此把持仓带出去。现在一律只显示图片说明文字,不发请求。 - 快照目录或文件是符号链接时,原来能读写数据目录之外的文件。 - 数字核对原来不看单位:证据是 12.34 亿元,正文写成 12.34 万元也算对上。现在写了万 / 亿 / % 就按写的量级比。 - SEC 联系方式的读写原来写死在通用核心里。现在挪进金融插件,核心只留通用的「设置页凭据」接口;回测列表取公司名的数据文件也改由插件声明。核心纯净检查的词表补了市场名、数据源名。 - **数据**: - 计算库在最新一季拆不出时退回上一季的值;Yahoo 财报缺报告币种时按上市地补成港元;停复牌名单在接口返回格式不对时写成 0 只。现在都按「不知道」处理,列进缺口或报错。 - 研报取数到页数上限时,样本篇数被写成「近一年 N 篇」;产业链差分把不同月份的环比放在一起比;招聘硬测试把「不等于产能」这类护栏句当成「等于产能」。 - 百度估值的总市值没给单位时,原来默认标成「倍」,现在不给数、说明量级不明。 - 收盘摘要在东财不通、板块资金流换成新浪时,推送里写「没取到」。现在用新浪的净额,并注明口径。 - B 股(900、200 开头)按美元、港元计价,原来当人民币 A 股记账和回测。现在台账、持仓收益、回测都直接拦下。 - **回测与持仓收益**: - **涨跌停价改按交易所规则算**:原来用前复权价算、不取整到分,低价股能在一字涨停时买进、一字跌停时卖出。「不计成本」那次没有滑点,偏差更明显:实测 7 只股票的 41 个一字板,旧判定放过了 22 个。 现在 A 股回测另取一份不复权的开盘价和前收(baostock adjustflag=3),按「前收 ×(1±限幅),四舍五入到分」算涨跌停价。开盘就在涨跌停价视为封板;加上滑点会越过涨跌停价的单子也不成交。取不到不复权价时退回近似判定,并在数据来源里写明。 - 分段胜率原来按开仓日归段,前一段会算进之后才平仓的盈亏。现在按平仓日归段。 - 持仓收益率在整组报价一起中断时,原来拿旧价当期末价,也不提示。现在列出缺口,期末市值和收益率给空。 - **界面**: - 行情刷新失败后旧价格继续当现价用。现在手动刷新失败马上撤价并提示;轮询要连续失败才撤。 - 流水改了以后,旧的收益表现还显示,还交给 AI。 - 隐私模式下,按金额排序后转存的手动顺序也会被先停用。 - CSV 改了勾选、新预览还没回来时,能按旧预览导入。 - 最高连板没取到时,复盘仍标「普通」。 - 提醒页操作失败的原因被随后的自动重读冲掉。 - 交给 AI 的持仓写成「现价null」。 - 删旧清仓记录没有确认步骤。 - 导出报告、下载分享卡时,点完链接的同一刻就释放临时地址,部分浏览器上会下载失败。现在隔 40 秒再释放。 - 两个标签页先后清空同一份对话会撞到同一个后台线程。 - 聊天记录目录读不出来时显示「还没有记录」,之后的对话也不再进目录。 - **启动与资料**: - `init` 不认 `VRA_DATA_ROOT`,设了自定义数据目录就启动不了。 - 资料转写被模型的输出上限截断时,剩下的哪怕是合法 JSON,也会当成完整草稿交出去。 - 资讯雷达的英文标题显示成 `‘Pure insanity’` 这样的实体:Atom 源(如 The Verge)的标题标了 `type="html"`,XML 解析只解一层,里面的 HTML 实体还得再解一次。 现在 RSS / Atom 的标题和摘要都会解实体(摘要先去标签再解,原文里转义过的 `<` 不会被当标签删掉);海外头条走 RSS 兜底时也和主入口一样处理标题。 - **Codex 代码审计三轮(2026-10-09–10,gpt-6.1-sol)**: - 第一轮全量审计报 44 条:修 40 条,1 条补说明,3 条待定。 - 第二轮核对修复,报 25 条:修 20 条,1 条按产品规则不改,1 条记为残留,3 条仍待定。 - 第三轮重新全量审计,报 27 条:全部修复并补测试,另顺带修了 2 处。 - 按用户能碰到的情况分: - **安全**: - 远程模式下页面填的模型地址,原来只查域名写法,解析到内网也照连;现在连接时检查解析出来的每个地址,DNS 重绑定也绕不过。 - 网页读取(CDP)放过了 100.64.0.0/10 共享地址段。跳转进内网、公网页面里指向内网的图片和脚本请求,原来都能发出去;现在每个请求都在发包前查,页面里的 WebSocket / WebTransport / RTCPeerConnection 换成抛错的空壳。 - 通知目录是符号链接时,原来能读写数据目录之外的文件。 - 模型 API 的成功回复原来不抹密钥。 - 持仓体检悬停框里的持仓名称没转义,可以注入脚本。 - 模型 API 的 key 里带引号时,工具参数里回显的是转义后的样子,原来抹不掉,会被写进报告。 - **持久数据**: - 通知文件读坏、或结构不对(写着 null、缺字段)时,原来当默认值或悄悄滤掉,下一次保存会覆盖原记录;现在报「文件损坏」。 - 持仓「确认转换」在旧记录改成 0 股、或字段被手改坏时,会先删掉原来的期初流水,新的又写不进去。现在先检查,再原地替换:新期初沿用旧期初的 id,一步写入。 - 两个标签页会互相覆盖已保存的对话;某次写入失败后,之后的合并还会漏掉没存上的那几轮。 - 研究页连续加两只自选,会把前一只删掉;加自选时读写都失败,按钮原来锁成「已在自选」。 - 记一笔交易后刷新失败,原来报「记录失败」,再点一次就记成两笔;批量导入也一样,现在报「已经导入 N 笔,不要再导入一次」。 - 两个研究同时归档,后写的会整份覆盖先写的,另一家公司从知识索引里消失。 - 清空对话时,新的线程编号没存下也照样清,刷新后模型又接回清空前的内容;现在存不下就不清,并说明原因。 - 两个标签页合并对话后仍没存上时,下一次保存会把另一页那轮再并一遍。 - 刷新后业务日变了,旧的复盘正文会被存成新业务日的记录。 - 一个赛道存了要点,换到另一个赛道也显示「已存入」,按钮锁住存不了。 - **数字不对**: - 「万 / 亿」写错的数字,原来能过报告数字核对和算式检查;「金额 + 百分比」这种量纲不同的算式也被当成对的。 - 人民币和港元的证据会被当成同口径比较。 - 研究对比把读不到的证据算成 0;删掉单个取数或计算文件,仍给出完整计数。 - 腾讯行情的空字段、大宗交易缺的价格被补成 0;大宗交易缺字段的那几笔,证据仍标「完整」。 - 东财接口业务失败或返回结构不对,被当成「零笔大宗 / 零次分红」。 - Yahoo 没给报告币种时,分析师预期按上市地币种标,腾讯的人民币预期被标成港元;现在币种不明就不出金额。 - 现价变了,体检和情景回放仍用旧权重;回放的「按现在的市值约」金额现在按现在的市值现算。 - 轮询只回来一部分行情时,缺的那几只沿用旧价。 - 解禁比例把「占流通股比例」标成「占总股本比例」,中芯国际一批 6.39% 写成 27.35%。 - 个股资金流、龙虎榜把源没给的金额写成 0。 - Yahoo 关键指标没给报告币种时,营收、现金、负债按上市地猜成港元 / 美元;现在这三项不出。 - FINRA 卖空数据只取到一部分日期,仍标「完整」。 - 报告里同名章节出现两次时,前一节的数字不再核对。 - 持仓变了重新体检时,新结果回来之前,横幅和 AI 仍用旧持仓的结果。 - **回测**: - 停牌超过 5 个共同交易日后,价格退回买入价;现在用最后一个有效价,并在必读披露里写明哪只、从哪天到哪天按最后收盘价估值。 - 胜率、期望、按代码统计等原来用扣费前盈亏,扣完费亏钱的交易也算赢;现在一律用扣费后净盈亏,trades.csv 加了手续费列。旧版 trades.csv 没有手续费列时,这几项拒绝计算并提示重跑,不按 0 费用算。 - 分段检验漏了每段第一天的盈亏。 - 算不出的 Beta 和平均持有期原来写 0,现在留空。 - 截止日在拆股之前时,港美股价格还原错了;还没实施的拆股现在不参与还原。 - 中文 Windows 下按 GBK 解码取数输出。 - 龙虎榜有缺净额的条目时,仍被归入净买或净卖组。 - 重抽样丢了「几次算得出」这个数。 - 敏感度网格会把用户自己的参数裁掉。 - 单独跑检验时,找不到本金记录就按 100 万算:10 万本金的回测被算成 −90%,还覆盖原来的结果。现在先读这次回测记下的本金,找不到就拒绝并说明。 - 交易顺序重排检验漏掉第一笔盈亏,首笔亏损的回撤算成 0。 - 持仓收益率里,断更的报价一直被沿用;期末还持有、报价停了超过 5 个交易日的,现在写进提醒。 - **合规**: - 「现在买入苹果」「Buy AAPL now」这类直接指令,以及换了大小写的写法,原来能过合规门。 - 历史成交事实、英文收购新闻(Apple to buy …)不受影响:用 3184 个真实报告和资讯文件实测,没有误拦。 - 「建议在回调后买入」「可以等回调到 900 元再买入」这类建议和动作中间插了条件的写法,原来能过合规门;「建议关注北向资金买入动向」「可以看到北向资金买入」这类叫人看信息、陈述事实的不拦。用 3186 个文件实测,新拦下的只有本来就豁免的免责声明。 - 用 Markdown 链接、行内代码、字符实体、标签把禁词拆开,页面上显示的仍是完整的词;现在按显示出来的文字也查一遍。 - 核心代码里残留的金融提示词换成了中性措辞。 - **其他**: - 批量研究重跑失败,仍拿上次的报告报「完成」。 - 扫描版 PDF 没有正文也算提取成功。 - 本轮没给资料时,编出来的资料引用不查。 - 隐私模式漏遮录入表单的金额。 - 资讯聚合和资讯雷达把来源故障显示成「没有资讯 / 暂无更新」;现在全部没取到按出错显示,部分没取到会写明几个来源没取到。 - AI 配置坏了,连 K 线也打不开。 - 浏览器不让读存储时,资讯雷达会崩。 - 体检、收益两处命中缓存时不取消旧请求。 - Windows 上原始文件引用用反斜杠,计算库读不了。 - 隐私模式漏遮回测对话和历史报告里自己写的股数、金额。 - 模型输出到上限被截断时,仍当成功回答显示,还记进对话历史。 - 自选超过 50 只时,提醒任务的行情整批失败;现在每 50 只一批取。公告取数失败时仍推进检查日期,恢复后那几天的公告不再提醒。 - 持仓体检横幅的「看明细」在默认分页点了没反应。 - 事件日历让用户去研究页写判据,但那里没有入口;现在挂在个股研究「概览」最下面。 - GPU 温度计的远期数据取到了也不显示;现在显示最近一个合约月的最低档和概率。 - 资料库识别港股、美股代码的规则写在核心里,现在放进金融插件,别的垂类不会照跑。 - **情景回放**:起点之前没有价格的持仓(多半当时还没上市),原来拿后来的第一个价格往前补成「持平」;现在进缺口,不算进组合。 - **已知限制**: - 两个标签页在同一刻保存同一个对话,仍可能丢一边的轮次(先后保存不丢)。 - 网页读取时,Worker 里自己开的 WebSocket 没有在真浏览器里实测能否拦住。 - 网页读取在预先解析域名和浏览器真正连接之间有时间差(DNS 重绑定),还没在真浏览器里实测能否借此连到内网。 - 分段检验里跨段的交易,盈亏算在开仓那一段。 - **待定**: - A5:报告里不带出处的数字,生产校验不拦。 - D2:期末强制平仓不受 T+1 和涨跌停限制。 - D9:报价晚到时按新股申购处理。 - **每日复盘点「让 Agent 复盘」报错「消息须为 1–4000 字符」**:复盘会把当天的大盘数据连同提示一起发出(实测约 6700 字),对话接口却把整条消息限在 4000 字, 点了就被拒。现在 4000 字的上限只管用户自己写的问题,页面附带的数据连同问题最多 64000 字;多轮对话的历史只记问题,不把每次附带的页面数据重复带进下一轮。 Agent、本机订阅单轮、模型直连三条路径用同一套长度检查(原来模型直连那条没有检查,本机订阅单轮仍按 4000 字整条卡)。 赛道「今日要点」和记录的「推理审计」原来把资讯、正文整段塞进问题里,长一点就超过 4000 字,现在放进页面数据那一段,问题里只留要求。 ⚠️ 页面数据是前端拼好一起发来的,后端分不出哪段是手打的:4000 字只是界面上的约束,真正挡住超大请求的是 64000 字的总上限。 - **伯克希尔 B(BRK.B)这类带股份类别的美股,研究几乎取不到数**:各源写法不同 —— 腾讯认 BRK.B,Yahoo 要 BRK-B(BRK.B 回 404), 东财要 BRK_B(BRK.B 搜不到,公告接口还静默回 0 条,像是「没有公告」),FINRA 空头日文件写 BRK/B,SEC 映射表写 BRK-B。 研究要的公司画像、一致预期、日 K、财报、美股业绩日、空头成交原先全部失败,现在各源按各自写法取:2026-10-09 实测伯克希尔 B 画像 16 条、一致预期 10 条、利润表 119 条、业绩日 41 条、空头成交 15 条。东财关键指标表本身不收录伯克希尔(与部分银行股一样), 这一项仍取不到。另外,自选里粘贴 Yahoo 写法 BRK-B 会归一成 BRK.B(腾讯不认 BRK-B,之前一直没有行情);已存的旧写法照原样读。 - **分红的每股派现放大了 10 倍**:东财分红表的派现是每 10 股(茅台 2025 年报 280.2423 元 = 每股 28.02 元),取数层却标成 「元/股」,研究里看到的每股分红是真实的 10 倍。个股页和日历早就按每 10 股显示(没受影响),这次把证据字段改名 `dividend_pretax_per_10_shares`、单位「元/10股」;缓存里的旧字段名照认。 - **报告里引错出处的股数、成交量没被拦下**:数字核对之前把不带单位的整数都当「计数」放过("3 家" / "近 5 年"), 于是「持股 1079451366 股」引了另一天的持股市值那条也照样通过。现在 1 万以上的整数同样要和所引证据对上 (像证券代码、紧凑日期的仍放过),对不上时提示「这个数在 ev-…」让 Agent 改对。在本机 181 个真实运行上核对: 放开后只多报出港股硬测试里那三处真错,没有误报。 - **自选里港美股的市净率一直是 0、港股换手率一直是 0**:腾讯批量行情按 A 股的字段位置读港美股,而港美股布局不同 —— A 股市净率那一位在港美股是英文名,读出来是 0;港股换手率在另一位。涨跌停价、量比、静态市盈率那几位在港美股是每股收益、 52 周最高 / 最低价,也被当成涨跌停价写进了证据。现在港美股按各自布局取市净率和换手率,港美股没有的几样不再出。 2026-10-09 实测:腾讯市净率 2.97 / 换手 0.22%,苹果 46.21 / 0.24%,伯克希尔 B 1.46 / 0.22%,建设银行 0.62 / 0.07%; 茅台各项不变。候选池核对自选 / 持仓里的港美股时,市净率之前一律当作取不到。 - **表格只在上方写一次出处,整张表的数字都没核对**:数字核对只看带证据或计算编号的行,Agent 常把出处写在表格上方或段落末尾, 表格各行、裁决点里的阈值和机构家数就没被核对。写稿要求改为编号标在数字所在的那一行;阈值照抄证据就标那条编号,要换算的先用计算算出来再引用, 算不了就用文字写条件。港美股硬测试(Claude Code 订阅真跑)里能核对上的数字:美股 94/102 → 139/143,港股 110/120 → 148/155。 港股按上面的大整数核对又重跑一次:报告第一次交稿被拦下一处引错出处的总市值,Agent 按「这个数在 ev-…」的提示改对,最终 127/131, 其余各项都通过。还没对上的:一行估值只引了计算编号,括号里却写了计算的输入(机构家数、预测区间);裁决点里「2 倍」这类阈值没标出处; 美股报告里「标普500」「25bp / 50bp」这类名称里的数字(硬测试故意不豁免,生产核对不拦)。 - **数字核对把「1,33」读成 133**:逗号一律当千分位,Agent 写「years=1,33 家」「25,50,75」时会拼成一个不存在的数, 可能碰巧对上别的证据而放行,也可能误报。现在逗号后面正好 3 位数字才算千分位。本机 181 个真实运行的核对结果不变。 - **板块页一句没有功能的提示**:「想在某个环节挂上自己关注的标的?」从 v2.0.0 起就在,点不了、背后也没有功能,去掉。 给 Agent 的页面摘要里,板块总览的标题还叫「板块中心」,改成「产业研究」。「问 Agent」判断页面接没接上一直判成「接上了」 (拿默认值 null 和 undefined 比),改成按 null 判;正常使用看不出区别,只在漏接时才会显示对的提示。 - **研究归档里港美股只显示代码**:名称只从 A 股的画像取数里找,港美股没有那份,归档、研究对比和周报里都只有代码。现在港美股看报价参考的简称,再看东财港美股画像。 - **硬测试与温度计回填从命令行跑不起来**:两个入口算错了仓库根(少上一层,不传 `--repo-root` 就找不到 `run.ts`),也没有注册金融插件 (硬测试判分一律报「未注入 Lexicon」,回填一跑就抛「未注入插件」)。 - **港股回测之前一直按美股规则在跑**:港美股共用一个引擎、要传市场参数切规则,这一步漏了,港股回测按碎股、零费用、0.05% 滑点算, 而报告披露写的是 100 股一手、印花税 0.1% 双边。现在按计划的市场建引擎,港股按 100 股一手、扣佣金 + 印花税 + 征费 + 结算费、滑点 0.1%。 实测腾讯均线交叉(2021–2025)费用从 0 变成 24,745 港元。 - **全市场龙虎榜只看得到净买入那一头**:当天上榜记录只取一页、按净买额从大到小,再截前 100 条,净卖出最多的那些排在后面被截掉, 复盘页的「净卖出居前」和收盘摘要里的上榜只数都会偏少;净买额没给的记录还被写成 0。现在按净买额排序翻页取全(最多 6 页、3000 条, 翻到上限还没取完会标「只取到一部分」),逐条证据留净买额最大和最小的两头,上榜只数按全部记录的代码去重另给一条;没给的数留空。 - **报告里的数靠上次的档案就放行了,读者在这一行点不到出处**:报告每个数要等于同一行所引证据或计算的值;引用上次研究档案里的旧值另有一条豁免。 这条豁免之前不分新旧 —— 本次证据或计算里就有的数,只要上次档案里也写过,同一行没引它的编号也照样通过。实测港股腾讯一行写了 FY2027 一致预期区间 27.6–34.19 元, 只引了前瞻增速那个计算,两个端点都靠档案放行。现在豁免只给本次没有的旧值;本次有的数同一行必须引它,报错时直接写出它在哪条证据 / 计算, 报告重写时补上即可。按新口径重扫本机已有的研究:新报出来的约 20 处都是这一类(同一行用了本次另一个计算的结果,却没引那个计算的编号),没有误报。 - **手机上系统字体调大后,右上角「问 Agent」会压住主题切换**:顶栏之前写死给它让 112 像素,字体放大 1.3 倍时只剩 1 像素,再大就压住。 现在按按钮实际宽度让位,字号或文案变了跟着变;首页没有这个按钮就不让。320 宽实测字体放大到 1.6 倍,两个按钮之间仍留 12 像素。 - **名称和规则阈值里的数被当成数据**:一致预期分歧的「max ÷ min ≥ 2 倍」是估值与催化剂两个研究步骤写死的规则,报告写「升至 2 倍以上算分歧扩大」时, 这个 2 之前会被要求给出处;现在同一句里前面有「分歧」或「max ÷ min」的整数 2 倍不再核对,2.5 倍这类具体倍数照样核对。 硬测试判分另外认所引证据说明里写着的数(预测市场合约「降 25bp」的说明原文就是 by 25 bps,「标普500」那行引的证据说明里就写着标普500):美股真跑判分从 139/143(4 处误报:标普500、降 25bp、降 50bp、分歧 2 倍)变成 142/142;港股剩下 3 处是上面那行真没引编号的。 - **六阶段研究把 9 开头的代码一律当成北交所**:按代码首位判交易所,9 开头的全算北交所,实际只有 92 开头是(900 是沪 B 股,93 开头是中证指数)。 现在按号段逐段判,其余 9 开头的不再当成北交所;B 股(沪 900、深 200)和 ETF 不在研究范围内,直接提示认不出。 资料里只认出这类代码时,六阶段研究会提示认不出市场,不再按北交所开跑。 - **回测读到坏掉的原始数据文件会整次崩掉**:文件内容不是 JSON 对象(列表、null、一段文字)时,原来直接崩、也不说是哪只票; 现在记进失败清单并写明是哪个文件,其余标的照常。 - 回测引擎跑完一次后会清掉「按代码查价」的表,之后再取基准价会崩(目前的流程走不到,类型检查查出来的);现在查不到就按没有价处理,和开跑前一致。 ### 测试 - 第四轮审计每条修复都补了用例。其中 15 处关键判断做了变异检查(改回去后对应用例变红):数字单位、缩略引用、快照链接、`init` 数据目录、转写截断、收盘摘要新浪口径、两标签页清空、整组报价中断、百度单位、招聘护栏句、隐私排序、涨跌停取整(两处)、不复权价参数、下载延后释放。 - 涨跌停用真实行情核对:9 只股票 2023-01 至 2026-10 的 37 个一字板(不含 ST),算出的涨跌停价与当天开盘价全部一致。 - 除权日的不复权前收是除权参考价,例如贵州茅台 2024-06-19:1521.5 − 30.876 = 1490.62。 - 10 只 A 股、5 年的完整回测(含不计成本对照和参数网格)用时 137 秒。只看取数,5 只股票从 15.7 秒变成 30.2 秒,多出来的就是不复权价那一份。 - 数字单位核对放到 83 次真实研究的报告上重跑,没有新增误拦,435 个数字走到了新的单位比对。 - 全量回归:calc 311、backtest 571、取数层 566、编排器 1225(1 条跳过)、前端 346,全部通过。编排器类型检查、前端构建、mypy(106 个文件)都通过。 - 新增 RSS / Atom 解析用例 3 条(`test_rss_feed.py`):Atom 的 HTML 标题与摘要、RSS 多转义一层的标题、海外头条 RSS 兜底的标题;三处修复各自改回去,用例都会变红(已实测)。 - 删重复端点时同步删掉只测它们的用例(腾讯港美股报价缺成交量、报价映射的单位与形状),新浪研报 / 交易日历的生成端点计数 36 → 34; 前端注册表测试里拿 `tx_us_quote` 当样例 id 的地方换成注册表里现有的 `cboe_quote`。 - 通达信:「停用端点指向替代」的用例改成「三个端点不再登记、替代端点都在」;选服验活用例只留财务验活(模拟服务器 K 线返回空,验活改回拿 K 线验会变红,已实测)。 前端:删掉解禁 / 龙虎榜函数的用例和 A 股指数函数的三行断言(首页指数条的用例照旧),以及只核对估值 / 分位 / 财报取数函数源码的 7 条(函数已删)。 README 数字测试:注册表没有停用端点时,改为要求中英文 README 都不再留停用说明(两种语言各改坏一次确认会红)。 - 新增表格排序测试:取不到的排最后、值一样保持原先后、金额列按币种分块(升序时块的先后不跟着反)、表头三下一个循环、自己排的先后(新买的跟在最后、挪到头不动)、 读回本机记录时列名不认识或格式坏了当没排、浏览器存储用不了不报错;页面接线(合计表六列、说明单独一行、隐私模式遮金额、首页和持仓页共用一份先后、 自选整行点选与键盘、移除不换图、K 线在自选总览下面、换股票清掉旧图)。8 处关键判断做了变异检查,全部抓到。 2026-10-09 在本机页面实测:合计表同一列在各行的右边缘完全一致;首页、持仓页排序与币种分块、调整顺序(两页共用)、自选点行换 K 线都按预期;手机宽度不撑破页面。 独立审查(Opus)后补:隐私模式不按被遮的列排序(首页、持仓页实测:被遮的列点不了、记着的排序先不用,关掉隐私又回来)、自选名称按钮(点按钮、点行都能换图, 换的那一刻不显示上一只的图)、已实现 / 分红 0 显示 0、「调整顺序」中卖到只剩一只也留着「完成」。按行情排着时行情回来之前先不画,本机行情回得太快没能在页面上看到中间状态,靠测试守住。 - 对话测试补上:页面数据多也能问、历史只记问题;问题超过 4000 字、没有标记的长消息、空问题、总长超过 64000 字都拒绝;模型直连同样拒绝且一次都没发出、本机订阅单轮的上限是 64000; 「今日要点」「推理审计」把材料放在页面数据那一段。2026-10-09 在 5932 用一个接不上的模型来源实测:超长的回「问题须为 1–4000 字符」或「超过 64000 字符」, 页面数据 9000 字、问题短的照常往下走到选模型那一步(回「接不上」),全程没有调用模型。审查修复后的 13 处变异检查全部抓到。 - 新增模型擂台测试:只列已登录的订阅 Agent、带表里已有几次,沿用这次的取数范围(没记录按核心);存进研究记录的表格每家一列、标出这次、读不到写「—」、单元格里的竖线不拆表、 不出现排名用词;周报只取近 7 天、已结束、正式研究、同一对象同一市场至少两次,同代码不同市场不算一组,每只只留本周那几次、至少两家不同 Agent 才列,超限和出错写明,一只都没有返回空; 研究记录前端每个分类都在垂类枚举里注册、有中文名;按钮跑着研究时禁用、没有已登录的指去接入 AI;页面只这一次用那家订阅、不收起报告、不改存的设置。 - 数字核对新增两条测试:1 万以上的整数引错编号要报并指出它在哪条证据(引对了放行,小整数计数、证券代码、紧凑日期仍放过); 逗号只在后面正好 3 位数字时算千分位(「1,33 家」读成 33、「3,825,848,811,520」读成一个数、「25,50,75」读成三个数)。 - 新增命令行入口测试:真从命令行跑一次温度计回填(注册不上会抛错退出),硬测试与回填两个入口都注册了金融插件;港美股研究在归档里取得到公司名,坏名字跳过看下一份,都没有就是不知道。 - 新增扣费前后对照测试:零成本参数逐个引擎(A 股、美股、港股、加拿大)核对费用为 0、成交价等于原价,默认参数下确有成本(测试不空转); 用同一份数据重跑、跳过稳健性检验,成本吃掉 = 不计成本 − 实际,有一边没有数时给空不给 0;重跑失败或仍扣了费用时不给对照; 港股按市场建引擎(100 股一手、有印花税),同一段行情港股实际扣费、不计成本那次一分不扣且期末钱更多;界面两列取数、一句话总结、 不到 0.1 个百分点的写法、没跑出来时附表不写对照。 - 新增全市场龙虎榜测试:两页 522 条翻完、逐条证据留住净买额最大和最小的两头、上榜只数按代码去重、净买额没给的不写 0;翻到上限还没完是 partial。 复盘的几处边界:昨日涨停池是空的不写「0 涨 0 跌」;东财三所全是空值(盘前)不当取到、要报缺口;腾讯成交额读成 0 的那家当没取到; 上游都没给数据日时按交易所日历标;收盘以后不再写「今天还没收完」;短线三张卡片各标各的数据日; 事件回看的「今天」按交易所时区;不计成本那次反而少得多时不说「成本几乎没有影响」。 - 界面样式测试改成锁「静默数据台」:石墨底与亮暗两套橙色主色、红涨绿跌的颜色、方框面板(底色 + 1 px 线框,不许出现渐变光晕、模糊和发光字)、34 px 标题条、表格默认样式用 `:where()`(单元格上的右对齐才能生效); 侧栏没点过收起就是展开的文字栏目、宽 216 px、顶栏 44 px、「问 Agent」按钮留出位置不压住主题切换。 - README 里的端点数、层数、停用数、栏目数与栏目名、受控工具数、研究阶段数、上游版本号都由测试对照实现,改了实现没改 README 时测试变红。 - 新增复盘页测试:界面查询的备用端点(主源失败 / 抛错才换、只取到一部分不换、备源也失败时仍报主源原因并另带备源原因、结果里不带端点名、注册期拒绝与注入上下文 / 用户参数同用)、 看法(盘中默认看上一个交易日、`live` 看今天且注入的日期跟着变、盘前不生效、没声明的看法拒绝)、注入时按 `injectAs` 改名后的参数名核对(此前测试没改名,漏掉了趋势块 `end` 参数没登记); 页面解析(涨跌分布档位、赚钱 / 亏钱效应、晋级率、指数趋势表、两融 5 日变化、股债收益率差、盘中成交额不和整天均值比而用截至上一个交易日的均值、取不到给「—」不给 0)、发给 Agent 的摘要逐块带读法 / 备源 / 缺口、 页面默认请求 `live`、刷新与切换带对参数、复盘页不再有自选和搜索框;涨停分档的最高板(同连板数按首封时间、首封时间不合法当没有)与梯队;取数层 5 个新端点的映射和盘中均值不含今天那根。 - 侧栏改版:导航结构放在单独的纯数据文件里,侧栏、顶栏标题、首页目录和测试都读它。测试对照它查:每个导航页面都有路由、每条路由都在导航里或是旧地址跳转、 旧地址跳到导航里还在的页面并带上原来的参数、README 的一级栏目数和栏目表(每个页面一行)、个股只有一个入口、多空辩论只在选了 A 股时能开始、 个股页选股票不会自动开始研究;README 栏目表和导航路由两条做了 9 处变异检查,都抓到。 产业研究的二级:各板块按板块数据的顺序接进来、不多列总览项,点一级进总览,板块页高亮它自己、顶栏显示板块名,名单里没有的板块地址退回总览; 每个板块在数据里写了图标且不重复(新增板块忘配图标会红),不认识的图标名退回格子图标;8 处变异检查都抓到。 - 首页看盘、产业研究与「发给 Agent」:「当日」的交易日(三地、周末、周一开盘前、跨月、美东冬令时切换、节假日按行情成交日期、开盘前行情日期先换了也不漏挡)、 三地成交时间写法、港股收盘竞价时段、A 股指数缺格与全空报错、持仓市值与两种盈亏(期初持仓、当日买入 / 送转、分红、 代码写法不同、现价 0、缺昨收、缺行情)、按币种合计与行情没回来时给「—」;20 个板块的步数、标题、每步开头带板块名,第 1 步的读研报要求,年份只来自当天日期 (把时钟拨到 2031 年核对),提示词里没有仓库、写死的年份、估值和买卖词;「发给 Agent」只填当前页、先收走再判断、不替用户发送,输入框按页记、最多 8 行。37 处变异检查,都抓到。 - 个股页换股票:上一只的报错、已结束的研究结果和发给 AI 的上下文不挂在新股票名下,还在跑的研究、跑完的辩论写明是哪只;打开历史报告途中换股票,以人最后选的为准; 搜索框跟着当前股票;持仓「记一笔 / 导入」开不开只在第一次拿到数据时定,记完第一笔不会自己收起。这几处做了 6 处变异检查,都抓到。 - 新增港美股行业暴露测试:GICS 对照表一个名字只对一个一级行业、GICS 2023 版几处调整(支付处理在金融、数据处理外包在工业、抵押 REIT 在金融)、港股只认四段路径、 美股名字对回一级、没有资料和资料里没写行业的归「没有行业资料」、对不上的和没收录的进缺口、细分行业名带到每只持仓;页面桶里列出成员、这一桶不算单一行业超线;东财只取行业两列、回了别的代码报错。 - 数字核对:上次档案里有、本次证据或计算里也有的数,同一行没引就报,并写出它在哪条证据 / 计算;本次没有的旧值照样放行;同行引了就放行。 同一句有「分歧 / max÷min」的整数 2 倍不当数字,2.5 倍、没有分歧语境的 2 倍照样核对、隔了句号不算同一句;词表的这一项必须带 g。 硬测试认所引证据说明里写着的数(合约名、指数名),说明里没有的照样判没出处。每条都做了变异检查(拿掉对应修复都会变红)。 - 新增回测图表解析、K 线、持仓体检、股票搜索、隐私模式、四档可信度、口径提示等测试;关键判断做了变异检查。 - 新增定时提醒测试:补跑与去重、休市 / 日历取不到不运行、失败重试与放弃、静默时段、设置文件权限与打码、飞书 / 钉钉签名(与独立实现对照)、 地址白名单、报错脱敏、收件箱上限、跨进程锁,以及两份摘要的逐行内容。 - 新增事件日历测试:各类事件的字段换算(解禁只认实际解禁股数、派息按每 10 股、宏观占位时刻不显示)、过期判定、排序、窗口天数上下限、 A 股超过 30 只时持有优先、取不到时进缺口;关键判断做了变异检查。 - 新增判据回看测试:两类判据的状态读法、起点按北京时间、补记的判据起点退回、到期判定(含今天)、回看表计数、公告窗口(含写下当天)与「没看全」说明、 提醒去重与改期再提醒、手动运行列全部、台账新字段校验,以及前端判定 / 改回待判的整条记录;关键判断做了变异检查。 - 新增报告对比与对话来源测试:章节切分、证据编号忽略(含连写的编号)、逐行差异与超大文本退化、可比较研究的筛选与默认对象、大数换算; 工具来源字段的限长与链接收紧、执行器在成功 / 报错 / 结果超长时的记录、各工具的来源字段,以及来源面板的合并计数、转义和「本轮没有查数据」说明;关键判断做了变异检查。 - 新增对话数字核对测试:单位换算与容差、千分位与数组两种读法、几千个价格的资料里编造的大数不放行、算式运算数要有出处、日期 / 钟点 / 引用 / 代码 / 窗口 / 参数组 / 指数名不核对、 「假设」句、表头单位、几十万个数的耗时,以及 API 与本机 Agent 两条对话路径的接线与开关(模型直连那条只核对了接线代码);31 处关键判断做了变异检查。 - 新增候选池测试:区间解析与报错、单位换算(万元换亿元用除法,边界值不被浮点尾巴挤出去)、0 只在三项上算缺数据、ST 简称的几种写法、开盘前停牌判不了、 三组归类;整条链路用假取数器跑:每 50 只一批、失败的一批和没返回的只数进缺口、成分没取到 / 只读到前 30 只 / 只数对不上、「重新取行情」不重取成分、 自选里的基金和港美股不核对,以及前后端的范围和指标同序同名、结果过产出红线;47 处关键判断做了变异检查。 - 新增异动接近度与涨停分档测试:各板块标准与 2026 年修订版规则原文逐条对照、累计偏离按区间涨幅之差、「连续 3 个交易日内」的边界、达到后和复牌后重新计算、 指数缺日不连起来、新股初期不纳入、严重异常波动三条;涨停池与题材标签解析、四档边界(前两天没取到不算连续)、过去日子的缓存什么时候要重取;关键判断做了变异检查。 - 新增财报前瞻与复盘测试:反应日认定(盘前 / 盘中当天、盘后次日、周末顺延、同一天合并、日 K 还没到算反应待定)、平均只算此前算得出的、跌的也按绝对值比、 业绩预告区间落点与单点预告;发布时刻按交易所当地时间(当地 0 点当作不明)、Yahoo 复权价不和未复权价混用、预约披露表去重与改期、业绩预告同一期取最新公告、 一致预期年份跟下一期走(跨年也对);整条链路用假取数器跑 A 股 / 北交所 / 美股 / 港股:缺口顺序固定、缓存与重新取、盘中标记;66 处关键判断做了变异检查。 - 新增研究分享卡测试:事实挑选(最新一期、同期去重并列、数一样单位不同不算重复、报告期不是日期或值不是数的不算、一致预期按北京时间定年份、机构数只认展示出来的来源)、 数量取不到是 null、缺口合并排序与命名(原型链上的键名、不像代号的归「其他」、原因句不上卡)、红线过滤、阶段名不合规不去读、报告没通过校验 / 符号链接 / 坏文件; 画卡片用假画布逐字核对:竖版横版、正常 / 塞满 / 空的都不出页边距、不重叠、不压页脚,只用墨色和蓝色,声明完整,关键数据怎么排不受缺口多少影响;81 处关键判断做了变异检查。 - 新增补洞端点的映射测试:单位与币种配对(百万港元、人民币列报的港股财务、每股派息)、记录键、AH 没有对应股票 / 只取到一边报价、 公司资料只把核心四项记缺口、估值历史 / FRED 某个指标取数失败进缺口、FRED 名单外的系列直接拒;字段名避开硬测试认金额的词(比值类不叫 price / revenue)。 - 新增港美股研究测试:区域契约(港美股取覆盖表、A 股照旧)、累计值逐项绑定(改一期的数 / 用旧一期作截止 / 单位写错都报)、汇率是可选实参(币种一致不传、传了必须照抄)、 一致预期 T / T+1、身份核对两条路、报价时效、口径提示(认百度序列、带汇率的计算不误报混用、「起..止」期末不一致照报)、港股代码不当数字、施工单按市场切换、 Deep 与研究页入口、分享卡;计算库新增 `calc/tests/test_currency_ttm.py`,取数层新增 `test_global_research.py`。 硬测试新增「G 港美股研究」组(AAPL / 00700 真实运行),判定逻辑已用合成运行离线测过;2026-10-09 用 Claude Code 订阅真跑, 两只都只差「报告数字 100% 绑定」一项(见修复里「表格只在上方写一次出处」)。按公告日过滤用 2025-12-31 作研究日联网回溯核对过: AAPL、腾讯都没有混进研究日之后才公布的数。新判断做了 30 处变异检查,1 处是等价写法,其余全部抓到(第一轮漏的 3 处补测试后抓到)。 - 阶段 C(提醒、日历、判据回看、报告对比、对话来源与数字核对、候选池、异动接近度、财报卡、分享卡)结束时做了一次独立只读审查,24 条发现都已处理, 修正处各补了测试;其中 3 条只做了一部分(报错横条仍是红色,界面改版时也没另换颜色;财报卡里一处日期天数差没挪进计算库等)。修正涉及的 47 处关键判断做了变异检查, 第一轮 3 处没被抓到(企业微信旧密钥的「已签名」显示、远程模式不把对外地址交给 API、代码块「像代码的行过半」的门槛),补测试后全部抓到。 - 阶段 D(港美股六阶段研究)结束时做了一次独立只读审查,3 条发现都已修正并补测试:下游可以引用没经过核对的上游计算(见「变更」)、 报告里「港股 8000 亿港元」「港股 12345 手」这类数字被当成港股代码跳过核对、研究页字母没选下拉就回车会直接按美股代码开跑。 修正处做了 17 处变异检查,第一轮 1 处没被抓到(代码后紧跟「港元」的写法),补测试后全部抓到。 - 新增交易流水测试:先进先出 / 移动加权平均的手算场景(含送转拆股、同一天先送转再成交、卖光后再买)、卖超与缺价格等失败路径、输入顺序不影响结果; 旧持仓迁移的备份(原样字节、附恢复说明)、中途断掉重跑、同代码冲突由用户选、旧记录被别处改过时撤回刚写的流水;人民币合计缺汇率不给。 - 新增持仓收益率测试:时间加权 / 资金加权的手算场景,并用 Ghostfolio 公开测试场景的输入和期望数字对拍(只用数字,不用它的代码); A 股送转、港美股拆股还原、像除权没录的提醒、取不到价格进缺口、价格比流水晚开始、币种分组。 - 新增表格导入测试:券商列名与类型写法、BOM / 换行 / 引号 / 制表符、原文行号、纯数字代码拒绝、逐行报错、表头缺列 / 重名 / 超限、 GBK 与 .xlsx 识别、模板每行都能过检查;后端预览的重复与卖超判定、默认勾选、整批写入「全写或全不写」(含写入后回读不对报错)、 导入备份、字段白名单、导入行排在已有同日流水之后;隐私遮挡与「不走 AI」的接线。导入相关 20 处关键判断做了变异检查,全部抓到。 - 交易流水这一段(流水记账、收益率、表格导入)结束时做了一次独立只读审查,12 条发现里 11 条已修正并补测试: 一只新股会把整组收益率的起点推后到它上市那天;区间起点从能取到价格那天算、而不是第一笔投入;空仓时记的送转拆股被丢掉(港美股卖光后拆股、再买回会把老价格还原错); 能算的只数上限没按币种分开、多年前就卖光的也去取价占名额(单次流水上限同时从 5000 笔提到 50000 笔);导入预览没说已记的哪几笔会因此算不了、预览前没查大小、 导入失败后可能把已写进去的再导一次;隐私模式下备注没遮;自动迁移失败时整页空白;没取到行情的只数没写在合计旁边;旧记录和已转的流水对不上时只能补、不能替换。 剩下 1 条(同一份数据同时开两个后端时迁移可能撞车)属于不支持的用法,写进代码说明。修正处做了收益率 25 处、页面 5 处变异检查,导入相关 20 处重跑,全部抓到。 - 新增情景回放测试:权重只在有价格的几只之间分、不到一半不给组合数字、还没上市 / 到结束还在停牌 / 起点停牌、最大回撤与最差单日的日期、按币种分开、取不到的时期按时间顺序排在原位、baostock 会话被挤掉时重试;页面的解析(缺的不补 0、路径长度对不上不画、各组只用自己的路径)、走势图、给 AI 的上下文不含金额、点按钮才跑、回到页面沿用记住的结果;Yahoo 粒度核对与 10 年上限、baostock 翻页失败报错。关键判断做了变异检查。 - 新增事件回看测试:手算的超额收益、公告日是周末、停牌天数、最近的事件只有部分几档、各种算不了的原因(含刚好凑够 6 个交易日的边界)、不到 8 次不给平均、停牌和没满的不进平均、按预告方向分组、同一交易日合并(方向不同算「其他」)、窗口重叠的边界(相隔 25 个交易日算、26 个不算)、没有事件时不取价格、来源显示名字、没有事件和取满上限时真跑取数脚本(退出码 2 不当失败)、盘中指数多出今天这根时截到股票最后一个价格;页面的解析(缺的不补 0、路径对不上不画)、和「全部」一样的组不重复列、逐次提示、图的刻度和第 0 天竖线、给 AI 的上下文、点按钮才跑、按票和事件类型记住结果、只给 A 股显示。关键判断做了变异检查。 - 新增港美股事件回看测试:港股收市后发布顺延到下一个交易日、同一天几份合并成一次、美股只用提交日不顺延、约 10 年前的事件合成一条缺口、没查到时提示 ADR(翻页到上限时不提示)、事件类型和市场对不上时说清楚能用哪类、对照换成盈富基金 / SPY;取数层披露易只认完全相同的代码、同一份公告挂在几个分类下只留一次、取不全要标出、8-K 只留 Item 2.02、翻页到总数时停、到上限或中途短页(总数说后面还有)标「没取全」、披露易空结果的几种写法都当没有而看不懂的报错、映射层没查到 / 没取全记部分成功;页面按市场给事件类型、从 A 股换到港美股不沿用没有的类型。16:00 收市边界、中途短页、空结果解析这几处做了变异检查,都抓到。苹果 2015 年以来 45 次业绩 8-K 的日期和 SEC 官方提交日逐日核对一致。 - 新增 A 股四类事件回看测试:回购按首次公告日、同一天几个方案合并、已回购 0 不写;机构调研按公告日、家数没写全不报合计;龙虎榜第 0 天是下一个交易日(上榜当天的涨幅落在事件前那一档)、净买入 / 净卖出 / 有正有负不归组、几条理由的净额分别写;限售解禁已到和已排期分开(当天算已到)、正好 1% 算较大、同一天几批相加、占比没写不归组、过去没有只有排期时不取价格;三类没有日期时缺口里说清是哪个日期。三个新端点:字段取对、首次公告日不是计划起始日、占总股本小数 ×100、不取成功率和占流通股比例、源没写留空不当 0、空表是 partial、回了别的股票报错。页面:七类按钮、日期列名、排期列表进上下文。 - 新增 SEC 联系方式与 SEC 业绩日期测试:联系方式整理空白(换行并成空格)、只收「英文姓名 邮箱」的可打印英文字符、打码、保存是 0600 且不留临时文件、填错不覆盖原来的、清除、环境变量优先并锁定页面、坏文件当没填、远程模式不许改、HTTP 接口只回打码;取数时只交给声明了它的端点和工具(设置页保存的也算,环境变量里有也不给没声明的;回测取数同样只给声明了的端点);环境变量里的值同样整理校验、格式不对不发请求也不回显、错误信息里整串遮掉;SEC 全文检索只留 8-K 本身的 Item 2.02、按编号去重、按日期重排、按总数停、短页和到上限标没取全、只重试 5xx;事件回看填了走 SEC、SEC 失败退回东财(另用一个目录)、没填时只在东财翻不完时提示去填(ADR 不提示)。33 处关键判断做了变异检查,都抓到。界面里用测试联系方式真跑:摩根大通事件回看 39 次(窗口完整的;之前 0 次),来源写 SEC EDGAR;苹果 10-K 申报列表取到;清除后摩根大通回到东财并出现提示。 - 新增工具说明红线测试:每个垂类工具的能力说明(会原样进模型上下文)都过一遍真的产品红线。baostock 翻页测试补上网络异常:用真 SDK 的翻页逻辑复现下一页没回应、和正好 2000 行下一页回空两种情况。 - 新增 RSRS 测试:斜率与逐窗最小二乘对得上、精确直线给出它的斜率、标准分按样本标准差手算对得上、最低价或斜率不变时无定义(不被浮点误差放大)且不让之后 m 天都没有读数、正好等于 ±阈值保留前值、预热期不持有、参数校验、守卫按预热算样本(拒绝、点名、不带预热的策略门槛不变)、结果口径(方法、预热、第一个读数、平仓记录太少、多只标的、不含产品红线词)、真引擎离线跑一遍、敏感度网格的两条轴、选项表默认值与构造函数一致、每个参数在界面上都有中文轴名。关键判断做了变异检查。 - 新增免安装包测试:运行时清单只认官方地址并核对 SHA256、构建布局与两个启动脚本一致、Windows 批处理只用 ASCII、PowerShell 脚本带 BOM、包内说明、 源码只取 git 记录的文件、冒烟用的干净 PATH 与假命令。Apple 芯片 Mac 包在本机实际构建,并在没有系统 Node / Python 的环境里冒烟通过 (启动、首页与深链接页面、体检 8 项、退出后两个端口都释放);Windows 与 Intel Mac 包要等 GitHub Actions 跑。 - 新增新版提示测试:版本比较、一天一次与失败一小时后重试、并发只查一次、真实 5 秒超时、GitHub 404 / 限流 / 坏回复、关掉 / 跳过 / 环境变量不联网、 查询中途改开关以磁盘为准、改坏或被改过地址的状态文件、写不了盘、接口鉴权;前端两处显示互相同步。 - 新增防篡改登记测试:规范化 JSON、序号与上一条指纹的衔接、绕开软件改 / 删 / 加台账记录和研究文件各报一种问题(过程日志不算,附录和查看器算)、没结束的研究不判没登记、 从软件删除不报、删了又被放回来、补登与要明说才认的重新登记 / 确认不在(只认 true)、删一条本来就没有的记录不登记; 改登记簿一行(含改完把这一条指纹也重算)/ 删一行 / 插一行各只报一处、写到一半中断的半行不算链断且下一次另起一行、链头的各种结果(含链头那一行被改坏、那一条被删而后面的还在)、 链头对得上但更早一行被改过、登记写不进去不拦保存、登记簿或它所在的文件夹是符号链接时拒绝读写且不往链接那头写任何文件、核对不改任何文件;研究成功、出错各登记一次,目录名和编号对不上不登记; 页面的显示名、文件中文名、结论分级、按钮只在有对应问题时出现、隐私模式遮标题里的金额股数、首屏不读盘。24 处关键判断做了变异检查,全部抓到。 三个接口另经由 HTTP 测了鉴权、补登只认 true、链头为空 / 太长 / 不是文字时拒绝。 - 新增研究过程对比测试:各项指标的算法(Agent 时间只加每轮用时、资料齐全与首轮过校验、分母按这次要跑的阶段、引用去重且只认存在的证据和计算、缺口、报告数字核对、 取数成败(超时、出错算失败,未知状态不计))、读不到给空不给 0(没有清单 / 没有阶段 / 阶段文件坏了 / 某一栏不是列表 / 取数账本是空的;没跑到的阶段不算坏; 取消或崩溃没收尾时,冲突和红线不把开跑时的空占位当 0)、只读普通文件(命名管道、链接进来的清单 / 阶段目录 / 取数文件、带路径的阶段名都当读不到,不卡住)、挑哪几次(最多 8 次、当前这次再老也在、按真实时刻从新到旧、不同时区写的时间、 没结束 / 别的市场或代码 / 测试场景 / 链接进来的目录不算、失败和取消照列、状态和归档同一判据、只有一次也不报错)、接口鉴权与读不到清单、只读不改文件; 前端字段和后端逐一一致、Agent 名与模型说明、用时与比值写法、读不到一律「—」、表格上方的几条说明、只标「这次」不排名不标最好、首屏不读盘。35 处关键判断做了变异检查:33 处抓到,1 处有双重保护(链接进来的目录在读清单时也会被拒),1 处对现有的事件类型没有区别。 按独立审查修正后(防篡改登记与研究过程对比),新加的判断另做 35 处变异检查:34 处抓到,1 处有双重保护(登记簿所在文件夹是链接时,写登记前先查一次,读登记簿时还会再拒一次)。 - **Python 类型检查进 CI**:新增 mypy(配置在 `mypy.ini`,CI 在三个系统上各查一次)。第一次全量检查 106 个文件,没有查出算错数的问题, 查出的两处遇到坏数据会崩的地方见上面修复;其余是标注写得不准,或同一个变量名前后装了不同类型的值,已改写,不加 `# type: ignore`。 从上游 a-stock-data 生成的 `sources/astock_ported.py` 不在检查范围,它的问题回上游修。 - **界面测试改测行为**:新增 `desktop/test/helpers/render.ts`,把组件真正渲染出来,再断言用户看得到的内容。回测图表的 3 处源码比对 (扣费对照、两处占比显示、敏感度说明)改成渲染测试,每处故意改坏都会报错。约定写进 `docs/development-validation.md`: 新写的界面测试一律这样写,旧的改到哪条换哪条。 - **踩过的坑写成自动检查**:`orchestrator/test/pitfall_rules.test.ts` 扫全仓正式代码,拦「只看首位判沪深北」和「用 `is_private` 一类属性判内网地址」 两种写法,并先自检规则认得出 11 种坏写法、不误伤好写法。上面 9 开头那处就是这样扫出来的。取数层统一判交易所的 `tencent_prefix` 那一行按原样豁免,同时新增测试把它的各号段钉死(删掉「先判 92」那一行测试就红);那一行改了,豁免自动失效。 - 删掉 4 个没有入口的前端旧文件(旧个股数据页、首页概览、错误边界、首页任务,共 829 行),以及测试里对它们的引用。 ## [2.0.0] - 2026-10-07(未单独发布,随 2.1.0 发布) ### 不再内置 Codex Harness:AI 可选 Claude Code、Codex、WorkBuddy 订阅或任意模型 API Vibe Research 是 A 股、美股、港股的投研工作台。v2.0 去掉内置的 Codex Harness,研究用的 AI 改为两类:本机已登录的订阅 CLI (Claude Code / Codex / WorkBuddy),或任意兼容 Chat Completions 的模型 API;不管用哪种,受控工具、研究方法论、校验与合规 gate 都是同一套。另新增远程访问模式:装在 macOS / Linux 云端电脑上,用带访问口令的链接打开;部署与接口说明见根目录 `AGENTS.md`。 ### Breaking Changes - **不再内置 Codex Harness / Codex SDK**:删除 SDK 进程与 worker、Codex 引擎生命周期、hooks 脚本与 `codex-version.json`, 依赖里不再有 `@openai/codex*`。大脑改为两类:本机订阅 Agent(Claude Code / Codex / WorkBuddy 的官方 CLI,用使用者自己的登录) 与模型 API(Chat Completions)。 - **取消产品专用 Codex 登录**(`.local/codex-home` 与页面「登录 Codex」):Codex 订阅与 Claude Code、WorkBuddy 同级, 直接用使用者 `codex login`(ChatGPT 账号)登录好的 Codex CLI,最低 0.160.0;Codex 用 API key 登录时不可用,每次调用前重新确认登录方式。 旧的 `.local/codex-home` 不再读取,留在本机不影响(里面是旧登录文件,别提交、别外传)。 - **模型 API 一律走 Chat Completions**:开启 Agent 时由产品在本机跑工具循环(function calling),不再需要 Responses API 端点或中间网关。 provider 模板改指各家官方地址:通义千问、智谱 GLM、Kimi 不再走百炼业务空间地址,MiMo 改用按量付费地址,OpenAI 补上官方地址; 默认模型改为 `deepseek-flash` / `glm-5.3` / `kimi-k3` / `mimo-v2.6-flash` / `gpt-5.4`(`qwen3.8-max` 不变)。 地址与模型名于 2026-10-07 按各家官方文档核对;模板全部按「未实测」标注,v1 的 MiMo 实测记录不沿用。 旧覆盖模板里的 v1 字段(`wire_api`、`auth_modes` 等)照样能加载,但不再使用。 - **不再替使用者选大脑**:命令行研究、批量运行与 MCP `start_research` 用后台默认(`<数据根>/config.json` 的 `provider.profile` 或环境变量 `VRA_PROVIDER`),都没有就报错;选定来源的前置条件不满足(没装、没登录、缺 key)也直接报错,不回落到别家。 - **来源 id `openai` 停用,OpenAI 官方 API 模板改名 `openai-api`**:v1 的 `openai`(v1 init 骨架的默认值)指产品内置 Codex 的 ChatGPT 登录, 若照旧解析成同名 API 模板,环境里恰好有 `OPENAI_API_KEY` 就会悄悄改成按量计费。现在 `provider.profile`、`VRA_PROVIDER`、`--provider`、 `scripts/init --provider` 与页面请求里写 `openai` 都直接报错,说明改成 `cli-codex`(ChatGPT 订阅)还是 `openai-api`(API 按量); 数据根里 v1 时复制的 `providers/openai.json` 覆盖模板不再读取;页面里存过的 OpenAI 预设自动按 `openai-api` 读出。 - v1 参数一律报错并给出改法:`--engine`、`--codex-path`、`--codex-home`、`--no-hooks`、`--execution-mode`、`--experimental-direct-deep`、 `--auth`、`--reasoning`;MCP `start_research` 传 `engine` 返回 `engine_removed`。旧配置字段与环境变量 `VRA_CODEX_PATH` / `VRA_CODEX_HOME` / `VRA_PROVIDER_AUTH` 不再生效,体检报「v1 旧配置残留」。 - 研究宪法从根目录 `AGENTS.md` 移到 `methodology/constitution.md`;根目录 `AGENTS.md` 改为给 Agent 的部署、接口与维护说明 (`CLAUDE.md` 引用它)。 ### 新增 - **研究执行对所有大脑统一**:每个阶段一次独立会话,只开放 5 个受控工具(`list_run_files` / `read_run_file` / `calculate` / `write_stage` / `write_report`),MCP 与 function calling 共用同一套实现;macOS / Linux 不再有 hooks 执行层,所有平台都只走受控工具。 订阅 CLI 关闭全部内建工具与用户配置(Codex 的全局 `AGENTS.md` 没有参数能关,产品指令以更高优先级下发);Codex 另加只读沙箱、关闭联网搜索与子 Agent,并按事件白名单监控,越界即终止进程树。 - **收工检查改由产品执行**(原 Stop 钩子):缺产物或阶段校验不过就把问题清单交回去接着修,对所有大脑生效;#46 的推进判据与累计上限保留 (模型 API:连续空转 6 次 / 累计 20 次;本机 CLI 每次拦截都要重开会话,上限收紧为空转 1 次 / 累计 3 次)。manifest 新增 `stop_guard`。 - 研究方法论注入:每个阶段的提示词都带上研究宪法、该阶段 SOP 与计算函数契约(`calc/SPEC.md`),所有大脑一视同仁;合规 gate 命中后的重写轮同样带报告阶段的 SOP 与契约。 研究线程读不到仓库文件,契约不给就只能猜参数名(实跑中 Claude Code 与 Codex 都猜错过同一个参数,各多花一次整阶段补跑)。 - manifest 如实记录所用大脑:`engine.capabilities`(协议、沙箱、结构化输出方式、审计级别等)与 `provider` (含 `matrix_status`:`verified` / `untested`)。 - **远程访问模式** `scripts/start --remote`:给 Muse 一类个人云端 Agent 部署在自己的云端电脑上,把带访问口令的链接发给使用者; 每个请求先过访问口令(首次换成 HttpOnly cookie),本机 API 仍只听回环;支持 `--public-url`、`--rotate-access` 与 `VRA_ACCESS_TOKEN`。 从网页聊天、邮件点开链接(跨站整页打开)正常进入,跨站的接口请求与写请求照样拒绝;能判断出用户走 https 时(`--public-url` 为 https、 代理标了 https,或浏览器带 Fetch Metadata 访问非本机地址)访问 cookie 带 Secure。远程模式下页面不能修改 WorkBuddy 位置, 页面填的模型地址只收 https 公网域名(不收 IP、localhost 与内网名字);本机模式会去掉环境里残留的远程开关。 目前只支持 macOS / Linux。 - 资料导入(截图 / 表格转写)支持模型 API(图片走 Chat Completions 多模态)与 Codex CLI。 - 兼容矩阵 `provider_matrix.ts` 改测 Chat Completions 的 10 项能力,给出模板 `direct` 段建议值(不自动改模板)。 ### 数据源:同步 a-stock-data v3.10.1,新增 33 个 A 股端点 - 数据端点从 117 个增至 **150 个(147 个启用)**,分层从 30 层增至 **34 层**;新增指数、期货与大宗、事件驱动、可转债四层。 global-stock-data 最新仍是 v2.0.3,美股 / 港股端点沿用既有移植。 - 新端点:腾讯 K 线(前 / 后复权 + 分钟)、通达信官网盘后包、腾讯当日逐笔、北交所行情备胎;新浪研报;ETF 份额、两融官方备胎; 华尔街见闻快讯、新闻联播;ST 股票清单;上证e互动;中债收益率曲线、回购定盘利率、LPR;全球宏观日历、深交所交易日历; 指数成分 / 权重 / 估值;期货日行情、期权日行情、持仓排名、期货实时、期货日 K、A50、上海金; 业绩预告、机构调研、增减持、回购、股权质押、新股申购;可转债。全部免注册、免 key。 - 移植方式:`datasources/port_astock.py` 把上游代码块原样生成为 `sources/astock_ported.py`,与上游只差联网入口(全部改为把响应原文落进 `raw/`); 默认日期按深交所官方日历取「最近一个数据已发布的交易日」,不带参数也能用。每次调用落一个整表文件,证据都指向它。 这批端点按需调用,**不进六阶段研究计划**,所以完整研究的取数项与耗时不变。详见 `datasources/UPSTREAM.md` ④。 - 通达信(上游 #52):2026-09 起公开服务器的 K 线 / 盘口 / 逐笔命令普遍返回空,`tdx_bars` / `tdx_quotes` / `tdx_transaction` 默认禁用、代码留档,禁用原因里写明改用哪个端点(买卖五档暂无替代,腾讯实时行情只有最新价);`tdx_finance` / `tdx_f10` 照常可用。 ### 修复 - 通达信财务快照 `tdx_finance` 每次都只有部分结果:映射读的字段名(eps / bvps / roe)在 mootdx 0.11.7 里不存在,改读每股净资产、总股本、流通股本, 日期取快照自带的数据更新日。`tdx_finance` / `tdx_f10` 原来拿 K 线命令检查服务器,K 线失效后会把能用的服务器全判死、卡在测速上, 改为用财务命令检查;F10 只取服务器实际提供的类别,没有的类别明确报出来。 - 数据根里的同名覆盖模板是符号链接、目录或内容为 `null` 时直接报错,不再悄悄改用产品模板(以前使用者会以为自己的覆盖已生效); 已有配置时 `scripts/init --provider` 会明说这次没生效。 - #50:WorkBuddy / CodeBuddy 装在自动检测找不到的位置时,可在设置页填写它的位置(存 `<数据根>/local-agents.json`,页面、对话与研究共用), 也可用环境变量 `CODEBUDDY_BIN` / `CLAUDE_BIN` / `CODEX_BIN` 指定(设了就只认它);补充 Windows 常见安装位置。 - 研究子进程现在也会拿到指定的 CLI 位置(此前页面检测得到、后台研究却找不到)。 - Codex CLI 进程不继承 `CODEX_API_KEY` / `OPENAI_API_KEY`,避免订阅卡片静默改成按 API 计费(Claude Code 与 CodeBuddy 的同类保护保留)。 - 收工检查交回的问题说清是哪一条、怎么改:必需项(必需取数或必需计算)还挂着缺口、阶段却标 complete 时,列出这些 operation, 说明按 operation 判(改 reason_code 不算修好),并给出两种改法(标 incomplete,或确实拿到了就删缺口、在 notes 说明)。 此前只有一句「有必需项缺口」,真实运行里大脑把 reason_code 改成 `optional_skipped` 当作修好,续跑一次就被收工检查终止。 - Claude Code 订阅卡片每次调用前都重新核对:CLI 是否带受限运行所需的参数、当前是不是 claude.ai 订阅登录。此前只在检测时拒绝 API key / Bedrock / Vertex 登录,命令行研究与实际调用只看版本,Claude Code 若存着 API key 登录会照样用它(按 API 计费)跑下去。 核对不了(超时、输出读不懂)报「检测未完成,请重试」,不会清除现有登录。 - 检测登录的几秒内取消研究:不再等检测结束后照样启动研究进程、再误报「进程没能停下」,直接按「已取消」收尾; Claude Code 与 Codex 的检测进程随取消一起结束。 - 很短的 API key(不足 8 位,自建端点常见)也会从错误信息与 `events.jsonl` 里抹掉,紧挨着其他字符(如 `invalid_`)也照样抹; 含引号、反斜杠的 key 不论以原样还是 JSON 转义的形态出现都能抹掉;模型端点的错误信息先脱敏再截断,不会在截断处留下半截 key。 - 运行目录里的 `fetch/`、`calcs/`、`stages/` 被换成指向别处的符号链接时,5 个受控工具一律拒绝读写, 不再顺着链接读到或写到运行目录之外(此前只检查最末一级文件)。 - 模型端点返回跳转(3xx)时不再跟随,拿到响应头就直接报错并提示填写最终地址(跳转的响应体挂着也不会等到超时): 地址校验(远程模式只收 https 公网域名)只看填写的那一跳,跟随跳转就绕过了它。研究遇到跳转整次停下、不再补跑; 连接测试、对话、标题翻译、资料导入,以及开启 Agent 时的快速定位,也都提示改成最终地址。 - 「我的研报」发起的完整研究停下时,显示编排给出的具体原因(地址跳转、额度用尽、登录失效、限流、超时)和该怎么办, 不再一律说「未完整通过最终校验」;没有具体原因时仍用原来的说法。 - 带了 `--provider` / `--model` 却没给值(`--provider=` 或后面直接跟别的参数)时直接报错,不再悄悄用后台默认来源或模板默认模型: 覆盖研究、批量、初始化(`scripts/init`,含 `--python`)与模型兼容矩阵;HTTP 接口显式传空的 `llm.model` 同样报错,只有不传才用模板默认模型; `<数据根>/config.json` 里 `defaults.model` 写成空串或全空格,加载配置时就报错(`null` 才表示不指定),程序化调用传空模型也一样; 页面判断「已配置」也按同一口径(页面本来就不让保存空模型,只影响手改过的本地配置)。 `--turn-timeout-min`、`--max-retries`、`--gate-retries` 收到非数字或负数(超时还包括 0,重试次数还包括小数)时报错, 不再让 NaN 或小数流进超时与重试逻辑。 - 本机订阅 Agent 在启动前出错(超时参数无效、进程没能启动)时归还并发名额。此前每出一次这类错占掉一个名额不还, 攒满 4 个后本机订阅 Agent 一律报「忙」,只能重启服务。 ### 界面 - 「接入 AI」:Codex 卡片改为检测本机 Codex CLI(未安装给出安装命令,用 API key 登录时提示改用 ChatGPT 登录),去掉「登录 Codex」; 新增「重新检测」,在终端装好或登录后不用刷新页面;WorkBuddy 卡片可填写位置;API 预设与默认模型同步模板,未实测来源标「有模板·未实测」。 - 「接入 AI」选「其它 OpenAI 兼容端点」时,Model 一栏留空等用户填,不再预填 `custom` 这个词(v1 就有,用户不改就会拿 `custom` 当模型名去请求)。 ### 文档 - 中英文 README、`docs/model-access.md`、`docs/development-validation.md`、`orchestrator/README.md`、`providers/README.md` 与发布清单同步 v2; README 不再要求出现 Codex Harness,改为只允许以「已移除」的身份提到它。 ### 测试 - 本机回归(macOS,Node 26,2026-10-08 最终代码):orchestrator **899 项:898 通过、1 项 Windows ACL 专项跳过**;desktop **96/96**; Python(计算库、回测、数据脚本)**859/859**(含新端点的 85 条离线测试);两处类型检查与 desktop 生产构建通过。 - 三种订阅在最终代码上复测(2026-10-08,Claude Code 2.1.285、Codex CLI 0.160.0、WorkBuddy 内置的 CodeBuddy 2.137.1): - 页面:`scripts/start` 启动后,首次打开的「请接入AI」引导和「接入 AI」页的「测试并保存」三家都连接成功;每家各做一次普通对话和一次开启 Agent 的取数问答(查最近交易日行情),都给出带证据编号和来源的回答。Agent 问答里有个别来源这次取数失败(百度 K 线 403、交易日历、一次联网搜索),回答如实说明了。 - 完整六阶段研究(300308,三家同时跑,各用独立的测试数据根):Claude Code complete(1540 秒,收工检查拦截 3 次);WorkBuddy / CodeBuddy complete(2594 秒,收工检查拦截 3 次,成稿第一次有 2 个数字与引用的证据对不上,被数字核对拦下,重试后通过);Codex incomplete(1377 秒,收工检查拦截 1 次)。三家都没有被强制终止,合规检查无命中,报告、附录和查看页都已生成,`manifest.json` 里的来源与方法论(宪法 + 6 个技能)都是本次所选。 - Codex 的 incomplete 与 2026-10-07 那次一样:它认为财务季度化缺数据(新浪财务摘要缺 2023 年中报累计值,三季度单季算不出),把财务、估值、风险与线索和成稿标为 incomplete,报告照常写出。三家这次都遇到东财个股基本面连接中断、申万证书校验失败,Claude Code 和 WorkBuddy 把这些写成缺口但判定阶段完成。 - 2026-10-07 的第一次实跑结果:Claude Code complete(565 秒)、CodeBuddy complete(848 秒)、Codex incomplete(1189 秒)。 - 模型 API 大脑本轮没有用真实 key 跑研究;工具循环、错误分类、跳转与脱敏由本机假端点测试覆盖。 Windows 只有单元测试,没有实机运行。 - 远程模式(2026-10-08):在一台全新的 Debian 12 容器(Node 22.23、Python 3.11,模拟云端电脑)里按 `AGENTS.md` 第 3 节部署, `scripts/setup` 一次通过,`setsid scripts/start --remote --no-open` 后台启动成功。 实测:没有口令或口令错误时,页面、静态文件与接口都返回 401;完整链接换成 30 天 HttpOnly cookie,地址栏里的口令被去掉,任意 Host 都能访问; 设置页拒绝修改 WorkBuddy 位置、拒绝回环地址的模型端点;SIGTERM 让页面与 API 一起退出;`--rotate-access` 重启后旧链接与旧 cookie 返回 401;带 https 的 `--public-url` 时 cookie 带 Secure。 同一容器里不接大脑跑了一次取数(300308),43 项取数中 35 项成功、1 项部分成功,失败的 3 项分别是东财断开连接、Exa 免费额度限流、本机代理导致的申万证书校验失败。 没有在真实云端平台部署,也没有在远程模式下接真实模型。 - 新增的 33 个端点 2026-10-08 上午(交易时段)在本机逐个实跑,全部正常返回:30 个成功;3 个部分成功——腾讯逐笔是盘中取数、上游没法核对完整,如实标注; ST 清单因东财列表接口连不上、按上游设计改用 baostock; 上证e互动用茅台测,源页面写着「近1个月暂无回复」,0 条是真实结果。 - 新端点另做了 4 轮 Codex 只读审计(7 / 2 / 3 / 2 条,后两轮是对前一轮修法的追查,都已修:逐笔完整性判断、盘后包里 ETF 与可转债的成交量单位、深市 ETF 早上的默认日期、 机构调研明细的次数与证据编号、F10 部分类别失败的状态、五档替代的说法、显式空参数被换成默认值、机构名很长或字段带分隔符时证据编号撞车、逐笔缺号的说法),每条都补了测试,并确认改回旧代码时测试会失败。 自查另补两处:取数层不算合计(去掉逐笔与 ETF 份额的合计);个股事件表取满 `limit` 时标为部分成功,写明更早的记录没取。 - 发版前用 Codex 做了五轮只读审计(第一轮全量 24 条发现,之后四轮复验分别新增 5、4、4、1 条,第五轮只剩一条测试清理问题); 上面「修复」里的多数条目来自这五轮,没修的见下节。 ### 已知限制(本版未修) - 研究进行中,如果本机另有进程把运行目录里的 `calcs/` 等目录换成指向别处的符号链接(恰好发生在检查与写入之间), 受控工具可能写到运行目录之外。前提是同一账户下已经有能改你文件的进程;研究线程里的大脑没有 Shell 和任意文件写入,造不出这种链接。 彻底修要按目录句柄打开文件,Node 目前没有对应接口。 - 远程模式不带 `--public-url` 启动,而平台代理把 Host 改成本机地址、又不转告原始协议时,访问 cookie 不带 Secure 标记。 启动时带上 `--public-url https://…` 即可避免(`AGENTS.md` 已写明)。 - `margin_backup`(两融官方备胎)对沪市代码报错:上游 a-stock-data 要求上交所数据单页返回完整,而上交所现在分两页给(2026-10-08 实测共 2002 条), 深市正常。属于上游问题,照原样移植,上游修好后重新生成即可。 - CodeBuddy 登录检测超时后,它自己派生的后代进程可能残留(v1 就有)。 - Windows 上研究正常结束时,不清理 CLI 留下的后代进程(v1 就有;要改用 Job Object 管理整棵进程树)。 - 研究被取消或异常中断时,manifest 的 `stop_guard` 计数可能漏掉本阶段已发生的拦截;`events.jsonl` 里的记录是完整的。 - 「接入 AI」里「重新检测」失败时,卡片仍显示上一次的检测结果(可能是「可用」);v1 就有。 - 开启 Agent 时的快速定位,遇到密钥被拒、限流、超时等对话错误,页面只显示笼统的「Quick 执行失败」;v1 就有(本版只给地址跳转补了改 Base URL 的提示)。 ### v1.2.0 之后已在 main 上、随本版发布的改动 #### 新增 - 研究归档可以删除(PR #49,感谢 @WenhuaXia)。删除许可要**正向证据**:清单缺失、清单损坏、清单或进程记录显示未收尾,一律拒删并说明原因,不做"确认不了就删"。删除成功时连带清掉该次运行的进程记录,不留孤儿(否则同名研究编号以后再也建不起来)。 #### 修复 - (v2 起这套判据由产品自己的收工检查执行,对所有大脑生效。)Stop 钩子按**有没有新增合法计算记录**判推进,空转预算不再误杀合规的攒算流(PR #46,感谢 @WenhuaXia)。判据是整套 `calculation_id` 的指纹变了且条数没减少:重算覆盖同名文件算推进,删记录不算;参数文件与函数清单没有 `calculation_id`,不能拿无意义写盘刷预算。 - 同时加了**累计拦截硬上限**(同一阶段的同一次重试内 20 次,不受推进影响):否则"每轮落一条计算、但永远写不出阶段产物"的一轮可以被无限拦截,把整轮额度耗在同一处上。终止标记与编排器提示同时给出累计次数和最后的空转次数,两种原因分得开。 - **进程记录读不出来时不再照删**:旧版把 `readResearchControl` 的异常吞掉后继续删目录,也就是记录损坏、路径含链接或读不到权限时,一次**还在跑**的研究也可能被删掉——这与该函数"删除许可要正向证据"的设计相反。现在一律拒删(`control_unreadable`);非记录本身的异常(`EACCES`、`EMFILE` 等)在**服务端日志**另留一行根因,免得排查被"可能损坏"这句提示引到错方向。 - 删除动作本身失败(权限、目录被占用)不再是 500 `internal`,而是 `delete_failed` 并说明这次归档可能只删掉了一部分。 - `control_unreadable` 补上自救路径:对齐 `manifest_missing` 的写法,告诉用户确认运行早已结束时可手动清理运行目录与 `.local/research-control/`,不再让这条归档在界面上永远删不掉。 - `DELETE /runs/:id` 补进 orchestrator README 的路由清单(破坏性端点此前没有文档露出)。 - 界面删除归档时,只有后端自己发的 `not_found` 才按"这条记录本来就不在了"处理并刷新列表,不再弹"删除失败:HTTP 404";代理或路由返回的 404(HTML 错误页、路径形状不对)照常报错,不吞成删除成功。 - 终止本轮的提示不再把"一直在算却写不出产物"说成空转:空转计数的 1 表示"上一次拦截前刚有新计算落盘",照字面印会把两种终止说反。 - 参考 PR #43(感谢 @WenhuaXia)及 AkShare 的新闻请求形态,为东财个股新闻加入一次有超时的备用请求;不携带 Cookie,不把同源重试当成独立信源。 - 区分明确空列表与请求、解析失败;备用成功时披露降级,并将每条新闻绑定到实际返回它的原始响应。补齐文章链接构造与完整取数入口回归。 - Issue / PR 核对与验证范围见 [2026-09-12 处理记录](docs/issue-pr-triage-2026-09-12.md)。 ## [1.2.0] - 2026-09-09 ### 暂撤 Mac 客户端,保留源码工作台 - 以已发布 v1.1.0 为基础移除 Mac 原生窗口、打包/签名工具、专属启动与静态网关;保留 React 浏览器 UI、源码 setup/start、Codex 引擎与所有已发布研究和模型接入能力。 - 暂以源码 + 本地浏览器工作台交付,便于使用者的 Agent 改造开发。中英文 README 和发布清单同步调整;原有客户端数据不删除、不自动迁移。 - 本次为源码更新,不构建新安装包;GitHub 历史 v1.1.0 Release、安装包及官网入口不变。详见 [源码交付说明](docs/source-delivery.md)。 ### Issue / PR 增量修复 - 排查 Issue #48 时修复自定义 API 的预设恢复:返回设置页时按来源和模型共同恢复,不再把用户编辑的模型名称当成下拉选项,也不因模型同名切换服务商。保存后回读浏览器存储,静默写入失败时明确报错;不声称复现了旧 Mac 客户端的全部存储故障。 - 适配 PR #42(感谢 @WenhuaXia):已引用计算记录中的 inputs/details 数字允许受限的舍入、百分比和单位换算,避免误拦合法中间值;保留 output.value 的 display 约束,不整体放宽派生结果校验。 - PR #45 的缺字段崩溃已由现有契约校验覆盖;PR #47 的报告表格与证据链接已有现行实现,不覆盖回旧方案。其余新增功能及风险项见 [Issue / PR 处理记录](docs/issue-pr-triage-v1.2.0.md)。 - 独立审查后排除 details 中结果形子对象的 value,防止嵌套派生结果绕过 display 规则;真实中间量仍可绑定。 - MCP 间接依赖 Hono 从 4.13.3 更新到 4.13.5,处理本轮依赖审计报告的安全公告,不改变 MCP SDK 或 Codex 引擎版本。 ## [1.1.0] - 2026-09-07 ### 多模型订阅接入与 Mac 独立客户端 - 统一前后端及依赖锁文件版本为 1.1.0,Mac 构建号递增至 40;旧 M38 的 1.0.4 安装包保留,不能改名当作新版。 - 新版重点:Codex / Claude Code / WorkBuddy 订阅和 API 接入、默认普通对话与按需开启 Agent、聊天优先首页和五类功能导航、截图/表格转写,以及独立 Mac 客户端。 - M40 隐私加固:截图/表格转写只开放本次上传清单的受控读取,文本与图片都要求实际读取完成;只产待确认草稿,不自动写持仓。成功、失败和取消后清理本次临时副本,不删除原文件或历史资料。 - 本地订阅进程改为必要环境变量白名单,避免继承无关服务密钥;Mac/POSIX 在退出成功前也确认所属进程组已停止,失败或取消仍保留真实状态。Windows 正常退出后的孤儿进程清理尚缺 Job Object 级保证,不能套用 Mac 的通过结论。 - Mac 打包仅接收精确公开根文件与目录,大小写变体的私密备份也排除;前端按锁文件重新安装后构建。安装版始终使用受控研究执行模式,避免安装路径改变工具边界。 - Mac 交付为已签名、公证的 Apple Silicon App 和签名 DMG,构建号40、引擎0.153.4;从最终DMG复制后的实际计算及退出/重启保持验证通过。安装包与更新说明见 [v1.1.0 Release](https://github.com/simonlin1212/Vibe-Research/releases/tag/v1.1.0)。 - 以下里程碑为开发历史;旧版本号、提交状态和测试数量仅代表各次记录。本轮结果见 [M40 发布候选与隐私验收](docs/发布候选与隐私验收_M40_2026-09-07.md),实际公开状态以Release页面为准。 - M24:左上角 AI 来源旁增加“开启Agent”,默认关闭,与设置页同步。订阅和 API 均支持无研究工具的普通对话, 开启后恢复完整 Agent;旧自动开启值迁移为关闭,明确选择跨刷新保留,同来源重测不重置。 切换中止在途聊天(含连接预检),不影响已启动的独立研究任务。详见 [M24 验收](docs/Agent开关与普通对话_M24_2026-09-06.md)。 - M23:首页以 Agent 对话为首屏,未接入时弹出三种订阅快捷测试和其他接入方式;左上角显示实际已保存来源。 测试失败、取消或配置被其他页面更改时不覆盖配置。交流框下用五个并排分类框展示 12 个一级栏目小按钮,保留原侧栏。 本地 Claude 真实接入、浏览器交互与验收边界见 [M23 验收](docs/首页快捷接入与功能导航_M23_2026-09-06.md)。 - M22:普通 Agent 聊天接通联网搜索、网页读取、数据取数、确定性计算/回测及研究记录等 13 个工具入口, 显示真实调用记录,不再把正常聊天固定为无工具模式。长研究通过界面一次性确认后启动,保持所选 AI 来源; 计算目录补真实参数契约,取数失败不标成成功。Codex 与 Claude Code 本机实测及四轮增量审查记录见 [聊天工具开放验收](docs/聊天工具开放验收_M22_2026-09-06.md)。本地开发,不代表所有平台/来源已验收或发布。 - 同步上游截至 `09e8404` 的 Issue #44 与 PR #34(原贡献 @WenhuaXia),保留未提交双引擎开发成果。 MCP 发现与执行共用产品 CODEX_HOME;新增默认关闭的 `VRA_LAN=1` 并接入两种启动器,API 仍绑回环。 本地适配在代理补 token 前增加同源检查,保留远程 HTTPS/本机 HTTP 边界及全站一次 AI 接入; 自托管模板未实测,不内置转换网关。回测、页面分析/反思与资料任务不依赖安全上下文的 randomUUID。 包版本同步上游基线 1.0.4,不代表未提交双引擎改动已发布。 - M12–M14 本地开发:Claude Code / WorkBuddy 辩论、Agent 回测与受控资料转写补齐,持仓页新增截图/表格 人工核对入口;不会上传后自动写台账,不暗换 AI 来源。真实路径与失败轮次边界见 [M12](docs/跨来源业务验收_M12_2026-09-05.md)。 - 剩余已确认审计问题完成分批整改:Sortino、初始等权持有对照、权重约束、路径及诊断错误、行情跨期对照、 PE 来源披露、行业校验契约、Windows 就绪探针与目录漂移,见 [M13](docs/剩余审计整改_M13_2026-09-05.md)。 - Codex 同会话在途保护、可取消的分批资料检索及 mootdx 安装/体检依赖补齐;串行后端 795 项(794 通过、 1 Windows ACL 跳过),前端 51/51、Python 699/699。当前仍是未提交开发版,不是发布就绪; full 实跑、端点失败与 Windows 边界见 [M14](docs/完整版本机验收_M14_2026-09-05.md)。 - 辩论进程树停止未确认时,保留明确失败原因与此前已完成内容,不误报“已取消”或“全场未启动”, 不自动归档为完成报告;跨模块审查及后继两轮修复复审闭环。 - 根路由增加中文异常恢复页,区分找不到页面和运行异常,提供重新加载与返回首页;不展示原始错误正文, 不清空本机配置,提醒未保存输入可能丢失。渲染回归、真实浏览器和独立复审通过。 - 受控计算工具复用现有引用契约,在执行前拒绝错误的证据/计算 id 格式,避免到整阶段结束才反馈; MCP/直连同源校验,不改变真实计算失败记录的保留规则。红绿回归、全量后端测试与独立复审通过。 - 报告、附录及内嵌报告的查看器只在运行结束且最终状态一致时开放;未校验草稿保留本地,但不经 HTTP/MCP 当作正式报告展示。资料不完整的合格报告仍可阅读并提示缺口;不再承诺固定十几分钟或对单标的取全部端点。 - 变化提醒沿用当前数据目录,页面查询不再写比较缓存,CLI 保留显式归档能力;补数据根隔离、只读与路径回归。 两项经真实浏览器验证、独立 Codex 审查及后继复审,无可行动回归。 - WorkBuddy 六阶段 full 实跑 complete / exit 0,1,011 条证据、23 条计算、最终错误与 gate 命中均为零; 约 112 分钟且画像/风险/报告各三次尝试才通过。Claude 同范围因额度限制失败,保留记录,不推广为所有来源成功。 - M11 深度研究取消本机闭环:取消与最终归档以原子决策互斥,等待取数、Codex SDK 和订阅 CLI 子进程树 退出后确认取消;刷新后可从历史继续跟踪,已完成阶段保留。三轮实际 Codex 审查修复五项,后端 744 通过、 1 Windows ACL 跳过,前端 44/44、Python 648/648,类型/构建通过。生产 HTTP/React 加合成 worker 浏览器 验收通过,真实模型与 Windows 不在本批结论内。未提交,见 [深度研究取消验收](docs/深度研究取消验收_2026-09-05.md)。 - 2026-09-05 本地检查点:M8 与原 14 项优先 P2 整改已按 Simon 授权提交为 `2ed80ac`,提交前 Gitleaks 扫描无泄漏;未 push、tag 或 Release。下方“未提交”保留为当时的历史状态,不覆盖本条。 - 后继批次修复跨数据根快照缓存、普通工具继承多余模型凭据、同名辩论覆盖,以及辩论请求取消传递; 暂未提交,详细验证与复审状态见 [验收记录](docs/运行隔离与辩论中止验收_2026-09-05.md)。 - 后续三项修复:资料检索改按同页窗口的不同查询词覆盖选择片段,避免封面重复词抢占且不串页; 今日复盘只发送一份页面摘要;计算 JSON 工具保留确定性展示串及嵌套情景展示,不改变原值与失败状态。 独立 Codex 复审无可行动回归;后端 730 项(729 通过、1 Windows ACL 跳过)、前端 40/40、Python 648/648, 类型检查/构建通过。仍未提交,边界见 [检索与计算展示验收](docs/检索与计算展示验收_2026-09-05.md)。 - 2026-09-05:整仓审计原 14 项优先 P2 完成本地修复、回归与独立复审。以下为接续 COV-F1–F4 的十项收口, 不是客户完整版或发布就绪声明;M8 与整改仍未提交、未推送、未发布。 - PE 分位序列现在绑定实际文件、列、过滤、日期列与选中期间;报价时效未知时要求同日 K 线和正成交量佐证。 回测补齐已接受号段的板块/历史边界,并强制披露价格来源、复权、未模拟现金分红及历史重述风险;特殊交易 情形未建模的边界保留,不承诺全市场微观规则或总回报精度。 - 合并取数按调用方独立取消;查看器通过固定脚本哈希恢复交互、保留 CSP 与无同源 sandbox;API 地址允许 字面 loopback HTTP,仍拒绝远程明文连接,不绕过模型直连能力验证。 - 首页提供今日复盘、公司研究、已有研报三个受控页面入口,普通聊天不承诺自动取数或全网收集;页面独立 分析与反思使用各自会话;自选行情显式重新取数,显示最早价格证据的快照时间,不再标成“每 3 秒实时”。 - 十项分三个范围由实际 Codex 独立复审,均无可行动 P1/P2。最终 orchestrator **721 项**(720 通过、 1 Windows ACL 跳过)、desktop **37/37**、Python **640/640**,类型检查及构建通过;实际 Chrome 合成数据 验证首页路由、快照和查看器交互/安全共 15 项。构建包大小警告保留,订阅六阶段修后重跑、全端点、Windows 真机、其余 P3 与跨来源业务缺口不在本次闭环结论内。下方旧数字保留为各阶段历史检查点。 - M8 完成 WorkBuddy 订阅引擎在核心数据范围(`endpoint_scope=core`)的真实六阶段验收: `m8-workbuddy-full-3` 用 102 分 54 秒完成 profile / financials / estimates / valuation / risk / report, 最终 `complete / exit 0`,产出 119 条证据、29 条计算记录(22 成功、7 失败尝试留痕)、0 处跨源冲突; 财务阶段一次修复错误计算参数,报告阶段一次超时后重试成功,六阶段 最终均由 validator 判定通过。 - 两次先行实跑暴露并修复报告数字忠实度问题:被忽略区段现在保持原始字符位置,不再把证据 id 内的数字 错认成正文主张;重试反馈会按原行汇总**全部**不匹配数字,不再只展示前三条或截断为 12 行。报告补跑 优先修正既有文件,逐行对齐同段证据 id 或 `output.display`,避免每次从头生成。 - 本机 Agent 的确定性前置错误现在立即终止当前阶段,不再把“未安装 / 未登录 / 版本过旧 / 配额不足” 重试 18 次;运行入口即使探针失败也会先建立 manifest,再通过真实运行路径写出可恢复的失败终态。 Claude Code OAuth 过期时,`m8-claude-auth-terminal` 在 5 秒内形成 `failed / exit 3` 的完整 manifest, 并给出重新登录提示。Simon 随后完成登录,本机 Claude Code 2.1.261 的 `m8-claude-full-2` 用 27 分 43 秒 跑完核心数据范围六阶段:119 条证据、25 条计算记录(24 成功、1 失败尝试留痕);最终各阶段 validator 通过,报告首轮 17 处数字引用问题修订后通过。仍保留早期历史财务期不足等 gaps,状态为 `incomplete / exit 2`,不能写成 complete。两种订阅的全端点 `full` 范围均未在本轮验收。 - 订阅 Agent 单阶段默认上限由 20 分钟校准为 30 分钟,显式用户配置仍原样尊重。WorkBuddy 最终报告首轮 在 30 分钟上限退出,第二轮随后正常完成;此前也发生过 20 分钟超时。该记录支持增加长报告运行余量, 但不能仅凭超时证明 CLI 当时仍在有效生成,速度和超时诊断仍需改善。 - 干净 macOS 临时副本完成从零 `scripts/setup` 与 `scripts/start --no-open`:初始化、依赖安装、API 8765、 UI 5930、鉴权健康检查与退出后端口释放均通过。Windows 契约 / 路径 / PowerShell 模拟为 114 项中的 113 通过、1 项真实 ACL 因当前为 macOS 跳过;没有 Windows 主机或允许 push 的远端 runner,故不宣称 Windows 真机干净安装已经验收。 - M8 独立 Codex 五轮审计依次发现并修复“重试反馈仍会截断”“探针失败早于 manifest”“旧 CLI 错误仍会 重试”等真实问题;最终两轮均为 `No actionable P1/P2 findings`。最终回归:orchestrator **714 项** (713 通过、1 项 Windows ACL 在 macOS 跳过)、desktop **34/34**、Python **577/577**;两端类型检查、 Vite 生产构建、Core 纯净度 0(63/63)与 diff 格式检查通过。M8 改动仍未提交、未推送、未发布。 - 登录恢复后,按 Simon 要求另由真实 Claude Code 完成四轮只读整仓范围审计,主审已复核并用隔离诊断 复现关键问题。新确认 14 项优先 P2,包括首页任务未接执行入口、跨功能会话共享、行情快照新鲜度、 并发取消耦合、证据查看器 CSP、回测规则与披露、序列输入溯源、报价二次验证及错误分类/脱敏等。 这些是更大范围新发现,审计结束时尚未修复;此前 M8 增量审计通过不等于整仓已可发布。详细覆盖、误报与待验证项 保存在本地审计交接材料;部分数据源族仅抽查,Windows 真机和扩展端点全范围仍待验收。 - 整仓审计首批关闭 COV-F1–F4,原 14 项优先 P2 仍有 10 项待修:运行期回测限制进入服务端强制披露, 不截断长提示来规避契约;取数/信号失败保留可读 JSON 原因,部分取数失败与样本不足同时说明。 Windows 单/双反斜杠用户名路径完成脱敏;通用 HTTP 404 与模糊 403 不再冒充业务无数据,FINRA/SEC 保留有界日期/形式回退,FINRA 空结果不再推断小票/覆盖范围。合法文件校验兼容当前小数成交量, 真实官方 2026-09-03 文件 12,266 条解析通过,未丢弃分数股数值。 - 首批修复经过 3 轮独立 Codex 复审:r1 两个真实错误链遗漏均修复,r2 闭环;其后实连发现的新整数 校验误伤已修复,r3 专项复审通过。最终 Python **623/623**、orchestrator **717 项**(716 通过、 1 Windows ACL 跳过)、desktop **34/34**,两端类型检查与构建通过;仍有主 JS 包大小警告。 本批未重跑订阅六阶段、全端点或 Windows 真机;M8 与整改仍未提交、未推送、未发布。 - M7 把 Claude Code / WorkBuddy 订阅接入正式六阶段研究:新增独立 `local_agent` 引擎与逐阶段 CLI 运行器, 不继承 OpenAI provider、Codex 路径、`CODEX_HOME`、hooks 或模型名,也不把它们冒充 Codex Harness。 - 本机订阅 Agent 每个阶段关闭内建工具,只开放既有五个 VRA MCP 工具;工具 schema、阶段所有权、确定性计算、 文件边界与最终 validator 继续共用一份实现,没有复制第二套研究状态机。自然语言回答或退出码 0 不构成完成。 - WorkBuddy Deep 首轮显式等待 MCP,并按官方加载机制设置 `alwaysLoad / defer_loading=false` 与 `NoDefer(mcp__vra__*)`。本机 WorkBuddy 5.2.6 / CodeBuddy Code 2.106.4 已真实完成 profile 阶段: 23 条证据、一次尝试、阶段 `complete`、validator 通过;刻意只跑一个阶段时整次仍如实为 `incomplete / exit 2`。这不是完整六阶段真实运行验收;Claude Code 路径已由机器测试覆盖,但本轮没有冒充 做过真实 Claude 订阅运行。 - M7 独立 Codex 首轮审计确认 4 个 P2:阶段超时被错误压到 10 分钟、父进程退出可能遗留订阅 CLI / MCP 进程树、订阅运行错误继承默认模型名,以及任务路由把本机 Agent 冒充 Codex Harness。四项均已修复并加回归; 收敛复审结论为 `No actionable P1/P2 findings`。 - M7 最终验证:orchestrator **708 项**(707 通过、1 项 Windows ACL 在 macOS 跳过)、desktop **34/34**、 Python **577/577**;两端类型检查、Vite 生产构建与 diff 格式检查通过。M7 已本地提交为 `b18799b feat: run subscription agents through six-stage research`,未推送、未发布。 - M6 新增 WorkBuddy / CodeBuddy 订阅适配器:设置页把它作为第三个真实订阅来源, 已安装并登录 WorkBuddy 桌面版时直接复用应用内置 CodeBuddy Code CLI;独立安装 CLI 的用户也可沿用 原有登录,不再强迫这类用户重复安装、重复登录或填写 API key。 - CodeBuddy 探针通过官方 stream-json initialize 控制请求判定登录,只向界面返回版本和布尔状态; 账号与 token 不返回、不落日志。执行时强制关闭工具、MCP、用户设置、自动记忆、后台任务与子 Agent, 并移除 API key、自定义端点和模型覆盖环境变量。WorkBuddy 内置旧 CLI 缺少无会话参数时,订阅凭据只在 内存中转给一次性临时用户目录中的回答进程,完成后删除,防止写入真实用户目录。 - M6 当时的边界如实保持在对话与有界材料任务;完整六阶段研究由后续 M7 独立实现。旧的 “CodeBuddy 适配器尚未完成”引导已移除。 - M6 使用腾讯官方 CodeBuddy Code 2.143.1 完成干净环境实装:版本探测、未登录识别及退出码为 0 的纯文本 登录错误均被稳定归类;又使用本机 WorkBuddy 5.2.6 内置 CodeBuddy Code 2.106.4 的真实订阅登录完成 受限回答,验证桌面端自动发现、内存凭据桥与临时用户目录清理。同时补齐 Windows 常见安装位置的内置 CLI 发现, 无扩展名入口由 Node 安全启动,旧版隔离运行同时改写 HOME / USERPROFILE / APPDATA / LOCALAPPDATA 及 XDG 目录,不留下从 Windows 绕回真实用户目录的口子。最终回归:orchestrator **699 项**(698 通过、1 项 macOS 跳过)、 desktop **34/34**、Python **577/577**,两端类型检查与 Vite 生产构建通过。独立 Codex 首轮审计对 `--setting-sources none` 的唯一意见经官方源码与真实命令证伪,收敛复审为 `No actionable P1/P2 findings`,未按错误建议放松隔离。补齐 Windows 发现与用户目录隔离后再做一轮独立收敛复审, 结论同样为 `No actionable P1/P2 findings`。 - M5 增加 macOS / Linux `scripts/setup` 与 `scripts/start`:普通用户不再手装两套依赖、全局安装 Codex 或打开两个终端。启动器会检查安装状态与固定端口,同时管理 API / 界面进程,读取实际数据根完成带鉴权 健康检查后才打开浏览器;任一进程退出会同步收口。 - 干净目录实装发现 npm 11 在依赖目录不存在时不能可靠处理绝对 `--prefix`;POSIX 安装器改为进入两个包目录 后执行 `npm ci`,不再让已有 `node_modules` 掩盖首次安装失败;两端安装器也不再让 npm 审计网络阻塞 已按锁文件完成的首次安装。 - Vite 固定使用 5930,端口被占用时明确失败,不再静默漂到 5931;首屏连不上后端时直接显示各平台的一键 启动命令和“重新连接”按钮;初始化与代理错误也不再把内部 Node / CODEX_HOME 命令交给普通用户。 - M5 独立 Codex 审计发现并修复 1 个真实 P2:启动健康检查完成前或关闭终端时,尚未注册停止信号会让 detached 的 API / 界面成为残留进程;现于首个异步等待前监听 Ctrl+C、终止与关闭终端信号,真实启动期 中断验证两端口均释放。末轮复审为 `No actionable P1/P2 findings`。 - 重构 AI 接入与执行方式:第一次打开只选择订阅或 API,连接成功后默认开启 Vibe Research Agent; 设置页用第二张独立卡控制 Agent / 模型直连,全站共用同一份来源与执行方式。 - 只有通过真实能力探针的 API provider 可以关闭 Agent。订阅登录与未验证 API 不会被伪装成裸模型直连; 直连普通对话和标题翻译走受限 API 传输层,研究、辩论、资料转写和工具任务在副作用前返回 `agent_required`。 - 「我的研报」移除 Auto / Quick / Deep 三选一,系统继续在内部按任务语义路由;路由指纹同时绑定 AI 来源 与 Agent 开关,不允许路由与执行阶段偷换 provider 或模式。全新浏览器无明确配置时进入“接入 AI”, 不再借后端默认值替用户做选择。 - 设置页、README 与官网如实区分 Codex Harness、Claude Code Agent、WorkBuddy / CodeBuddy 和模型 API; M6 完成前的 API 引导已由真实本地适配器取代。 - 本轮独立 Codex 审计发现并修复 3 个真实 P2:原始工具入口绕过执行方式、Claude 订阅进入尚不支持的 辩论 / 转写 / 引导工具流程,以及默认模型来源指纹没有绑定后端实际配置;末轮复审为 `No actionable P1/P2 findings`。 - 最终验证:orchestrator **691 项**(690 通过、1 项 Windows ACL 在 macOS 跳过)、desktop **34/34**、 Python **577/577**;两端类型检查、Vite 生产构建、Core 纯净度 0(60/60)与真实浏览器首次接入 / Agent 默认开启 / 直连开关 / 官网入口断言全部通过。 - 完成双引擎任务架构 M4 收口:公开产品固定为 Browse / Quick / Deep,Deep 仍由 Codex 六阶段承载; 既有 Direct 六阶段只保留为显式 `--experimental-direct-deep` 开发者入口,公共 `/research` 与 MCP 均拒绝它。 - 把通用 `AgentRunner / EventsLog` 从 Codex 专属 runner 抽离,Codex SDK 只在 Codex 分支动态加载;阻断全部 `@openai/codex*` import 的子进程探针仍可加载 Direct 路径,Direct 也不再探测 Codex 二进制。 - 运行清单如实区分能力:Codex 为 `constitution_and_skills`,Direct 为 `stage_prompt_only`;Direct 记录真实 provider / model 并把 Codex 路径与二进制置空,Codex 使用 provider 默认模型时也记录实际解析值。 - 修复 MCP 静默剥掉 `engine=direct` 后启动默认 Codex、调用方注入环境的 Direct 密钥可能漏入事件账本, 以及 `user_reports` 16 份产品上限与 schema 不一致。真实 Direct + MiMo 单阶段运行得到 23 条证据、 profile 完成且 validator 通过;整次因刻意只跑单阶段如实为 `incomplete / exit 2`。 - M4 独立 Codex 审计确认并修复 3 个 P2,自查修复 1 个密钥脱敏问题;一条 hooks 意见经真实构造链与 运行清单证伪,最终复审为 `No actionable P1/P2 findings`。 - M4 最终验证:orchestrator 670 项(669 通过、1 项 Windows ACL 在 macOS 跳过)、desktop 30/30、 Python 577/577;两端类型检查、Vite 生产构建与 Core 纯净度 0(60/60)全部通过。 - 完成双引擎任务架构 M3:统一 `/tasks` 现可把 Deep 路由交给既有 Codex 六阶段研究,并通过 `/tasks/resume` 按运行 ID 与路由指纹恢复;没有新增第二套研究状态机,旧 `/research` 保持兼容。 - Deep 任务把关注点、唯一 A 股标的和最多 16 份圈选资料的版本绑定到运行,实际读取时再次核对版本;缺失、 变化、多标的或其它市场资料均在启动前拒绝。16 份材料各自至少有一个片段进入 40K 专用上下文,未勾选资料 不会因同代码被扩入。 - 页面会持续读取六阶段进度;运行中 manifest 的占位退出码不再误判为失败,只有 `complete + exit 0` 才显示完成; 启动目录一分钟仍未出现时明确失败,不再永久轮询。独立 Codex 三轮审计共发现 6 个真实 P1/P2 并全部修复, 最终复审为 `No actionable P1/P2 findings`。 - M3 全量验证:orchestrator 663 项(662 通过、1 项 Windows ACL 在 macOS 跳过)、desktop 30/30、 Python 577/577;两端类型检查、Vite 生产构建与真实浏览器功能断言全部通过。 - M3 真实 Deep 运行经统一 `/tasks` 启动并由 `/tasks/resume` 收口:六阶段全部实际执行,生成 1,099 条证据、 20 项计算和正式报告,圈选资料引用进入报告。因一个外部财报日源失败,底层状态如实为 `incomplete / exit 2`, 任务层准确映射为 `failed` 而未冒充完成;临时测试资料已删除并复核资料库恢复为空。 - 完成双引擎任务架构 M2:新增统一 `/tasks` 两段式任务入口、真实研报材料与确定性操作适配器,以及 「我的研报」Auto / Quick / Deep 任务面板。执行必须携带路由指纹,材料变化时拒绝而不是透明换路线; M2 的 Deep 只显示路由结果并明确未启动长流程,旧 `/research` 保持兼容。 - Quick v1 只用一次直连模型请求从服务端预切段落中定位原文;材料版本、完整段落引用、取消、合规 gate、 超时和输出上限均在服务端校验。确定性任务已接真实页面查询、数据源刷新与计算注册表。 - M2 阶段验证:orchestrator 653 项(652 通过、1 项 Windows ACL 在 macOS 跳过)、desktop 29/29、 Python 577/577;两端类型检查、前端生产构建、真实浏览器 Deep 路由与临时资料清理通过;最终 Codex 复审 `No actionable P1/P2 findings`。 ## [1.0.4] - 2026-09-05 上游发布记录:Issue #44 修复 Codex MCP 隔离发现时使用了用户配置目录的问题。 来源 `9633210`,发布提交 `500f0f9`;本地通过适配补丁同步,未移动开发分支 HEAD 或创建发布。 PR #34 在该 Release 之后进入 main,不属于 v1.0.4 标签内容。 ## [1.0.3] - 2026-09-02 V1.0.3 收口 Issue #38 / #39 / #40:普通对话不再被资料库泛词误召回,设置页连接检测改走专用探针, Node 运行时要求写准并在 CI 补齐 Node 22。 - 修复 #40:「接入 AI」的「测试并保存」不再借用普通 `/chat`。新增 `/llm-probe` 专用探针:后端生成 一次性令牌、固定 developer 指令、不召回资料库、不复用线程,成功判据是模型 回复里原样出现本次令牌。除不召回资料外与业务对话走同一条路(同一份开场白、developer 层与合规 gate、 自由文本回复),仍是仓库规则要求的「真实对话测试」。此前探针语句会被「连接 / 检测 / 成功」等二字片段 命中用户资料,资料片段随之发给正在测试、尚未验证的 provider;而模型只回一句「连接成功」又会因缺少 `[资料:…]` 引用被判成测试失败。 - 修复 #39:`/chat` 不再对每条消息全库检索。新增 `reportRecallPlan`:只在用户明确提到资料库 / 上传 / 附件 / 原文、消息命中某份报告的证券代码、或命中报告文件名主体词时召回,后两种只在命中的报告内检索; 「今日」「市场」「数据」等泛词不再触发。个股研究按代码强制召回的路径不变。 - 修复 #38:`engines.node` 从 `>=22.6` 改为 `>=22.18`(与 README 一致,原生 TypeScript 类型剥离默认 开启的最低版本),desktop 补同样声明;`npm test` / `npm run run` 前先跑 `scripts/check-node.mjs`, Node 版本不够或构建未启用 TypeScript 支持(`process.features.typescript` 为 false,见于部分 Linux 发行版打包的 Node)时给出明确指引,而不是 `ERR_UNKNOWN_FILE_EXTENSION`;`scripts/init`、`scripts/doctor`、 `start.ps1`、`setup-windows.ps1` 等直接执行 `.ts` 的入口同样先过预检;CI 矩阵新增 Node 22。 - 新增回归:探针令牌 / 一次性线程 / 无资料注入 / 错误回填判失败;召回计划的泛词、明确意图、代码边界、 标题主体四类用例。 - Codex 首轮审计 4 条(1 P1 / 3 P2)全部核实为真并修复:英文主体词改整词匹配(`cat` 不再命中 `education`, 否则一份无关私有资料会被送去模型);连字符文件名拆词(`apple-annual-report` → `apple`);中文只剥首尾停用词、 剩余不足 2 字即停(公司名里含通用词不再被剥空);`probe_bad_output` 进入前端可原样显示的错误码白名单, 不再被吞成「连接失败」。 - Codex 第二轮 4 条:英文虚词与公司后缀(for / the / inc…)不再构成文件名主体;点名带扩展名的完整文件名 (`summarize notes.txt`)即视为显式指定该资料;预检接入全部直接启动入口;探针改走业务对话同一路径(见上)。 - Codex 第三轮 2 条:按页问答的消息由前端以「【问题】」分隔页面上下文与用户问题,召回意图与检索打分只看用户 问题(页面上下文里的「近期公告」、代码不再触发);明确要资料且停在某主体页面时只召回该主体的资料; 公司全称后缀(股份有限公司 / 集团…)计入通用停用词,「贵州茅台股份有限公司…年度报告」剥出「贵州茅台」。 - Codex 第四轮 3 条:问题里明确指到的目标(完整文件名 > 代码 > 文件名主体词)优先于页面主体,「资料里怎么说 300750」 停在 600519 页面时召回的是 300750 那份;港股写法 `700.HK` / `HK:700` 规范成入库的五位码再比对;两个 package-lock 根包的 `engines` 与 package.json 同步(`npm version` 不会更新它)。 - Codex 第五轮 1 条:明确要资料但问题无目标时,页面上下文里列出的**完整文件名**也算页面主体(「我的资料」页 的建议问句对没有代码的主题类资料不再漏召回)。 - Codex 第六轮 2 条:字母代码只认**大写整词**(`ON` / `$ON` / `ON.US`),文件名里本就大写的词同样要求大写匹配, 「focus on margins」「my cat is sick」不再命中 onsemi / CAT 的资料;「这两份报告」「所有报告」「these reports」 这类量词式指称计入明确意图。 - Codex 第七轮 4 条:点名文件按边界比对(`meeting-notes.txt` 不再连带 `notes.txt`);代码分支把入库形式的代码并入 打分查询(问 `700.HK` 选中了 `00700` 那份却打 0 分);「this / that / the report」英文单数指称计入明确意图; 页面上下文列出 ≥3 个文件名视为列表页(前端只显示最新 60 个),不按它限定召回范围,但文件名仍进检索键。 - Codex 第八轮 1 条:常驻控制台的「(我正在看「某页」这一页)」前缀也算页面上下文,「我的研报」页标题不再触发召回。 - Codex 第九轮 3 条:页面范围内代码命中与文件名命中取并集(「比较这两份」不再丢掉无代码的那份);页面上下文里的 港股写法同样规范成入库码;中文文件名按体裁词(报告 / 点评 / 分析 / 深度…)切段取候选主体,「贵州茅台深度报告 消费税影响分析」也能剥出「贵州茅台」。 - Codex 第十至十四轮(召回细节):问题里点了数量(「比较这三份报告」)且页面恰好列了那么多份时按页面那几份来;一句话里 混用文件名 / 代码 / 主体词时三类目标取并集;打分查询键在前、问题在后(长问题不再把键挤出检索窗口);点名文件名按 Unicode 边界整段匹配、且被已知更长文件名覆盖的出现不算(「年度报告.md」不再连带「报告.md」,「meeting notes.txt」 不再连带「notes.txt」,库里没有的长文件名也不会命中它的短后缀;中文句子里文件名要与前后文以空格 / 标点隔开,紧贴着写的 仍可经文件名主体词召回);意图门槛的数量词与 `quantifiedCount` 对齐(中文到十、英文到 ten、阿拉伯数字)。 - **不做「跟进沿用上一轮召回范围」**:第十轮曾按会话记住上一轮命中的资料让不带目标的跟进句沿用,随后四轮审计连续指出 沿用条件过宽(换页 / 换主体 / 换凭据 / 非承接句 / 普通疑问词仍沿用、指纹不稳),最终移除——服务端猜「这句是不是 跟进」不是可靠的资料边界。跟进句要用资料请点名(代码 / 文件名 / 「这份报告」);否则不召回,线程按既有设计随召回 集合变化重开。 - Codex 第十五至二十九轮:文件名边界与覆盖规则如上;金融垂类意图补「这份年报 / 财报里」这类带明确指称的说法 (「年报季到了」仍不触发);英文复数指称补 attached / uploaded;明确选中 N 份时检索给 N 个位置并按份数放宽 上下文字数(此前固定 5 份 / 12k 字,「比较这六份报告」会静默少一份),仍放不下时在上下文末尾明示「比较不完整」; 查询组装给用户问题保留窗口(列表页 60 个文件名不再把问题挤出检索的 500 字 / 80 词);点名文件后,文件名自带的代码 / 公司名不再把同名兄弟文件并进来(遮罩按空白灵活匹配);选中份数超过检索 20 份硬上限或有几份没打到分时,同样在 上下文末尾明示不完整;`AI` / `EV` 这类两字母全大写主体保留;键优先时先给键留预算、单键截到 160 字,超长文件名不再被整体丢弃; 明确要资料且停在没有列文件名的主体页时,页面上下文里的公司名 / 主题名也算页面主体(没有解析出代码的资料不再漏); 明确意图的措辞收紧:裸的「资料 / 文档 / 报告中」「the report」不算,须带资料库 / 上传 / 附件 / 我的 / 指示词等限定 (「如何给技术文档添加目录」不再触发),「这一份报告」计入;裸的 PDF / DOCX 同样须带指示词;document / file 这类 通用名词计入英文停用词;「所有报告 / 总结全部文件 / all reports」圈定整个资料库、选中的不再按相关性过滤(检索 20 份硬上限或字数上限放不下时提示不完整);4 / 9 开头的六位代码 (北交所老号段 / 新号段)入库时可识别(资料索引 schema 升到 3,旧索引读取时按新规则重算),问题里的裸代码即使没登记也 只按代码本身打分兜底(仅限合法号段,日期 / 金额式六位数不算);「every report」计入全库请求;垂类可经 `Plugin.reportRecall.documentNouns` 注入自己的资料名词(金融:研报 / 年报 / 财报…),「总结所有研报」「比较这六份财报」 同样参与全库 / 数量判定(含初始意图判定);「所有的报告」「all (of) the reports」这类带助词 / 冠词的写法也认; 裸「上传」不算意图(须为「已上传 / 上传的 / 上传了」);点名多个文件时遮罩按长度降序,短名不再把长名剩下半截; 「我的资料」页内置建议改为「帮我给这些资料排个阅读顺序」以便触发召回;页面列了文件名时只按文件名圈定(代码 / 主体词 只在没有文件名可认时兜底,没列出的同代码旧文件不再被并进来);资料索引版本要求整数,畸形值判损坏而不是静默迁移; 「总结 300750 的所有报告」这类带目标的「所有」只作用于该目标(这几份全部注入),没有目标时才是整个库;≥6 字母的全大写文件名词 (NVIDIA)按公司名不分大小写,只有 ≤5 字母才当 ticker。 - 最终验证:orchestrator **571 项**(570 通过、1 跳过)、desktop **26/26**、Python calc 201 + backtest 139; Node 22.23 官方二进制下 chat / report_library / core_purity / plugin / release_version **113/113**; 两端类型检查与前端生产构建通过;Core 纯净度棘轮保持 0。 ## [1.0.2] - 2026-08-31 V1.0.2 修复 Windows 用户在 V1.0.1 接入 API 后,Agent 对话可能全部报“本地 Agent 暂时没有连接成功”的问题。 故障发生在模型请求之前,与 DeepSeek 等 API key 是否有效无关。 - 修复 MCP 隔离配置生成:不再递归扫描并提升未启用 profile 或 Apps 运行时中的 MCP 名称,避免生成只有 `enabled = false`、却缺少 `command` / `url` transport 的根配置,触发 Codex 0.149 `invalid transport in mcp_servers.` 启动错误。 - MCP 隔离改为以产品捆绑的官方 Codex 在相同 `CODEX_HOME` 与工作目录下解析出的当前有效集合为准; 预检阶段同步关闭 Apps、MCP Apps 与 plugins,只禁用该引擎入口实际报告的有效 MCP,无法核验时继续 失败关闭。 - 新增真实引擎回归:构造“根配置有有效 MCP、未启用 profile 含 `codex_app`”的配置,要求产品生成的 覆盖能被捆绑 Codex 直接解析,并且只禁用当前有效 MCP,不再把休眠配置投影到根层。该测试会在 Windows、macOS 与 Ubuntu CI 中随平台契约运行。 - 最终验证:orchestrator **540 项**(539 通过、1 项 Windows ACL 专项在 macOS 跳过)、desktop **25/25**、Python **575/575**;两端类型检查与前端生产构建通过,联网体检 **20/20**。 ## [1.0.1] - 2026-08-30 V1.0.1 是 Windows 与公开 Issue 收口版本:补齐 Windows 原生 PowerShell/CMD 接入和受控研究执行层, 合并 Claude Code 对开源版的审计整改,并复核仓库全部未关闭 Issue。 - 新增 Windows 11 原生支持,不依赖 WSL:提供 PowerShell/CMD 初始化、体检和一键启动入口,补齐 Windows venv、PATH/PATHEXT、用户目录、临时目录、DNS 探针、进程树终止和文件打开语义。 - Windows 六阶段研究采用受控 MCP 执行层:关闭 Shell、unified exec、图片读取、子代理、插件、应用和 联网搜索,线程只读,只能读取净化后的运行产物、调用确定性 calc、写当前阶段 JSON 与最终报告。 该设计绕开上游 native Windows PowerShell lifecycle hook 尚不完整的问题,同时保留编排器与 validator 的机器校验边界;macOS/Linux 继续走既有 hooks 链路。 - 新增 `windows-latest` / `macos-latest` / `ubuntu-latest` CI 矩阵;orchestrator 新增 Windows 路径、 环境、只读线程、受控工具读写、NTFS 私密 ACL、JSON 账本路径与真实 calc 回归,当前 **539 项** (本机 538 通过 + 1 项 Windows 专项跳过),Core 行业词仍为 0。Windows 还会以两个真实 Python 进程验证东财请求锁确实互斥;Unix 跑完整 orchestrator 套件,Windows 跑平台契约与全量 Python 回归。 Windows CI 统一以 UTF-8 解码 Python 的 JSON 管道,Node 动态加载的测试路径改为标准 `file://` URI。 PowerShell 入口保留 UTF-8 BOM,兼容 Windows PowerShell 5.1 对中文脚本的编码识别。 - 开源版审计修复:研报索引升级到 v2,收紧 A 股代码识别并支持公司名召回;删除板块页写死的 `300308`;缺失行情不再伪装成 0,二十日资金流只有数据完整时才合计,官网 Star 获取失败显示未知。 - 合规 gate 补齐常见动作建议与个股评级赋予语境,同时保留机构评级篇数统计;回测工具把自标的基准和 换手不足口径作为服务端强制可见披露,不能由模型省略或藏进 HTML 注释。 - 最终验证:orchestrator **539 项**(538 通过、1 项平台跳过)、desktop **25/25**、Python **575/575**; 两端类型检查与前端生产构建通过,联网体检 **20/20**,Codex 收敛复审无可操作 P1/P2。 - 重建 [viberesearch.wiki](https://viberesearch.wiki) 官方网站,主叙事升级为“基于 OpenAI Codex Harness 打造的本地金融研究 Agent”,并展示当前工作台、模型接入、回测 Agent、研报库与证据纪律。 - 官网源码迁入 `website/`,中英文 README 恢复官网入口;Release 链接使用稳定的 `releases/latest`, 具体版本号由 GitHub API 动态同步,避免后续发布时出现新旧版本并存。 - Issue #26:当前全球行情链在搜索接口返回空结构时会自动逐市场直查,美股与港股代码不再因搜索端点 异常整块失效;新增搜索空结果和港股短码回归测试。 - Issue #21:事件概率已接入 Kalshi + Polymarket 实时公开定价;修复 `Borussia` 命中 `russia` 导致 体育比赛被误分为地缘政治的问题,结构化体育元数据现在优先于标题子串。 - Issue #20:API 与 MCP 继续从 `orchestrator/package.json` 读取唯一产品版本,并新增发布元数据一致性测试, 强制同步 orchestrator、desktop、两个 lockfile、中英文 README 徽章与 CHANGELOG。 - Issue #16:旧版直接调用 PATH 中 Codex CLI 的链路已由产品隔离运行时替代;设置页可检测版本与登录状态、 启动官方 Codex 授权并执行真实“测试并保存”,失败返回受控且可行动的错误,不再只显示裸退出码。 ## [1.0.0] - 2026-08-28 Vibe Research 从直接调用模型 API 的个人投研看板,升级为基于 Codex Harness 的本地金融研究 Agent。 V1.0.0 以源码 + 本地浏览器 UI 发布,包含首页 Agent、每日复盘、资讯雷达、产业信号、个股研究、 本地研报库、Agent 驱动回测、多空辩论、三市场自选与持仓、报告归档,以及 Codex 订阅与模型 API 双通道。 发布验证:orchestrator **525/525**、desktop **22/22**、Python **569/569**;两端类型检查和前端生产 构建通过。Codex 订阅与 MiMo API 均完成从空配置到真实业务报告的端到端验证。 ## 1.0.0 开发记录 · 发布前模型接入闭环(2026-08-28) - “接入 AI”新增 Codex 订阅登录入口:从产品专用 `CODEX_HOME` 未登录状态点击“登录 Codex”, 自动打开 OpenAI 官方授权页;授权完成后设置页自动轮询并切换为可用,不要求用户打开终端或复制认证文件。 - 订阅登录任务单实例运行,具备明确的等待、失败与超时状态;超时时清理整个登录进程组,避免残留回调进程 继续占用端口或让下一次登录永久卡在等待状态。 - 订阅与 API 两种接入统一改为“测试并保存”:先通过本机后端发起真实模型对话,成功才覆盖当前配置; 失败不再出现“配置存下来了、到业务页才发现不能用”的假成功。 - **全新 Codex 订阅实测通过**:产品隔离登录态从未登录 → 官方浏览器授权 → 自动检测为可用 → 测试保存 → “每日复盘”真实生成完整报告;最终配置不含 API key,也不读取 `~/.codex`。 - **全新 MiMo API 实测通过**:清空浏览器模型配置,从 API 接入重新填写官方地址、 `mimo-v2.5-pro` 与用户 key → 测试保存 → “每日复盘”真实生成完整报告;结束后默认配置恢复为 Codex 订阅。 - Codex 独立审计三轮:前两轮共抓出 4 个 P2(设置页并发刷新覆盖新状态、登录超时只杀父进程、 其他刷新入口仍可竞态、父进程退出早于回调子进程);全部修复并加回归测试,第三轮结论为 **无可操作 P1/P2**。 - 验证:orchestrator **525/525**、类型检查通过;desktop **22/22**、类型检查与 Vite 生产构建通过; 数据脚本 **231/231**。 ## 1.0.0 开发记录 · 本机订阅运行时检测与 Claude Code 接入(2026-08-28) - 对照 `nexu-io/open-design` 0.21.0 的 runtime registry / CLI detection,补回原先只移植了模型清单、 没有移植真实运行适配器的缺口。 - 新增本机 Agent 状态探针:设置页实时显示 Codex / Claude Code 的安装、版本和登录状态;未安装或未登录 就禁用,不再把“已登录”或“开发中”写死在卡片上。 - Claude Code 订阅已接通真实对话链:用户正文走 stdin,强制 `safe-mode`、空工具集、空 MCP、无联网工具、 无插件与无会话落盘;同时清除可能静默改走 API / Bedrock / Vertex / Foundry 的环境变量。 - Qwen Code 与 DeepSeek CLI 不再冒充免 key 订阅:前者旧免费 OAuth 已停止,后者使用 API key;两者继续 通过现有 API 接入区配置。 - 实机验证:本机 Claude Code 2.1.226 已登录,并经产品适配层返回 `CLAUDE_RUNTIME_OK`;orchestrator 517/517、desktop 16/16、两端类型检查与前端生产构建通过。 ## 1.0.0 开发记录 · 从 API 分析升级为 Codex 本地金融 Agent(2026-08-28) - 上一版 Vibe Research 由应用直接调用模型 API 完成一次次分析;当前版本改造为基于 **OpenAI Codex Harness** 的本地金融 Agent,Agent 运行时与模型供应商正式分离。 - Codex Harness 负责在本机维持上下文、读取工具目录、连续调用工具、推进多步任务、展示进度并处理失败; 金融层继续提供数据源、研究 SOP、确定性计算、证据校验和合规边界。 - 首页对话、个股研究、我的研报、回测与报告归档开始共用同一套 Agent 能力,不再是彼此独立的 API 问答。 - 模型层支持已接通的 Codex / Claude Code 订阅登录和大多数 Responses API;本机状态由后端实时检测, 不把预留接口写成已可用。 - 相比旧版单次 API 分析,当前版本在长任务执行、工具调用、上下文保持、失败恢复与推理质量上均有显著提升。 ## 1.0.0 开发记录 · 「我的研报」真正接入 Agent 底座(2026-08-28) - `我的研报` 不再是占位页:支持上传 PDF / DOCX / TXT / MD / CSV,本机保存原文件与抽取文本,按行业、公司和代码归档;同一文件按 SHA-256 去重,删除采用事务式落盘。 - 新增本地资料检索:关键词与中文二元词召回匹配片段;PDF 保留页码,Agent 收到的上下文统一标为不可信资料,并以 `[资料: p.<页码>]` 回引。 - 对话输出新增机器校验:只要使用了召回片段,回答就必须保留本轮真实资料 id 与页码;错引、漏引、引用未知资料都会拒绝返回。 - A 股六阶段研究会按代码自动召回相关资料,实际注入清单写入运行 manifest,最终报告同样必须保留真实引用;港股、美股资料仍可归档并在 Agent 对话中检索,但完整六阶段取数链目前只开放 A 股,后端会拒绝空跑。 - 对话执行改用专用无工具入口:关闭 Shell、图片读取、子代理、插件、应用和联网能力,防止不可信文档诱导模型绕过服务端检索读取本机文件;真引擎探针确认工具调用为 0。 - 新增资料列表、上传、下载、删除 API 与真实浏览器界面;扫描版 PDF 因无文本层会明确提示需要 OCR,不会伪装成导入成功。 - 验证:orchestrator 500 项测试全绿、Core 行业词 0、类型检查通过;desktop 9 项测试、类型检查和生产构建通过;Codex 四轮审计收口,末轮无可操作 P1/P2。 ## 1.0.0 开发记录 · 发行形态回退为源代码 + 浏览器 UI(2026-08-28) - 删除 `shell/` 下的 Electron 主进程、`app://` 协议、载荷装配、DMG 打包配置与客户端测试。 - 删除 `build/` 下只服务于 macOS App 的图标资产;保留 `desktop/` React 浏览器 UI 与本机 HTTP API。 - 编排器不再透传 `ELECTRON_RUN_AS_NODE`,源码纯净度测试新增“不得恢复 `shell/` 客户端”的棘轮。 - 中英文 README 明确当前交付是**源码 + 本地浏览器 UI**,补齐浏览器 UI 的安装与启动步骤。 ## 历史 · 已移除的 macOS 安装包:Electron 桌面外壳(2026-08-26) > 本节只保留当时的开发记录。当前工作树已移除 Electron / DMG 客户端,不再按这一形态发行。 `shell/` —— 用户拿到手的形态。Electron 主进程拉起编排器、`app://` 协议服务界面、 `/api` 转发到本地后端;`scripts/assemble.mjs` 装配载荷(引擎二进制 + 可重定位 Python + 界面构建产物 + 编排器源码),`electron-builder.yml` 出 dmg。 **一条命令出片** `npm run dist`(外壳重编 → 界面重构建 → 载荷重装配 → 验证 → 打包)。 产物 `VibeResearch-0.1.0-arm64.dmg` **331 MB**,已装到 `/Applications`、 **清空数据根当全新用户**实测:0.6 秒起后端 → 界面加载 → 真实行情,退出无孤儿进程。 🔴 **五条实测才定下来的**(与最初方案不同): 1. **`.app` 名字不能带空格** —— 产品根就在 App 包里,而编排器对"产品根 / 数据根含空格"是硬拒绝 ⇒ `productName: VibeResearch`,显示名走 `CFBundleDisplayName: Vibe Research`。 2. **数据根 = `~/.vibe-research-agent`**,不是 `~/.vibe-research` —— 后者是**开源版看板的** (里面有它的 portfolio.json / myreports / monitor),第一次装机跑起来才发现。 3. **编排器发 `.ts` 源码不编译** —— 编译反而更脆(它自己按硬编码路径拉起 `orchestrator/src/run.ts`); 宿主 Node 24 默认能剥类型。 4. **引擎打整个 npm 平台包**不抠二进制 —— 给 SDK 显式路径会让它把 `codex-path/` 那份 PATH 清空。 5. **字节码要预编进发行版** —— akshare 冷 import 带缓存 1.15 秒 / 不带 **21.9 秒**, 而 App 包在别人机器上很可能只读(+55 MB,值)。 底座六处配套修复:`--port 0`(0 是 falsy,原来被两个 `||` 各吃一次)· `VRA_DATA_ROOT` 可改数据根 · `ELECTRON_RUN_AS_NODE` 透传(装机版的 node 就是 Electron 二进制,丢了它子进程会去开窗口)· doctor 跳过 `payload` / `release`(不跳会把密钥扫描的额度吃光、真源码反而没扫)· 纯净度棘轮覆盖 `shell/src`。 🔴 **两次"成功地打进了上一版"**:一次是没重跑 esbuild 就打包,一次是 `beforePack` 只检查三个载荷文件在不在。 ⇒ `beforePack` 改成**无条件重做**,不判新鲜度。 🔴 **`ps` 按 locale 转义非 ASCII** —— 中文安装路径下收尸静默匹配不上,已改成 ASCII 片段有序匹配 + `LC_ALL=C`。 外壳过 **Codex 8 轮审计**(4 初审 + 4 复审 + 打包侧 1 轮,20 条全部处置),每条修复做过变异测试。 测试 shell **77** · orchestrator **433**。 **还差**:应用图标(现在是 Electron 默认)· 签名 + 公证 + 自动更新(等 `Developer ID Application` 证书)· 🔴 **装机版怎么拿到模型 API key**(从访达双击启动的 App 没有 shell 环境,而密钥只从环境变量读)—— **这是产品决策,不是 bug**。 ## 五个功能逐个实测:两个真 bug,一个功能确实没做(2026-08-27) Simon 让把回测 / 自选股 / 持仓 / 我的研报 / 研究记录逐个跑一遍。**都在界面上真跑**,数字逐条手算核对。 ### 🔴 两个 bug,都是我做回测页时留下的 1. **「回测」这个分类没注册**。我写了 `addNote("回测", …)`,却没在垂类包的 `note.category` 枚举里加它 ⇒ 点「存进研究记录」抛错 「分类「回测」没有对应的台账枚举」。 2. **而这个错用户看不见** —— 我在回测页**手搓了一个按钮**、用 `void addNote(...)`, `void` 把 rejection 吞掉了:**既不报成功也不报失败,错只进控制台**。 ⚠️ 仓库里本来就有 `SaveNoteButton`,它的注释开头就写着 「写失败照样显示成功…这种谎比报错难查得多」——**我把它警告的坑又踩了一遍**。 ⇒ 回测页改用 `SaveNoteButton`;分类在垂类枚举 + 前端本地映射两处都注册。 ### 实测结果 | | 结果 | |---|---| | **回测** | ✅ 两只票(茅台+五粮液)跑通:−17.40% / 回撤 −29.59% / 18 笔;对照 −35.53% 并标注「不是指数」;限制 6 条 + 口径 3 条 + 数据来源(各 968 根、起止日期)随结果列出 | | **自选股** | ✅ 加两只,实时行情正常(旭创 877.01 +3.07% / 三花 36.88 +2.05%,PE/PB/换手齐全) | | **持仓** | ✅ 加两笔,**逐项手算吻合**:茅台 (1291.16−1500)×100 = −20,884 / −13.92%;旭创 (877.01−600)×500 = +138,505 / +46.17%;合计 567,621 / 450,000 / +117,621 / +26.14% 全对 | | **我的研报** | ⚠️ **确实没做** —— 页面明说「还没接到底座上(不是没有数据,是这条链路还没做)」。后端虽有 `ingestFiles`,但那是**把文档读成台账记录草稿**,与这页要的「文件归档 + 行业分类」是两个功能,不是没接线 | | **研究记录** | ✅ 两条(回测 + 问 AI),展开后指标 / 限制 / 数据来源全在;落盘 `.local/ledger/note.json` | 顺带验了「问 AI」:它读到了本页真实数据(总市值约 56.8 万、浮盈 +26.14%),与手算一致,并成功存入。 ⚠️ 台账里现在有 **2 笔持仓 + 2 只自选 + 2 条记录**,都是**测试数据**,要删随时说。 测试 orchestrator 454 · Python 555 · desktop tsc 0 错。 ## 辩论产出的数字校验(2026-08-27) 补上上一轮敞着的那个口子:**引用来的数字能跟资料包比对,算出来的数字比不了** —— 后者成了唯一一类「谁都没在看」的数字,而它就摆在核对过的数字旁边,看着一样可信。 ### 三档,必须分开报 新增 Core 模块 `arithmetic.ts`(算术是领域无关的,**不带任何行业词**),把一段产出里的数字分三档: - **对得上资料包** —— 可溯源 - **写了算式且重算通过** —— 没有对应的已知值,但它把算式写出来了,就地重算过 - **两样都不是** —— **不等于错**,但这一档没经过核对,要让人知道有多少 外加 `badMath`:**算式是它自己写的、结果对不上** —— 唯一可以断言「这里错了」的一类。 界面上每段产出下面挂一条,算错的用红块单独列出并给出重算值。 ⚠️ 只标不改。重算对不上不代表结论一定错(也可能是算式写得不规整),但**必须让人看见**。 ⚠️ 这一层**只查它自己写下的算式,不判断算式选得对不对** —— 拿错了年份的两个数相除,算式本身可以是自洽的。能查的和不能查的要分清楚。 ### 三次「以为做好了、其实没有」 1. **不认正号**:真实文本写的是 `= +0.2%`,而第一版 NUM 只认负号 ⇒ **那句错话整条识别不出来**,安然过关。 2. **不剥标注**:`2026H1 444.64 亿 [ev-x] ÷ 2025H1 453.90 亿 [ev-y] − 1 = −2.04%` —— 这**正是我们要求模型写的形状**,而带着期间标签与证据引用时一条都匹配不上, 等于这层校验对规范写法完全失效。⇒ 先剥 `[ev-…]` 与 `2026H1`/`2025 年度`(**整体剥**, 只剥字母会留下 `2026` 被当成运算数)。 3. 🔴 **只支持 `A ÷ B − 1` 与 `− + ×`,漏了纯除法**。而实测里模型写的大多是 `453.90 ÷ 910.94 = 49.83%` 这种 ⇒ 一段**写满算式**的产出只认出 **1 条**。 **「识别不到」和「没有算式可查」在结果上长得一模一样**,不测就发现不了。 补上纯除法与「运算符和数字之间的标签」后,同一段正文识别 **1 → 6 条,全部重算通过**。 ### 一条测试的自我更正 原本写了「标签间隙不能宽到造成误报」并配了四句反例。**变异测试把间隙从 8 放宽到 40, 四句照样一条不匹配** —— 说明挡住误报的是**字符类**(排除数字 / 运算符 / 逗号),不是宽度, 断言与真正承重的机制对不上。已按实情改写,并改为直接钉字符类: 去掉「排除数字」这一条会红 8 条,含那句具体断言。 ### 顺带 五条角色提示词加了「算式要写出来 + 注明两个数各自的资料期 + 跨期比较用同一口径的相邻期」。 实测有效:同一只票再跑一场,多方把六条算式全写出来了(旧产出一条都没写),且逐条重算通过。 ⚠️ **提示词不保证正确** —— 它只是提高了「有算式可查」的比例;真正兜底的是上面这层重算。 ⚠️ Core 纯净度棘轮当场抓到我把 `营收` / `净利` 写进了 `arithmetic.ts` 的注释举例里,已换成中性例子。 测试 orchestrator **454**(新增 11 条,用例全部抄自两次真实辩论的产出)· Python 555 · shell 77 · doctor 18 ok。 ## 多空辩论实测:深度档位是装饰性的 + 算出来的数没校验(2026-08-27) 真跑了一场(600519,选「一轮」)。**结论:引用是可信的,算出来的数不是。** ### 🔴 深度档位选了没用 界面上那个「一轮 / 两轮」下拉框**是装饰性的**:适配层把参数命名成 `_rounds` (下划线 = 声明「我不用它」),**整条链**(界面 → 适配层 → API → service → debate)都把它丢了, 永远跑完整五阶段。而旁边的耗时提示还跟着档位变 —— **告诉你 100 秒 / 3 次调用,实际跑了 6 分多钟 / 5 次。** ⚠️ 控件说一套、系统做一套,比没有这个控件更糟。 修法:契约加 `Plugin.debate.depths`(档位 → 跑哪几个阶段;**档位怎么分是垂类的事**, Core 不知道「轮」是什么),沿链透传。实测 depth=1 → 3 阶段、depth=2 → 5 阶段、 **不给 depth → 回落到全部**(认不出的档位少跑,等于悄悄换了一个更弱的产物)。 `sees` 本来就按「这一场里存不存在且已完成」过滤,少几个阶段不用另外处理。 ### ✅ 证据引用是真的(逐个核过) 正文引用的 30 个 ev-id 里,12 个属于财务端点(值不随行情变、可比对)—— **全部真实存在,且数值与正文逐个吻合**(445.17 / 444.64 / 453.90 / 822.93 / 862.41 / 1720.54 / 1741.44 亿)。没有编造引用。 ### 🔴 但**算出来的数**没有任何校验 同一场里抓到两处,都出在没有 ev-id 的派生数字上: 1. 「2026H1 扣非 444.64 亿,**同比仅增 +0.2%**(2025H1 为 453.90 亿)」—— 实为 **−2.04%**,**方向反了**;而它自己在反驳段又写了 −2.04%,**前后矛盾**。 2. 「2025 全年**同比 +7.2%**(822.93 vs 747.53)」—— 747.53 确实在资料包里, 但那是 **2023** 年的数(**取错年份**);且 822.93/747.53 = **+10.1%**, 连它自己那两个数都对不上;用真实的 2024 基数 862.41 应是 **−4.6%**,方向也反了。 ⚠️ **这两个百分比就摆在正确引用的数字旁边,看着一样可信。** 研究流程有 `judgeNumberBinding` 做数字绑定校验,**辩论一处都没有**(`debate.ts` 里 0 处), 提示词里也从没要求「算出来的数要能复算」。 **这一轮只做了两件够得着的**:① 五条角色提示词都加了「算式要写出来 + 注明两个数各自的资料期 + 跨期比较要用同一口径的相邻期」;② **界面上把这条限制说出来** —— 「带 [ev-…] 的数字可溯源;同比、差额这类算出来的数没有经过校验」。 ⚠️ 提示词不保证正确 —— **真正的解法是给辩论也加数字绑定校验,那是另一件事,没做。** ### 顺带证实的两条(注释属实,不是许愿) - 每个阶段**一条全新会话**(`debate--`)—— 同一会话里连着扮演多空 = 一个人写辩论稿 - 产出**照常过合规 gate**(经 `chatSend` → `applyGate`,无条件执行); `debate.ts:260` 那个三元的另一分支是测试注入用的,生产走不到 ### 另有一处未修 模型的**草稿泄漏进了正文**:「2025 全年营收同比仅 +1.1%(1741.44/1720.54−1**...不对, 这里要用 2024 全年营收**:…)」—— 自我更正的过程被原样输出。属表达层问题,未处理。 测试 orchestrator **443**(新增 3 条钉深度档位,变异验证过)· Python 555 · shell 77 · doctor 18 ok。 ## 个股研究页实测:六处「不报错但结果是错的」(2026-08-27) Simon:「个股研究的模块你测试过吗?没测试过的话跑一遍,这个还是挺关键的。」 —— **没测过**(它来自整套 UI 搬入那批 `8c91116`,只跑过 tsc)。真跑了 A 股与美股各一遍。 ⚠️ **排查过程里我先误判了一次**:直接读 `/fetch` 响应的 `d.evidence`,恒为 0, 一度以为 8 个 legacy 端点全挂了。实际证据在 **`d.envelope`** 里,端点全是好的 (`fetch_financials` 48 条 / `fetch_announcements` 30 条 …)。**差点报一个假的严重故障。** ### 修掉的六处 🔴 **`noteKV` 白名单漏键 —— 同一个坑的第三次**(前两次:研报的 `industry`、GPU 现货卡的可租张数)。 `买方 / 卖方 / 当日涨跌 / 龙头 / 板块代码 / 概念` 都没登记 → 被安静丢掉 → 上层 `?? r.note` 回退 → **界面上直接显示 `板块代码=BK0438;当日涨跌=-0.38%;龙头=五芳斋` 这种内部字符串**。 ⚠️ 回退到原始 note 比显示空更糟:它看着像内容,用户不知道那是调试文本。 🔴 **note 末尾没有键的尾注被上一个值吞掉**:大宗交易的 note 以 `;单位按东财数据中心口径` 收尾, 于是卖方显示成「广发证券…营业部;单位按东财数据中心口径」。终止符加了第三条 (`;<末尾一段不含等号的文字>$`),只在字符串末尾且那段不含 `=` 时匹配。 🔴 **板块名取错来源**:板块名是**证据的 value**(食品饮料 / 白酒Ⅲ),代码却在找不存在的 `name=` 键。 同处的涨跌与龙头也一直是空的(它们在 note 里)。 🔴 **大宗交易的买卖方取的是不存在的字段**(`block_trade_buyer/seller`), 端点只给 price / premium / volume / amount / count,买卖方在 note 里 → 界面上显示成「买 · 卖」,像渲染坏了而不是没数据。 🔴 **美股现金流量表两个轴写反了**:`record_key` 实际是 `<报告期>|<科目>`,代码写成 `[item, period]`。 于是表头那句 `report_date.slice(0,7)`(为日期写的)套在科目名上, 把「投资活动产生的现金流量净额」截成「投资活动产生的」; **数值因为转置一致所以还对得上,只有表头是错的** —— 最难看出来的那种。 顺带:期间标签改用**证据自己的资料期**(真实日期),不用 record_key 里的 `2026/Q9` —— 没有第 9 季度,那是把一个编出来的期间摆到界面上。 🔴 **财务块的数据来源标错**:写着「同花顺财务摘要」,实际走的是**新浪** (akshare `stock_financial_abstract`,落盘 raw 的文件名就是 `extracted_sina_abstract_…`)。 一个卖溯源的产品把来源标错,比不标更糟。 ### 顺带改了两处表达 - 财务块原本摆着 ROE / 毛利率 / 净利率 / 每股净资产 / 每股经营现金流 **五个写死的「—」**。 用户分不清是**这只票没有**还是**这个源不提供**(实际是后者:该端点只给四项)。 ⇒ 去掉五个空格子,换成一句说清楚的话。 - 页面说明写「输入一个 6 位股票代码」,而输入框提示写着支持美股 / 港股 / 韩股 —— 两处对齐。 ### 还没做 美股的**总市值**显示「—」:`em_global_quote` 确实不返回市值(不是 bug), 但和上面那五项同一个问题 —— 光一个破折号看不出是"没有"还是"这个源不给"。要接得另找端点。 测试:orchestrator **440**(新增 3 条钉 `noteKV`,均做过变异验证)· Python 555 · shell 77 · doctor 18 ok。 ## 大盘指数换成 A股 + 美股 + 港股(2026-08-27) Simon:「把下面那排去掉,换成美股的道指跟纳斯达克,还有恒生指数、恒生科技」。 第二排原来是 科创50 / 上证50ETF / 沪深300ETF —— 两个 ETF 与第一排的宽基重复, 换成 **道琼斯 · 纳斯达克 · 恒生指数 · 恒生科技**,变成干净的 4(A股)+ 4(海外)两排。 ⚠️ **科创50 也一并去掉了**(它在那一排里)——要留的话说一声,加回来是一行的事。 腾讯 `qt.gtimg.cn` 本来就能取这四个,两处要改: 🔴 **代码大小写敏感**:`usDJI` 有数据,`usdji` 返回 `v_usdji="1";`(20 字节空壳)。 而 `tencent_prefix()` 里有个 `.lower()` —— 转了小写不会报错,那一条**静默地没有了**, 界面上表现为"少一张卡片"。⇒ `us` / `hk` 前缀**原样透传,不转小写**。 🔴 **市场要逐行判,不能沿用端点级的 CN**:不然道指 53463.88 会被标成 `CNY`。 数字对、标签错,而**界面上不显示币种所以看不出来** —— 错的那份会随证据进 AI 上下文。 ⇒ mapper 里按代码前缀给每行自己的 market(市场决定币种,见 `ev()`)。 实测:道指 → US/USD、恒生 → HK/HKD、上证 → CN/CNY。 解析正确性用**自校验**验过(涨跌额 ÷ 昨收 ≈ 涨跌幅),八条全对 —— 腾讯对 A股短式(11 字段)与长式(60+ 字段)的字段位置完全不同,只看数字"像不像"是看不出错位的。 ## 侧栏默认收起 + Agent 按钮改配色(2026-08-27) Simon:「把那些小三角都默认收起来,让大家一打开就是一个一级 Tag 的全览」 「左下角那个 Agent 对话,橙色加白色有点傻,能不能弄成高级点的、灵动一点的」。 **侧栏分组默认收起**。🔴 顺带把存储键升了版(`vr-*-open` → `vr-*-open2`): 默认值从"展开"改成"收起"时,老键里存着的 `open` 会让已经用过的人照旧全展开 —— 那不是 bug(它在记住你的选择),但**新默认就等于没生效**。换个键 = 旧记忆不再适用, 所有人重新从收起开始;之后手动展开的仍然会被记住。 (Simon 当场就撞上了这个:改完他那边"产业信号还是打开的"。) **Agent 按钮**从实心橙 + 纯白字改成**橙作强调、不作底色**: 很淡的橙色渐变底 + 细橙环 + 橙图标 + 常规前景色文字;悬停时有一道掠过的高光(走一次,不常驻), 打开时环变亮、加一层柔光、图标极缓呼吸。右侧「对话 / 收起」小标做成淡色胶囊 —— 原来是压透明度的白字,在浅色主题下几乎看不见。 实测对比度(连底色一起合成后量): 暗色 文字 13.16 / 图标 5.97 / 小标 6.21;亮色 12.3 / 3.59 / 4.69 —— 两套主题全部达标。 ⚠️ 中途量到过"文字对比度 1.11",查下来是**我自己连点主题切换弄出的不一致状态**, 不是真问题 —— 刷新到干净状态复量才是对的。差一点就去修一个自己搅出来的现象。 ## 回测接进界面 · Core 新增「垂类工具」机制(2026-08-27) Simon:「你的回测研究应该是需要加入到一个模块里面吧?就是左侧的,我没有看到呀。」—— 上一轮**只做了能力层**:回测能跑,但只能在命令行跑,侧栏里根本没有入口。这一轮补上产品层。 ### Core:一个通用的「跑垂类工具」机制 🔴 **Core 里不许出现行业词**(棘轮零容忍)⇒ Core 只提供 「起进程、把 stdin 喂进去、把 stdout 当 JSON 读回来」这件事,**不知道这些工具各自是干什么的**。 「回测」这个概念只存在于垂类包里。 - 契约槽位 `Plugin.tools`(可选):`{ label, module, timeoutMs? }`,注册期按安全模块名校验 - `service.runTool()` / `listTools()`;`GET /tools`、`POST /tool/:name` - 复用既有的**异步** spawn(`spawnSync` 会阻塞整个事件循环),给它加了可选的 stdin —— stdin 只在真要喂东西时才开管道,无条件 `pipe` 会让不读 stdin 的脚本在管道满时挂住 🔴 **加一个可选槽位要动四处**:schema properties / 键集白名单 / 注册期 `decl` 投影 / `currentPlugin()` 返回投影。这次前两处改了、后两处漏了 —— **注册通过、437 条测试全绿**, 但 `currentPlugin().tools` 是 `undefined`,界面上表现为「工具清单是空的」,**没有任何一层报错**。 ⇒ ① 键集白名单改为**从 schema 派生**(以前是手抄的第二份,加槽位要同时改两处); ② 新增测试:schema 里声明、垂类也设了的槽位,必须都活到 `currentPlugin()`。 ### 垂类:`backtest.cli`(JSON 进 / JSON 出) 三种结果**分得清**:`{ok:true, result}` / `{ok:false, refused:{reason, remedy}}` / `{ok:false, error}`。🔴 **「被闸口拦住」与「出错了」必须分开** —— 混成一个 error,界面就只能显示「失败了」,而用户真正需要看到的是那句 「为什么不成立、怎么才能跑」。 ⚠️ 引擎会往 stdout 打整份 metrics JSON,CLI 里用 `redirect_stdout` 接住, 不接的话我们这份 JSON 前面会多出一坨,调用方 parse 直接失败。 ### 界面:`/backtest`(侧栏「回测」,在多空辩论之后) 选项(口径 / 策略 / 参数 / 市场规则)**由后端下发,前端不写死一份** —— 写死的那份迟早与真实实现对不上,而对不上的表现是「选了没反应」或 「真实存在的选项不在列表里」,两种都看不出是配置漂移。 - **限制与结果同屏**:回测最容易被误读的不是数字算错,而是读的人不知道它在什么约束下算出来的 - **被拦住 = 结论,不是错误**:橙色说明块,带原因 + 怎么才能跑 + 为什么要拦,不是红色报错 - **对照那一行说清楚是什么**:默认是「等权买入持有这几只标的本身,不是指数」 - **取不到的标的要点名**;数据来源(端点 + 根数 + 起止)随结果一起列 - 「问 AI」把整份结果**连同限制**一起带进上下文 —— 只给数字不给限制,等于替它打包票 - 跑一次几十秒(要先拉几年日线再逐根撮合),按钮旁边**明说**「通常十几到几十秒,别关页面」 实测:茅台 MA20/60 四年 → 总收益 −22.43% / 回撤 −30.64% / 11 笔(对照 −20.63%); 混市场(600519.SH + AAPL)→ 被闸口拦住并说清怎么办。 ## 界面那批的 Codex 审计闭环(2026-08-27) `01ee2e4` 是三个提交里唯一没审过的。七轮审计共 **17 条,逐条核实全部成立、零误报**,已全部修完。 产物在 `.local/reviews/ui-r{1..7}.md`。 ### 🔴 源码里的裸 NUL 字节(我自己发现的,不在审计清单里) heredoc 里写的转义序列被 shell 解释成**真正的 NUL 字节**写进了两个源文件 (`desktop/src/core/ai/pageContext.tsx`、`orchestrator/src/snapshot.ts`)。后果不是编译错: - TypeScript **接受**字符串字面量里的裸 NUL ⇒ `tsc` 0 错 - Core 纯净度棘轮、前端边界棘轮**全绿** - 但 **git 把文件判成二进制**(`Bin 0 -> 3047 bytes`):代码审查看不到内容、合并无法逐行, Codex 读到那里直接截断 —— 上一轮审 `pageContext.tsx` 其实**只审了一半** ⇒ 一个**谁都没报错**的失效。新增棘轮 `orchestrator/test/source_hygiene.test.ts` (裸 NUL / 非法 UTF-8 / **逐个根**断言真的扫到了东西)。 换成转义写法后哈希实测不变,快照缓存不失效。 ### 修掉的 17 条 **AI 对话状态机**:空回答(后端返回空串)被当完整回答落盘并进入下一轮 · `loading` 是陈旧闭包,同一事件里连点两次会留下永远转圈的空气泡 · **会话目录**:读不出来(损坏 / localStorage 不可用)与"真的空"混为一谈, 下一次写入会把目录压成只剩当前这条,**之前那些对话的内容还在但永远找不到入口** · 删内容前没确认目录写成功,失败时内容已没、旧目录还留着条目(点开一片空白)。 **控制台 / 抽屉**:换对话那一帧 msgs 还是上一条的,却仍能发送 / 清空 · 拖拽高度落盘的是上一帧的旧值 · 页面登记了但上下文为空时**发裸问题**, 模型会凭一般知识答一段看着正常的话 · 漏挂 Provider 时两端静默降级, 把"接线故障"伪装成"这页没有内容"。 **存档优先**:刷新锁是布尔且跨 run 共享 —— 切查询时新的那次被旧的在途请求锁死, 要么只显示旧存档且不报错,要么 `loading` **永远是 true**。 **行情信封**:核心字段走 `n0` 兜成 0 ⇒ 缺项显示成「0.00 元 / 0.00 倍」,与真实的 0 分不开。 ⚠️ 这条规则**本来就写在那个文件头**,当时只在新加的两个字段上执行了。 改成 `number | null` 后类型系统逼出 12 处调用点,连 `Holding` 的行情派生四项一并改可空 (取不到行情的持仓原本整行显示「现价 0.00 / 市值 0.00 / 浮盈 0.00」)。 **中文输入法**:Enter 没查 `isComposing` ⇒ 选字期间按回车会把没成词的拼音直接发出去。 **GPU 取数层**:没有统计序列时发 `gpu_available_count = 0`、远期不可用时发 `gpu_forward_rung_count = 0` —— 上游只说了"没取到",没说"真的是 0"。 改用 status 型证据(与管制与准入层同一套写法),前端卡片过滤同步放行, 否则未覆盖的那张卡会**整张消失**(同一个坑的另一面)。 现货证据的资料期改用**曲线末点自己的日期**,不是取数日 —— 上游停更几天后 陈旧读数会看着像当天的,而这个温度计的用处正是判"还热不热"。 ### 两条我自己引入的(第六轮抓出来) ① 提交锁用布尔 ⇒ **旧请求的 `finally` 会释放新请求刚拿到的锁** —— 与我在存档 hook 里刚做对的 `busyRun` 是同一条规矩,在这里没应用。改成锁里存持有者。 ② 目录把空串当"还没建过",且 `filter` 静默丢掉格式异常的条目再写回去 —— 那些条目的入口就永久没了。改成只有 `null` 才是未创建,有一条不认识就整份当损坏。 第七轮:**无新 P1/P2**。 ### ⚠️ 遗留:desktop 零测试 `desktop/` **没有任何测试**,只有 `tsc` 与一条读文件文本的边界棘轮。 而这一批里最危险的逻辑(对话状态机、会话目录)恰恰全在那儿。 试过用 orchestrator 现成的 runner 覆盖,卡在 desktop 用的是**无扩展名 import**(打包器风格), Node 的 ESM 解析器认不了。本轮改用**在跑着的页面里实测**verify(损坏目录场景已验证: 目录原样未动、两条对话内容都还在),但那不是常驻测试。**要不要给 desktop 配测试跑器,等拍板。** ## 回测模块(2026-08-26) 从 [HKUDS/Vibe-Trading](https://github.com/HKUDS/Vibe-Trading)(MIT)移植回测引擎, 覆盖 **A股 / 美股 / 港股的日线**,长线与短线两种口径。归属与改动清单见 `backtest/NOTICE.md`。 **只搬引擎,数据走本产品自己的取数层** —— 上游那 25 个 loader 一个没用: 回测吃的每一根 bar 都带 `raw_ref`,与看板数字同源可复算。搬来 4,896 行(逻辑未改, 仅把两路可选增强的 import 改惰性、删掉 yfinance 兜底),新写 1,010 行,测试 137 条。 **闸口**(`gate.py`)在跑之前判这个回测成不成立:判市场 → 判口径 → 判限制, 只输出能跑的 `Plan` 或说得清的 `Refusal`。**运行期守卫**(`run.py`)补上闸口看不到的两件事: 实际 bar 数不够、策略发出了引擎会静默拒掉的信号 —— 两者都会产出看着完全正常的报告。 移植中挖出并修掉的静默错(共同形状:**不报错,给一个看着正常的结果**): - 传裸六位代码 → 要 `000001.SH`(上证综指)拿到 `sz.000001`(平安银行),回测照常跑完 - pandas 3 保留 `datetime64[s]`/`[us]`,而上游 `_align` 把 `asi8` 当纳秒 → 所有 bar 掉到 1970 年 → **零成交但不抛异常**,产出"总收益 0.00%"的完整报告 - 形状守卫写宽 → `EURUSD` / `BTCUSDT` 被判成 A股(上游认不出时一律回落 `a_share`) - ETF / 指数 / 可转债 → `bs_kline_qfq` 是个股接口,对它们返回空序列而不报错 - Yahoo 只 `dropna(close)` → 留下 `open=NaN` 的行,表现为"少成交一笔"而非数据有问题 - A股做空信号被引擎静默拒掉,报告里无任何字段说明 → 描述的是另一个策略 **Codex 审计 r1–r5 闭环**:13 条,逐条核实 = 11 条成立已修 · 1 条误报 · 1 条观察成立但建议的修法会误杀 (做空检查若按建议改成 `or`,会把"美股 + 调用方没声明做空"拦掉)。 r4 报的 2 条**都是我修前几轮时自己引入的**。每条修复均做变异测试,确认红在对应测试上。 r5 无新 P1/P2。 买入持有的收益经**独立手算逐基点核对**(滑点方向 / 印花税卖出单边 / 佣金最低 / 过户费双边 / 期末平仓成本)。 ## 1.0.0 开发记录 · 全局 AI 入口 + 存档优先 + GPU 图表接齐(2026-08-26) ⚠️ **这批还没过 Codex 审计** —— 界面还在按反馈迭代,说好等定稿再一次性审。别把它当已审过的。 ### 全局 AI 入口(两个,用途不同) - **右上角固定按钮** —— 问**这一页**。对话按页分开存,换页就是另一份记录; 只带这一页当前显示的数据。 - **侧栏「Agent」(高亮橙色) → 底部控制台** —— 一条**长期**对话,翻页不断,聊什么都行; 打开时把主内容区**挤上去**而不是浮在上面(浮层会盖住正在看的表格,而这块面板的用处 恰恰是"一边看着页面一边聊")。左侧一栏聊天记录,自己一条滚动轴,可新建 / 切换 / 删除。 不做写入预设 —— Simon:「客户有各种各样的需求,所以没办法去预测的」。 两个外壳共用一份状态机 `core/ai/useAiChat.ts`,因为这套逻辑里有一半是"看不出来但会出错"的: **没答完的那一轮不落盘、也不进下一轮**(半截回答会被模型当成自己上一轮的完整发言); **换 key / 关面板要中止在跑的请求**(迟到的回答会被写进另一份对话); **session id 带哈希**(`/a/b` 与 `/a-b` 单纯替换非法字符会撞成同一个后端线程,而界面上看不出来)。 🔴 **换 key 之后有一帧 `msgs` 还是上一份的** —— 真踩过:点「新对话」之后,新的那条被写上了 **上一条的标题**。⇒ `AiChat` 暴露 `key`,调用方拿 msgs 做事之前先对一下。 ### 存档优先(`core/data/useArchiveThenRefresh.ts`) 资讯 / 公开新闻 / A股公告 / 事件概率 / 产业信号:**打开先给上次的存档**,同时后台真取一次、 标「刷新中」。🔴 **刷新失败绝不清空已有内容** —— 把一屏存档换成一句"加载失败", 是拿一次网络抖动抹掉用户本来能看的东西,而且他不会知道刚才那些去哪了。 第一次打开没有存档时照实说在取,**不显示"暂无数据"**(那是把"还没取"说成"没有")。 ### GPU 租金图表 按开源版 Vibe Research 的样子接齐:曲线走 500farm 近一年逐日中位,现货卡三张(B200 / H100 SXM / A100 SXM4)。两处真 bug:**时间戳单位差 1000 倍**(秒当成毫秒);`noteKV` 白名单外的键被安静丢掉 ⇒ 现货卡的"可租 X / 共 Y 张"与观测时间**在界面上就是不显示,而代码里明明取了**。 ### 其它 行情信封补 `float_mcap_yi` / `amount_yuan`(**单位写进字段名**,换算只发生在展示层); 侧栏署名改 `https://phoenixtree.ai`。 ## 1.0.0 开发记录 · 让 Codex 看真实页面 + session resolver + 界面查询契约(2026-08-26) Simon:「你先把这个 UI 的页面告诉他地址,让他打开看一下……听听他的建议,然后再综合进行推荐」。 ### 一、Codex 真的点了 8 个页面(不是读代码),抓到一个我没看见的数据 bug 产物 `.local/reviews/ui-r1.md`。它说「净流出最多」下面的数字**全是正的**。查下来是一串套娃: 1. 端点默认只取 50 个,`slice(-5)` 拿到的是"流入最少的五个" —— 仍是流入; 2. 我改成 200,以为够了 —— **上游 total 是 496**; 3. 改成 500 还是只回 200 ⇒ 挖到取数层:**代码请求每页 200,东财实际每页只给 100**, 而循环里写着 `if len(more) < 200: break` —— **第 2 页就断了**。 修完取全 496 个,**净流出的板块有 273 个**,之前一个都看不到。 ⇒ 新教训:**别假设上游认你请求的页大小**。(这是"取前 N 条之前先问源头能给多少"的第三次。) 顺带扫出板块中心那行 `api.fetch` 漏传 `refresh`(嵌套花括号让批量替换没匹配上),该页刷新对它无效。 它另外两条也成立、已列入后续:决策链没连起来(新闻不知道影响哪个主体、信号不知道在验证哪条假设); 核心功能要求用户先完成一套看不见结果的配置(空台账时几页就是空壳,没有示例与引导)。 ### 二、`session.ts`(金融包):这一页该看哪一天 交易日收盘前 → 上一个交易日;收盘后 → 今天;非交易日 → 最近一个交易日。 **前端不许按本地时间猜**(用户机器的时区与时钟都不可信,而且"今天是不是交易日"要查日历)。 ⚠️ 拿不到时段时**保守退回上一个交易日**并说明理由 —— 宁可显示一天前的完整数据, 也不要把半天的盘中数据当成"今天的复盘";后者从数字上看不出是错的。 实测:盘中打开复盘页 → `业务日期 2026-08-25 · 今天还没收盘,显示上一个交易日 · 盘中 true`。 ### 三、界面查询契约(BFF):页面不再认识物理端点名 新增契约槽位 `Plugin.pageQueries` 与 `Plugin.pageContext`,Core 侧执行器 `service.pageQuery`, 路由 `GET /page/:query`。前端只说要哪一屏,端点 id / 参数 / 分页上限全在垂类声明里。 - **今日总览 = 盘中**(指数 · 情绪 · **成交额榜** · 人气 · 资金),**每日复盘 = 已收盘的那一天**。 - 新增端点 `em_turnover_rank`(全市场成交额榜,沪深京 A 股)—— 原来没有,是 Simon 点名要的。 - 返回带**页面级一致性**:`oldest_fetched_at` 与 `mixed_ages`(各块取数时刻跨天时出声)。 只在每块标"X 分钟前"不够 —— 一屏并排的几块可能差好几天,而用户会把它们当成同一时刻的快照。 - 🔴 上下文注入是**按块**的。第一版无差别注入给每一块,结果不接受该参数的端点全被校验拒掉、 一屏五块全 missing —— **错了会响、不会静默**,正是靠这一点当场发现的。 - ⚠️ 板块资金流那个源**只给当日**(没有"指定某一天"),复盘页盘中看到的是今天的进行时。 如实写进该块的说明,不假装整页是同一天。 两处 Core 边界被棘轮当场挡下并已改(注释里写了行业词、Core 里 import 了 `finance/`); `pageContext` 含函数 ⇒ 与 `quoteDecision` 那批一样走手查,不进 ajv。 测试 **392 TS · 417 Python** · Core 行业词 **0**(38/38 文件)。 ### 四、前端 Core / 垂类边界 按 Codex 的建议把 `desktop/src/` 拆成 `core/`(通用外壳与组件)与 `verticals/finance/`(页面、导航、文案)。 新增 `core/lib/ui.ts` 注册点:**Core 的外壳不认识任何一个具体栏目**,只按注册进来的分组渲染; 组装根 `main.tsx` 是唯一把垂类接进 Core 的地方。依赖方向单向:垂类 → Core,永不反向。 顺手落地两条 Simon 提的:**看板改名「投研看板」**;分组从「经营闭环」改成 **盘面 / 研究 / 我的** (对应"看市场 → 做研究 → 落到自己的决策",不是按技术模块摆一排)。 🔴 **新增边界棘轮 `test/ui_boundary.test.ts`,一上来就抓到 6 处** —— 和后端那条棘轮当初一样, 人眼看全都"很正常": - 三处是**注释**里的行业词(改写即可); - 三处是**用户可见文案**躺在通用组件里(对话框提示"写下标的代码"、导入示例"券商 App 的持仓页截图") —— 那不是注释问题,是真耦合:换个行业这句话就得改,而它在通用组件里没人会想起来。 ⇒ 新增 `VerticalUi.copy`,由垂类提供自己的界面文案。 棘轮同时双向查导航与页面表(有导航没页面 = 点了白屏;有页面没导航 = 永远点不到), 两种失效都不报错、没人会发现。变异测试:把垂类 import 塞回 Core,4 条测试立刻红。 测试 **396 TS · 417 Python** · 前端构建通过 · Core 行业词 **0**。 ### 五、三页接上界面查询:端点名从界面消失 `Today` / `Review` / `Sectors` 改用 `PageShell`(取数、资料期、刷新、缺块提示都在外壳里)。 每块的**标题与说明来自后端的垂类声明**,前端不再写死 —— "这一块在回答什么"只有一处真相。 真界面确认: - 卡片右上角原来印着 `em_limit_up_sentiment` / `ths_hot_reason`,现在**没有了**; - 复盘页顶部写明「今天还没收盘,显示上一个交易日」,数据是 **2026-08-25** 的; - 今日总览补上了 **成交额榜**(新端点 `em_turnover_rank`,全市场 5,904 只里的前 20); - 整页一个统一的资料期与刷新,不再每块一个。 顺手改对两处: - 🔴 复盘页的龙虎榜我先前**删错了** —— 我看的是 `em_dragon_tiger`(单只主体,需要 symbol), 而这一页要的是 `em_daily_dragon_tiger`(市场级日榜,`symbol_kind=none`)。转换页面时才发现拿错了端点。 - 缺块**统一在顶部列出并说明原因**,不再让页面少画一块了事 —— 少画一块时用户会以为"这里本来就没有东西",而真相是取数失败,两者处置完全不同。 ⚠️ 还没接的:`Signals` / `Radar` 仍在用 `EndpointPanel`;从 Vibe Research 搬 12 页尚未开始。 ## 1.0.0 开发记录 · 取数快照层 + 一致性契约(2026-08-26) Simon:「每日复盘每次点开都要读取一遍,这个其实是不对的……所有的这些页面,都应该有一个存档的功能, 就是上次打开是什么就是什么。就不能每次都跑,那太浪费 Token 了」。 ### 一、快照层(`src/snapshot.ts`,Core) 取数结果按 `端点+主体+参数` 落盘 `/snapshots/`,默认读上次的、不重取。 **照搬 Vibe Research 原版已经跑通的三层**(内存 TTL → 磁盘快照 → 显式刷新),没自己发明。 前端每块显示「数据取于 X 分钟前(上次的,未重新取)」+ 刷新按钮。 三条纪律:**拿旧数据必须说是旧的** · **失败与空结果不写快照**(否则一次网络抖动被记住且永不自愈)· **参数进键**(同端点不同参数是不同数据)。 ### 二、先跟 Codex 碰架构,碰出四个真问题 Simon:「你先把这个架构跟 Codex 碰一下,然后再开始改造」。产物 `.local/reviews/arch-r1.md`。 它指出我那版设计的四个真缺陷,全部已修: - 🔴 **只有 `refresh: boolean` 不够**。那等于"不刷新就接受任意年代的快照" —— 对界面尚可,对别的调用方全不成立:**MCP 的 schema 里根本没暴露刷新 ⇒ 它永远只能拿旧快照**; **体检的网络探针读快照 ⇒ 把历史上的一次成功报成「当前网络健康」**,一条彻头彻尾的假诊断。 改成显式策略 `cache_only | prefer_cache(max_age) | fresh`;MCP 暴露给调用方且默认 fresh;体检强制 fresh。 - 🔴 **含"按此刻算出来"字段的端点会被永久冻结**。注册表新增 `cache_max_age_sec`, **端点声明的上限调用方放宽不了**(那是数据本身的性质,不是调用方的偏好)。 已标注 20 个:交易日历 `0`(从不缓存)· 报价类 300 秒 · 榜单类 900 秒。 实测:交易日历连打两次都 `cached=false`,公司画像第二次 `cached=true`。 - 🔴 **快照键只排了第一层** ⇒ `{a:{x,y}}` 与 `{a:{y,x}}` 是同一个查询却各存一份、互相看不见。改成递归规范化(数组保序 —— 顺序是语义的一部分)。 - 🔴 **无 single-flight** ⇒ 一屏五个卡片指向同一端点就打五次上游;更糟的是**先发后回**的慢请求会把新结果覆盖成旧的。 另新增端点 `exposure: ui | agent | internal` —— 「管制与准入这类只让 AI 调用、界面不展示」 **光靠前端不渲染守不住**:以后任何一个通用端点列表组件都会把它列出来。 顺带被 TypeScript 抓到一个真 bug:`onClick={reload}` 会把鼠标事件当成 `refresh` 参数传进去(truthy) ⇒ **每次点都变成强制真取数**,正是这次要消灭的行为。 测试 **381 通过** · Core 行业词 **0**(38/38 文件)。 ## 1.0.0 开发记录 · 国产模型真跑:MiMo 兼容矩阵 + 结构化产出降级(2026-08-26) Simon:「国产模型的兼容矩阵你就用 MiMo 的试一下嘛。真实测试一下」。 ### 一、实测结果 新增模板 `providers/mimo.json`(小米 MiMo,`https://token-plan-cn.xiaomimimo.com/v1`,原生 Responses)。 `mimo-v2.5` 跑完 10 项:**pass 7 · partial 1 · error 1 · n/a 1**。 - ①②③④⑤⑥⑨ pass —— 含**并行工具调用**(事件流观察到峰值 2 条同时在途)与 200 行长流。 - ⑦ partial:`mimo-v2.5` 不回传 reasoning。⚠️ 但**换 `mimo-v2.5-pro` 直连实测是有的** ⇒ 这项跟**模型**走不跟 provider 走,不能记成"MiMo 不支持"。 - ⑧ **error** —— 这条是真问题:`text.format type 'json_schema' is not supported, only 'text' and 'json_object' are allowed`。独立 curl 复核过,不是矩阵判错。 ### 二、⑧ 不是"矩阵上少一分",是**整条研究流程跑不了** 产品的每个阶段都硬传 `outputSchema` ⇒ MiMo 会把整轮拒掉。实跑验证: `--stages profile` 直接 failed,事件流里就是那条 `responses_feature_not_supported`。 **修法:模板可以声明 `structured_output: "prompt"`**,产品改为把 schema 写进提示词、不再硬传。 🔴 为什么这不算放松要求:**`outputSchema` 从来就不是校验边界**(`ingest.ts` 的注释早写着这句)。 产物合不合规是产品自己校验的 —— 阶段过 validator、导入草稿过 `parseOutput`。 降级损失的是**命中率**(模型少一层硬约束、可能更容易写歪、重试上升),不是**正确性**; 写歪了照样过不了产品这关。⇒ 所以这条降级**不能**顺手把校验也省掉,那才是真放松。 **改完真跑验证**:`mimo-v2.5` 完整跑通 profile 阶段 —— **validator 通过、79 条证据**, summary 还正确处理了"证监会行业分类与东财行业口径不同"并明确判定**不算冲突**。 ⚠️ 慢:agent 那一轮 4.7 分钟,turn 超时压到 5 分钟会连续两次超时(当时的 20 分钟默认值对 MiMo 够用; 2026-09-05 为 WorkBuddy 正式报告留余量后,产品默认值已调整为 30 分钟)。 ### 三、顺带挖出一个更严重的:对话与导入**根本不认用户配的 provider** 变异测试("把修复改坏,看测试红不红")发现 ingest 那条降级**永远不会触发** —— 往回查根因:`chat.ts` / `ingest.ts` 都是直接 `makeConfig`,而 `provider` 有内置默认(openai)、 `providerProfile` 恒为 `null`。⇒ **用户配了 DeepSeek / MiMo,研究运行认,这两条路不认**, 照样去打 OpenAI;没有 OpenAI 凭据的用户会看到"研究能跑、对话和导入报错",而且报的是别人家的错。 两处都改成走 `loadProductConfig`(和 `run.ts` 同一条路)。写测试时又带出第二层: 调用方给了 `dataRoot`,而 `loadProductConfig` 默认按 `repoRoot` 推数据根 —— **两处对"用户配置在哪"口径不同,用户改了配置却不生效且不报错**。已按 `dataRoot` 显式指路。 ### 四、教训 **只测纯函数测不出接没接上。** `withOutputSchema` 的单测全绿,而"runner / ingest 有没有真去调它" 两处都没被覆盖 —— 变异测试一改就露馅(两次都是"仍绿")。 ⇒ 新增一层能力/开关时,**除了测那个函数,还要测每一个消费点真的问了它**。 ### 五、两条"清单上写着没做"的,实测后都不成立 - **`service.fetchEndpoint` 的 spawnSync 串行化** —— **本次会话早些时候已经修掉了**, 我却照着一条过期记忆向 Simon 报"这条还没修"。实测 5 个真实端点:**同时在途峰值 5**, 并发墙钟 2.14s vs 串行 4.97s。⇒ **报状态前先实测,别念记忆。** - **`fetchrun.ts` 里另一处 spawnSync** —— 看着是同类问题,其实**不能动**: 研究运行靠"每个脚本执行前后各拍一次 raw 目录快照"把 raw 文件归属到脚本, **顺序是承重的**;并发会让两个脚本的 raw 文件张冠李戴,而 `raw_ref` 是整条证据链可复算的根 —— 归错了**不会报错**,只会让"这个数字来自哪次抓取"从此对不上。已把这条写进函数注释, 免得以后(包括我自己)把它"优化"坏。 ### 六、Codex 审计九轮:12 条,逐条核实全部成立,只有 1 条不采纳(附理由) 产物 `.local/reviews/mimo-r{1..9}.md`。⚠️ **其中 5 条是我修上一轮时自己引入的** —— 这一串的价值不在"发现了多少",在"逼出了根因": - 导入降级后**没有按契约校验草稿** ⇒ 我刚写下的"降级不损正确性"在这条路上不成立。 - 补校验时**用了完整契约却忘了 null**:模型对读不到的字段按设计给 null, 最常见的合法草稿会整批被拒(我的夹具里恰好没有 null,所以没红)。改成校验 `dropNulls` 之后的对象。 - 缺必填的草稿放行 ⇒ 落库才报错。改成标 `missing_required` 并**禁用按钮** —— 然后被指出"禁用而无补填入口就是死路",于是复用契约驱动表单做**补填**。 - 补填表单又把 `onClose` 当"存好了"用 ⇒ **点 X 关掉会被记成已写入**。拆出 `onSaved`。 - 初始化依赖用对象身份 ⇒ 别的草稿保存会重置正在填的内容;改成按内容比较后, 又被指出"`editing` 是父组件快照、永远不刷新" ⇒ 改为**从 store 按 id 读当前那条**; 再被指出"重置会丢用户正在打的字" ⇒ 加脏标记 + 外部变更提示,让用户自己决定。 - 会话指纹我**手挑了四个字段**,漏掉 wire_api / env_key / http_headers,**连轮换密钥都不体现** ⇒ 改成对 `codexOptionsFor(cfg)`(真正传给引擎的原物)取哈希。 - 校验器缓存键只有 `id::kind`,换一个同 id 不同契约的插件会命中旧校验器;ingest 与 ledger 两处同改。 - 用户配置与 provider 覆盖模板**从两个根读** ⇒ 新增 `dataRootOverride`,三者同根。 **唯一不采纳**:"store 里同 kind 可能有重复 id"——后端 `loadFile` 逐条查重并直接判文件损坏 (`ledger.ts:297`),**结构上不可能**出现,不为够不到的场景加代码。 测试:orchestrator **368 通过**,Python 413,doctor 18 ok / 0 warn / 0 fail, desktop `tsc` 干净,Core 行业词 **0**(37/37 文件)。每条修复都做过变异测试。 ## 1.0.0 开发记录 · 桌面看板 + 可写台账 + 对话 / 导入(2026-08-26) Simon:「就先按这个来吧,然后你开始生产真正的版本吧」→ 从可点原型转成**接真后端**的桌面前端; 随后「那 5 页都做实吧」「剩下 4 页仍缺可写的用户台账后端,把这些都完成了」。 ### 一、桌面前端(`desktop/`,新目录) - Vite + React + Tailwind,**11 个页面全部接真后端**(不再有假数据页): 今日总览 / 每日复盘 / 板块中心 / 个股数据 / 资讯雷达 / 产业信号 / 数据源 / 组合经营 / 计划与风险 / 资金与风险 / 行动。 - 设计令牌 1:1 取自开源版 Vibe-Research;浅色下重新标定了 `--primary` / `--danger` / `--success` / `--warning` 的明度 —— 🔴 **对比度不足的根因不是令牌太浅,是嵌套着色**: 选中行 `bg-primary/15` 会把页面底色合成进去,量出来的是那层米色不是令牌值。 - **A 股色向**:`--danger` = 涨(红)、`--success` = 跌(绿),与美股相反。 - Bearer token **每个请求重新读盘**注入(API 重启会换 token);`host` 写死 `127.0.0.1` (`localhost` 在本机解析成 `[::1]`,后端绑 IPv4 → 502)。 - 证据数字用 `show()` **只加千分位、绝不改精度**;`compact()` 才做单位换算并总是标出目标单位。 上一版 `show()` 对 ≥1000 取整(9895.96 → 9,896),等于**悄悄改掉证据值**。 - 每页右上角悬浮「问 Agent」按钮与左下角开关是**同一个状态**,不能各说各话。 ### 二、可写用户台账(`orchestrator/src/ledger.ts`,Core;`finance/ledger_kinds.ts`,垂类) - 四种记录(持仓 / 论点 / 判据 / 行动)**由垂类契约声明**,Core 一个行业词都不含; 表单字段由后端 JSON Schema 驱动渲染 —— 垂类改字段,前端自动跟着变。 - 写入:`linkSync` 原子锁 + 唯一 token + inode 比对释放;整条替换而非合并; UUID 主键并在碰撞时重取;**逐条校验**(信封字段 / kind 相符 / id 唯一), 一条坏记录不会把整份文件读成"空"。 - `fileOf` 与 `validatorFor` 统一用 `hasOwnProperty` 判 kind —— 此前一个用白名单、 一个用真值查找,**两道闸门两把尺子**;并显式禁掉 `__proto__` / `constructor` / `prototype` (它们能通过 kind 名的正则)。 - ⚠️ 锁是 TOCTOU 缓解不是消除,已在代码里写明残余风险,不假装它是原子的。 ### 三、对话与导入 - `chat.ts`:只读沙箱 / 不联网 / 不联网搜索,回答过产出红线 gate。 🔴 **开场交代刻意不列举禁用词** —— 实测模型会照抄一句「我不给目标价」,子串匹配命中后 **整行被自己的 gate 删掉**。考虑过给 gate 加"否定豁免",**否决了**:窗口式否定判断会被 双重否定绕过("不要错过建仓机会"),合规判断只允许往严的方向错。改因不改果。 - 提示"这里少了东西"的措辞**不回显命中的词**(先前写成「已移除(建仓)」= 把要挡的词又打了出来)。 - `ingest.ts`:截图 / 文本 → **只产草稿**,逐条确认才落库。扩展名白名单; **PDF / xlsx 明确拒收** —— 没有可靠转写工具时,给出一份看着像模像样、实则乱猜的草稿比不支持更糟。 - 结构化产出的 schema **由契约生成**(平台要求每层 `additionalProperties:false`, 与"字段开放"冲突)→ 全字段必填但可为 null,解析时丢掉 null。 ### 四、后端与取数 - `fetchEndpoint` 改**异步**(spawn + 手写超时 / maxBuffer / 错误,`close` 而非 `exit` 才 resolve): 实测并发在途 5 个。⚠️ 判并发**不能拿"串行耗时之和 vs 并发墙钟"比** —— 子进程在争抢下各自变慢, 这把尺子会得出相反结论;正确判据是**同时在途数 > 1**。 - 改异步时漏了 3 处 `assert.throws(() => fetchEndpoint(...))`(同根因),已用正则系统性找齐。 - `ledgerList` 全量读此前**绕过了 `safePath`**;`/import` 路由的 `b.record ?? b` 改用 `hasOwnProperty`。 - `ths_hot_reason` 的 note 此前会把 Python 的 `None` 拼进字符串 —— **这条 note 也会喂给 agent**。 - 申万行业接口加 3 次重试;错误信息**先提本机代理**(见下)。 - doctor 新增 `net_proxy` 检查项(状态 `ok` 不是 `warn`):本机全部域名解析到 `198.18.x.x` fake-IP、走 `127.0.0.1:7897`。🔴 这条我诊断错过两次(先判"证书问题"、再判"偶发,重试能好"), 第三次才对 —— **重试打的是同一台服务器**。这是本机环境不是产品缺陷,如实写在体检里。 ### 五、国产模型接入:不是"没开工",是**坏在很深的地方** - 🔴 引擎(`codex-rs/model-provider-info`)对 `wire_api = "chat"` **硬报错**,而四个国产模板 全是 `chat`,`codexProviderConfig` 原样传下去 ⇒ 配置能存下、能加载、能启动, **跑到引擎深处才炸**,报错还出现在一个跟 provider 配置八竿子打不着的地方。 - `validateProfile` 现在**在选用时**就拒 `chat`,并把两条出路写进报错(换 Responses 端点 / 架 Responses→Chat 网关)。枚举里保留 `"chat"` 只为**读得懂旧档并给出解释**,不是放行。 - 四个模板按 2026-08-26 实查重写,全部 `responses`:DeepSeek 走官方 `https://api.deepseek.com` (`deepseek-v4-flash`);Qwen / Kimi / GLM 走**阿里云百炼** compatible-mode (智谱官方开放平台当日没有原生 `/responses`;月之暗面官方是否提供**未核实** —— 未核实的不写成事实)。 - 百炼三件套的 `base_url` 带 `{WorkspaceId}`,**选用时当场拒**并告诉用户复制到 `.local/providers/.json` 填好再用 —— 而不是把密钥发到一个不存在的主机上。 - ⚠️ 「`responses_support=native` 要求 `wire_api=responses`」这条校验**现在够不到** (chat 在它之前就被拒),代码与测试里都如实标注,没有写个假断言把它凑绿。 - README / README_en / providers/README / model-access / release-checklist 里的旧事实 (`deepseek-chat`、`MOONSHOT_API_KEY`、`open.bigmodel.cn`、`src/provider_matrix.ts` 旧路径)已一并订正。 ### 六、Codex 审计五轮闭环(2026-08-26) 按项目铁律"每个环节建完都要过 Codex 审计闭环"补审本次的新后端。 产物 `.local/reviews/desk-r{1..5}.md`。**共 12 条,逐条核实全部成立、零误报**; r5 判"没有新问题"。⭐ 每条修复都做了**变异测试**(把修复改坏,确认对应测试真的变红)。 **r1(台账 / 契约 / 路由)** 1 P1 + 2 P2: - 读取路径**不按契约复核** —— 台账 JSON 用户能直接编辑,写入侧的字段校验绕得过去, 然后以 200 成功返回给界面和下游。修法是**报出来但不删不改**(`listRecordsChecked` + `/ledger` 的 `issues` 字段 + 界面提示):若在这里抛错,垂类日后加一个必填字段就会让用户的台账**整份打不开**, 比原来的 bug 更糟。 - 日期只查外形 ⇒ `2026-02-31` / `2026-99-99` 能存进"到期清单",**排序永远不对、提醒永远不触发, 保存却一路报成功**。新增 Core 的 `formats.ts`(自己实现日历日,不装 `ajv-formats`)。 - 锁的 TOCTOU:数学上消不掉(见 `withLock` 注释),但**最坏后果**可以消 —— 写完**回读复核**, 丢了就报 `write_lost`,不返回一个假的成功。 **r2(对话 / 导入 / 取数)** 2 P1 + 3 P2: - 对话会话只按**客户端给的会话名**索引,而线程绑定着某个数据根的工作目录 ⇒ 另一个数据根用 `default` 会接上别人的线程、在别人的目录里读文件。键改成"真实数据根 + 会话名"。 - `parseOutput` 的注释写着"不许尽力还原",代码却把 `source_file` 缺失补成 `""`、`fields` 非对象补成 `{}`、 `uncertain` 非数组补成 `[]` —— **声称与代码不符**,而且补掉的恰好是"模型说自己没看清哪几处"。改严格。 - base64 **解码之后**才查大小(解码本身就要扫一遍、分配内存)→ 改成先按编码长度卡。 - 失败路径不清暂存目录 —— 里面是用户的**私密截图**,而调用方拿不到 batch 路径、根本不知道要去清。 - 类型只认扩展名 ⇒ PDF 改名叫 `.txt` 就绕开了"不收 PDF";任意二进制叫 `.png` 就进了图片解码器。 加**内容嗅探**(图片查魔数、文本查 UTF-8 与 NUL);诚实边界:挡"改名混进来",挡不了"格式合法但内部畸形"。 **r3(复审 + 前后端接缝)** 2 P1 + 4 P2: - `loadFile` 把"JSON 损坏"当成"文件不存在" ⇒ 读接口返回空列表(伪装成"你本来就没记过东西"), **下一次新增会把只含新记录的文件盖上去,原台账永久没了** —— 而回读复核还会确认新记录在、一路报成功。 这与同一函数里"已保留原文件,请人工处理"那句直接矛盾:那条路根本走不到。 - 🔴 **同一根因漏改**:`format` 只补了 ledger 一处,兄弟编译点 `stageSchemas` 与运行期全局 ajv 都漏了 ⇒ 阶段产物里写 `format: "date"` 等于没写。**上一轮刚犯过一次同类,这轮又犯。** - 回读只比 `id + updated_at`:并发覆盖会保留同一 id,同毫秒里时间戳还一样 ⇒ 改成比**整条内容**。 - `/ledger` 分两次读盘 ⇒ records 与 issues 来自不同快照,界面会显示"这几条都合规"而展示的正是坏的那几条。 - 请求体上限按 UTF-16 码元数算:一个中文 3 字节只算 1,256KB 的上限实际能塞进约 768KB。改按字节。 - 运行产物 `viewer.html` 以 `text/html` 在**已认证的源**上渲染且无 CSP。加 `default-src 'none'; …; sandbox`。 **r4(收口)** 1 P2 —— **指着我自己的修复**:超限后 `req.pause()` 不收连接会把它挂住, 而且注释写着 413、代码走的是统一 400(**自己的测试只断言了 error 码、没断言状态码,所以放过去了**)。 最终改法是**边读边丢**:`destroy` 会让客户端拿到 EPIPE 看不到错误、`pause` 会挂住连接、 "响应 flush 后再 destroy socket"照样 EPIPE(客户端还在写)—— 只有边读边丢能同时做到内存有界、 客户端写得完、写完能读到 413。测试补上状态码与 `Connection: close` 断言。 **r5** 判"没有"。⚠️ 但它打印的代码里留着一句我没删干净的注释(还写着 `pause`),已自行删掉 —— **审计者说没问题 ≠ 每个字都对**。 ### 测试 新增 `ledger.test.ts` 12 · `chat.test.ts` 6 · `ingest.test.ts` 9 · providers 占位符与 chat 拒绝各 1; 审计各轮又补 20 条(台账 8 / 导入 4 / 对话 1 / 契约 1 / 服务与 API 3 / 其它 3), 每条都做过变异测试。合计:orchestrator **357 通过**,Python **413 通过**,desktop `tsc` 干净, doctor **18 ok / 0 warn / 0 fail**,Core 行业词仍为 **0**(37/37 文件干净)。 ## 1.0.0 开发记录 · 全面审计的 29 条全部修完(2026-08-25) Simon:「之前都是小模块的审计,现在进行一个全面的审计」→ 四轮 Codex(每轮一个**跨模块视角**, 让它自己读代码)找出 29 条 → Simon:「全部修复」。汇总见 `全面审计_2026-08-25.md`, 原始产物 `.local/reviews/full-audit-{1..4}-*.md`。 ### 一、产出红线可以绕过(发布阻断) - **gate 只有 26 个中文子串**,「值得买入」「跌破 50 元离场」「BUY, target price」一条都拦不住。 新增 12 条**正则规则**(中文语义组合 + 英文)。 ⭐ **在 431 个真实产物上量过误报,零命中才收进来** —— 量的时候刷掉 4 条候选,其中一条会拒掉 **正确的免责声明**「不是目标价或合理价」。还有一条「给予 X 买入评级」刻意不收:它命中的是 **被引用的事实**(机构评级分布本来就是合法证据)。 - **阶段产物的自由文本根本不过 gate**(只查 report),而 viewer / 附录会把整个 record 抄给调用方。 改为**按值递归**过 gate(刻意不枚举字段名——那会把金融字段写进 Core,而且新增字段必漏), 用**收窄后的词表**(去掉 8 个"会出现在提及语境"的词):320 个真实阶段产物零误报。 - **附录与查看器在最终 gate 之后生成、从不复检,却经 API / MCP 回传** —— 而且它们自己写着 「不含任何判断与建议」。**声称与代码不符**:两处措辞已改成代码真做得到的,并加上生成后复验。 - **events 泄露用户名 / 内网地址 / `user:pass@`**;**取数错误信封泄露 `VRA_SEC_CONTACT` 里的姓名邮箱** 与第三方 traceback 里的 token。两侧都加了环境类脱敏(纵深防御,不承诺"绝不回显")。 ### 二、静默失效("没跑"和"跑了没拦到"在产出上一样) - **钩子 enabled + installed 却零调用 / 全报错,运行照样 complete** —— 我真跑分离安装时踩到的正是 它的变体(5 次调用 5 次 error,只有 manifest 里一个计数写着 5)。现在这两种情况一律**降为 incomplete** 并出事件。⚠️ 判 incomplete 不判 failed:研究结果本身可能是好的,只是少了一层保证。 - **必需 calc 返回 `error` 也算"已完成"** ⇒「必须计算」退化成「存在一条同名调用记录」。 ⚠️ `not_meaningful` 仍算完成 —— 那是**确定的结论**不是失败。 - **必需端点 `partial` 只是 warning** → 现在要求写进缺口。⚠️ 收窄为"端点**自己声明了丢了什么**"才要求: 实测 25 个真实 partial 里 24 个带 `degraded`,唯一不带的是行情陈旧(已由 quote_decision 单独披露)。 - **角色级 gap 带后缀(`quarterize:revenue_cum`)被语义槽位接受,状态推导却只认裸函数名**。 - **注册表里阶段名拼错 → 端点永远不执行、零告警**,现在注册期当场拒绝。 ### 三、同一概念的两份实现 - `criticalAllFailed` 绑死金融阶段名 `"estimates"` → 改成看**关键脚本本身在不在本次作用域**。 - manifest 的 `market` 枚举写死沪深四项,而证据 / 取数用插件枚举 ⇒ 跑 US/HK 时**全阶段完成、收尾判 failed**。 - `referencedIds` 没有 token 边界(`citedIds` 一直有)⇒ `ev-abcdef123456xyz` 能冒充合法引用。 - 证据合并同 id 只比 `value` ⇒ 口径不同(单位 / 复权)的两条**静默折叠**。改为比事实键。 - `dataRoot="/"` 时钩子边界拼成 `"//"`,执行层全程 fail-open。 ### 四、垂类边界:从"第二个垂类做不出来"到有验收装置 r4 的结论是**新增一个垂类包跑不起来**,至少 10 组 P1。全部处理: - **9 个入口无条件注册金融** → 库模块(service / viewer / knowledge / fixture)的自注册全部去掉, 只留 6 个真入口(composition root),并加**守卫测试**防止长回来。 顺带发现 `thermo_history` / `hardtest` / `provider_matrix` 三个**包内模块也在自注册**, 形成 `finance/plugin → stages → thermo_history → register` 的循环依赖。 - **Core 主循环直接 import 金融模块** → 新增 `beforeFetch` / `afterFetch` / `transformFetch` / `afterRun` / `doctorChecks` 五个钩子,产业门控、卡口扫描、温度计历史、体检项全部搬进包里。 - **按字面量阶段名分支** → 新增 `reportStage` / `topicsSourceStage` / `stageSchemas` / `stageValidators` 四个插槽;`schemas.ts` 里整段金融字段(报价判定 / 不可替代性标签 / 反证 / 裁决点)与 `validator.ts` 里两段阶段专属校验全部移入 `finance/`。 - **`regionOf` 的市场映射** → `marketRegion` 插槽。alerts / service 的市场校验改用契约枚举。 ⭐ **给棘轮补上它此前看不见的那一类**:英文阶段名、市场代码、结构性 import。 旧棘轮只扫中文词表,所以「行业词 0」给的是**错误的安心感** —— 新棘轮一上来就抓到 **32 处**。 ⚠️ 判定只看**代码不看注释**(注释里写"这里原本是 `stage === \"profile\"`"是有价值的历史说明), 且只算**当阶段用**的字面量 —— 实测有四处纯误报(HTTP 路由段、体检项 id、HTML tab 名), 把它们也算进去只会逼人改无关代码,**棘轮误报会让人开始无视它**。 ⭐⭐ **新增第二个垂类的验收装置** `test/second_vertical.test.ts`:一个完全不含金融概念的 最小餐饮包(`intake → menu → competition → report`,市场 `SG`),**不改任何 Core 代码**就能注册、 拿到自己的 schema、按自己的口径解析作用域。它一上来就打红三处契约缺陷: `extraTopics` 强制每阶段非空、`alertFields` 强制非空、`selfTestCalc` 强制存在 —— **金融包恰好都满足,所以这些约束一直没暴露**。 (`extraTopics` 放宽的前提是把"没有议题"表达成 `maxItems: 0` 而不是留一个空 enum —— 后者的报错说"topic 不在允许值里",看不出根因。) ### 验证 每条修复都做**变异测试**。过程中抓到自己的三个问题: ① 测试直接调内部函数、绕过真实路径(把调用点删掉测试照样绿)→ 改为走 `validateStage`; ② 两处**不可达的冗余检查**(validateStage 一报错,后面的状态降级永远走不到)→ 删掉, 不留"永远不会红的校验";③ 变异脚本备份晚了一步把调用行弄丢,全量测试当场打红。 ### 修复复审四轮(r1 3P1+3P2 / r2 1P1+3P2 / r3 1P1+2P2 / r4 1P1+1P2) 🔴 **好几条是我修上一轮时自己引入的**,最典型的两组: - **viewer 净化改了四版**:①按行删除 → 把整个 `