mirror of
https://github.com/ThearchyHelios/AgentLab.git
synced 2026-11-15 01:01:59 +00:00
时间线认得核查日志里的 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;改之前这一项变红。
This commit is contained in:
@@ -3782,6 +3782,12 @@ export const DUAL_CHECK_TEXT = {
|
||||
} as Record<string, string>,
|
||||
limitAny: '上限',
|
||||
limitDailyNext: '今日核查费用已达上限。请在「设置 → 偏好设置 → 核查」中调高每日金额上限,或等到次日再运行',
|
||||
/**
|
||||
* 单次运行时限将至(日志带 cause: run_deadline,服务端 engine/deadline.py):一段执行(两次人工审批之间)有单次运行
|
||||
* 时限,核查节点为后续节点预留时间,剩下的时间不够就不再开始新的一项,开始了的按剩余时间缩短时长。双盲复算、反方审稿
|
||||
* 这几行共用这句副标题,seconds 是单次运行时限(设置页「运行环境」里的叫法)
|
||||
*/
|
||||
deadlineSub: (seconds: number) => `单次运行时限为 ${formatNumber(seconds)} 秒,已为后续节点预留时间`,
|
||||
log: {
|
||||
skippedDisabled: '双盲复算未启用,已跳过',
|
||||
skippedDisabledNext: '如需复算,请在节点的「启用双盲复算」中选择「开启」,或在「设置 → 偏好设置 → 核查」中启用双盲复算',
|
||||
@@ -3823,6 +3829,14 @@ export const DUAL_CHECK_TEXT = {
|
||||
unchecked: (n?: number) => (n ? `双盲复算有 ${formatNumber(n)} 个指标无法复算,已记为缺口`
|
||||
: '双盲复算有指标无法复算,已记为缺口'),
|
||||
uncheckedNext: '无法复算的原因见展开内容。来自合并查询、遮罩列的输入无法单独复算;盲算触顶、出错的,可调高「设置 → 偏好设置 → 核查」中的上限后重新运行',
|
||||
/**
|
||||
* dual_check_unchecked 带 cause: run_deadline:单次运行时限将至,没来得及盲算、缩短时长后到时没算完的指标(服务端
|
||||
* 另起这一条,原因都一样,副标题只点名)。调高每项的上限只会更快撞线,检查模型、数据源也无济于事:下一步说怎么腾出时间
|
||||
*/
|
||||
deadline: (n?: number) => (n ? `运行时限将至,双盲复算有 ${formatNumber(n)} 个指标未能复算,已记为缺口`
|
||||
: '运行时限将至,双盲复算有指标未能复算,已记为缺口'),
|
||||
deadlineNext: '如需全部复算,可在节点的「复算的指标」中减少指标,或在双盲复算前加人工审批(时限按审批前后分段计算);'
|
||||
+ '确需更长时间,请联系管理员调大单次运行时限(AGENTLAB_MAX_RUN_SECONDS)',
|
||||
},
|
||||
/**
|
||||
* 出具缺口里双盲复算、反方审稿报上来的那几条(缺口以「双盲复算「节点名」:」「反方审稿:」开头):时间线、成果卡片、
|
||||
@@ -3980,6 +3994,19 @@ export const CHALLENGE_TEXT = {
|
||||
unreviewed: (n?: number) => (n ? `反方审稿有 ${formatNumber(n)} 句结论未能反查,已记为无法判断`
|
||||
: '反方审稿有结论未能反查,已记为无法判断'),
|
||||
unreviewedNext: '原因见展开内容。请检查核查模型和数据源是否可用,修正后重新运行;报告未引用数据库查询的结论无法反查',
|
||||
/**
|
||||
* 带 cause: run_deadline 的两条(服务端 engine/deadline.py):单次运行时限将至,反方审稿为后续节点预留时间。
|
||||
* challenge_unreviewed 是剩下的句子不再反查;challenge_limit 是开始了的句子按剩余时间缩短了反查时长、到时按查到的结果
|
||||
* 收尾(n:这样的句数,skipped:其中未能给出判断的)。调高每句的上限只会更快撞线,检查模型、数据源也无济于事
|
||||
*/
|
||||
deadline: (n?: number) => (n ? `运行时限将至,反方审稿有 ${formatNumber(n)} 句结论未反查,已记为无法判断`
|
||||
: '运行时限将至,反方审稿有结论未反查,已记为无法判断'),
|
||||
deadlineLimit: (n?: number, skipped?: number) => {
|
||||
const head = n ? `运行时限将至,反方审稿缩短了 ${formatNumber(n)} 句结论的反查时长` : '运行时限将至,反方审稿缩短了反查时长'
|
||||
return skipped ? `${head},其中 ${formatNumber(skipped)} 句未能给出判断` : `${head},已按查到的结果给出判断`
|
||||
},
|
||||
deadlineNext: '如需全部审完,可在节点或「设置 → 偏好设置 → 核查」中减少每份报告审的句数,或在反方审稿前加人工审批'
|
||||
+ '(时限按审批前后分段计算);确需更长时间,请联系管理员调大单次运行时限(AGENTLAB_MAX_RUN_SECONDS)',
|
||||
/** challenge_sources_lost:反查了,但该查的数据源有停用了的,判断不含它们的数据 */
|
||||
sourcesLost: (n?: number) => (n ? `反方审稿有 ${formatNumber(n)} 句结论只查了部分数据源` : '反方审稿有结论只查了部分数据源'),
|
||||
sourcesLostSub: (names: string[]) => `未能查询:${names.map((x) => `「${x}」`).join('、')}(已不存在或已停用),判断不含其中的数据`,
|
||||
@@ -4043,9 +4070,14 @@ export const VERIFY_SETTING_TEXT = {
|
||||
} as Record<string, string>,
|
||||
toleranceHint: '两边的值相差不超过这个比例时算一致,例如 0.000001 表示百万分之一,0 表示必须完全相同',
|
||||
unlimited: '不限',
|
||||
/** 某项设成不限时写明它还受什么约束,不要悄悄生效。by:眼下还设着上限的相关项 */
|
||||
unlimitedNote: (kind: 'queries' | 'claims' | 'timeout' | 'daily', by: string[]) => {
|
||||
/**
|
||||
* 某项设成不限时写明它还受什么约束,不要悄悄生效。by:眼下还设着上限的相关项。runTimeout 是双盲复算、反方审稿的
|
||||
* 时长:它们在运行里执行,一段执行有单次运行时限,时限将至时按剩余时间缩短(服务端 engine/deadline.py),设成不限
|
||||
* 也一样;timeout 是审批质询的,不在运行的那一段里执行
|
||||
*/
|
||||
unlimitedNote: (kind: 'queries' | 'claims' | 'timeout' | 'runTimeout' | 'daily', by: string[]) => {
|
||||
if (kind === 'timeout') return '不设上限,时长仅受模型接口自身的超时约束'
|
||||
if (kind === 'runTimeout') return '不设上限,时长仍受单次运行时限约束,时限将至时按剩余时间缩短'
|
||||
const what = kind === 'queries' ? '查询次数' : kind === 'claims' ? '句数' : '每日核查费用'
|
||||
return by.length ? `不设上限,${what}仅受${by.join('、')}约束` : `不设上限,${what}不受其他上限约束`
|
||||
},
|
||||
|
||||
@@ -179,7 +179,8 @@ export function VerifySection({ cur, errors, onEdit, refresh }: {
|
||||
|
||||
/** 某项设成不限时,它还受哪些眼下设着的上限约束 */
|
||||
const note = (k: LimitKey): string => {
|
||||
if (TIMEOUTS.has(k)) return S.unlimitedNote('timeout', [])
|
||||
// 审批质询不在运行的那一段里执行,只受模型接口的超时约束;双盲复算、反方审稿还受单次运行时限约束
|
||||
if (TIMEOUTS.has(k)) return S.unlimitedNote(k === 'inquiry.timeout_s' ? 'timeout' : 'runTimeout', [])
|
||||
if (k === 'challenge.max_claims') return S.unlimitedNote('claims', [S.bound.claims])
|
||||
if (k === 'daily_max_usd') {
|
||||
const counts = [...COUNTS].some((c) => cur[c] !== null)
|
||||
|
||||
@@ -804,6 +804,14 @@ const cjkText = (v: unknown): string | undefined => (typeof v === 'string' && /[
|
||||
/** 个数:给的是数就取整,给的是清单就数一下,别的(缺了、写坏了)当不知道 */
|
||||
const countOf = (v: unknown): number | undefined => (typeof v === 'number' && Number.isFinite(v) && v >= 0 ? Math.round(v)
|
||||
: Array.isArray(v) ? v.length : undefined)
|
||||
/**
|
||||
* 核查类日志的 cause:单次运行时限将至(服务端 engine/deadline.py)。核查节点为后续节点预留时间,没开始的、缩短时长后
|
||||
* 到时没做完的另起一条带上它。这几行不叫人调高核查的上限(只会更快撞线),也不叫人去查模型和数据源
|
||||
*/
|
||||
const RUN_DEADLINE = 'run_deadline'
|
||||
/** run_seconds(单次运行时限)→ 那句副标题;不是正数(缺了、写坏了)就不写 */
|
||||
const deadlineSub = (v: unknown): string | undefined =>
|
||||
(typeof v === 'number' && Number.isFinite(v) && v > 0 ? DC.deadlineSub(v) : undefined)
|
||||
|
||||
/**
|
||||
* 几种「看着跑完了、其实没做成」的状况(NI-3/4/5)。后端这几条日志是写给排查的,原样
|
||||
@@ -1136,17 +1144,20 @@ function explainLog(code: string | undefined, message: string, d: Record<string,
|
||||
}
|
||||
}
|
||||
case 'dual_check_unchecked': {
|
||||
// metrics 是 [{id, name, reason}]:副标题点名、说原因(没起名字的写 id)
|
||||
// metrics 是 [{id, name, reason}]:副标题点名、说原因(没起名字的写 id)。带 cause: run_deadline 的是单次运行时限
|
||||
// 将至没核成的那几个(服务端另起这一条,原因都一样):副标题只点名、带上时限,下一步说怎么腾出时间
|
||||
const list = Array.isArray(d.metrics) ? d.metrics.filter(isRecord) : []
|
||||
const late = d.cause === RUN_DEADLINE
|
||||
const parts = list.map((m) => {
|
||||
const name = str(m.name) ?? str(m.id)
|
||||
const why = cjkText(m.reason)
|
||||
const why = late ? undefined : cjkText(m.reason)
|
||||
return name ? `「${name}」${why ? `:${why}` : ''}` : ''
|
||||
}).filter(Boolean)
|
||||
const sub = late ? [parts.join('、'), deadlineSub(d.run_seconds)].filter(Boolean).join(';') : parts.join(';')
|
||||
return {
|
||||
title: DC.log.unchecked(list.length || undefined),
|
||||
sub: parts.length ? parts.join(';') : undefined,
|
||||
next: DC.log.uncheckedNext,
|
||||
title: (late ? DC.log.deadline : DC.log.unchecked)(list.length || undefined),
|
||||
sub: sub || undefined,
|
||||
next: late ? DC.log.deadlineNext : DC.log.uncheckedNext,
|
||||
level: 'warn',
|
||||
}
|
||||
}
|
||||
@@ -1189,6 +1200,16 @@ function explainLog(code: string | undefined, message: string, d: Record<string,
|
||||
case 'challenge_limit': {
|
||||
const which = str(d.limit)
|
||||
const skipped = countOf(d.claims_skipped)
|
||||
if (d.cause === RUN_DEADLINE) {
|
||||
// 时长按剩余时间缩短过的那几句到了时(limit 照旧是 timeout_s,服务端单起这一条):不说「已达时长上限」,不叫人
|
||||
// 调高每句的上限。claims:这样的句数
|
||||
return {
|
||||
title: CL.deadlineLimit(countOf(d.claims) || undefined, skipped || undefined),
|
||||
sub: deadlineSub(d.run_seconds),
|
||||
next: CL.deadlineNext,
|
||||
level: 'warn',
|
||||
}
|
||||
}
|
||||
return {
|
||||
title: CL.limit((which && DC.limitLabel[which]) || DC.limitAny, skipped || undefined),
|
||||
next: which === 'daily_max_usd' ? DC.limitDailyNext : CL.limitNext,
|
||||
@@ -1196,7 +1217,16 @@ function explainLog(code: string | undefined, message: string, d: Record<string,
|
||||
}
|
||||
}
|
||||
case 'challenge_unreviewed': {
|
||||
// claims_skipped:未能反查的句数;reason:第一句未能反查的原因(一句中文)
|
||||
// claims_skipped:未能反查的句数;reason:第一句未能反查的原因(一句中文)。带 cause: run_deadline 的是单次运行
|
||||
// 时限将至、剩下没开始的句子(服务端另起这一条):副标题说时限,下一步说怎么腾出时间,不叫人去查模型和数据源
|
||||
if (d.cause === RUN_DEADLINE) {
|
||||
return {
|
||||
title: CL.deadline(countOf(d.claims_skipped) || undefined),
|
||||
sub: deadlineSub(d.run_seconds) ?? cjkText(d.reason),
|
||||
next: CL.deadlineNext,
|
||||
level: 'warn',
|
||||
}
|
||||
}
|
||||
return {
|
||||
title: CL.unreviewed(countOf(d.claims_skipped) || undefined),
|
||||
sub: cjkText(d.reason),
|
||||
|
||||
@@ -2396,5 +2396,92 @@ await section('审批质询 approval.inquiry(期 4):一行「审批人质
|
||||
check('……有回答、没写成没成:只说已回答,不说完成', oddRows[4]?.sub === '已回答' && oddRows[4].level === 'info', `${oddRows[4]?.sub} / ${oddRows[4]?.level}`)
|
||||
})
|
||||
|
||||
await section('单次运行时限将至(cause: run_deadline):核查没做完的那几行说时限,下一步不叫人调高上限、不叫人查模型和数据源', async () => {
|
||||
// 一段执行(两次人工审批之间)有单次运行时限。双盲复算、反方审稿为后续节点预留时间:剩下的时间不够就不再开始,开始了的
|
||||
// 按剩余时间缩短时长(服务端 engine/deadline.py)。以前这几项照常记成「已达时长上限」「未能反查」「无法复算」,下一步叫人
|
||||
// 调高每句、每项的上限(调高了只会更快撞线),或者去查核查模型和数据源(它们本来就没问题)。现在服务端另起一条、带
|
||||
// cause: run_deadline 和 run_seconds,界面照它说。先核对后端还是这么发的
|
||||
const dlPy = readFileSync(`${root}backend/app/engine/deadline.py`, 'utf8')
|
||||
const chPy = readFileSync(`${root}backend/app/engine/nodes/challenge.py`, 'utf8')
|
||||
const dcPy = readFileSync(`${root}backend/app/engine/nodes/dual_check.py`, 'utf8')
|
||||
check('后端发的还是这几种形状', dlPy.includes('RUN_DEADLINE = "run_deadline"')
|
||||
&& chPy.includes('code="challenge_unreviewed", cause=deadline.RUN_DEADLINE')
|
||||
&& chPy.includes('{"cause": deadline.RUN_DEADLINE, "run_seconds": self.run_seconds, "claims": touched}')
|
||||
&& dcPy.includes('code="dual_check_unchecked", cause=late[0]["cause"], run_seconds=seconds'),
|
||||
'改了 deadline.py、challenge.py、dual_check.py 里这几条日志的字段,就同步改 decode.ts 的 explainLog 和这里的夹具')
|
||||
const E = (seq, type, node_id, data = {}) => ({ seq, type, node_id, ts: 1790000000 + seq, data })
|
||||
const LATE = '本次运行即将达到 600 秒的时长上限,为保证运行按时完成,剩下 3 句未审'
|
||||
const BLIND = '本次运行即将达到 600 秒的时长上限,为保证运行按时完成,未进行盲算'
|
||||
const events = [
|
||||
E(1, 'run.started', null, { total: 3 }),
|
||||
E(2, 'node.started', 'dc', { node_type: 'dual_check', label: '复核五个指标' }),
|
||||
// 同一节点里别的原因照旧一条,时限将至的另起一条
|
||||
E(3, 'log', 'dc', { level: 'warn', code: 'dual_check_unchecked', message: '双盲复算未能核对 1 个指标:「订单数」(盲算没有查到这个数),按无法复算计入缺口',
|
||||
metrics: [{ id: 'orders', name: '订单数', reason: '盲算没有查到这个数' }] }),
|
||||
E(4, 'log', 'dc', { level: 'warn', code: 'dual_check_unchecked', cause: 'run_deadline', run_seconds: 600,
|
||||
message: `本次运行即将达到 600 秒的时长上限,为保证运行按时完成,双盲复算有 3 个指标未能复算:「付款客户数」「最大单笔」「low」,按无法复算计入缺口`,
|
||||
metrics: [{ id: 'buyers', name: '付款客户数', reason: BLIND }, { id: 'top', name: '最大单笔', reason: BLIND }, { id: 'low', name: '', reason: BLIND }] }),
|
||||
E(5, 'node.finished', 'dc', { duration_ms: 20 }),
|
||||
E(6, 'node.started', 'ch', { node_type: 'challenge', label: '审周报' }),
|
||||
// 第 1 句触了自己的每句时长上限,第 2 句的时长缩短过、到时没给出判断:两条都是 limit: timeout_s
|
||||
E(7, 'log', 'ch', { level: 'warn', code: 'challenge_limit', limit: 'timeout_s', claims_skipped: 0,
|
||||
message: '有 1 句反查已达上限(每句时长上限 90 秒),已按查到的结果收尾' }),
|
||||
E(8, 'log', 'ch', { level: 'warn', code: 'challenge_limit', limit: 'timeout_s', claims_skipped: 1, cause: 'run_deadline', run_seconds: 600, claims: 1,
|
||||
message: '有 1 句反查已达上限(本次运行即将达到 600 秒的时长上限,反查时长已按剩余时间收紧),已按查到的结果收尾,其中 1 句未能给出结论' }),
|
||||
E(9, 'log', 'ch', { level: 'warn', code: 'challenge_unreviewed', claims_skipped: 1, reason: '反查没有执行成功任何查询',
|
||||
message: '反方审稿有 1 句结论未能反查,已记为无法判断:反查没有执行成功任何查询' }),
|
||||
E(10, 'log', 'ch', { level: 'warn', code: 'challenge_unreviewed', cause: 'run_deadline', run_seconds: 600, claims_skipped: 3, reason: LATE,
|
||||
message: `反方审稿有 3 句结论未能反查,已记为无法判断:${LATE}` }),
|
||||
E(11, 'node.finished', 'ch', { duration_ms: 30 }),
|
||||
E(12, 'run.finished', null, { status: 'succeeded' }),
|
||||
]
|
||||
const all = flatten(mod.decodeRun(events))
|
||||
const rows = (code) => all.filter((s) => s.code === code)
|
||||
const [dcOther, dcLate] = rows('dual_check_unchecked')
|
||||
const [ownLimit, lateLimit] = rows('challenge_limit')
|
||||
const [chOther, chLate] = rows('challenge_unreviewed')
|
||||
const late = [dcLate, lateLimit, chLate]
|
||||
check('每条一行,挂在自己的节点下', all.find((s) => s.nodeId === 'dc' && s.kind === 'node')?.children?.filter((x) => x.code === 'dual_check_unchecked').length === 2
|
||||
&& all.find((s) => s.nodeId === 'ch' && s.kind === 'node')?.children?.filter((x) => /^challenge_/.test(x.code ?? '')).length === 4,
|
||||
all.map((s) => s.code).filter(Boolean).join('、'))
|
||||
check('dual_check_unchecked:标题说运行时限将至,副标题只点名(没名字的写 id)、带上时限', dcLate?.title === '运行时限将至,双盲复算有 3 个指标未能复算,已记为缺口'
|
||||
&& dcLate.sub === '「付款客户数」、「最大单笔」、「low」;单次运行时限为 600 秒,已为后续节点预留时间' && dcLate.level === 'warn', `${dcLate?.title} / ${dcLate?.sub}`)
|
||||
check('challenge_limit:缩短过的那条不说「已达时长上限」,说几句缩短了、几句没给出判断', lateLimit?.title === '运行时限将至,反方审稿缩短了 1 句结论的反查时长,其中 1 句未能给出判断'
|
||||
&& lateLimit.sub === '单次运行时限为 600 秒,已为后续节点预留时间' && lateLimit.level === 'warn', `${lateLimit?.title} / ${lateLimit?.sub}`)
|
||||
check('challenge_unreviewed:标题说几句未反查、记为无法判断,副标题说时限', chLate?.title === '运行时限将至,反方审稿有 3 句结论未反查,已记为无法判断'
|
||||
&& chLate.sub === '单次运行时限为 600 秒,已为后续节点预留时间' && chLate.level === 'warn', `${chLate?.title} / ${chLate?.sub}`)
|
||||
check('……三行的下一步都说怎么腾出时间:减少句数或指标、在核查前加人工审批、请管理员调大单次运行时限', late.every((s) => !!s?.next?.includes('人工审批')
|
||||
&& s.next.includes('单次运行时限') && s.next.includes('AGENTLAB_MAX_RUN_SECONDS'))
|
||||
&& dcLate?.next?.includes('「复算的指标」') && !!chLate?.next?.includes('句数') && lateLimit?.next === chLate?.next, late.map((s) => s?.next).join(' / '))
|
||||
check('……不叫人调高核查的上限,也不叫人去查核查模型和数据源', late.every((s) => !/调高|核查模型|数据源是否/.test(`${s?.title}${s?.sub ?? ''}${s?.next ?? ''}`)),
|
||||
late.map((s) => s?.next).join(' / '))
|
||||
check('……原话留在展开区,标题、副标题、下一步里没有内部代码', late.every((s, i) => s?.detail === events[[3, 7, 9][i]].data.message
|
||||
&& !/run_deadline|cause|run_seconds|timeout_s/.test(`${s.title}${s.sub ?? ''}${s.next ?? ''}`)))
|
||||
// 别的原因照旧:同一节点里的两条分得开,不是两行一样的「已达时长上限」
|
||||
check('别的原因那几行照旧:触了自己的上限仍叫人调高上限,未能反查、无法复算仍按原因说', ownLimit?.title === '反方审稿已达时长上限'
|
||||
&& !!ownLimit.next?.includes('调高') && ownLimit.title !== lateLimit?.title
|
||||
&& chOther?.title === '反方审稿有 1 句结论未能反查,已记为无法判断' && chOther.sub === '反查没有执行成功任何查询' && !!chOther.next?.includes('核查模型')
|
||||
&& dcOther?.title === '双盲复算有 1 个指标无法复算,已记为缺口' && dcOther.sub === '「订单数」:盲算没有查到这个数' && !!dcOther.next?.includes('合并查询'),
|
||||
[ownLimit, chOther, dcOther].map((s) => `${s?.title}|${s?.sub ?? ''}`).join(' / '))
|
||||
|
||||
// 都缩短了、都给出了判断;缺字段、类型不对(别的服务端版本):不崩,不出 undefined、NaN、[object Object],不瞎填数
|
||||
const odd = flatten(mod.decodeRun([
|
||||
E(1, 'node.started', 'ch', { node_type: 'challenge' }),
|
||||
E(2, 'log', 'ch', { level: 'warn', code: 'challenge_limit', limit: 'timeout_s', claims_skipped: 0, cause: 'run_deadline', run_seconds: 1800, claims: 2, message: 'x' }),
|
||||
E(3, 'log', 'ch', { level: 'warn', code: 'challenge_limit', limit: 'timeout_s', cause: 'run_deadline', run_seconds: 'x', claims: 'y', message: 'x' }),
|
||||
E(4, 'log', 'ch', { level: 'warn', code: 'challenge_unreviewed', cause: 'run_deadline', claims_skipped: 'x', reason: LATE, message: 'x' }),
|
||||
E(5, 'log', 'ch', { level: 'warn', code: 'dual_check_unchecked', cause: 'run_deadline', run_seconds: -1, metrics: 'x', message: 'x' }),
|
||||
E(6, 'node.finished', 'ch', {}),
|
||||
])).filter((s) => s.code && s.kind !== 'node')
|
||||
const [settled, bareLimit, bareUnreviewed, bareUnchecked] = odd
|
||||
check('都给出了判断:说按查到的结果给出判断,时限照写(大于 1,000 用千分位)', settled?.title === '运行时限将至,反方审稿缩短了 2 句结论的反查时长,已按查到的结果给出判断'
|
||||
&& settled.sub === '单次运行时限为 1,800 秒,已为后续节点预留时间', `${settled?.title} / ${settled?.sub}`)
|
||||
check('缺字段:标题不带数,没给时限就不写那句副标题(未能反查的退回原因)', bareLimit?.title === '运行时限将至,反方审稿缩短了反查时长,已按查到的结果给出判断'
|
||||
&& bareLimit.sub === undefined && bareUnreviewed?.title === '运行时限将至,反方审稿有结论未反查,已记为无法判断' && bareUnreviewed.sub === LATE
|
||||
&& bareUnchecked?.title === '运行时限将至,双盲复算有指标未能复算,已记为缺口' && bareUnchecked.sub === undefined,
|
||||
odd.map((s) => `${s.title}|${s.sub ?? ''}`).join(' ; '))
|
||||
check('……不出 undefined、NaN、[object Object]', !odd.some((s) => /undefined|NaN|object Object/.test(`${s.title}${s.sub ?? ''}${s.next ?? ''}`)))
|
||||
})
|
||||
|
||||
console.log(failed ? `\n✗ ${failed} 项未通过` : '\n✓ 解码器全部通过')
|
||||
process.exit(failed ? 1 : 0)
|
||||
|
||||
@@ -1601,6 +1601,42 @@ await section('设置页「核查」一节:老服务端没有这一组时不
|
||||
}
|
||||
})
|
||||
|
||||
await section('设置页「核查」一节:双盲复算、反方审稿的时长设成不限时,写明仍受单次运行时限约束;审批质询的照旧', async () => {
|
||||
// 双盲复算、反方审稿在运行里执行:一段执行有单次运行时限,时限将至时每项、每句的时长按剩余时间缩短(服务端
|
||||
// engine/deadline.py),设成不限也一样。以前这里写「仅受模型接口自身的超时约束」,管理员会以为设成不限就能查到底。
|
||||
// 审批质询不在运行的那一段里执行,不受单次运行时限约束,照旧
|
||||
const off = (part) => ({ ...fx.verify[part], timeout_s: null })
|
||||
const { page, errors } = await settingsPage({ verify: { ...fx.verify, dual_check: off('dual_check'), challenge: off('challenge'), inquiry: off('inquiry') } })
|
||||
await page.waitForSelector('[data-verify-settings]')
|
||||
const note = (k) => text(page.locator(`[data-verify-limit="${k}"] [data-verify-unlimited]`))
|
||||
const RUN = '不设上限,时长仍受单次运行时限约束,时限将至时按剩余时间缩短'
|
||||
check('双盲复算、反方审稿:说仍受单次运行时限约束', await note('dual_check.timeout_s') === RUN && await note('challenge.timeout_s') === RUN,
|
||||
`${await note('dual_check.timeout_s')} / ${await note('challenge.timeout_s')}`)
|
||||
check('审批质询:照旧只受模型接口自身的超时约束', await note('inquiry.timeout_s') === '不设上限,时长仅受模型接口自身的超时约束',
|
||||
await note('inquiry.timeout_s'))
|
||||
check('没有运行时报错', errors.length === 0, errors.join(';'))
|
||||
// 这句比原来长:390px 下照样折行、不横向溢出,深浅色都读得清
|
||||
for (const theme of ['dark', 'light']) {
|
||||
const narrow = await settingsPage({ width: 390, height: 844, theme,
|
||||
verify: { ...fx.verify, dual_check: off('dual_check'), challenge: off('challenge') } })
|
||||
await narrow.page.waitForSelector('[data-verify-settings]')
|
||||
await narrow.page.locator('[data-verify-limit="challenge.timeout_s"]').scrollIntoViewIfNeeded()
|
||||
const w = await narrow.page.evaluate(() => {
|
||||
const box = document.querySelector('[data-verify-settings]')
|
||||
const vw = document.documentElement.clientWidth
|
||||
const right = Math.max(...[box, ...box.querySelectorAll('*')].map((e) => e.getBoundingClientRect().right))
|
||||
const hint = document.querySelector('[data-verify-limit="challenge.timeout_s"] [data-verify-unlimited]')
|
||||
return { box: box.scrollWidth - box.clientWidth, beyond: Math.round(right - vw), color: hint && getComputedStyle(hint).color,
|
||||
base: getComputedStyle(document.body).backgroundColor }
|
||||
})
|
||||
const ratio = contrast(w.color, w.base, w.base)
|
||||
check(`390px(${theme}):这句说明折行、不横向溢出,对比度 ≥ 4.5`, w.box <= 0 && w.beyond <= 0 && ratio >= 4.5,
|
||||
`${JSON.stringify({ box: w.box, beyond: w.beyond })} · ${ratio.toFixed(2)}`)
|
||||
await shot(narrow.page, `settings-run-timeout-${theme}`)
|
||||
check(`390px(${theme}):没有运行时报错`, narrow.errors.length === 0, narrow.errors.join(';'))
|
||||
}
|
||||
})
|
||||
|
||||
await browser.close()
|
||||
console.log(failed ? `\n✗ 双盲复算与反方审稿:${failed} 项未通过` : '\n✓ 双盲复算与反方审稿:全部通过')
|
||||
process.exit(failed ? 1 : 0)
|
||||
|
||||
Reference in New Issue
Block a user