ThearchyHelios
8ede152b6f
可验证报告:口径卡取的列是 SQL 里改了名字的遮罩列时,整张卡同样只给哈希
...
口径卡上记着每个输入的值和代入式,有输入取自遮罩列的整张卡只给哈希;但以前只按列名认:查询写 phone AS tel、经子查询
或 WITH 转一道、套个函数,卡上取 tel 那一格就是号码,卡照样原样嵌进要发给别人的文件。现在那几列算不算遮罩列另按 SQL
认改了名字的(_Store.hidden → _derived_columns,用 inquiry._derived_hidden,和质询、双盲复算同一个认法;SQL 按每种
读得通的读法各认一遍合起来,都读不通的写着遮罩列就整份的列都算,出错时整份的列都算)。同一条查询里没取自遮罩列的
列照常嵌入。新测试覆盖别名、子查询、WITH 加函数三种改名,以及没改名的列、认的过程出错;每处都做过去掉实现测试变红的
验证。
2026-10-06 17:11:41 +08:00
ThearchyHelios
02883dea7b
可验证报告:查询快照只给哈希时照实说明原因,样本页和浏览器检查补「遮罩源上的汇总查询可核对」
...
核对页对只给哈希的查询快照原来写「含遮罩列,未随文件附带」。现在没碰遮罩列的快照照常附带,只给哈希的是这条查询
用到或可能用到设了遮罩的列(条件里写到的、解析不了的也算),原文改成「这条查询用到或可能用到设了遮罩的列,快照未随
文件附带,只能核对到哈希」;口径卡的说法不变。核对逻辑不变,只是按工件种类挑说法(verifier.js 的 maskedQuery);
内联脚本的 CSP 哈希由 render_html 按脚本现算,不用另改。顺手改正 verifier.js 开头一句过时的注释:口径卡现在会因遮罩
只给哈希,导出时不会出现的是报告文档标着遮罩。
tests/bundle_samples.py 加样本页 masked-source:会员库设了号码遮罩(查询当时记下了、数据源现在也设着),报告引用会员
按地区汇总的查询和选出了号码的那份。check-bundle 断网打开它:汇总快照在 ③ 通过、引用它的两个数字在 ⑤ 通过、点开看得
到汇总的 SQL 和被引用的那一行;选出了号码的快照和引用它的数字无法核对并写明原因;总览「可核对的项全部通过」,页面里
找不到号码。另在这一页上篡改:汇总快照改一个字节 ③ 变红,改它的数字的引用值并重算全部哈希 ⑤ 变红。base 页上的原因
文案跟着改。test_bundle_build 守住样本页的形状。
2026-10-06 17:11:41 +08:00
ThearchyHelios
faf21894a3
可验证报告:数据源设了遮罩时,能证明没碰遮罩列的查询快照照常随文件附带
...
以前只要查询当时记下了数据源的遮罩列,或者数据源现在设了遮罩,整份快照就只给哈希——哪怕这条查询只按地区汇总了
金额。数据源里只要有一列设了遮罩(客户手机号),报告里引用查询格子的数字就全成了「无法核对」,对外几乎没法核。
现在 build._untouched 全部满足才嵌入,任何一条不满足、判断过程出错都照旧只给哈希:
- 认得这份快照:数据源查询工具落的那种、哈希对得上;不是合并查询;没有不认识的键(以后核查 agent 在查询时就遮过、
另记下遮了哪些列的快照,照现有规则只给哈希);
- 结果的列名对不上遮罩列;
- SQL 原文里没写到遮罩列,条件里、COUNT 里也不行:SQL 随快照一起附带,WHERE phone = '…' 的字面量就是遮罩值;
MySQL 会执行的注释、Postgres 的 Unicode 转义名字这类语法树认不准的写法也不行;
- SQL 解析得了(不知道是哪种库,按每种支持的库的读法各解析一遍,读得通的每一种都要过关),没有认不出结果里哪一列
取自哪一列的写法:列名表、整行引用、可能展开出遮罩列的 *(展开了数据源里的表,又不在只按名字往外传的派生来源、
EXISTS / IN 子查询里);按 SQL 认遮罩列的那一套(inquiry._derived_hidden,双盲复算、质询同一个)也认不出哪个
结果列取自遮罩列。
查询事件(tool.end)的规范字符串跟着快照走:快照随文件附带的,事件也带内容。新测试覆盖按地区汇总(查询时记下的、
数据源现在设的遮罩各一种)、WITH / 子查询 / LATERAL / EXISTS 里的 *、反引号,以及选出遮罩列、别名、子查询、CTE、
SELECT *、函数包着、只在条件里、整行引用、列名表、解析不了、改过的、不认识的键、合并查询、判断出错;每一条规则都做过
去掉实现测试变红的验证。
2026-10-06 17:04:45 +08:00
ThearchyHelios
3f17fd3c71
合入期 5 前置修复 K4:运行把这一段执行的截止时刻交给节点(engine/deadline.py),反方审稿与双盲复算开始每一项前看剩余时间,按剩余时间收紧每项时长、给下游留出余量,来不及的记为未能反查 / 无法复算并写明「运行时限将至」,整次运行不再被时长上限中止;继续运行取 checkpoint 里的结果不重复反查
2026-10-06 16:26:45 +08:00
ThearchyHelios
4314a7fc44
合入期 5 前置修复 K2:核查与裁判模型的输出额度提到 16384,服务方嫌大时退回 4096(和助手共用 providers/budget.py);每次调用认截断,因推理占满额度没交出结果时照实说(verify_truncated、judge_truncated),不再说成盲算没查到、没按结构交结果
2026-10-06 16:26:37 +08:00
ThearchyHelios
54ab06d615
合入期 5 前置修复 K5:写作模型把整篇报告包在 markdown 代码块里时去掉外层围栏(重写的几轮同样处理),结论句照常可审、裁判和反方审稿有句子可看;别的语言的代码块、围栏外有文字、多个代码块、开闭不配对的原样不动
2026-10-06 16:26:37 +08:00
ThearchyHelios
0a875fd3af
合入期 4 整合 J4:质询回答工件在记录页有名字和说明;问答串在审批列表取失败时不再漏条目;运行对比的默认基准与定时任务自动对比用同一条规则(同一任务、同一工作流、比这次先发起的上一次成功并封存的运行),触发历史在基准不是紧挨着的上一次时写明「与上一次成功的运行对比」
2026-10-06 16:23:40 +08:00
ThearchyHelios
ed888d59df
合入期 4 整合 J3:出具横幅按「核查未通过 / 核查未完成 / 校验未全部完成」分组;审批卡把运行类别交给反方审稿概况;证据接口的核查类型契约挪进 types.ts;反方审稿加单句模式、证据面板不再谈出具;证据接口带上句子的反方判断映射,正文给被审过的句子挂句末标记;质询图标平时对比度达标
2026-10-06 16:23:33 +08:00
ThearchyHelios
39068c9636
合入期 4 整合 J2:审批质询遮罩收口——阈值只在同一个数在别处确实被换掉时才遮、夹住某一个值的边界按条件与作用域认、质询工件里未遮罩文字格夹着的遮罩值按值换掉;算式边界、分档标签列、CAST 类型参数等变体照实处理,已知局限写进模块说明
2026-10-06 16:23:26 +08:00
ThearchyHelios
2da4d34fec
合入期 4 整合 J1:双盲复算写业务日期加类型门槛(两边的时间列都在表结构里声明为日期 / 时间类型才写,原因说清是哪一列);跟上 SQL 差异说明收尾的测试与预览夹具(time_range 改为兜底变体,新增 time_column);按位置取自另一份快照遮罩列的输入判为无法复算;可验证报告里被改过、解析不出的口径卡按内容认遮罩
2026-10-06 16:23:26 +08:00
ThearchyHelios
76b485a0ca
审批质询遮罩收口(第 3 轮复核):标签列按作用域认取自哪个来源,UNION 另一支、子查询里的遮罩列流进标签列照收;取模、整除、整数相除按算出来的值认;CAST 的类型参数不当边界换
...
复核留下的一条 major(第 2 轮只修了一部分)和两条次要问题:
- 分档标签列:以前按名字认,从「所有名字都只装着标签」起往下剔。遮罩列原样选出(SELECT vip_level)时名字就是它自己,
永远剔不掉;结果的 UNION 按位置那一遍只往里加标签,另一支取的是遮罩列也不剔;派生来源里的 UNION 根本不按位置看。
于是标签在前、遮罩列在后(不起别名、别名不同、外层再套子查询、CTE 里的标签再 UNION),遮罩列经按原名选出的子查询、
以标签的别名传出,或者两个子查询 JOIN 起来同名,等级 1 撞上 THEN 1 都不收,WHERE vip_level = 1 在查询清单、事件、
质询工件里照原样封存(对基线是回退)。现在 _label_columns 按作用域认每一项取自哪个来源:结果的这一列在 UNION 的
每一支里都要是结果全为写死常量的 CASE / IIF,或者取自子查询、CTE、LATERAL 里只装着标签的一列(派生来源里的 UNION
也按位置看每一支,写了列名表的按列名表);取自数据源里的表的一律不算,哪怕和标签同名。没写表名的列,派生来源出
这一列的就是它(SQL 执行过,别的来源就没有同名的列,不然报列名有歧义),按这一列 USING、NATURAL 合成的除外;递归的
CTE、UNION 里落在某一支 * 里的列认不准,照收(多遮)
- 取模、整除:_arithmetic、_worked_out 补上 %、MOD、DIV、//(往零取整,同 SQL)。顺带 / 照数据源的算法算:SQLite、
Postgres 里两个写成整数的数相除只留整数部分(sqlglot 记在 typed 上),以前一律按小数算,age >= 25 AND age < 53 / 2
在 SQLite 里夹住了 25 却认不出;写成小数的(53.0 / 2)、MySQL、DuckDB 照小数算
- CAST 的类型参数(第 2 轮引入,只多遮):_halves 只收往上走得到这一边的字面量(_lifts),CAST(30000 AS DECIMAL(10, 2))
的 10、2 不再当成算出边界的数换掉,SQL 检查结果的片段里别处的 10、2 也不跟着换;_wraps 里 CAST 只算被转换的那个值,
Oracle 的 CAST … DEFAULT 0 ON CONVERSION ERROR 里的 0 照原样
- 模块说明的已知局限照实更新:标签列认得出、认不准的几种写法;认得出的算式补上取模、整除和整数相除,认不出的补上
位运算、POWER、CAST 改了值的
测试:单元补标签在前、遮罩列在后的八种写法(不起别名、别名不同、子查询里的 UNION、写了列名表的 CTE、CTE 里的标签再
UNION、经按原名选出的子查询传出、两个子查询 JOIN 同名、RIGHT JOIN USING 同名列),按作用域仍认得出的五种标签(外层连上
数据源里的表不写表名、按别的列 USING、两层子查询写了表名、UNION 两支、派生来源的 UNION 经 * 带出);取模、整除、整数
相除的六种写法和照小数算的三种;CAST 的类型参数和 DEFAULT。端到端补 UNION 标签在前的两种写法、取模和整数相除算出来的
边界。每处实现都逐个去掉验证过测试变红(十一个变异全红)
2026-10-06 16:01:28 +08:00
ThearchyHelios
5d4d1fdc15
审批质询遮罩收口(第 2 轮复核):算式边界、套了 CAST / 汇总的列、换个写法的数、两头不是整数、范围再排除一头都认得出;只装着标签的列才不收标签;截断片段整段去掉
...
复核留下的三条 major 和两条次要问题:
- 范围的一头是算式(age <= 25 + 0、buyer_phone BETWEEN 13900000000 + 1 AND 13900000009 - 8):夹住的值认得出,算式里的数
却照原样留着,一算就是那个号码。现在几个写死的数的加减乘除按算出来的那一个值认(_lifts):夹住某一个值的边界、等值、
IN 里的算式,里面的数都换;选出列里算出来的号码按值换;没夹住的算式阈值和写成一个数的阈值一样照原样,正文里复述它
(连同算出来的值)不遮,算出来的值在别处换掉了也不留。原有两条用例(BETWEEN 13900000001 AND 13900000002 - 1、
… AND 13900000001 + 0)的期望随之改成算式里的数都换(多换一个 1、0,号码照样不露)
- 几种找值写法以前认不出:被比较的一边套了 CAST、汇总(CAST(age AS INTEGER) = 25、HAVING MAX(age) BETWEEN 25 AND 25)
改按它的值取自哪些列认(_columns_of);同一个数换个写法(25.0、025、2.5e1、013900000001)按规范写法和遮罩值比
(_canonical);两头不是整数的范围(age > 24.5 AND age < 25.5、BETWEEN 25 AND 25.9)在整数上隔开紧挨着的两个整数;
范围再用不等、NOT IN 去掉一头(buyer_phone >= 13900000001 AND buyer_phone <= 13900000002 AND buyer_phone <> 13900000002,
以前号码被当成阈值、回答正文跟着不遮):等值一类只在同一个条件里和范围合起来看,整数上紧挨着的被排除的数越过去接着
看(age <= 30 时 27 照样成立,不算夹住),跨条件配对仍只看范围比较,不等、IN 单拿出来不当「写出了这个值」
- 算式求值改成不递归(_constants):visits <= 1+1+…写到 1500 项时以前超过递归深度,整条 SQL 退回按词认,同一句里夹住的
年龄照原样封存
- 分档标签不收进遮罩值的规则太宽(第 1 轮引入):改了名字的遮罩列(vip_level AS 等级)的 1、2、3 撞上同一条 SQL 里按
条件数个数的 THEN 1 ELSE 0,1 就不算遮罩值,WHERE vip_level = 1 照原样封存。现在只跳过只装着标签的列的格子
(_label_columns:选出项本身是结果全为常量的 CASE / IIF,或者经别名、子查询、CTE 原样传下去的,没起别名的按位置认;
同一个名字在哪一处装着别的就照收)
- SQL 检查结果的说明:码值表里的码值和别的字一样按值换,说明照实写(多遮,不漏),补测试钉住
- 截断的片段停在带空格的遮罩文字值中间(地址):以前只去掉最后一段,前半截还留着;现在从没闭合的引号、注释起整个去掉
- 模块说明的已知局限照实更新:两个产品取舍保持;夹住的认法补上不等、NOT IN、两头不是整数和越过排除数的规则;新增一条
列出认得出的找值写法和仍认不出的(值藏进和列一起算的算式、拼接、函数拼出来的值)
测试:单元补算式边界、套了 CAST / 汇总、换个写法、两头不是整数、排除一头、不该夹住的几种(范围加不等仍不只一个值、
IN 列表旁的阈值、选出列里的等值和 WHERE 的范围)、上千项连加、改了名字的遮罩列撞上标签、标签列经子查询 / CTE / 没起
别名、截断片段、码值表;端到端补长号码的五种写法(算出来的边界、算出来的等值、两头不是整数、范围再排除一头、补零)、
年龄的六种写法和改了名字的等级列。每处实现都逐个去掉验证过测试变红
2026-10-06 15:08:56 +08:00
ThearchyHelios
6a54ab06c2
J3 复核修正(第 1 轮):过期的证据图重取一次,只有反方标记的句子在面板里先写判断,没反查成的不说成反方模型的判断
...
证据图缓存会过期:正文有运行就取证据图,之后一直用缓存。审批卡里展开过报告的话,缓存的是运行停在审批上那一刻的图:报告
改写后(第二次审批、同一张卡换稿)新稿在那份图里找不到,一个标记都挂不上;审批之后才审完的反方审稿,成果区也看不到;证据页
挂上时只管「运行已结束、图没封存」,停在第二次审批上的运行、别处正在取的那份都不管,画的是旧稿、审计表却是新取的。改成:
- EvidenceDoc(useRunGraph)挂上、换稿那一刻手里已有的那份,找不到正文这一稿,或者正文是运行的成果(EvidenceField 给
settled)而那份没封存,就按(运行、报告、工件)重取一次;重取回来还是这样就作罢,挂上时还没有、正在取的那份不算过期;
- 证据页挂上时手里那份不是「封存了、封存的就是这一版(manifest_seq)」就重取,不看运行停在哪;别处正在取的取回来再看一眼;
重取回来之前占位,第一次渲染就按挂上那一刻手里的那份定,不先画一帧旧稿。
整句面板的反方审稿:只有反方标记的句子(没有可点片段、也没有裁判判定)只能从标记点进来,面板却只认片段接口的
unit.challenge,还在取时这一节空着,答 500 时整节消失、也不说为什么。EvidencePanel 收下正文的标记(marks),片段接口还没答、
答不了、答了却没有可用内容时先按标记写出判断(ChallengeSummary 导出的 ClaimVerdictPending),说正在获取、未能获取(带重试,
重试后焦点落到「反方的理由与查询」或新的「重试」上)、无法查看;拿到 unit.challenge 换成完整的单句展示。
没反查成的句子:单句展示里一定没反查成的那一句不再写「判断由反方模型给出」(那是服务端按规则记的无法判断,反方模型没看过);
无法判断的句末标记悬停说明、先行版的落款写「可能是反方模型的判断,也可能是未能反查时记下的」,说不准的仍写判断出自反方模型。
其余几处:
- 挂上时一个键盘目标都没有、反方标记随证据图后来才到:Tab 位交给第一枚标记(以前三枚都是 tabindex=-1,Tab 跳过整份报告);
- 只有反方标记的句子,读屏不再把「反方审稿」念两遍;
- 带字的醒目标记悬停、展开时不铺浅底(10px 的失败色、提醒色字叠在 14% 的浅底上,浅色主题只有 4.0 左右),改描 1px 内边,
和裁判徽标并在一起的同样;无法判断换成省略号盾牌,不再和裁判的「?」、质询的问号挤成三个问号,也和经受住的勾分得开。
检查:check-evidence 新增 mark-panel(片段接口压着、答 500、重试,390px 不溢出)、mark-tab(标记晚到进 Tab 顺序)、stale(审批卡
换稿、同一张卡换稿、成果区、证据页停在审批上和别处正在取,各重取一次、对上了不再取、旧稿一帧都不画)三节,marks 一节补读屏原文
逐字比、展开和悬停时的对比度、图标形状、无法判断的说法,verify 一节改等单句展示(原来等的选择器单句模式里没有,每遍白等 4 秒);
新预览用例 evidence-marks-text、evidence-marks-stale(dev/fixtures/evidence_marks.tsx)。check-challenge 新增 challenge-claim-quiet:
单句、不谈出具,给齐正式运行、运行 id、degrades 也不写降档、不取运行类别(以前这个开关在哪个用例里都观察不到)。
2026-10-06 14:36:21 +08:00
ThearchyHelios
53f06855dc
运行时限测试的两处说明对上代码:下游余量那条写剩 239 秒时不再开始(代码查的就是 239),慢写报告那条写明写报告的执行器换成了要 3 秒的替身
2026-10-06 14:32:30 +08:00
ThearchyHelios
48f656f362
证据裁判截断的回复整批不采信,截断另记 judge_truncated,时间线的下一步指到换模型
...
复核第 1 轮的发现:
- 有的网关把截断的强制工具调用解析成半截清单:第一条判定写完、第二条只写了编号。_ask 拿到清单就交出去,不再看截断,于是记成一句支持、一句格式不对、两句未给出判定,llm.end 也不标截断。现在回复被截断就整批记 truncated(最后一条可能只写了一半,也可能判定写完、理由写到一半,分不清哪条完整),纯文本调用同理
- 截断的那一批原来只发 llm.end(时间线标题「结论句裁判未能执行」)和 judge_failed(下一步「检查裁判模型的接入后重新运行」):截断时接入是好的,同一个模型重新运行多半还是截断。现在另发 judge_truncated(max_tokens、unjudged),judge_failed 不再带截断;时间线上调用那一行说「裁判模型的输出达到上限(N token)被截断」,judge_truncated 那一行的下一步指到在报告撰写节点的「结论句裁判」或设置里换不带推理的裁判模型,入口落到节点的结论句裁判;check-decode 加一节
- 复核层(review.py)认得 judge_truncated:是缺口,记成它自己的 kind
- 退回小额度按 budget_refused 认,和核查同一种记法记在进程里:之后每份报告、每次点击直接用小的
测试补上半截清单(剧本和真实 ChatAnthropic)、纯文本清单后面还在写、截断和格式不对各记各的日志、跨报告记住被嫌大、自建服务的 max_new_tokens
2026-10-06 14:30:15 +08:00
ThearchyHelios
4905de728c
核查截断的回复一律不采信,触顶原因的先后照旧,截断的建议按模型从哪来的说
...
复核第 1 轮的发现(主要一条):Anthropic 的工具调用写到一半到了上限时,回复照样带着 tool_use(input 是空的,有的网关给半截对象)。工具循环只在没有工具调用时才看截断,于是一轮轮执行空参数的查询,撞到步数上限,最后记成「没有按结构交结果」;收尾的强制工具调用截在半路时解析出空对象或半截对象,空对象记成没按结构交,反方审稿的半截对象(结论写完、理由写到一半)被当成「经受住」,质询把半句话当成回答。
- 工具循环:回复被截断就停,带着的工具调用不执行(半截的 SQL 查出来的数是错的),也不收尾
- 截断前查到过东西的也不再按查到的收尾:截断前查到的不一定是要的那个数,交出去的结果只在 notes 里写一句「可能不完整」,审批卡、反方结论、质询回答都看不到,残缺的结果还照常参与比对和处置。同时长到点一样算半路被掐断,原因照截断说,查过的照记;TRUNCATED_SETTLED 和日志里的 delivered 字段去掉
- 收尾:回复被截断时,解析出来的、从回复里抠出来的都不采信(结构化、普通调用都是),也不退回普通调用
- 上一轮的 give_up 把触顶原因的先后从「先 stopped」换成了「先 refused」:去掉 give_up,收尾被上限拦下时照旧报先撞上的那个(双盲复算按它写无法复算的原因,反方审稿按每日上限决定还派不派后面的句子)
- 截断的原因开头只说「未能给出结果」(质询里提问人看到的就是这句,不说「核查未能完成」);建议在节点里说「在节点上指定不带推理的模型,或在设置里更换核查模型」(节点上的模型优先于设置,和时间线上的下一步一致),质询只说设置
- 退回小额度按 budget_refused 认,按 (接入, 模型, 额度) 记在进程里
- 时间线:verify_truncated 的副标题固定说「这次核查未能给出结果」,check-decode 跟上;review.py 里 verify_truncated 的注释跟上
测试补上真实 ChatAnthropic(只有 HTTP 层是假的)的循环截断、收尾截断(空对象、半截对象),真实 ChatOpenAI 写到一半的工具调用参数,Bearer 鉴权下 SDK 在本地拒绝时退回 4096,自建服务的 max_new_tokens,跨次核查记住被嫌大,触顶原因的先后
2026-10-06 14:30:03 +08:00
ThearchyHelios
5afa7a9a70
核查、证据裁判退回小额度时多认两种拒绝,被嫌大过的接入记在进程里
...
复核第 1 轮的发现:
- 自建服务(text-generation-inference 一类)嫌额度大时回 422,原话说的是 max_new_tokens,不含 max_tokens,认不出就不退回;核查、裁判的额度从 4096 提到 16384 之后才容易撞上。新增 WIDER_BUDGET_WORDS 和 budget_refused,只给核查、裁判用;助手改图仍按 budget_rejected 认,BUDGET_WORDS 不动(data/recipe_ai.py 的测试拿它比对)
- Bearer 鉴权的 Anthropic 接入(factory 换上的 SDK 客户端没设超时)调 Opus 4、4.1 这一代的 id 时,16384 的非流式请求 anthropic SDK 在本地就抛 ValueError(Streaming is required…),请求根本没发出去。budget_refused 把它也认成额度被挡下,退回小额度;重来不会重复输出,也没花钱
- 退回的开关原来只在一组调用里共用:双盲复算的几路盲算、反方审稿的每一句、每次质询、每次点击裁判各自先按 16384 撞一次。BudgetFallback 加 key:被嫌大一次就记进进程里的 _REJECTED,之后同一个 key 新建的一开始就用小的(同 factory 的 _NO_STREAM_USAGE,重启就忘);不给 key 的(助手改图)不记也不查,行为不变
2026-10-06 14:29:48 +08:00
ThearchyHelios
b2878fde59
时间线认得核查日志里的 cause: run_deadline:单次运行时限将至没核成的那几行说时限,下一步说怎么腾出时间,不再叫人调高核查的上限或去查模型和数据源;设置页双盲复算、反方审稿的时长设成不限时写明仍受单次运行时限约束
...
为什么(复核第 1 轮):反方审稿、双盲复算为后续节点预留时间,没开始的、缩短时长后到时没做完的以前读成「反方审稿已达时长上限」「未能反查」「无法复算」,下一步是「调高反方审稿的上限」「检查核查模型和数据源」「调高……中的上限后重新运行」——调高了只会更快撞线,模型和数据源本来就没问题。服务端现在另起一条、带 cause 和 run_seconds(单次运行时限),这里照它说。设置页「不限」的说明原来写「仅受模型接口自身的超时约束」,可这两种核查在运行里执行,时限将至时照样按剩余时间缩短。
- decode.ts:dual_check_unchecked、challenge_unreviewed、challenge_limit 带 cause: run_deadline 时,标题写「运行时限将至,……」,副标题写「单次运行时限为 600 秒,已为后续节点预留时间」(双盲复算前面再点名指标),下一步写减少句数或指标、在核查前加人工审批(时限按审批前后分段计算)、请管理员调大单次运行时限(AGENTLAB_MAX_RUN_SECONDS);不带 cause 的照旧
- terms.ts:叫法放在 DUAL_CHECK_TEXT(共用的副标题和双盲复算两句)、CHALLENGE_TEXT.log(反方审稿三句)、VERIFY_SETTING_TEXT.unlimitedNote 多一种 runTimeout
- VerifySettings.tsx:时长设成不限时,审批质询照旧(它不在运行的那一段里执行),双盲复算、反方审稿用 runTimeout 的说法
检查:check-decode 新增一节(追加在文件末尾),先核对后端还是这么发,再看三种日志带不带 cause 各怎么说、同一节点里两条分得开、缺字段不崩;对着改之前的 decode.ts 这一节 7 项变红。check-verify 新增一节(追加在文件末尾):三项时长设成不限时各自的说明,390px 深浅色不横向溢出、对比度 ≥ 4.5;改之前这一项变红。
2026-10-06 14:25:53 +08:00
ThearchyHelios
e3f5d566d0
核查因运行时长上限将至没核成的,时间线另起一条并带上原因(cause: run_deadline);收紧过的核查 agent 触顶时也改说时长上限将至;给下游留的余量看下游还有几个要调模型的节点,时长上限调短时余量跟着缩小
...
为什么(复核第 1 轮):没开始的句子、指标和收紧后到点的,以前和别的原因记在同一条日志里,没有可机读的字段,界面只能照旧叫人调高每句、每项的上限(调高了只会更快撞线),或去查核查模型和数据源(它们本来就没问题);前面有一句因别的原因没审时,运行时长上限这个原因还被藏进「等」里。双盲复算只给下游留 60 秒,惯常接法「双盲复算 → 写报告 → 反方审稿 → 成果」里写报告一慢,运行照样在写报告时被中止;时长上限调到 180 秒左右时,固定的 60 秒余量又让核查一项都开始不了。
- 反方审稿:没开始的句子另发一条 challenge_unreviewed,带 cause、run_seconds,不混进别的原因;收紧后到点的那条 challenge_limit 照记 timeout_s(老界面认得),另带 cause、run_seconds 和触顶的句数 claims,同一节点里有句子触了自己的上限时两条分得开。产出的 unreviewed 照算
- 双盲复算:没开始、收紧后到点的盲算结果带 cause、run_seconds,_compare 记无法复算时一并带上(只这一行),dual_check_unchecked 按有无 cause 分两条发,时限将至的那条另带 cause、run_seconds,原话列指标名(最多 5 个)
- deadline.relabel 包住交给核查 agent 的 emit:收紧过的那一项到点时,verify_limit 改说「本次运行即将达到 600 秒的时长上限,时长已按剩余时间收紧到 52.3 秒」,带 cause;别的事件、别的上限原样转发,没收紧时原样交回
- 余量按份算:一份取 60 秒和这一段的 10% 中大的,这一段不到 240 秒时按 25%;下游这一段里(到人工审批为止)每个还要调模型的节点(模型、Agent、协作、子工作流、写报告、双盲复算、反方审稿)各再加一份,合计不超过这一段的一半。默认 600 秒的一段、下游只有成果节点时和以前一样
- 没有截止时刻时一切照旧;决定都还在原来的 @task 里,接着运行取 checkpoint
测试:反方审稿、双盲复算各补一条「另一个原因 + 时限将至」两条分开说、带不带 cause 的用例,反方审稿补一条触了自己上限和收紧后到点分得开的用例;原有用例补上 cause、run_seconds、原话的断言。假的钟钉住下游有写报告时第 3 项只查 40~50 秒(没有时 100~110 秒);真的钟用 10 秒一段、盲算查到时长用完、写报告要 3 秒,以前在写报告时被中止,现在运行成功。单元测试钉住短时长的余量、下游每个节点加一份和一半的上限、数下游节点(人工审批之后不算、汇合只算一次、环回自己不算)、relabel 改什么不改什么。去掉下游余量、去掉 relabel 后对应用例都变红。
2026-10-06 14:25:38 +08:00
ThearchyHelios
dde0927460
审批质询遮罩收口(第 1 轮复核):「夹住某一个值」在整条 SQL 里认,只有分档的几种写法各算各的;分档标签不当遮罩值;SQL 检查结果的片段、说明照整条 SQL 换
...
- 夹住:上一轮只在同一个条件里配对,把找值拆到 ON 和 WHERE、WHERE 和 HAVING、INTERSECT / EXCEPT 两支、包在 CASE / 函数 / 算式里、子查询和 CTE 里,完整手机号就照原样封存、回答正文也跟着不遮。现在整条 SQL 里配对,只有 CASE 的不同分支、IIF 的真假两支、SELECT 里不筛行的不同项(选出列、GROUP BY、ORDER BY)、UNION 的不同支各算各的(_apart,看最近公共祖先);同一个条件里照旧按合起来的真假细看。整数上 <= v、>= v 也隔开相邻的整数(age <= 24 OR age >= 26 就是 age <> 25);BETWEEN v AND v、>= v AND <= v、> v OR < v 条件里哪一层这样写都算(被更宽的范围吸收、旁边有矛盾的条件、隔着别的条件写也认得出),整数的半开区间仍只看整个条件,成百个相邻分档照旧不遮。条件的各层摊开一次反复用,600 档的耗时和上一轮相当
- 分档标签:CASE / IIF 结果全是写死常量的,标签文字是 agent 写在 SQL 里的,不收进遮罩值,规格原句的 SQL、回答里的档名照原样;当分组键(每一档一行)或套在汇总里按条件数个数(SUM(CASE … THEN 1 ELSE 0 END))不算派生值,格子照常显示,分得清哪一档几笔;逐行的标签列、汇总遮罩列本身的值照旧整列遮
- 质询工件的 SQL 检查结果:片段是检查器重新写出的表达式,单拿出来认不出在找哪一个值,改为按整条 SQL 里整个换掉的字面量换(简单 CASE、行值、BETWEEN v AND v 里的短的数也换掉,阈值照原样);说明里照引的取值(「没有码值「3」」)一样换;截断处半截的号码去掉
- 同一个短的数在别处换掉时,别的列上的阈值、LIMIT 照原样:一律换会回退第 2 轮起的「age = 25 AND amount > 25 … LIMIT 25」,写进已知局限并补测试钉住
- 模块说明的已知局限照实改写(分档拆进两个 CTE / FROM 子查询、同一选出列里两档汇总相除会多遮,拆进 CASE 分支 / 不同选出列认不出,运行详情的工件页签不经这里的遮罩)
- 测试:端到端改回规格原句(文字档位、SUM(CASE …)、年龄段 CASE),补 ON/WHERE、WHERE/HAVING、INTERSECT、包在 CASE 里、CTE、相邻整数的端到端用例,单元补拆分写法、被吸收的 BETWEEN v AND v、分组标签、检查结果片段与说明;每处去掉实现都验证过变红
2026-10-06 14:05:52 +08:00
ThearchyHelios
b080302e77
可验证报告复核修正(第 1 轮):只给 id 的遮罩工件,服务端的文件和 id 对不上的标 mismatch、解析不出来的标 unparsable,核对页对不上的判不通过、解析不出来的照实说认不出是否含遮罩列
...
上一轮让被改过、解析不出的口径卡不再原样嵌入(号码不进文件),可这样一来它在页面上和正常的遮罩卡一模一样:「? 无法核对 含遮罩列,未随文件附带」,总结论从「有 1 项不通过」变成「可核对的项全部通过」,篡改的证据丢了;截断的卡服务端其实认不出输入,却被说成「含遮罩列」。现在 _Artifacts.add 对只给 id 的遮罩工件(口径卡、查询快照都算,带遮罩的快照被改过原来就有同样的问题)照实带上服务端看到的:store.intact 为假标 mismatch,解析不出对象标 unparsable。verifier.js 在遮罩分支认这两个标记:mismatch 判不通过,原因「导出时服务端的这份文件与工件 id(哈希)不一致,可能被改过;按含遮罩列处理,未随文件附带」;unparsable 是正常的无法核对,原因「导出时服务端的这份文件无法解析,认不出是否含遮罩列,按含遮罩列处理,未随文件附带」,引用它的数字跟着用这句。pytest 补被改过、截断、不是对象、哈希对得上却解析不出的卡和被改过的遮罩快照;check-bundle 在 masked-card 样本上补两条篡改检查。
2026-10-06 13:43:04 +08:00
ThearchyHelios
a7b8854dc4
双盲复算复核修正(第 1 轮):业务日期只认带日期的类型、原因按哪一边说清;遮罩列在子查询或 WITH 里改了名不再收窄,交给盲算的分组取值按 SQL 认出取自遮罩列的;按位置取的格点名原因、认不出出处的不写进计算式、不再改变容器输入的判法
...
业务日期的类型门槛:只有时刻的 TIME / TIMETZ 不再算(一天里的几点几分不是日期,MySQL 还常拿它存时长;和 catalog.is_date_column 同一个口径,记成业务日期后 SQL 检查会对按真实日期列统计的查询一直报错误级),原因说「只有时刻,不含日期」。类型照表结构里记的说「类型是 X」(introspect 存的是 SQLAlchemy 反射出来的类型,SQLite 里写成 TIMESTAMPTZ 的反射成 NUMERIC),没写类型的列反射成「NULL」,按没有声明类型说。被采纳的一边有问题说「被采纳的盲算按时间筛的列……」,未被采纳的一边另说清为什么也要看它(两边都是日期列时,审核人选的才是业务日期按哪一列)。数据源还没有可用的表结构(未探查、探查失败)时说表结构不可用,不说这一列不在表结构里。上传表格建的数据源(origin=upload,节点认出后经候选的 uploaded 交给 derive)日期一律存成文字,原因说「来自上传的表格,表格里的日期一律按文字保存」,不说成用户声明了 TEXT;预告和真写逐字一致。
遮罩:收窄补等值条件、交给盲算的分组取值,都按 SQL 认出取值来自遮罩列的名字(复用审批质询的 inquiry._derived_hidden:起别名、套函数、经子查询或 WITH 转一道、写在列名表里的都认,解析不了又写着遮罩列的整份算)。以前外层按 area 分组、area 在子查询里由 region 改名而来时照常补上「area = '华东'」,差异说明还原成「region = '华东'」进了审批卡、对照工件和目录日志,「华东」也进了盲算的任务;和遮罩列无关的 WITH 照常收窄。按位置取自遮罩列的输入直接交回「输入 vars.res.rows[0][0] 取自设置了遮罩的列,不能用于复算」(同 cell() 的说法),「核对不了」改成「无法核对」。伸进查询结果的行、却认不出取自哪一列的(下标不是字面量、改过形状的结果没带快照 id 和数据源名)计算式里写成「其他输入」,不把卡上的值交给盲算。按位置取的格落在的快照只为认遮罩算遮罩,不再进重算的快照清单:以前同一个指标里装着它整份行的容器输入会对上它、被它的遮罩列挡下。
2026-10-06 13:42:51 +08:00
ThearchyHelios
f815b1232a
审批质询收尾:审批列表取不到时别的审批里问的单独一组写「无法确认提问时的报告版本」并给重试;质询回答的问题摘要截在空格上也补省略号;工件页签里运行结束之后才写下的工件不给航迹跳转
...
- 审批列表没取到时,那几条以前被标成「报告其他版本上的质询」:同一屏上卡里挂在句子下面的一条,证据页签却说是别的
版本,审批人会以为报告换过稿,也没有办法重取。现在单独一组照实说没能确认、给「重试」,取到后按结果各归其位(这张
审批里问的回到句子下面,审的是另一稿的才算其他版本);取到了列表却没有那张审批的、报告没有报告文档的照旧算对不上
- 质询回答工件的说明:服务端先去掉问题首尾的空白再截前 40 字,摘要以空格结尾只会是截断截在了空白上。以前先去空白再
数字数,少一个字就漏了省略号,半句话读成整个问题;改为按原样数、显示时才去空白
- 运行详情「工件」页签:晚于运行结束的工件(封存后追加的质询回答和它查询的快照)以前也给「T+…」跳转,点了把航迹拖到
运行结束之后几十分钟、几天;现在只写时间。pages/runs/ArtifactsPane.tsx 只加了结束时刻这一道边界,运行中、停在审批上
的运行照旧(航迹还没有结束时刻)
- 预览用例 inquiry-run-artifacts 换成带起止时间的航迹、多一件以空格结尾的问题摘要;check-inquiry 补对应断言,以及审批
列表取不到时的标题、重试、重试后的归拢和深浅色对比度
2026-10-06 13:33:54 +08:00
ThearchyHelios
1bee9b5100
触发历史不再给基准已过时的自动对比;对比页找不到默认基准时标题不再和「可在上方选择」打架,换基准的下拉和基准卡写明失败、取消的运行
...
- 中间失败的那次事后被接着运行成功之后,第 3 周存着的那份对比(比的是第 1 周,previous 为假)和运行详情「与上一次
对比」的默认基准(现在是第 2 周)又对不上,两处却都写「上一次成功的运行」。auto_compare.outdated 对基准当时就不是
紧挨着的上一次的那几份按 pick_base 现挑一遍,基准变了的算过时;api/schedules._fire_outs 对过时的给 null(不给链接、
不给旧计数),两个同名入口比的始终是同一对运行。基准没变的照旧给:中间那次还没结束、后来失败、被删掉都一样。紧挨着
的上一次不会过时(两次之间插不进新的运行),不核
- test_base_follows_launch_order_not_finish_time 补上:接着运行完之后第 3 周的触发记录不再带对比、任务列表的 last_fire
同样不带、运行详情的默认基准是第 2 周;另加一条基准仍是挑出来的那一次时照旧给出
- 对比页找不到默认基准:标题由「未找到可作为基准的运行」改为「没有默认基准」——失败、取消但封存了的运行不当默认基准,
却照样能在上方手动选;服务端的原因改成「没有找到上一次成功的运行:需要同一工作流、同一运行类别里比这次先发起、成功
结束并已封存的运行」,运行详情弹出的提示单独读也说得清
- 换基准的下拉给失败、已取消的运行写上状态,基准卡也标出来;下拉说明补一句默认基准只取成功结束的运行
- 运行详情「更多」的菜单项点之前不知道基准是哪一次,基准不是紧挨着的上一次时仍叫「与上一次对比」,和触发历史的叫法
不同:注释照实写明,留作后续
2026-10-06 13:33:40 +08:00
ThearchyHelios
9f0e453884
整篇包在 ``markdown 里、中间再套一段一样长的 ``sql 时照样去掉外层围栏:带信息串的一行开、不带的一行收,两两配对。以前一样长的内层围栏一律不去,模型最常见的这种写法仍是 0 句结论,裁判和反方审稿没有句子可审,正式运行照样出具
...
规则:中间和外层同种符号的围栏行,比外层短的跳过,比外层长的不去(规格原文),一样长的按配对看——带信息串的开一个代码块,不带的收掉它;没有可收的 ``` 说明外层在这里就收了(好几个代码块),开着时又来一个 ```sql、扫到最后还开着的,都不去。去掉外层后 compose_doc 和前端每见到一行 ``` 开合一次,配好的一对正好切成一个代码块,原 docstring「见到 ``` 就收」的理由不成立,改准确了。
一样长的行只认 compose_doc 和前端认得的写法(信息串是紧跟着的一个词):``` sql 这种它们不认,算一行正文。不然它会和后面的 ``` 配成一对、去掉外层,而后面那个 ``` 在它们眼里成了开头,把结论句吞进代码块。比外层长的照旧按行首判,````sql title 这样的也不去。
外层反引号里套 ~~~、四个以上反引号的代码块照常去掉外层:compose_doc 和前端只认 ``` 围栏,这段按正文核对,和模型不包外层、直接这么写时一样,比整篇一个代码块强;docstring 写明,测试钉住。
测试:same-fence-inside 挪到去的一边,补多段内层代码块、~~~ 里套 ~~~、反引号里套 ~~~;不去的补没有可收的 ```、开着时又来 ```python、内层没收、``` sql 开头、更长的带词围栏。compose_doc 一级补 ```markdown 套 ```sql(SQL 仍是代码块,结论句 2 句)和 ~~~ 块按正文核对。端到端(正式运行,裁判 + 反方审稿 + 出具契约)加一组套 ```sql 的写法:两句都判、都审,完整出具。裁判退回改写(rewrite_once)那一稿也包在代码块里时照样去掉:改写稿被采用,第二轮判到改过的那句,以前这条路没有测试守着。每条判断各做过一次去掉、测试变红。
2026-10-06 13:32:38 +08:00
ThearchyHelios
ed6f5d064a
截断和退回小额度在真实的 ChatOpenAI、openai SDK 上也核对一遍:只有 HTTP 层是假的(经 OpenAI 兼容网关接入的推理模型就是这一路)
...
核查:工具循环那次只有 reasoning_content、finish_reason=length;收尾走 json_schema 时 SDK 抛 LengthFinishReasonError(用量从异常里取);网关嫌 16384 太大回 400 时退回 4096,之后工具循环和收尾都用小的。裁判:json_schema 那次被截断记未裁判(truncated)、不退回纯文本;网关回 400 时退回 4096。请求体里的额度(max_completion_tokens)逐个核对。
2026-10-06 13:17:19 +08:00
ThearchyHelios
3bb06e32f1
整理:核查收尾时一条报错的续行对齐,裁判的 _TRUNCATED 挪到用它的 _ask 前面
2026-10-06 13:13:49 +08:00
ThearchyHelios
d9acfbfc0b
收紧后的时长取到 0.1 秒、往下取:核查 agent 触顶时时间线写「时长上限 69.7 秒」,不写 69.7012 这样一串小数;往下取不会超出算好的余量,差一点不够的照样不开始
...
另把 segment、allot 的说明补全:deadline 为 None 时放的是 None(里面看不到外面的截止时刻),配置的是不限时按收尾宽限算最短时长。
2026-10-06 13:07:23 +08:00
ThearchyHelios
2c2672cc04
时间线认得核查模型的输出被截断(verify_truncated):标题说「核查模型的输出达到上限(N token)被截断」,副标题说这次核查未能完成或已按截断前查到的结果收尾,下一步指到换不带推理的模型,入口落到节点的模型
...
decode.ts 按结构化字段(max_tokens、delivered)解读,不从原话里认,缺字段时只给不带数的标题;文案放在 terms.ts 新的 VERIFY_TRUNCATED_TEXT。check-decode 加一节:先核对 verify_agent.py 还是这么发的,再核对三种取值(没交出结果、退回 4096 后交了结果、缺字段)的标题、副标题、下一步、入口和原话。
跑完之后的复核层(engine/review.py 的 WARN_CODES)登记 verify_truncated:同 verify_limit 记成它自己的 kind、degraded,不落成笼统的 warn,也不触发「重跑一次大概率能好」。
2026-10-06 13:06:18 +08:00
ThearchyHelios
4b5b3ecbf7
正文给被反方审过的句子挂句末标记,「质询」图标平时的对比度提到 3:1 以上:EvidenceDoc 按证据图 reports[].challenge_verdicts 给被审句子挂标记(被推翻、被削弱带字醒目,经受住、无法判断只有淡色图标),已有裁判徽标的并在同一枚徽标里,点开是整句面板,没有可点片段、没开裁判的句子也打得开;有运行就取一次证据图(同一次运行只取一回,不逐句请求),只认工件 id 对得上的那份报告;证据页挂载时手里那份证据图是运行收尾前取的(没封存)就重取。句末「质询」图标平时改用暗字色压到 70%,深浅两套、页面底色和面板底色上都在 3.3 以上,不撑开排版。check-evidence 补标记、整句面板、未能反查的说法和平时对比度的断言,probe 改在打开页面之前挂路由(证据图一挂上就取)
2026-10-06 13:02:30 +08:00
ThearchyHelios
4a3de10d38
证据裁判按 16384 的额度判、服务方嫌大时退回 4096,判定写到一半到了上限的记未裁判(truncated),照实说是输出额度
...
裁判原来固定 4096、thinking off;经 OpenAI 兼容接入的推理模型收不到 thinking=off,思考能把 4096 用光,结构化调用写不出判定、退回纯文本也一样,最后记成「裁判返回的结果格式有误」。现在:
- 额度 MAX_TOKENS(16384),服务方嫌大(400/422 且报错提到 max_tokens 一类)时退回 FALLBACK_MAX_TOKENS(4096)再问一次,之后各批都用小的、只撞一次;小额度的模型要退回时才建
- 每次调用看有没有被截断:Anthropic 的 stop_reason=max_tokens、OpenAI 系的 finish_reason=length、openai 结构化输出抛的 LengthFinishReasonError。截断的这一批记未裁判,原因是新的 truncated(和格式不对分开记:说成「格式有误」人会去查提示词,该换的是模型),理由写「裁判模型的输出达到上限(N token)被截断,这句未裁判。通常是推理占满了输出额度,可换用不带推理的裁判模型」,缺口、llm.end 的 error(带 truncated、max_tokens)、judge_failed 日志同样写明
- 结构化调用被截断的不再退回纯文本多花一次额度;截断那次的用量从异常里取,照记账
- 别的批照常问(同格式不对);没有截断时原有说法不变
测试:新增 test_judge_truncation(结构化调用截断、LengthFinishReasonError、纯文本只有思考、一批截断不影响别的批、退回 4096 只撞一次、退回后截断写 4096、格式不对的说法不变)。
2026-10-06 13:02:24 +08:00
ThearchyHelios
a25fed002e
出具横幅把核查缺口分组,审批卡把运行类别交给反方审稿:IssuanceBanner(运行面板成果区、问数据回答、证据页同一个)把双盲复算、反方审稿报上来的缺口另起「核查未通过」「核查未完成」两组,排在「校验未全部完成」上面,先后同时间线和成果节点印章;证据页去掉另列一遍的 IssuanceWithChecks 包装,直接用横幅。RunPanel 的审批卡把 approval.run_class 传给 ChallengeSummary,运行的 GET 失败也照样写「出具会降档」、不另取。check-stream 补横幅分组的断言(新预览用例 issued-verify),check-verify 的 verify-gaps 改读横幅里的新组,check-challenge 补整张审批卡带运行类别的用例
2026-10-06 13:02:04 +08:00
ThearchyHelios
b54545b5d4
双盲复算在运行时长上限内收尾:每项盲算开始之前看这一段执行还剩多少时间,不够就不再开始、按无法复算记缺口,够的话时长上限按剩余时间收紧;运行不被中止
...
为什么:盲算最多 3 路并行、每项 120 秒再加 30 秒收尾宽限,指标多了一样能耗光一段执行的时长上限,整段盲算没进 checkpoint,「继续运行」全部重做、再花一次钱。
- 只动安排盲算的 _blind:开始一项之前问 deadline.allot。不够时交回一个没有模型的结果(原因「本次运行即将达到 600 秒的时长上限,为保证运行按时完成,未进行盲算」),走现有的路径:_compare 记无法复算、dual_check_unchecked 点名、出具缺口照记;第一项就不够时和核查模型用不了一样,后面的不再一个个去试
- 时长收紧过的盲算到了点:照样按无法复算记(同触了每项时长上限),原因说运行时长上限将至、盲算时长已按剩余时间收紧;不留 limit,不发 dual_check_limit——它叫人调高每项的上限,调高了只会更快撞线
- 决定都在 dual_check_blind 这个 @task 里:审批恢复后重放取 checkpoint 里的结果,不再盲算,哪几项没来得及照旧
- 时间充裕时时长上限照传原值,和以前一样;_plan_metric 等别处没动
测试:假的钟钉住五个指标只够盲算 2 项、第一项都来不及、收紧的那项到点怎么说、审批恢复后不重做;真的钟用 5 秒的时长上限、一项接一项的慢盲算,以前被中止,现在运行成功。去掉判断后这几条都变红。
2026-10-06 13:01:20 +08:00
ThearchyHelios
573313cbc2
证据接口的核查状态类型挪进 types.ts,证据面板的反方审稿改用单句展示:EvidenceDualCheck、EvidenceUnitChallenge、输入步骤的 masked / mask_unverified、证据图的 challenge_verdicts 照服务端逐字核对;审批卡上的概况类型补上 unreviewed、degrades。ChallengeSummary 加单句模式(scope=claim,只画这一句的判断、它可能没反查成的说明、展开看理由和查询,不画报告级的标题和计数)和显式的「不谈出具」开关(issuance=false,不预告降档、也不为此取运行类别),证据面板改用这两样,去掉传 runId 为空的做法;check-evidence 的核查一节跟着改成单句的断言
2026-10-06 13:01:17 +08:00
ThearchyHelios
4a3899f4d5
反方审稿在运行时长上限内收尾:每句派出去之前看这一段执行还剩多少时间,不够再审一句就停下,这句和后面的记为未能反查,节点照常收尾、运行不被中止;够的话这句的时长上限按剩余时间收紧
...
为什么:逐句串行反查(为了时间线看得出哪条查询在审哪一句、每日余额扣得确定,这个设计保留)默认 5 句、每句 90 秒再加 30 秒收尾宽限,最坏正好是一段执行的 600 秒,加上取数、写报告必然被中止;中止时反查的 @task 没做完,「继续运行」从头再审、再次超时。
- 判断用 deadline.allot(给下游留余量、扣收尾宽限),只在要派 agent 的句子上做:没有可查数据源这类不花时间的句子照记原来的原因。一旦停下,后面的句子照同一个原因记(同每日金额用完、核查模型用不了的处理),理由写「本次运行即将达到 600 秒的时长上限,为保证运行按时完成,这句未反查」,challenge_unreviewed 的原因写「……剩下 N 句未审」,产出的 unreviewed 照算进去
- 时长收紧过的句子到点按查到的结果收尾,challenge_limit 照记 timeout_s(界面认得),说法另起:说运行时长上限将至、反查时长已按剩余时间收紧,不说「每句时长上限 90 秒」——那会叫人调大每句的上限,调大了只会更快撞线
- 决定都在原有的 @task 里做,输入指纹不含截止时刻:接着运行时取 checkpoint 里的审稿,不重审,没来得及的照旧
- 时间充裕时时长上限照传原值,和以前逐字一样(现有用例全过)
测试:假的钟(每派出一句拨钟若干秒)钉住 5 句只够审 2 句、收紧的那句触顶怎么说、一句都来不及、接着运行不重审;真的钟用 7 秒的时长上限和查不完的慢 agent,以前被中止,现在运行成功、计数对得上。去掉判断后这几条都变红。
2026-10-06 13:00:48 +08:00
ThearchyHelios
a1d5dcd0ac
runner 把这一段执行的截止时刻交给节点:进入 asyncio.timeout(max_run_seconds) 时放进 ContextVar(engine/deadline.py),退出时清掉,节点、节点里的 @task、子工作流都看得到;没有上限时为 None,节点照旧
...
为什么:反方审稿逐句串行反查、双盲复算按项盲算,一个核查节点就能把一段执行的 600 秒用光,整次运行被中止,装着反查、盲算的 @task 没进 checkpoint,「继续运行」从头再来一遍、再次超时。核查节点要先知道还剩多少时间,才能在上限之内收尾。
deadline.allot(时长上限, grace=收尾宽限) 给核查节点在开始每一项之前问:先给下游留出余量(60 秒或这一段总时长的 10%,取大的:60 秒够成果节点复核、再做一两次普通的模型调用;时长上限调大了的,节点多半本来就慢,余量跟着放大),再扣掉收尾宽限,剩下的比配置的时长短就收紧到它;收紧之后不到 min(配置的时长, 收尾宽限)(一次模型调用的时间)就不再开始。不经 runner 执行时原样放行、时长上限还是传进来的那个值。
runner 只改一行:async with deadline, segment(deadline.when(), max_run_seconds),截止时刻就是 asyncio.timeout 的那一个、同一个钟。测试钉住 allot 的各档、余量随总时长放大、退出(含出错)时清掉,以及节点和节点里的 @task 都看到同一个截止时刻、审批恢复后的那一段重新计时。
2026-10-06 12:59:49 +08:00
ThearchyHelios
a552f4feab
核查模型的输出额度改为 16384、服务方嫌大时退回 4096,截断照实说:工具循环、收尾的每次调用都看有没有到了上限被截断
...
额度:judge.MAX_TOKENS 从 4096 改为 16384(核查的 verify_model_spec 沿用它)。经 OpenAI 兼容接入的推理模型收不到 thinking=off,思考算在额度里,4096 常常想完就没额度发查询、交结果;16384 是常见网关接受的输出上限里偏大的一档,cite_fields 的抽取也是这个数。服务方嫌大(400/422 且报错提到 max_tokens 一类)时退回 judge.FALLBACK_MAX_TOKENS(4096)再试一次,工具循环和收尾共用一个开关,之后都用小的;小额度的模型要退回时才建。
截断:工具循环里没有工具调用、finish_reason=length(或 stop_reason=max_tokens)不再当成「模型说完了」,一条查询都没成功时不再收尾(收尾只能交「查不到」,双盲复算就会记成「盲算没有查到这个数」);查到过东西的照常收尾,取不到要的数时同样交回截断的原因,取得到的照常交、notes 里注明。收尾被截断(Anthropic 强制工具调用写到一半、openai 结构化输出抛 LengthFinishReasonError、普通调用只有思考)时交回截断的原因,不再退回普通调用多花一次额度;截断那次的用量从异常里取,照记账。给人看的原因写明「核查模型的输出达到上限(N token)被截断,核查未能完成。通常是推理占满了输出额度,可在「设置 → 偏好设置 → 核查」中换用不带推理的模型」,经 error 交给双盲复算的无法复算原因、反方审稿的「反查未完成」、质询的报错;节点里调用时另记一条 verify_truncated,llm.end 标出 truncated 和额度。没有截断时原有说法不变。
测试:新增 test_verify_truncation(假模型返回 finish_reason=length、只有思考、LengthFinishReasonError,覆盖工具循环、收尾结构化和普通调用、退回 4096、别的 400 不重试、三条渠道);三处钉着 4096 的断言改成 16384。
2026-10-06 12:58:37 +08:00
ThearchyHelios
4dd40ed201
输出额度的通用逻辑挪到 providers/budget.py:认截断(finish_reason=length、stop_reason=max_tokens、openai 的 LengthFinishReasonError)、认服务方嫌额度太大(400/422 且报错提到 max_tokens 一类)、截断那次的用量、给人看的「某某模型的输出达到上限(N token)被截断」,以及退回小额度的 BudgetFallback
...
BudgetFallback 在助手原来的做法上补齐核查和裁判要用的:非流式 ainvoke 也认;bind_tools、with_structured_output 包出来的和原来的共用同一个开关,另一份配置建的模型(核查收尾时关掉思考的那个)经 shared_with 也共用,工具循环里退回过,收尾那次直接用小的;小额度的模型可以要退回时才建,平常一个都不多建。只在还没吐出任何东西时重来,和原来一样。
助手改为引用它,_cut_off、_BudgetFallback、_BUDGET_WORDS 留着老名字,行为不变,助手和配方助手的测试照样通过。
2026-10-06 12:51:36 +08:00
ThearchyHelios
0600144b73
写作模型把整篇报告包在一个代码块里时去掉外层围栏再核对:不去的话整篇在 compose_doc 里是一个代码块,裸数字照样标出,可一句结论都切不出来,证据裁判、反方审稿没有句子可审(反方审稿记 no_claims 直通),正式运行照样出具,界面上整篇显示成代码
...
报告节点的 compose 统一先过 _unfenced:第一稿、重写稿、裁判退回的改写稿都经过它。只在拿得准时去——去掉首尾空白后第一行是围栏(``` 或 ~~~)、信息串为空或 markdown / md(大小写不敏感),最后一行是同种符号、同样长的收尾围栏,中间没有同种、不比它短的围栏行;信息串是 sql、json 等别的语言、围栏外有前言结语、有多个代码块、开闭围栏对不上、里面嵌着同样长或更长的同种围栏的,原样交给 compose_doc(返回的就是原字符串,文档哈希不变)。正文自己的代码块套在更长的围栏或另一种符号里时照常去掉外层,里面的原样留下。doc["source"] 记去掉围栏之后的正文,markdown 由它渲染,出口契约复核取回的也是这份文档
测试:各种去与不去的写法逐条钉住(每条判断各做过一次去掉、测试变红);节点里裸数字照样标出、引用照常渲染、重写稿同样处理、别的代码块原样不动;端到端(虚构 SQLite 源)带围栏的报告里单元格引用照常解析,裁判两句都判、反方审稿两句都审,出口完整出具
2026-10-06 12:44:44 +08:00
ThearchyHelios
898bd8a276
审批质询遮罩收口:模块说明和取质询工件的说明写上 SQL 检查结果的片段照 SQL 换
...
上一处改动(f0e97f6)只在接口说明和 _masked_checks 里写了,模块说明的「读取」一条和 inquiry_artifact 的说明补上,免得读的人以为工件里的 checks 原样给。
2026-10-06 12:34:55 +08:00
ThearchyHelios
8ca750d7ee
审批质询遮罩收口:说明跟上实现——「夹住」越过的连接词含异或、条件长到细看不过来时多遮几个阈值写进已知局限
...
- 模块说明的已知局限补一句:条件长到细看不过来(PIN_WORK)时,两边都隔开的一律按夹住算,会多遮几个阈值
- 测试说明对齐:同一个条件里夹住的那组用例越过的连接词含异或(XOR 用例),HAVING 的用例已挪到自己那条测试;年龄段那条
补上说明
2026-10-06 12:32:48 +08:00
ThearchyHelios
238fe94fee
质询回答工件兜底说明的注释照实写:服务端都会记问题摘要,没有时只是兜底,不说成「这一版之前存的」
2026-10-06 12:32:15 +08:00
ThearchyHelios
f0e97f614f
审批质询遮罩收口(后端):质询工件里的 SQL 检查结果字段照证据面板,片段里的遮罩值照 SQL 换掉
...
做项 3 时发现的同一类缺口:agent 的查询快照带着 SQL 检查结果(数据源查询工具对照数据目录查出的问题,checks),质询工件接口
原样带出——sql_excerpt 是从这条 SQL 摘的片段(按遮罩列筛选的那个条件,例如 buyer_phone = '13900000001'),for_model 是给模型
的改法、也照抄了片段。事件和工件里的 content.sql 已经换掉遮罩值,旁边的片段没换,等于从旁边把值露出来;证据面板对报告快照
本来就只给约定的几个字段、不给 for_model。
- inquiry_artifact 里的 checks 经 _masked_checks:字段照证据面板的 _query_checks(不交 for_model),sql_excerpt 照查询清单的
SQL 换(_scrub_sql,和遮罩列做等值比较的短的数、日期这样的字也认得出)
- 界面不读 checks,只是接口上不再带原值
- 补单元测试和端到端测试(把 SQL 检查换成会摘出遮罩值片段的假检查)。做过去掉实现、测试变红的验证
2026-10-06 12:30:52 +08:00
ThearchyHelios
aa2b93f587
check-compare 里找不到基准的假答复照服务端的新说法写;触发历史的对比链接去掉没人用的标记
...
- 「不属于已保存工作流」那一段伪造的 404 说明原先抄的是旧的 NO_BASE_TEXT(更早结束并已封存),改成服务端现在的
「上一次成功的运行……比这次先发起、成功结束并已封存的运行」,假答复和接口约定保持一致
- FireHistory 的 CompareLink 去掉 data-fire-compare-previous:检查只看看得见的字,不靠这个标记
2026-10-06 12:30:44 +08:00
ThearchyHelios
32c3119086
审批质询遮罩收口(后端):质询工件里文字格夹着的遮罩值按子串换掉,回答一路照旧整份不交
...
第 1 轮起留着的缺口:备注列(没设遮罩)一格写着「客户13900000001来电改址」,手机号设了遮罩、被报告取数选中。agent 引用这一格,
回答被正确拦下(「回答中含有设了遮罩的值……已不予展示」),可事件的 inquiry_artifacts 照样记着这份快照,
GET /api/runs/{id}/inquiries/artifacts/{artifact_id} 返回原样的格子、masked 为空,等于在「不予展示」旁边一点就能看到原值。
- _masked_view 加 embedded:没设遮罩的列里,一格文字(JSON 列按界面画出来的样子)夹着按值认得出的遮罩值,把那一截换成
「已遮罩」,这一格别的字、别的格子照原样;门槛同整格(_Secrets.scrub:够长的数、两个字以上的文字,提问人自己写的、报告
列出的指标和运行输入的值不换)。这一列不记进 masked:界面把记进去的列整列画成「已遮罩」,这一列在数据源里也没设遮罩
- 只有取质询工件这一路按子串换,而且只换要取的那一份(_plan 的 embedded 是工件 id 的集合);回答一路不动,渲染出来露了
照旧整份不交
- 接口说明写清 masked 的含义:有格子整格被遮掉的列;一格文字里夹着的只换那一截,列不记进去
- 补单元测试(文字格、字典形状的行、JSON 列、整格照旧整格换、回答一路照旧)和端到端测试(回答整份不交,工件里那一格变成
「客户已遮罩来电改址」、其余格子照原样、masked 为空)。做过去掉实现、测试变红的验证
2026-10-06 12:25:48 +08:00
ThearchyHelios
4690063f5d
审批质询遮罩收口(后端):「夹住某一个值」只在同一个条件里、按条件合起来的真假认;阈值只在同一个数在这条 SQL 别处确实换掉时才不留
...
复验留下的两条多遮回归(遮得太多,不漏):
- _pinned 收全句所有范围比较一起配对,列名认不出的(SUM(amount)、函数)还和哪一列都配:分档的两个 WHEN 分支、两个选出列、
UNION 两支、WHERE 和 HAVING 各写一边,共用的边界被当成「夹住了某一笔」遮掉,回答里「以 20000 元为界」也跟着遮。改成从每个
比较往上只越过且、或、非、异或、括号,走到同一个条件根的才放在一起看;同一个条件里两边都被隔开了,再按条件合起来的真假看
是不是真只认这一个值(条件里别的部分当成不知道真假,有一种取法夹住就算)。BETWEEN v AND v、>= v AND <= v、> v OR < v、
整数的半开区间照旧认得出;age > 31 AND age <= 25 AND 25 < age AND age NOT BETWEEN 25 AND 31 这种谁也找不着的不算,第 2 轮的
原输入恢复并通过。列名认不出的只和写得一样的表达式配
- 夹住的值另记下来:两头都不是那个值的整数开区间(age > 24 AND age < 26)按夹住的 25 换,不再留着 24、26 等于写出 25
- 几百个条件连成一长串:条件改成不递归地算(以前上千层会超过递归深度,退回按词认,短的数就漏了);细看夹没夹住按步数设了
上限(PIN_WORK),看不过来的两边都隔开就按夹住算
- _literals 的「别处出现过同一个数」从所有非保留字面量里抽数字片段,日期里的 31、天数修饰里的 30、标签里的 30、没设遮罩的
列上的 amount = 30 都算,阈值就改记成等值遮掉,可那些地方一个字没换,回答正文又照样写着它。改成和真去换的同一套判断
(_swap_literal,_scrub_sql 也照它换):只有同一个数在这条 SQL 别处确实被换掉了(等值、别处的长数整个换掉,字符串里按值
换掉的遮罩数)才不留;换掉的是文字标签不牵连阈值。查询之间的正文免遮(_shown_literals)同理,按查询各自认遮罩列的比较
- 模块说明补上已知局限:按值认的门槛两头都有误差(短的数在正文里遮不住、5 位以上的数会误遮巧合的数)、遮罩数值列的
SUM/AVG/MIN/MAX 和按遮罩列分档的 CASE 标签算派生值(产品取舍,保持现状)、「夹住」只在同一个条件里认(拆进子查询或 CTE 的
认不出)、遮罩值收集有上限
- 补单元测试和端到端测试:重叠的分档边界(两个 WHEN 分支、两个选出列、UNION 两支、年龄段)、日期、天数、标签、未遮罩列的
等值照原样封存、正文不遮;同一条件里夹住一个值的几种写法(旁边有别的条件、CASE WHEN、HAVING 里同一个汇总值、整数开区间、
XOR)和别处确实换掉的同一个数照旧遮。每处改动都做过去掉实现、测试变红的验证
2026-10-06 12:24:54 +08:00
ThearchyHelios
21e8455403
双盲复算审批卡的预览夹具跟上收尾版差异说明:变体换成仍有代表性的一组,预告按带日期类型的表结构重新生成
...
- 收尾版差异说明对同一列上的时间范围只给兜底,旧的 time_range 变体失去意义:改名为 fallback(说不清的,兜底加
逐行对照,审批卡默认展开对照),另加 time_column(按哪一列筛时间不同,两列都声明为日期类型,预告写业务日期);
有效记录条件(filter_extra)、去重规则(dedup)和其余仍说得出的变体照留。夹具由服务端重新生成:filter_extra、
two_filters、peers.filter 的筛选说法也跟上了现在的输出(「……的行和 status 为空的行」),原先排在 time_range
后面没被比到。
- test_dual_check_fixture 的表结构把 paid_at、created_at 声明为 TIMESTAMP(业务日期的类型门槛),预告、合并预告、
被挡下的那一份照旧写业务日期;新增一条守住几种变体的方面和预告会写的项,免得规则一改变体悄悄变了形状。
- check-verify 跟着改:没有预告的那一节换上 fallback、time_column,兜底的那种对照默认已展开、不再点一下收起;有预告
的那一节兜底变体按兜底说明核对,换了时间列两边都写同一项时后一条按省略写法核对,并看选盲算时加重的那一条;几个
输入都差在时间列的合并用例改取 time_column 的说法。check-verify、check-decode 浏览器检查通过。
2026-10-06 12:19:44 +08:00
ThearchyHelios
a358fbd244
审批质询收尾:工件页签认得质询回答;几处问答串要对的审批不同、审批列表取不到时各自照样列出
...
- 工件名:质询的回答文档以 inquiry_answer 登记在运行名下,工件页签原先直接显示英文原值。ARTIFACT_KIND_LABEL 加「质询
回答」,说明在 meta.question 有值时写「质询「…」的回答」(服务端只记前 40 字,满 40 字的补省略号),没有时写「审批
质询的回答:逐段的片段和每个数字的出处」;文案放在 INQUIRY_TEXT
- 问答串的竞态:loadApprovalDocs 发现别处正在取审批列表就直接返回,没把这一处要对的审批记进 asked。请求回来后这一处的
unknown 不变、effect 不再执行,settled 一直为假,头上写着「· N 次」,别的审批里问的那几条一直不显示(一张卡审两份
报告;运行详情的待审批卡和证据页签同时挂着、审批列表失败时)。现在提前返回前也把这一处的 id 并进 asked:列表按运行取,
在路上的那一份本来就带着全部审批,不另发请求
- 预览用例:inquiry-approval-two(一张卡审两份报告)、inquiry-run-waiting(待审批卡和证据页签同时挂着)、
inquiry-run-artifacts(工件页签);夹具补探索运行的工件列表 run_artifacts
- check-inquiry:审批列表压住、再答 404,两处的条目都列出(查不到审批的单独成组),头上的次数和列出的条数一致、审批
列表只取一次;工件页签里有「质询回答」的名字和说明、不出现英文的种类名、打开的弹窗标题也是中文;390px 深浅色下不溢出、
看得清
2026-10-06 12:19:13 +08:00
ThearchyHelios
eccde61c05
可验证报告里被改过、解析不出的口径卡不再原样嵌入:遮罩按卡上记的输入认,不看哈希
...
- bundle/build.py 的 _Store.card_masked 以前先看哈希:服务端的卡文件被改过(哈希对不上)时当它没有输入,
不算带遮罩,_Artifacts.add 随后把原字节 base64 嵌进页面,卡上记着的遮罩列号码进了文件;解析不了的卡同样原样
嵌入。这和同一文件里快照的做法相反(content 不看哈希,读不出来的快照按带遮罩算)。现在卡按解析出来的内容认
遮罩,不看哈希;读得出字节、解析不出一张卡的(截断的 JSON、不是对象)认不出输入,整张按带遮罩算、只给 id。
改过但没有遮罩列的卡照旧原样嵌入,浏览器自己算出哈希对不上。
- 补用例:改了口径版本、哈希对不上的卡只给 id、页面里没有号码;改过但不带遮罩列的照常嵌入;截断的 JSON、
不是对象的卡只给 id。恢复成先看哈希时这三条变红。
2026-10-06 12:13:49 +08:00
ThearchyHelios
3843a1cd89
双盲复算按需算任意快照的遮罩:按位置取自另一份快照遮罩列的输入不再当字面量交给盲算
...
- 预检以前只为 cell() 输入的快照算遮罩。口径卡上按位置取的一格(vars.res.rows[0][0])若来自另一份快照,重算
认不出它在遮罩列上,指标照常盲算,遮罩值作为字面量写进了交给盲算模型的计算式。现在 _plan_metric 对这类输入
顺着取值链认出取自哪份快照的哪一列(recompute.input_origin,和证据面板、推演、可验证报告同一个认法),按需
算那份快照的遮罩交给重算的预检:取自遮罩列的按无法复算记缺口(原因同同一份快照上的那种);那份快照读不出来、
数据源现在的遮罩又没遮这一列的,查询当时记下的遮罩无从核对,同样按无法复算记,原因说清。
- _Sources.hidden 改用证据面板那一套(api/evidence 的 _Masks、_merge_masks、_recorded_masks):合并查询也按它
合并的几个数据源算,快照读不出来时按取值链上带着的数据源名算,结果按快照记下来不重复查。
- 两个遮罩分组用例换一对盲算 SQL(不分组、按下单日筛):收窄的话说明和对照里会带出「region = '华东'」;照整条比
时说明是「时间列 + 另有未能归纳的差异」、对照里留着 GROUP BY,以此断言没有收窄,替换失效的「差异不止一条」。
去掉 _narrowed 的遮罩判断后三个遮罩分组用例都变红。
- 补用例:两份快照(cell() 取 A、按位置取 B 的遮罩列)不盲算、取值不进任务和产出,没设遮罩时照常盲算;快照读不
出来时的两种情况;时间列声明成文本的库,审批卡预告不记、真写跳过的原因和预告一字不差。
2026-10-06 12:11:50 +08:00