Commit Graph

261 Commits

Author SHA1 Message Date
ThearchyHelios 5e8d2c9c36 定时任务自动对比复核整改(前端):页头的定时任务链接在窄窗口里不再被挤没、带日历图标、任务删了写纯文本;触发历史的对比入口改叫「与上一次对比」并写出有几个指标有变化
- 运行详情页头:元信息这一行改成可换行,定时任务链接至少留 7 个字宽。以前这一行不换行、只有链接能缩,820 宽的探索
  运行只剩「由…」,768 宽为 0,Tab 停在看不见的链接上,「2 条事件」被压成竖排。链接前加和「定时」标记一样的日历
  图标,平时看得出能点。取回的定时任务列表里没有这个任务(已删除)时写成纯文本「由定时任务「X」发起(已删除)」,
  不再链到「不存在」页;列表取不到时不算删除
- 触发历史:「对比上一次」改成和运行详情「更多」菜单同一个叫法「与上一次对比」(复用 RUN_COMPARE_TEXT.menu),旁边
  写「N 个指标有变化」,触屏和键盘也看得到变化的规模,悬停照旧写各类个数。基准不是紧挨着的上一次(服务端给
  previous: false)时悬停写明是哪一次,也不再带「默认基准:同一定时任务的上一次运行」的来历
- 「通知中的运行链接」改成「通知中的链接」,说明里写清对比页链接也靠这个地址
- check-schedules:对比入口的叫法、计数、previous 为 false 时的悬停和来历;页头链接在 768、820 宽(含「提取为草稿」
  的探索运行、署名的立即运行)写得下「由定时任务」且「条事件」不竖排、Tab 到时看得见;图标;定时任务删除后的纯文本
  和列表取不到时照旧是链接;390 宽深浅色下计数在屏幕里、对比度够
2026-10-06 08:49:10 +08:00
ThearchyHelios 11d44ebc8a check-verify 补一节:记录页的工件列表里双盲复算对照、反方审稿记录有名字和说明
期 3 新加的两种工件此前没登记叫法,工件列表里露的是键名 dual_check、challenge,说明一栏只有一句「工件」。叫法表(pages/runs/model.ts 的 ARTIFACT_KIND_LABEL)已补上,这里守住:种类的叫法、说明(双盲复算带指标个数,没有 meta 的老数据也有一句),两种都算证据。按页面自己加载的那一份取,同 check-evidence 的工件一节
2026-10-06 08:25:23 +08:00
ThearchyHelios b0cf23ddda 双盲复算审批卡的写目录预告和服务端逐字一致,盲算的理由按理由文档画(前端)
- 预告逐条说:会写的说「哪张表的哪一项会记为……」,不写的照服务端的原话说「不会记入:原因」(和裁决后时间线上跳过的原因一字不差),不再只有一句「不记」看不出为什么。三条分行列出,原因再长窄屏也不撑宽
- 被目录挡下的一边(已确认、驳回过、和已有条件合不起来)服务端照样带着写到哪,卡上据此认出几个指标是不是落到同一项上
- 同一次裁决里几个指标按当前的选择落到同一项上时,照完整对照里服务端算好的合并预告(catalog_joint)说:会写的是合起来的值、写明和哪几个指标一起记入,不写的照原因说;选择一变跟着换成那一组合的结果。工件里没有(老服务端、组合太多、工件还没取到)或认不出时,回到按其余指标当前的选择有条件地推
- 盲算的理由:对照工件带了 rationale_doc(核查 agent 组装、裸数字已标出)时按文档画,和反方审稿的理由同一种画法:有出处的数字画实线、挂盲算自己的查询编号,裸数字画点状线、挂「无证据」,下面再醒目地说一句;老工件只有正文,照旧纯文本
- 夹具 dual_check.json 补 catalog_blocked(目录里已有人工确认的业务日期时的真实预告)、merges 各组合的 catalog 与 joint(服务端按那一组合的目录算的真实输出)、filters_rejected(驳回过的条件),盲算理由换成 compose_doc 的真实输出;test_dual_check_fixture 核对预告与服务端一字不差、joint 里按选择取出的那一条就是真写的结果
- check-verify 补三节:被目录挡下的一边、照合并预告说并和真写核对、合并预告认不出时回退;理由文档的实线、裸数字、提醒和老工件的纯文本
- dual_check_facts._write 的返回标注改成和 _record 一致(写进去的说法或 None)
2026-10-06 08:11:02 +08:00
ThearchyHelios f8adbaa463 核查类节点检查器的通用控件合成一份:选画布节点、三态开关、核查模型选择只留在 verifyFields.tsx
期 3 两个工作包各写了一份:双盲复算在 DualCheckFields.tsx(选口径卡、启用三态、盲算模型),反方审稿在 verifyFields.tsx(选报告、启用三态、反方模型),说法和细节各不相同、修一处漏一处。现在双盲复算改用 verifyFields 的 NodePick、TriState、ProviderPick、ModelInput,只给自己的文案;它特有的选指标、口径说明、相对误差留在 DualCheckFields.tsx。写进配置的值不变(留空写回 undefined,三态只认真布尔)。

- NodePick 加可选的分组(上游的一组、画布上其余同类的一组,选了不在上游的照样能选、下面提醒连到上游)、下拉项和缺省名的写法;写着的卡被删了、写的不是口径卡(助手改图、导入 JSON 会写出这种配置)时双盲复算也照实列出、说一句,不再只认「不在画布上」
- TriState 可选在「跟随设置」后面写出设置里现在是开是关(双盲复算用,每次打开检查器重取设置);设置的取法 useVerifyDefaults 挪到这里共用,用不上的控件不发请求
- 画布节点、连线的类型收窄成两边都给得出的 CanvasNode、CanvasEdge,节点卡片摘要和检查器共用 upstreamOf、resolvePick
- check-verify 跟着改:提示、三态、按模型名找接入的标记换成共用控件的;字段叫法从 engine/labels.py 读(期 4 从 schema.py 挪过去);补写着的卡不在画布上、不是口径卡两种情形
2026-10-06 08:10:10 +08:00
ThearchyHelios 0726a97512 审批质询(前端):报告排版变了时浮出的「质询」跟着选区走,check-inquiry 去掉一处时序竞争
- 浮出的「质询」原来只在选区变化、滚动、窗口变化时重新量位置。悬停一句时它的「质询」出现、那一段多折一行,下面的字整体下移,既不滚动也不改选区,按钮却停在原处、压到字上。改为同时用 ResizeObserver 看文档自身的尺寸,变了就重新量
- check-inquiry 加一段:选区上面的内容变高(不滚动、不改选区),按钮仍贴在选区下方;先确认没有这处改动时变红(按钮落后 24px)
- 「贴着报告框底边」那段:Esc 之后焦点下一帧才回到原文起头那一句的「质询」,它一出现那一段多折一行、量好的那一行被挤出框外,负载高时偶发超时(三遍里挂两遍,诊断确认是这个次序)。改为等焦点落定再量,并先把报告框放进视口;四道并行连跑三遍全过
2026-10-06 08:08:06 +08:00
ThearchyHelios 20c24fcf8c 反方审稿审批卡说清「根本没反查」和「到底降不降档」,运行类别取不到时不说出具(前端)
- 服务端给了 unreviewed(核查模型不可用、触顶、数据源不在了等没能反查的句数)就另起一行「N 句没能反查,已记为无法判断」:这几句混在「无法判断」里,分不出是查了数据不够还是一条都没查
- 「出具会降档」只在正式运行、有被推翻的结论、服务端的 degrades 为真时写(老服务端没给时照旧按「不是只标注」算);按降档处置却不在带出具契约的成果节点上游的,说一句为什么不影响出具档位,不再让审核人以为会降档
- 运行类别取不到时一句和出具有关的话都不说:以前写「暂时无法确认运行类别;如为正式运行……会降档」外加重试,卡顶却按审批自带的运行类别写着正式运行,两处打架。窗口重新拿到焦点时照旧再取,取到正式运行后降档提示才出现
- 理由文档的画法(RationaleDoc)导出给双盲复算的审批卡用:没给跳转时有出处的数字不是按钮,只画实线、挂查询编号、读屏念出处
- 检查器帮助里「结论被推翻时」的选项名照下拉写(出具降档 / 只标注 / 报错并停止运行),和服务端报错里点的名字一致
- 预览用例补没能反查、不在出具路径上两种;check-challenge 补这两段、改写取不到运行类别那一段,并新增一节逐项比对 engine/labels.py 的 CHALLENGE_LABEL、CHALLENGE_ON_REFUTED_LABEL 和检查器的字段名、下拉选项
2026-10-06 07:53:47 +08:00
ThearchyHelios e35d19d014 出具缺口里核查报上来的另起一组「核查未通过」,时间线认得期 3 留下的三个核查日志代码(前端)
- 时间线的出具那一行、成果节点卡片的出具印章、证据页的出具横幅:双盲复算、反方审稿报上来的缺口(「双盲复算「节点名」:」「反方审稿:」开头,按节点类型的前缀认,名字里带这几个字的别的节点不算)归在「核查未通过」下,不再和「校验不完整」混在一起——它们是核查查出来的问题(两路结果不一致、结论被推翻、指标无法复算),不是校验没做完。分组只有 run/decode.ts 的 splitIssuanceGaps 一处,三个地方共用
- 时间线解读 dual_check_unchecked(哪几个指标无法复算、各自的原因)、challenge_unreviewed(几句没能反查、第一句的原因)、challenge_sources_lost(几句只查了部分数据源、没查成的源):以前认不得,只能照原话显示;记入数据目录那一行带上写进去的值,写法同审批卡的预告
- 反方审稿的时间线文案从 DUAL_CHECK_TEXT.challengeLog 挪到 CHALLENGE_TEXT.log(各节点的文案放在各自的块里),decode.ts 跟着改引用
- 工件种类叫法补上 dual_check(双盲复算对照)、challenge(反方审稿记录),工件列表不再显示键名
- check-decode 补一节:三个日志代码、出具缺口的分组和顺序、前缀不重复节点类型、缺字段的老日志不崩
2026-10-06 07:53:18 +08:00
ThearchyHelios 35ec307baf 运行对比前端打磨:离开运行详情后晚到的答复不再跳走,下一步只指向真走得通的路
查找基准期间离开运行详情:以前只靠组件卸载时取消请求。路由按过渡渲染换页,地址已经换了、新页面还没画出来的那一下
答复回来,组件还在、请求也没取消,照样把人拽到对比页。现在答复回来时再比一次地址(只比路径,换视图、改筛选不算离开),
人已经不在点菜单时的那个运行详情上就不跳,找不到基准时也不弹提示。

换基准的下一步:409、422、缺基准的 404、找不到默认基准,都先看下拉里有没有能换的运行(已封存、不是本次、也不是当前的
基准,409 时出问题的可能正是它),没有就照实说没有其他可换作基准的已封存运行,不再叫人去上方选;还不知道时先不说。
本次的运行记录不存在时,换基准的位置只说列不出同一工作流的运行,不给重试几次都一样的「重试」。

check-compare:「离开之后答复才回来」改成去定时任务列表(进去之后不再自己换地址,/data 会再换成 /data/databases,
晚到的跳转能被盖住),等那一页落定、运行详情卸下再放行,断言走过的地址里从没出现过对比页;另加「立刻放行」:只换地址、
先不通知路由,把空当撑住再放行,找到基准的不跳、找不到的不弹提示。再加下拉里没有能换的运行时 409、422、缺基准 404 的
下一步,和本次记录不存在时换基准的位置不给重试。去掉实现后这些检查各自变红(两轮,共 8 项)。
2026-10-06 07:44:49 +08:00
ThearchyHelios f8ac8dc1d6 定时任务自动对比收尾:基准那一次不在终态或被删时不给对比、对比工件读不出来时触发历史照常打开;检查脚本按实际底色量对比度
- 触发历史的 compare:以前只看这一次的运行在不在终态。基准那一次被强制删除、失败后被继续执行时,对比页比不了,
  「对比上一次」链过去只会报错——基准一侧同样要在终态,否则给 null
- 对比工件读不出来(权限、磁盘出错)时记一条警告、给 null:以前 OSError 直接抛出,整页触发历史回 500。被改过
  (内容与哈希不符)的以前就给 null,这次补上用例
- check-schedules:页头的定时任务链接、触发历史的「对比上一次」改成量 WCAG 对比度(≥ 4.5),底色顺着祖先叠到
  不透明为止。以前比的是「字色不等于页头的底色」,页头本身透明,那样比永远成立;深色也补上同样的检查。另加一项
  署名的立即运行配长名字:署名照写、链接截断、页头不横向溢出
2026-10-06 07:43:01 +08:00
ThearchyHelios a4e0043985 审批质询(前端):划选原文浮出的「质询」挂在报告文档里,画布审批浮层里点它不再把浮层收掉
- 原来浮出的按钮挂到页面末尾(fixed)。画布节点上的审批浮层(canvas/NodeCard)在 document 上按捕获阶段听 pointerdown,按在浮层外面就收起:一点浮出的「质询」,浮层连同报告一起收掉,划选原文问不成
- 改成挂在文档里一个高度为 0 的定位锚点下面(absolute,坐标按锚点算),按下的位置就在审批卡里;挂在文档里会被限高滚动的报告框裁切,所以按可见范围摆:视口和每一层会裁切的祖先取交集,下方放不下放到选区上方,左右收进文档宽度(不把报告框撑出横向滚动),选区整个滚出可见范围时不留按钮
- check-inquiry 加一段:模拟浮层「按在外面就收起」的监听,点浮出的「质询」不算外面;报告框压矮、一句的第一行贴着框的底边时划选,按钮看得见(不被框裁掉)。两项都先确认在旧写法 / 去掉上下翻转时变红
2026-10-06 07:40:43 +08:00
ThearchyHelios 98eb9436a1 审批质询(前端)收尾:问答串的时间排序与焦点交接改稳,check-inquiry 的耗时按实测登记
- 问答串按提问时间排序改用 lib/format 的 parseServerTime(不带时区的服务端时间按 UTC 认,秒级时间戳照认),不再自己拼一套
- 焦点交接改成按「这一次提问」记:提交时焦点丢了才接到正在回答的那一条,回答回来、条数确实多了才播报并接到回答上;没问成(提问框带着报错重新打开)不抢焦点,列表重新取回来也不误报「已收到回答」
- 报告文档在有问答、开着提问框或正在回答时就取:回答引用报告已有出处时要靠它在报告里找到那一处,不再只在问答带句子时取
- check-all 的 ESTIMATE 里 inquiry 按四道并行的实测改成 22 秒
2026-10-06 07:34:26 +08:00
ThearchyHelios ddc95ccbad 证据面板显示核查状态:指标步骤的双盲复算一行,整句的反方审稿判断,遮罩列的输入只写「已遮罩」
指标步骤多一行双盲复算的结果:一致(带盲算值)、不一致(带盲算值和审核人选了什么,没选的照实说)、无法复算(带原因)、
已跳过(关闭了、口径卡上没有来自查询的输入、这个指标不在复算范围内)。结果都写成字,颜色只表达要不要多看一眼。
点开一整句时,反方审稿的判断复用审批卡上的展示(run/ChallengeSummary,只读它的导出),只列这一句,点开看反方的理由和查询。
取自遮罩列的输入,标签照查询表格里遮罩格的样子写「已遮罩」,输入来源里核对不一致时只说不一致、不写两边的值。
接口字段的类型就近写在面板里,不动 types.ts;界面文案放 EVIDENCE_TEXT。

check-evidence 加一节:六种双盲状态的文字和颜色、深浅色对比度、没复核过的不画;遮罩输入的标签、代入式、遮罩说明、输入来源;
整句面板的反方审稿判断、降档说明、点开取审稿记录看理由、没审到的句子不画、390px 不横向溢出。
2026-10-05 19:15:14 +08:00
ThearchyHelios 3dd5216af2 审批质询(前端):报告上的入口、问答串与提问框、回答渲染,审批卡与运行详情的挂法,check-inquiry 换成真检查
- run/Inquiry.tsx:质询的 store(列表按运行与报告缓存、一次运行同一时刻只有一条在回答、请求不随组件卸载作废)、ReportInquiry(问答按句子归拢、同一句下按时间排,进入时按列表接口恢复;就整份报告提问;正在回答的那一条)、提问框(显示被问的那句或划选的原文,Esc 关掉、焦点回到点开它的「质询」,Ctrl+回车提交,字数上限 1000、原文 500,409/422 照服务端的中文说明显示、问题留着)、回答渲染(数字的出处同报告:质询自己的查询点开按质询工件接口取快照、标出那一格;引用报告已有出处的交给页面在报告里打开证据面板;裸数字点状线)、查询列表(SQL、行数、截断、遮罩)、recorded 为假时醒目说明
- EvidenceDoc.tsx 只加入口:父组件传入 inquiry(是否可问与 approval_id)。每句结论后的「质询」平时宽 0、透明,悬停或焦点在这一句上时出现,只在焦点在这一句上时进 Tab 顺序,整份报告不多出一串 Tab 位;没有可点内容的句子,「质询」本身进方向键的顺序;触屏一直显示。划选原文浮出「质询」,原文按选区克隆、去掉徽标和小标签,证据面板里的字不算
- ApprovalReport.tsx:报告核对概况下面挂问答串,逐段证据带上入口;回答里引用报告已有出处时展开逐段证据、在那一处打开证据面板
- 文件所有权之外的两处最小改动(交付说明里写明):RunPanel.tsx 把待处理审批的 id 传给 ApprovalReports,回答期间批准 / 驳回停用并说明原因;pages/runs/EvidencePane.tsx 对封存了的探索运行给入口并挂问答串(判断用 Inquiry.tsx 导出的 inquiryOpen),正式运行不给
- 预览用例 dev/fixtures/inquiry.tsx 与夹具 inquiry.json(报告文档、回答文档由后端 build_catalog + compose_doc 真实组装,虚构数据);check-inquiry.mjs 用 page.route 假接口逐项断言入口、请求体、回答期间停用、问答串恢复、数字取质询工件、报告出处、recorded 为假、409/422、已处理审批与正式运行封存后无入口、390px 与深浅色
2026-10-05 19:13:07 +08:00
ThearchyHelios 59f1868dac 可验证报告的运行结果按封存范围内真正截止的那条结束事件核对
早期运行先失败、经继续运行跑到成功的,封存范围里留着中途那条运行失败,成功结束的那条在范围外(run.finished 落库之前封存)。
以前 checkMeta 拿范围内最后一条结束类事件去对,把运行结果改成「已失败」也标「已核对」。现在只认范围内最后一条、且是结束类
事件的那一条;没有这样一条时,早期运行成功结束照旧说无法核对,别的说法写明那条失败之后运行又继续了、没有事件印证,判不通过,
页面顶上显示「—」而不是把文件里写的当成核对出来的。

样本页加一份 continued(先失败、继续运行到成功的早期运行),check-bundle 断言它原样时无法核对、运行结果改成已失败或已取消时不通过。
2026-10-05 19:06:32 +08:00
ThearchyHelios 863b0b2894 定时任务前端:触发历史加「对比上一次」,运行详情页头的「由定时任务「X」发起」改成键盘可达的链接
- 触发历史:服务端给了 compare 的那次触发,在运行链接前加「对比上一次」,链到对比页(本次是这次触发的运行、
  基准是服务端自动对比时取的同一任务上一次),带上来历让对比页写「默认基准:同一定时任务的上一次运行」。悬停写
  各类指标的个数,和 Webhook 通知那一行同一个写法(三类总写、其余有才写、两边都没有指标时不写一串 0 个),读屏
  当说明念;只有个数。compare 为 null、老服务端不给时不显示
- 运行详情页头:定时任务发起的运行,「谁发起的」那一段换成到 /schedules/:id 的真链接(Tab 到得了、回车能开,
  有焦点环)。到点发起的(署名是「定时任务:X」)整句换成「由定时任务「X」发起」,不再写两遍;有人署名点了
  立即运行的,署名照写、后面接「来自定时任务「X」」。名字取定时任务现在的名字,取不到用署名里记的;长名字截断,
  全名在悬停里。记录页「定时」标记的说明同步改成指向这里
- types.ts 定时任务那一段加 ScheduleFireCompare 和 ScheduleFire.compare;文案进 SCHEDULE_TEXT
- check-schedules:触发历史的对比链接(地址、悬停的计数、只在有 compare 的行出现、Tab 到得了、回车打开对比页)、
  运行详情页头的链接(现在的名字、真链接、不重复署名、Tab 到得了且有焦点环、回车去定时任务、署名的立即运行、
  手动运行没有、长名字截断不撑宽、浅色可读),390px 深浅色下对比链接在屏幕里、看得清
2026-10-05 18:58:25 +08:00
ThearchyHelios 23cdc986fc 审批质询(前端)第一步:质询的类型与接口、时间线解读 approval.inquiry
- types.ts 末尾按前后端约定加 Inquiry、InquiryRequest/Response、查询与快照的类型,字段名一个不改
- api/inquiry.ts:提问(POST,不设超时,服务端自有时长上限)、列出问答、取质询引用过的查询快照(外层包不包一层都交给界面认)
- decode.ts:approval.inquiry 不再落进「未识别的事件」,解读成顶层一行「审批人质询」:标题带问题前 40 字,副标题说回答完成 / 不完整(写明哪个上限)/ 未能回答、查了几次,封存之后问的写明封存后追加;缺字段、类型不对的照实少说,不拿 0 顶查询次数
- check-decode 断言上述说法与缺字段的兜底;check-trace 加「运行停在审批时来了一条质询,相位仍是等待」:等待段不被收掉、执行时长不涨、恢复后照常跑完、每个前缀上 trace 与 decodePhase 一致
2026-10-05 18:46:03 +08:00
ThearchyHelios 14dcbe19bb 合入期 3 反方审稿(前端):审批卡与证据里的反方审稿概况、逐句判断与理由、检查器
# Conflicts:
#	frontend/src/canvas/nodeDefs.ts
#	frontend/src/types.ts
2026-10-05 18:10:06 +08:00
ThearchyHelios bcad199e0f 双盲复算前端复核修正(第 3 轮):同一次裁决里几个指标落到数据目录的同一项上时,卡上按其余指标当前的选择说——说法不同的改说都不记,有效记录条件说合成一句
问题:服务端写目录前把同一次裁决里落到同一张表同一项上的说法归拢(dual_check_facts._merged):业务日期、去重规则只要说法不同就一项都不写,有效记录条件用 AND 合成一句写。审批卡上的预告是每个指标单独算的,卡上不看别的指标选了什么:一个指标采用原流程(paid_at)、另一个采用盲算(created_at),两块里各自加粗说「记为……」,服务端一项都不写;两个指标都采用去重的一边、去重的列不同,也是这样。结尾只说按发起审批时的数据目录预告,看不出选择的组合也会让写入作废。审核人可能为了不让同一张表出现两个业务日期,把本该分开的选择改成一致。

审批卡(run/DualCheckApproval.tsx)
- 按其余指标当前的选择,给每个指标的两种选择各找出落到同一数据源、同一张表、同一项上的指标(peersOf)。只看预告会写的一边:选「两边都不对」、还没选的,服务端不会并进来。说法照服务端的 _same_fact 比:业务日期只看哪一列,其余压掉多余的空白比。
- 业务日期、去重规则说法不同时,那一句改说「……与「退款率」的选择说法不同,都不记」,不再算作会写。有效记录条件在「记为……」后面补一句「与「退款率」采用的条件用 AND 合成一句」。
- 选择一变,各块的说法跟着变。没选中的那几句也按别的指标当前的选择说,审核人改选之前就看得出这一选会不会让整项作废。
- 结尾改成「写入的项记为人工确认的事实;以上按发起审批时的数据目录和各指标当前的选择预告……」。原来是「两边都不对时不记。记为人工确认的事实」,读起来像在说不记的那一项。
- 没有预告时的结尾同样改。时间列、去重两句补上「同一次裁决里几个指标给同一张表记的业务日期(去重规则)不同时都不记」。

夹具与检查
- 夹具加 peers 和 merges。peers 换掉「退款率」对不上的那个输入,和「销售额」落到 orders 的业务日期、去重规则、有效记录条件上。merges 是四种组合:业务日期分开选、选同一列、去重的列不同、有效记录条件不同。
- peers 的差异说明和预告是服务端的真实输出。merges 的 written 是 record_choices 在空目录上真写一遍的结果。
- test_dual_check_fixture.py 新增两项。一项不依赖服务端,查每种组合真的落到同一项上。另一项在服务端合入后建临时数据源真写一遍,逐项比对。
- 在 vs/f1a 的 f7d1a2e 和 233afd1 上都跑过:8 项全过,regenerate 逐字节不变。
- 预览用例 dual-check-approval 认 peer 参数。
- check-verify 新增一节:
  - 分开选时,两边加粗的那一句都说都不记,写明哪张表的哪一项、和哪个指标说法不同。
  - 没选中的那一句按别的指标当前的选择说;一个指标改选两边都不对后,另一个回到「记为」。
  - 选同一列照常记;去重的列不同都不记;有效记录条件说合成一句。
  - 390px 下深浅色都不横向溢出。
- check-verify 没有预告的一节补两项:「人工确认」说的是写入的项;说法不同时都不记。
- 变红验证:去掉实现(peersOf 返回空),check-verify 变红 6 项;把有效记录条件也当成说法不同,变红 1 项;把还没选、两边都不对也当成采用了一边,变红 2 项。
- 改动后 297 项全部通过(原来 274 项)。check-all 里 check-verify 的耗时估计按实测改成 71 秒。
2026-10-05 17:47:21 +08:00
ThearchyHelios b206665856 双盲复算前端复核修正(第 2 轮):「记入数据目录」不再说得比服务端宽——有服务端预告时照预告说,没有时只说必要条件、不写的几种照实说
问题:审批卡上那句「记入数据目录」的提示是照 vs/f1a 早先的规则写的。F1a 在 1491b5c 把写目录的规则收紧以后,有三种常见情况卡上说会记入,服务端却都不写:
- 只有一边按时间筛:卡上写「两边只差在按哪一列筛时间」,和正上方那条差异「盲算没有按时间筛选」自相矛盾
- 只多一个指标自己范围的条件(channel = 'web'):服务端只把排除退款、作废、测试这类无效记录的条件记成有效记录条件
- 只差去不去重,而审核人采用的是不去重的一边:服务端不写
审核人可能为了不让目录被写错,避开本来正确的原流程,结果出具降档;节点设为「判为失败」时运行还会终止。

审批卡(run/DualCheckApproval.tsx)
- 服务端在摘要里另带预告(payload.summary[].catalog,F1a 在 f7d1a2e 加的,约定之外另带)时照它说:三个选择各说一句,会写的写明哪张表的哪一项记成什么,不写的写「不记」。两边都不写就不提数据目录。审核人当前选中的那一句加重,选完一眼就能看出这一选会写什么。预告跟着摘要一起来,完整对照还没到或取不到时也照样能说。预告的形状认不出时整份不用,回到有条件的说法。
- 没有预告时(老服务端、升级前挂起的审批),三句改成只说必要条件(「仅当……才」),并把不写的几种照实写出来:只有一边按时间筛时不记;多出的条件得只在一边、并且是在排除无效记录,只看某个地区、某个渠道这类条件不记;采用不去重的一边时不记。
- payload 带了实际生效的「未采用原流程时」(同样是 f7d1a2e 加的)就照它说,不再去取图快照。子工作流里的节点在图快照里找不到,有了它也能说准;值认不出时仍回到图快照。

夹具与检查
- 夹具新增两个变体:只有一边按时间筛、只多一个渠道条件,差异说明都是 explain_sql_diff 的真实输出。每个指标、每个变体都附上服务端预告的真实输出(catalog_preview、variants[].catalog)。backend/tests/test_dual_check_fixture.py 有两项检查:一项不依赖服务端,查预告的形状和写目录的门槛;另一项在服务端模块合入后,逐项比对夹具和 dual_check_facts.preview。regenerate 也会一并重新生成预告。
- 预览用例 dual-check-approval 认地址参数 variant / catalog / on_reject,不带参数时 payload 只有约定里的几项。
- check-verify 按服务端的预告核对两种说法:没有预告的一节,在三种情况下都要以「仅当」开头,并照实说出不写;只差去不去重时,两种选择各断言一次。有预告的一节,核对两边写什么或不记、两边都不写时不提、选中那一句加重(去重的两种选择分别看)、认不出时回到有条件的说法、取不到完整对照时照样说,以及 390px 下深浅色的对比度。payload 的 on_reject 那一节核对:照它说、不取图快照、子工作流也说准、认不出时回到图快照。
- 去掉实现以后,检查脚本在这三种情况、预告和 on_reject 上共有 13 项变红。改动后为 274 项全部通过(原来 218 项)。check-all 里 check-verify 的耗时估计按实测改成 65 秒。
2026-10-05 16:56:05 +08:00
ThearchyHelios 52baa0d65c 双盲复算前端复核修正(第 1 轮):高亮按服务端真实的差异输出做,「记入数据目录」只在服务端真会写时有条件地说,后果和提示按节点的处置说
审批卡
- 对照两条 SQL:text_diff 是规范化之后的行(列名带表名、条件并成一行),和原文逐行对不上,原来按「两边逐行相等」高亮在真实输出上一处都标不出。改成两段原文按行做一次 LCS(不看空白、大小写和行尾逗号分号)高亮不同的行,一行都对不上时不乱标;text_diff 分原流程、盲算两栏,每行高亮(窄栏上下排)。
- 「只差一个方面、会记入数据目录」:照服务端 dual_check_facts 的门槛收紧——不等价、没用兜底、差异恰好一条(几个输入都对不上时合并后至少两条,所以也就是只有一个输入对不上),且是时间列、筛选条件或聚合;按这三种分别有条件地说会记成哪一项,选「两边都不对」不记、已有人工确认的不覆盖、以时间线为准。时间范围、两条筛选、关联、解析失败、多个输入合并都不再说。
- 后果和提交后的提示:payload 不带 on_reject,从这次运行的图快照里按节点 id 读「未采用原流程时」;判为失败时写明采用盲算或都不对会终止运行、提示也照实说,缺省时不再挂那句,读不到时有条件地说、提示不下结论。
- 只有解析失败时和摘要阶段一样按兜底说(固定那句 + 解析的原话),默认展开对照;兜底的原话另有原因(比较超时)时附在下面,一边没有 SQL 时不说「两条 SQL 的写法不同」。
- 认不出任何指标时留一个「驳回并终止」(approved 为假),运行不再一直挂着。

时间线
- dual_check_catalog 的 item 是目录项的键(business_date 等),按数据目录的叫法写成「「orders」(shop)的业务日期」,认不出的键不显示。
- dual_check_limit 的 metric 是指标 ID,不再当名字加引号。
- challenge_skipped 的 no_report 是报告文档读不出来(报告节点找不到时节点直接报错),说法和下一步改成去查报告节点有没有执行成功、在不在执行到的分支上。

检查器
- 字段名和服务端校验报错的叫法(schema.py 的 DUAL_CHECK_FIELD_LABEL)对齐,处置选项以服务端的短说法开头;check-verify 在服务端合入后逐项比对。
- 盲算模型移出高级选项:时间线「模型相同」的定位要找得到它。
- 上游有几张口径卡时写明必须选(服务端校验会挡住发起运行),不再说「建议指定」。
- 「跟随设置」的当前值每次打开检查器都重取,改了设置回到画布不再是旧值。

测试
- 夹具里的差异说明换成 explain_sql_diff 对同一对 SQL 的真实输出,新增几对 SQL 的变体;backend/tests/test_dual_check_fixture.py 核对夹具和真实输出一致,并可重新生成。
- check-verify 补真实形状下的高亮、各种差异下「记入数据目录」说不说、只有解析失败和兜底原因、按处置说后果和提示、认不出指标时的驳回、叫法比对、多张口径卡、设置重取;check-decode 改用服务端真实的日志形状。check-verify 的耗时估计按实测改成 45 秒。
2026-10-05 16:10:55 +08:00
ThearchyHelios 12dc47b976 期 3 反方审稿(前端)复核修正:要审的报告按服务端的认法定,校验报过的不再重复,补齐降档提示的反例检查和运行类别取不到时的说明,修好显示全部的焦点与去重,处理审稿记录没存上的情况
检查器
- 「要审的报告」留空时,照服务端 schema.challenge_report 的认法:先看直接连着的报告撰写节点,恰好一个就审它;不是一个时,整个上游只有一个才取那一个。以前只认第二步,「初稿 → 终稿 → 反方审稿」这种接法下会误报「上游有 2 个,请选择」,同模型提醒也不出。现在留空项写出实际会审的那份(「未选择:审上游的「终稿」」),同模型提醒也按同一套认法判断。
- 认法写成 nodePickField / upstreamModel 的 rule 选项。缺省是 'upstream'(只看整个上游),和 F1a 的 dual_check_card 一致,双盲复算以后也能直接用。
- 选中的节点在上游、类型却不对(例如输入节点),以前写成「不在上游」,现在照实写「不是报告撰写节点」,提示里说清它是哪类节点。判断顺序和服务端一致:先看存不存在,再看类型,最后看在不在上游。
- 画布校验已经在 report / model 字段上报过问题时,不再画本地那句提示,避免同一件事一琥珀一红说两遍。判断哪些问题属于本字段,用和 Inspector 挂字段时相同的 fieldOfIssue;下拉里照实标出的那一项保留。
- 文案里的设置入口统一写成「设置 → 偏好设置 → 核查」,和设置页的真实标签、双盲复算、证据裁判的写法一致。

审批卡
- 降档的原因改为常显在概况下面,不再只放在悬停提示和读屏文字里。
- 运行类别取不到时,不再悄悄不写降档:照实写「暂时无法确认运行类别;如为正式运行,被推翻的结论会使出具降档」,并给出重试按钮;窗口重新拿到焦点时也会再取一次。
- 「显示全部」补句时按 unit 去重:两边都有 unit 时只比 unit,有一边缺 unit 才比原文。以前原文相同、unit 不同的一句会被吞掉,被吞的可能正是被推翻的那句。条目缺 unit 时不再补假的 #i。
- 键盘按「显示全部」、补句那一行的重试、一句详情里的重试、运行类别的重试之后,焦点都会接到新出现的内容上,不再掉到 body。焦点已经被用户移到别处时不抢。
- 审稿记录没存上(artifact 为 null)时,每句只列判断,不能点开,整块说一句「反方审稿记录未保存,无法查看理由和查询」;「另有 N 句未列出」照常显示,只是不给「显示全部」。

检查(check-challenge 共 153 项)
- 新增预览用例:正式运行且没有被推翻的结论(降档 / 只标注)、探索运行配只标注、运行类别取不到、原文相同而 unit 不同、审稿记录没存上、链式接法的检查器。
- 「只标注、探索运行、没有反方审稿」拆成各自独立的段,一段出错不会遮住其余几段。
- 新增的检查项包括:降档原因常显、取不到运行类别时的说明和重试(含窗口重新拿到焦点后再取)、显示全部和各处重试后的焦点、按 unit 去重、审稿记录没存上、链式接法、类型不对的节点、校验报过就不重复说,以及窄屏和深浅色下新增几行说明的对比度。
- 复核时用来证明检查不够的两个变异,M1(正式运行一律写降档)和 M10(探索运行也写只标注说明),连同本次各项修正的变异,都已逐一确认会被检查发现。
2026-10-05 15:35:01 +08:00
ThearchyHelios f2e854842c check-all:check-verify 的耗时估计按实测改成 25 秒
占位时登记的是 1 秒;换成真检查后单独一遍约 20 秒、四道并行时约 20 秒,按略宽的数排队
2026-10-05 14:44:31 +08:00
ThearchyHelios 5093e98c49 双盲复算前端(四):设置页「核查」一节
- pages/VerifySettings.tsx(新):核查模型(照证据裁判的写法:两项都空时醒目提示将使用证据裁判的模型,只填模型时写明
  按模型名用哪个接入);双盲复算(启用、允许的相对误差、每项最多查询次数、时长上限);反方审稿(启用、每份报告最多
  审几句、每句最多查询次数、时长上限);审批质询(启用、每次最多查询次数、时长上限);每日金额上限(可不限)和今日
  核查花费(GET /api/settings/verify/spend)。上限照 LimitField 的写法:勾「不限」框变灰、写明还受什么约束,勾掉填回
  原来的数;只校验改过的项;字段名就是服务端 VERIFY_SETTING_LABEL 的叫法,422 的报错对得上
- SettingsPage:PrefsTab 另持一份核查草稿,和其余设置共用保存条(改动计数、项名、放弃、校验都算上),保存时整组写
  verify(不限存 null),存完再取一次今日花费;老服务端没有 verify 一组时不显示
- check-verify 加设置页读回各项、叫法逐项比对、整组写的请求体、错了不让存、422 照实说、老服务端不显示、
  390px 不溢出、对比度
2026-10-05 14:31:16 +08:00
ThearchyHelios fb6f5c0ff9 check-all:check-challenge 的耗时估计按实测改成 17 秒(只影响排队顺序) 2026-10-05 14:26:15 +08:00
ThearchyHelios 7a9dc93dde 双盲复算前端(三):检查器字段、节点卡片摘要,以及检查器与节点卡片的钩子
- nodeDefs:照约定一字不差地加 FieldDef.render 与 FieldRenderProps;NodeDef 加可选的 summary(ctx) 钩子
  (ctx:id、config、画布上的 nodes 与 edges,只返回字符串);dual_check 换成真字段:要复算的口径卡、复算的指标、
  口径说明、启用、审核人不采用原流程的结果时(基本),盲算模型的接入与模型、允许的相对误差(高级)
- Inspector:照约定一字不差地在 FieldInput 的 switch 前交给 field.render
- canvas/DualCheckFields.tsx(新):口径卡下拉分上游、其余两组,不在上游或不在画布上照实提醒;指标逐个勾,
  全勾回到缺省不写、最后一个不让取消;口径说明逐个指标写,被取消的指标上已写的说明列出来可删;盲算模型照「结论句
  裁判」的写法(只填模型时写明按模型名用哪个接入);相对误差的占位写出设置里的值;启用三态,跟随设置不留 null。
  每个控件只写自己的键,留空写回 undefined
- NodeCard:用只返回字符串的 studio 选择器调摘要钩子,有就用、没有照旧 summarize;摘要写「复算「卡名」 · N 个指标」,
  关闭时标出;去掉 dual_check 的占位 case
- 预览用例加检查器(小画布用真的节点卡片 + 360px 检查器),check-verify 加检查器写配置、摘要跟着变、窄屏和对比度
- 去掉 nodeDefs 里已经不成立的「下面两种还是占位」注释
2026-10-05 14:23:17 +08:00
ThearchyHelios b58321f6b8 期 3 反方审稿(前端):先写检查——类型、预览用例与 check-challenge
- types.ts 末尾加反方审稿的类型(约定里的审批概况 payload.reports[i].challenge、challenge_artifact 工件),
  ApprovalReport 用声明合并补上 challenge 一项,不动前面的定义
- 预览用例 dev/fixtures/challenge.tsx:审批卡七种情形(正式运行默认降档、只标注、探索运行、没有反方审稿、
  超过十句、工件取不到、360px 右栏)和检查器(两个上游报告、一个下游报告的虚构图,旁边是节点卡片和实时配置)
- 夹具 challenge.json 与检查脚本共用;理由文档是后端 run_verify_agent + compose_doc 真跑出来的,库、表名、
  地名、数字都是虚构的
- check-challenge.mjs:概况计数、被推翻时的降档提示(只标注、探索运行不写)、逐句标签、点开后取工件并显示
  理由(数字的出处、裸数字)与查询、工件取不到可重试、超过十句显示全部、检查器字段写进节点配置、卡片摘要、
  390px 不横向溢出、深浅色对比度;登记进 check-all

此时还没有实现,检查全部不通过(7 段都超时),下两个提交补上
2026-10-05 14:09:45 +08:00
ThearchyHelios cac34c90dd 双盲复算前端(二):两路对不上时的审批卡,三选一裁决
- run/DualCheckApproval.tsx:期 0 的空插槽换成真组件。先按 payload.summary 画两个值、相差比例、摘要里的差异,
  完整对照(card_artifact)到了再补盲算模型、全部具体差异和「对照两条 SQL」;只有兜底说明时写明未能归纳成具体差异
  并默认展开对照;对照区先列每个输入两边各取到多少,只对照不同的输入,两条 SQL 按卡片宽度左右并排或上下排,
  text_diff 里有的行在原文中高亮,规范化后对不上原文的不乱标、另列规范化后不同的行;只差一个方面时说明选择会记入
  数据目录;每个指标三选一(原生单选,键盘可操作),缺一个都不能提交,回复走审批接口,value 为 {choices, note};
  后果按运行类别说,写明「采用盲算」不替换报告里的数,探索运行不提出具;完整对照取不到时按摘要照样能裁决
- RunPanel:payload.kind 为 dual_check 时不画通用的输入框、备注和「提交 / 驳回并终止」,署名那行保留,
  onResolved 交给 DualCheckApproval;其他审批卡不变
- 预览用例 dev/fixtures/dual_check.tsx(夹具 dual_check.json 与检查脚本共用,数据虚构)
- check-verify:期 0 的占位换成真检查——核查设置的叫法和服务端逐项比对,审批卡的摘要与补全、具体差异、只有兜底、
  并排与高亮、不选全不能提交、请求体、取不到完整对照、探索运行、390px 与右栏不溢出、深浅色对比度
2026-10-05 14:07:57 +08:00
ThearchyHelios 4d29b67cef 双盲复算前端(一):时间线解读双盲复算和反方审稿的全部日志代码,补类型和文案
- decode.ts:约定里的 12 个日志代码(dual_check_* 7 个、challenge_* 5 个)按 code 和结构化字段说成标题、副标题和下一步,
  不从原话里认;后端发成 info 的(一致、裁决、记入数据目录、审稿完成)也上时间线,否则这两种节点在时间线上什么都不说;
  有缺口、有推翻时用提醒色,完整对照和审稿记录的工件可下钻;老日志缺字段、类型不对时不崩、不瞎填数
- check-decode:每个代码一条断言,另有换一种取值和缺字段两组
- types.ts 末尾加双盲复算的审批 payload、对照工件、节点配置和设置里核查一组的类型
- terms.ts:DUAL_CHECK_TEXT 写全检查器、节点摘要、审批卡、时间线的文案(反方审稿日志的说法暂放 challengeLog);
  VERIFY_SETTING_TEXT 顶层和服务端 VERIFY_SETTING_LABEL 的键和叫法一字不差,其余放 section
- 去掉双盲复算节点说明里的「功能开发中」和节点卡片上的占位摘要
2026-10-05 13:54:45 +08:00
ThearchyHelios 8ed74bbe97 合入期 2 变化三分法(前端):运行对比页(摘要、指标表、效应拆分、维度归因、查询与模板差异),运行详情加「与上一次对比」
# Conflicts:
#	frontend/src/types.ts
#	scripts/check-all.mjs
2026-10-05 12:50:04 +08:00
ThearchyHelios 190b36ad91 合入期 2 定时任务(前端):定时任务列表、创建编辑(频率预设、实时预览、输入模板变量、Webhook 设置与测试)、触发历史,运行列表标出定时来源 2026-10-05 12:49:19 +08:00
ThearchyHelios 4b972b4f43 定时任务前端复核修正(第 2 轮):错过已跳过的悬停不再替服务端认定是超出补发宽限,没有记原因时不指向不存在的原因
服务端把两种没有补发的触发都记成 kind=misfire、status=skipped_misfire:一是超出补发宽限,二是在宽限内恢复时
积压的那几次(只发起最近一次,更早的不补)。触发类型「定时」的悬停却一律写「错过后已超出补发宽限」,积压那条的
原因写的是「积压的触发不补,只发起最近一次」,同一行给出两个互相矛盾的原因,而这条明明是在宽限以内被跳过的。

- 触发类型的悬停改成不点明原因:「按计划应在此时触发,错过后没有补发,原因见本条记录」;本条没有记原因时去掉
  「原因见本条记录」。
- 结局悬停的兜底说明(本条没有记原因时用)一起改:错过已跳过不再写「超出补发宽限」,两种原因都适用;发起失败
  不再写「到点」(手动立即运行也会发起失败),也不再写「原因见本条记录」(用到兜底时本条恰好没有原因)。
- check-schedules 的触发历史夹具按服务端的原话各放一条积压不补、超出宽限的跳过,外加错过已跳过、发起失败各一条
  没有记原因的;断言整行连同各处悬停只说本条记的原因,不说另一种,不指向不存在的原因。修复前这几项红 5 项。
2026-10-05 11:05:42 +08:00
ThearchyHelios defd118ea6 定时任务前端复核修正(第 1 轮):时区检查改成真能拦住,服务端会拒的组合当场拦下,修几处时序问题
- check-schedules:浏览器本机时区改成 America/Los_Angeles,和夹具里的 Asia/Shanghai、America/New_York 都不同。列表的下次运行和上次触发、触发历史 20 行、预览 5 个时刻,都改为比对按定时任务时区写出的原文;假预览照真服务端那样按所选时区排时刻。把页面改成按本机时区显示的变异会让 6 项变红。原先恒为真的「只读」断言改为真正检查写请求。
- 测试消息的结果:服务端的 message 只是补充说明时接在结局后面,已经是整句时不再套一层,状态码只写一次(webhookTestText)。
- 正式运行 + 工作流没发布、必填输入没填、填了已发布版本里没有的字段:照服务端保存时的核对规则当场拦下(新建总查;修改只在改了工作流、运行类别或输入时查),说明写在对应那一项下面。保存被拒、服务端指明 run_class 或 misfire_grace_s 时,说明也写在那一项下面。
- 保存被 422 拒绝后,改了被指出的那一项,字段下的说明和底部的「保存失败」就收起;名称框的 aria-invalid 和 aria-describedby 也把服务端的说明算进去。
- 时序:列表和详情页在写操作成功时作废还在路上的读,晚到的刷新不再把开关盖回旧值。详情页先开触发历史再切到设置时,版本对齐到表单所基于的那一份。保存途中又改了别的字段时,只保留途中改的那几项,替换过的 Webhook 地址不再以明文留在输入框里。
- 其他:预览时间改用 parseServerTime 解析;换工作流时,自动填的名称跟着换;开关遇到 409 用前端自己的说明,服务端原话放进详情;错过且超出宽限、没有补发的触发,类型写「定时」而不是「补发」;记录页的「定时」标记让读屏念出是哪个定时任务发起的。
- 未达标:记录页的「定时」标记在整行的按钮里面,键盘到不了。键盘能到的入口要加在运行详情的页头,或者把整行改成「打开运行」按钮和链接并排的结构,这两处都不在本包的文件范围内,留给集成时处理。
2026-10-05 10:26:22 +08:00
ThearchyHelios c7a9116424 运行对比页复核修正(第 1 轮):照服务端的实际输出改查询编号、无法比较的原因、读不到的基准和未保存工作流的说法
- 查询区不再拿服务端的 (node_id, ordinal) 当键和编号:配上的一对取本次的序号、落单的基准查询取基准的序号,
  Agent 换了查询先后时两者会撞上,React 报键冲突,「第 N 条」重复或缺号。改按同一节点在列表里出现的先后编号,
  键是「节点:第几」。
- 「拆分或原因」一栏:无法比较、新增、移除的指标,服务端只把原因放在 reasons 里,这一栏原来只剩「—」,现在写
  reasons 的第一句。不能拆的「为什么没拆」也写进展开的明细,窄屏上那一格横着滚也看不全。服务端有意不做维度归因
  的几类,写明为什么不做。检查夹具改成服务端的实际形状(decomposition_note 为 null):原来那一项是靠编出来的字段
  通过的。
- 换基准下拉:当前的基准读不到时单列一项,写短 id 和「记录不存在」或「无法读取」,不再显示成另一次运行被选中、
  选它又没反应。本次的记录读不到时写明原因并给重试,不再一直停在「正在读取」。运行卡读取失败也给重试,记录不存在
  的照实写。
- 不属于已保存工作流的运行(没保存过,或工作流已删除):「与上一次对比」不可点并写明原因,对比页也不再叫人去上方
  选基准。服务端对这两种运行都不比。
- 错误说明:409 按机读码分「尚未结束并封存」和「封存核对不一致」,去掉界面上没有的「封存凭证条」。基准不存在时
  提示在上方另选。找不到默认基准时,下拉里有能选的运行才说「可在上方选择」。
- 菜单查找基准超过 300 毫秒就挂一条提示;离开运行详情时取消请求,晚到的答复不再把人拽到对比页。
- 一边的 SQL 拿不到时不做逐词比较,另一边不再整条标成「独有」。SQL 注释整段算一个词,注释里的撇号不再吞掉后面的
  语句。
- 分类、结构的悬停说明照服务端的分类口径改写;查询按「条」计数,和「第 N 条」一致。
- check-compare 按服务端的实际输出补上这些场景,并加段过滤 COMPARE_ONLY;check-all 里 compare 的耗时估计按实测
  改为 45 秒。
2026-10-05 10:16:15 +08:00
ThearchyHelios a9d7cba884 定时任务复核修正(第 1 轮):重启挂起的运行不再让任务静默停摆,格式选错、地址发不出去时照实报,整份回写不再丢掉到点的触发
- 挂起:上一次运行在服务重启时被挂起(interrupted、没有待审批)不会自己接着执行,之后每次触发都按重叠跳过,原因写
  「还没有结束」,一条通知也不推,任务就此静默停摆。interrupted 照规格仍算没结束,但跳过原因按挡路的运行分三种写
  (仍在进行中、正在等待审批、已挂起并请在「记录」中继续运行或放弃),运行编号写成界面上的 #前 6 位,去掉「按设置」;
  挂起的那次按 failed 事件推一次,写明原因和处理办法,不是每次触发都推。停在审批时每停一个审批点推一次(已处理状态
  带上第几段执行,以前第二个审批点不再推);审批刚批完、还没接着执行(answered)不当挂起
- 没有结束时间的失败运行(服务重启时还在排队、被改成 failed)永远不会封存:等封存改按最后更新时间算,以前按「现在」
  等,每一拍都等、永远不推
- 平台错误码按地址的主机认,不看所选格式:格式和地址对不上时,测试显示「已送达」、正式推送记成功,群里却收不到;
  现在记失败并带上平台的错误码。群机器人的地址(飞书、企业微信、钉钉)保存时要配它平台的格式,否则 422;格式省略时
  按地址认。只在地址或格式真改了时查,库里已有的旧设置不挡停用、改名
- 地址校验:端口不是 1 到 65535 的数字、夹着空格或不可见字符(零宽空格、控制字符)、httpx 建不了请求的(主机名不合
  IDNA 规则)保存时就回 422 和中文说明;推送时另兜住 InvalidURL 和其他异常,测试接口不再回 500 或英文报错;端口写错
  的地址也照样取出主机名
- PATCH 看值变没变,不看键在不在:整份表单回写不再重新校验没改的工作流(工作流删了也能停用),cron、时区、启用状态
  真改了才重算下一次触发。启用着改 cron、时区时,从原来那个到点的时刻接着算,新表达式也覆盖那一刻就还发起这一次。
  补两人同时保存的测试,证明条件 UPDATE 守住了乐观锁
- 发起中的占位:接口读到正在发起的触发按「已发起」给(run_id 为空),不再闪一次「未能发起:服务在发起运行前停止」;
  库里仍先写占位,进程被强杀时照实说没有发起
- stop:先置停止标志再取任务,这一拍收尾不再新起通知扫描(以前会落下一个不在等待名单里的通知任务);循环和通知两件
  事并行等,宽限缩到 3 秒和 1.5 秒,给关停时的 run_manager.shutdown 留出 docker stop 的大半时间
- 通知正文:立即运行写「手动触发」,补发标明「错过后补发」;失败不再写「原因:运行失败,详情请查看运行记录」,改写
  失败节点的名字和处理办法;状态叫法和界面一致(等待审批,已挂起,可继续运行);「封存哈希」改叫「清单哈希」,运行
  编号写 #前 6 位;测试消息只说收到它证明得了的事(企业微信、没配密钥时不提签名)。测试接口的 message 改成 ok、
  http_status 之外的补充说明(送达时提醒去接收端确认,失败时是原因),前端接在「测试消息已送达(HTTP 200)」后面不再重复
- 422 文案:不回显 Python 的值(None 写「未填写」,列表不原样回显、点出不认识的那一项),格式、事件写中文名;
  copy-allow.json 为平台名「钉钉」加一条(和前端包为 terms.ts 加的那条并存,试合并不冲突)
- test_loop_ticks_until_stopped:下一次放在整分上、只认发起的那一条,去掉约 1/60 的偶发失败
- 逐个做过变异,改回后对应测试都变红:挂起不推、跳过原因退回旧写法、没结束时间按现在等、错误码只看格式、去掉版本
  条件、到点保留和值比较一起去掉、不屏蔽发起中的触发、stop 既不查停止标志也不兜底、answered 当挂起、审批状态不带段号、
  不建请求校验地址、保存时不查格式
2026-10-05 10:00:25 +08:00
ThearchyHelios a0837cc82c 运行对比页复查修正:互换时不重取运行列表,拆分句的总变化为 0 时写「0」,展开控件只指向在场的明细
- 互换、换了本次之后,新的运行记录还在路上时沿用上一次知道的工作流:下拉不再先退回「正在读取」、再把同一工作流
  的运行列表取一遍(能比的两次运行本来就是同一个工作流);check-compare 补这一项
- 口径变了、数值却碰巧没变(两效应正好抵消)时服务端不给变化量的写法,拆分那句话的总变化写「0」,不再写成
  「两者之和等于总变化 无变化」
- 指标展开、查看 SQL 的按钮只在明细展开时才带 aria-controls,不指向页面上不存在的元素;参数前后两个值之间的箭头
  对读屏补一句「改为」
2026-10-05 09:06:18 +08:00
ThearchyHelios c77a7f38d5 check-schedules 换成真检查
真页面走真的应用外壳,接口全部在浏览器层答掉:定时任务、触发历史、预览、变量、工作流列表是虚构的门店周报、库存日报,写请求照接口约定改这里的假状态(PATCH 核对版本、Webhook 地址省略即不改、空串即删除);设置读真的、只换 notify 一组和主题,别的写请求一律拦成 503,不碰真实写接口。

查的是:
- 纯函数(借 vite 转译 model.ts):预设生成的 cron、cron 落回预设、按时区写时间和偏移(含夏令时)、距下次运行的取整、修改时只交改了的字段、Webhook 地址和密钥的省略与空串
- 列表:名字、工作流、频率说法、下次运行(相对加按时区的绝对时间、悬停看时区)、上次触发链到运行、暂停和跳过照实写;空态、老服务端
- 启用开关发 PATCH 且带版本、再点带新版本、409 说原话并重新载入、键盘空格切换
- 立即运行发 POST 并说结果(发起、跳过、被拒)、「查看运行」直达;删除先站内确认
- 新建「每周一 09:00」:工作流可搜索、默认勾周一、正式运行字段取已发布版本、点变量插入、预览 5 次触发和渲染结果、预览防抖,POST 的 cron、时区、输入模板、Webhook 逐项核对;创建后地址只显示 url_hint、页面和输入框里都没有完整地址
- 非法 cron、不认识的时区和变量:说明写在出错那一项下、标 aria-invalid、清掉旧的预览、不能保存;离开前确认
- 详情:只改事件时不带地址、替换地址、删除 Webhook、发送测试消息、运行链接地址写 notify 组;页头开关之后表单用新版本、别处改过时 409 给重新载入
- 触发历史分页(before 游标、去重、已全部加载)、各种类型和结局、原因和通知结果;直接打开触发历史不先请求表单的预览
- 记录页的定时标记:只标定时发起的、悬停写定时任务名、点了去定时任务不打开运行
- 390px 深浅色:列表、新建表单、触发历史都不横向溢出,按钮在屏幕里,窄屏预览排在频率下面

check-all 里 check-schedules 的耗时按实测改成 40 秒。
2026-10-05 09:02:02 +08:00
ThearchyHelios 72da2e178a 运行对比页对齐服务端的实际输出:变化百分比按百分数写,归因、遮罩、差异说明照服务端给的显示
对照运行对比后端的实现核过一遍字段的写法:
- delta_pct 服务端已经乘过 100(12.5 是 +12.5%),占比 share 仍是小数(0.4 是 40%),两处分开格式化;原先把
  delta_pct 也当小数,会写成「+1250.0%」
- 维度归因服务端只给前 10 项、另有几项写在 note 里,照写;归不了因(查询结果截断、度量列遮罩、快照读不出来)时
  给空的 rows 和一句说明,只写说明、不画空表;万一多给了仍只列 10 项并写明另有几项
- 约定之外服务端顺带给的几项按可选字段用上:输入的 masked(两边写「已遮罩」,不标变了)、查询的 differences
  (结构变了差在哪,列在并排的 SQL 上面)和 problem(快照读不出来、与哈希不一致)、模板配置项的 labels(按节点
  类型翻好的叫法,键名放进悬停提示;没给或对不上时照写键名)
- 找默认基准时的 404 分两种:本次这条运行不存在(机读码 run_not_found)写「运行记录不存在」,其余写「未找到
  可作为基准的运行」
- check-compare 的夹具照服务端的写法改,补上述几种情形;菜单入口另查「问到基准之后才跳」(先跳到只带本次的地址、
  再让对比页去找,原先查不出来);check-all 登记实测耗时
2026-10-05 08:58:34 +08:00
ThearchyHelios 4deffd62f7 定时任务前端底座:接口约定的类型、api.schedules、页面用的纯函数和文案
types.ts 末尾一段写定时任务的接口约定(Schedule、Fire、预览、变量、立即运行、触发历史、Webhook 测试),字段名和形状照前后端共用的约定,不各自发挥;运行列表的 schedule_id 用同名接口合并补在这一段,不去改上面 Run 的定义。

api/schedules.ts 挂上全部接口:列表、详情、新建、修改(只带改了的字段和读到的版本)、删除、预览(可取消,丢掉过时的请求)、变量、立即运行、触发历史分页、发送测试消息。

pages/schedules/model.ts 是不碰 React 的纯函数:
- 频率预设和 cron 互转:每天 / 每周(连着三天以上写区间)/ 每月 / 每隔几小时(只给 24 的约数,*/5 在跨天处会断)/ 自定义;填得不完整时返回空串,不拿猜出来的频率顶上;认不出的 cron 一律算自定义、原文照放
- 按定时任务自己的时区写时间(Intl 取各段再拼中文,周几、偏移照算),本机时区另给;距下次运行先取整再判档
- 表单和请求体互转:修改时和打开时的表单比,只交改了的字段(cron 写法不同但人没动不算改);Webhook 按约定地址省略即不改、空串即删除,密钥省略即不改、空串即清除,交 Webhook 时格式和事件总是一起交
- 表单的问题按字段给出,写在对应的输入框下

terms.ts 的 SCHEDULE_TEXT 写全定时任务页的文案;占位页的两条先留着,换成真页面时删掉。「钉钉」是 Webhook 的产品名,会被「钉住」那条规则误报,在 copy-allow.json 里登记一条例外并写明理由。
2026-10-05 08:56:02 +08:00
ThearchyHelios e6c77ea4ee 运行对比页(前端):两次运行的指标变化按数据、口径、模板与 SQL 拆开讲
- 运行详情「更多」加「与上一次对比」:先问 compare/base 找默认基准再跳到对比页;没封存、还在运行的不给点;
  找不到基准时留在原页,提示服务端给的原因,并可去对比页手动选择基准
- 对比页(/runs/compare?target=…&base=…):顶部两次运行(名字、时间、类别与版本、定时来源、未封存标记,可点进
  各自详情)、互换、换基准下拉(运行列表接口按工作流取,未封存的列出但不能选);摘要条八类的个数照服务端的
  summary,点一类只看这一类;指标表用服务端渲染值,能严格拆分的并列口径效应和数据效应、画两截条形,并写明两者
  之和等于总变化,不能拆的写服务端给的原因;展开看变化说明、输入对比、维度归因前 10 项(没有占比时写原因);
  查询区标结构状态,只参数变列出字面量,结构变并排两条 SQL 逐词标出各自独有的部分;模板区写版本、变化的节点和
  配置项;说明照实列出
- 加载、找基准、409(未封存或封存核对不一致)、422(不是同一工作流)、404、找不到基准、空对比都写清楚;请求按
  「本次 + 基准」取,换基准、互换时丢掉过时的答复,开发模式的 StrictMode 下同一份对比也只请求一次
- 窄屏表格在自己的框里横向滚动(指标名一栏钉住,展开的明细按可见宽度排),深浅色下分类标签、差异高亮对比度都
  在 4.5 以上
- check-compare.mjs 换成真检查:page.route 假接口覆盖入口、摘要、分类、拆分、归因、SQL 并排、换基准与互换、
  过时答复、各类错误、窄屏和深浅色
2026-10-05 08:43:32 +08:00
ThearchyHelios 26595b70f7 合入期 1 数字推演沙盘:证据面板里改口径卡的输入、排除查询结果的行,即时看指标和报告引用处的新值;推演只读、不写运行记录,醒目标注推演非出具;口径卡的容器型输入此后另存完整值
# Conflicts:
#	scripts/check-all.mjs
2026-10-05 07:53:42 +08:00
ThearchyHelios 4debcf2ef3 数字推演复核修正(第 2 轮,界面):整个指标推演不了时只写原因,check-whatif 补遮罩列、输入还原不了的用例
- 后端对整个推演不了的指标(口径卡没记输入、用到了遮罩列、有输入还原不了)都给了 input 为空的那一条,界面沿用 wholeReason:
  结果区只写原值和原因,不写「无变化」,不画输入框、勾选框,不列报告里引用它的地方;注释和类型说明跟着改
- 推演结果里的原因写着输入路径,窄屏里允许在任意处折行
- check-whatif:假接口照后端新的形状作答。新增「输入还原不了」「用到了遮罩列」两段:一打开就写原因、本来能改的数也不给
  输入框、查询步骤里不出勾选框、不说报告引用处「不受影响」;口径卡没记输入那段改成后端新给的 unsupported;「不支持的
  输入」改用推演得了的指标(文本条件、加工过的列表);窄屏、深浅色补整个推演不了时的检查。把 wholeReason 改坏后这几段
  都变红。ESTIMATE 按实测改成 33 秒
2026-10-05 06:49:45 +08:00
ThearchyHelios 633af950db 数字推演复核修正(第 1 轮,界面):整份结果在推演区里勾行,只让用到的行可勾,勾完结果就在手边,加载中和失败后不摆上一次的答复
- 整份结果、数组字段作输入时,输入下面给「勾选要排除的行(共 N 行)」,按页取整份快照来勾:证据链里没有它的查询步骤、
  或者查询步骤只给前后 2 行时也勾得全
- 查询步骤里的勾行表格只让这个指标用到的行可勾(row_span),别的行禁用并说明没用到,勾了也不发请求
- 勾行表格底下带推演结果(旧值 → 新值或原因)和「回到推演结果」;勾完、答复回来后各把它带进视野一次(答复回来时上面
  的内容会变高,把表格往下挤)
- 推演的请求和答复提到片段那一层,推演区和查询步骤共用一份;答复回来之前随改动变的部分变淡、标为忙,请求失败时结果、
  排除标记、报告中会变的地方、下游口径卡都不显示,不拿上一次的答复充数
- 整个指标推演不了(口径卡没记输入)时只说原因,不再同时写「无可推演」和「无变化」,也不画勾选框
- 快照读不出来的输入写「查询快照无法核对,不显示原值」;没有能改的输入、也没有能勾的行时说一句为什么
- check-whatif 补对应检查:整份结果勾行、上下文行不能勾、勾完结果整个在视野里、封存核对未通过、加载中和失败后、整个
  指标推演不了、窄屏里的勾行表格;ESTIMATE 按实测改成 28 秒
2026-10-05 05:43:17 +08:00
ThearchyHelios e7c8d2a1f3 可验证报告复核修正(第 1 轮):运行信息拿已核对的事件对照,报告徽标连同数字一起算,遮罩判定宁严勿宽,各分支在浏览器里有确定的检查
- 页面核对加 ⑥ 运行信息:运行结果看封存范围内最后一条结束类事件的类型,运行类别看运行开始事件记下的运行参数,
  出具档位认最后一条出具判定(不再信元信息指的那一条);页面显示事件里的值,元信息写得不一样算不通过、计入总览。
  工作流名、版本、起止时间、节点名称绑不进封存,单列一组写明取自运行记录,封存说明里也写明要到系统里一并对照
- 报告标题旁的徽标连同正文里的数字一起算,旁边写分项:重算全部哈希的伪造只在 ⑤ 露馅,徽标不能还写着通过。
  分块条目多时不通过和无法核对的都列在外面,有无法核对的显示「部分无法核对」和分项计数;⑤ 改叫「数字与取值」并分开数,
  读屏分别读作数字、取值,「显示格式由服务端渲染」只附在带出处的数字上;无出处数字的说法改成未使用引用标记
- 服务端不会给出的状态算不通过:被引用的工件不在清单里、非查询快照标着遮罩、工件既没内容也没说明;报告文档导出时
  已不在服务端,总览不再是绿色的通过,写「有 N 份报告未能核对」,报告处写明是服务端已没有这份文档
- 认 json.dumps 写出的裸 NaN / Infinity,没被改过的文件不再误判不通过;哈希对得上但读不懂的照实写「无法核对」,
  和哈希不一致分开说
- 宽屏打开出处面板时正文让出右边一栏,表格里右对齐的数字不再被面板盖住;补上斜体(不用后行断言,较早的 Safari 也能执行)
- 封存哈希、运行 ID、工作流名直接写进页面,不执行脚本时写「尚未核对」而不是一直「正在核对」;脚本挪进 head,
  执行后核一遍页面顶部写出的封存哈希和数据里核对用的一致
- 成果节点和运行结束事件的规范字符串,只在封存范围内每次数据源查询都对得上无遮罩的快照(或确实没交回数据)时才给:
  升级前的运行从工具快照认出查询快照,协作团队成员的查询认不出就按带遮罩算,数据源现在设了遮罩的按工具名就挡
- 封存核对不一致的 409 改成一句固定的话,不再叠冒号、让人去本来就在的记录页;失败结束的运行在页面封存说明和导出提示里
  写明之后继续运行会重新封存;记录页上左边写着「已封存」却不能导出时,原因写在屏幕上
- tests/bundle_samples.py 用虚构数据真实生成九份样本页(遮罩快照、两份报告、早期运行、失败结束、两条出具判定、
  服务端缺文件、裸 NaN、别的运行的文档),check-bundle 断网打开逐项断言,在上面篡改引用链、运行信息、拿掉被引用的口径卡,
  量宽屏面板,看不执行脚本的样子;把核对改成恒通过、徽标不看数字等七种改坏法都会变红。pytest 补遮罩判定的三种形状、
  事后设遮罩(去掉接线即变红)、页面静态内容和样本页本身
2026-10-05 05:30:50 +08:00
ThearchyHelios ca09aed612 check-whatif 补空态:原式没有引用输入时说清无可推演,不画空列表,也不画「报告中会变的地方」 2026-10-05 04:16:01 +08:00
ThearchyHelios cf038c95f5 证据面板加数字推演:指标步骤上「推演」,改输入、勾掉查询结果里的行,看这个数和报告怎么变
- run/WhatIf.tsx:推演区。顶上醒目横幅「推演,非出具:不会写进运行记录,也不会改动报告」,运行未封存另行提示;
  旧值 → 新值和变化量(比率、百分数写「个百分点」)、推演代入式、输入(数值可改:停顿 450 毫秒或回车、失焦才提交,
  写的不是数提示并保留上次的结果,Esc 退回)、不支持推演的输入和原因、报告中会变的地方(可定位)、可能受影响的
  下游口径卡、恢复原值;加载、失败(可重试)、空态都有。新改动来了旧请求直接丢掉,答复按请求体缓存
- EvidencePanel.tsx:MetricPart 挂「推演」开关和推演区;QueryPart 只在推演时把结果窗口换成带勾选框的表(WhatIfRows),
  勾掉的行划掉、遮罩列照旧写「已遮罩」。草稿按(运行、报告、口径卡、指标)认,同一个指标的几处引用之间来回切不清空
- 接口 api.whatif.run、推演相关类型(types.ts 末尾独立一段)、WHATIF_TEXT 文案
- 预览用例 ?syn=whatif / whatif-rail 和 check-whatif.mjs(54 项,用 page.route 假接口):请求体、防抖、回车、排除行、
  恢复原值、收起、不支持的输入、遮罩列、加载 / 失败 / 未封存、390px 与 360px 右栏不横向溢出、深浅色横幅对比度
2026-10-05 04:04:30 +08:00
ThearchyHelios 183814d2c1 可验证报告页面补全:列出参与清单核对的原文供页面外自行重算,写明运行结果,自查认法与服务端一致,打印时收起面板
- 封存清单一项可展开参与核对的每一行(序号|类型|节点|内容哈希),读的人不信页面脚本也能复制出去用别的工具算;
  check-bundle 在页面之外用 node 重算这段原文,等于封存哈希
- 元信息加「运行结果」(已完成 / 已失败 / 已取消):失败的运行报告照样导得出去,读的人要知道它没跑完
- 报告节点认最后一次记下了文档的自查,和服务端、证据接口同一个认法,后面多一条没记文档的自查不再误报不通过;
  运行记录里有自查、文件里却没附带文档的报告照实报不通过
- 核对下不了结论(数据块坏了、内置 SHA-256 自检不过)时也标上核对结束,等结果的一方不必干等;打印时收起出处面板
- check-bundle:拿不到导出页面时,依赖它的几节跳过并注明原因,不再一个原因报五次
2026-10-05 04:04:06 +08:00
ThearchyHelios a651a2e7d5 check-bundle 换成真检查:真服务端导出、断网打开全部通过、篡改各自变红、去掉 crypto.subtle 照常通过,外加记录页的导出按钮
- 从服务端找一份已封存、核对一致、有报告文档的运行下载 bundle.html:附件名、零外链、内容安全策略、数据块转义、导出不追加事件;
  找不到可导出的运行照实报失败并说明原因;有未封存或还没结束的运行时核对它回 409
- 拦掉一切网络请求从本地文件打开:五项核对通过、没有发出请求、数字点开看得到出处;页面加载前删掉 crypto.subtle 照常全部通过
- 篡改事件内容、工件的一个字节、封存哈希,各自对应的核对项不通过、总览不通过、其余项仍通过;另做一次改引用值并重算全部哈希的伪造,
  只有报告数字的核对拦得住
- 390 宽深浅色都不横向溢出、出处面板从底部抽出;导出按钮的几种状态用预览用例和假接口核对,不碰真实写接口
- 输出只打印计数和运行号前 8 位,下载的文件放临时目录、跑完删掉;check-all 里这一项按实测改成 10 秒
2026-10-05 03:59:00 +08:00
ThearchyHelios 35bb23d372 check-ui-kit 跟着改源码路径:缺工具那段报错随发起运行的规则搬到了 engine/launch.py,「新样本的片段在后端源码里都还在」那一项按新位置找 2026-10-05 02:52:28 +08:00
ThearchyHelios 6041073ef2 检查脚本骨架:check-all 另起的后端带 AGENTLAB_SCHEDULER=0,拷来的数据目录不会替原库到点发起运行、发出 webhook。新加 check-schedules、compare、verify、inquiry、bundle、whatif 六个占位检查(只打一行通过,输出格式和别的检查一样),登记进 ORDER 和 ESTIMATE,各工作包换成真检查 2026-10-04 23:40:20 +08:00
ThearchyHelios 90dac0992b 复核套件骨架(前端):节点库加双盲复算、反方审稿(把关类,图标、配色、空配置,说明和卡片写明尚未生效,检查器照常打开)。路由加 /runs/compare(排在 /runs/:runId 前,标签页标题写「运行对比」)和 /schedules、/schedules/:id,都是页头加「功能开发中」的占位页;导航和命令面板在设置前加「定时任务」,快捷键 ⌥8,设置仍是 ⌥7;八个导航项在 480px 高的窗口里放不下,矮窗口的导航项从 40px 收到 36px。请求层从 api/client.ts 拆到 api/http.ts,client.ts 原样转出原有导出并加转请求函数;schedules、compare、bundle、inquiry、whatif 各一个空的命名空间文件,从 http.ts 取请求函数、挂到 api 上,不和 client.ts 互相导入。terms.ts 给各包占好文案块(RUN_COMPARE_TEXT 和配方对照的 COMPARE_TEXT 分开)。审批卡留两个插槽:payload.kind 为 dual_check 时的 DualCheckApproval,报告核对概况后面的 ChallengeSummary,都先返回 null。预览页自动收 dev/fixtures/*.tsx 导出的 cases,?syn= 先查这里再走原有用例。check-shell 跟着改导航项和快捷键的断言,check-copy 的 for_model 检查把 http.ts 和 client.ts 合起来看 2026-10-04 23:40:20 +08:00