任务:重复策略(V07):动态层按声明的次数和聚合方式汇总,混合的结果记确定的“间歇”
依据:
- 决定 35 第 13、16 项(
docs/hub-r4-progress.md):V07(重复策略)要做。 - 模型:V07 DEF、R[0]–R[5];W02 F[6];V03 F[1]、R[4]、R[5];P07 R[1]、R[3];V04 R[0]、F[5];V05 R[7](首因不丢);B06 F[0](意图键带次序);W03 F[0](次数与时长预算);展示规则 16(
displayRules[16]:重复执行的结论显示观测分布)。用node tools/show-element.ts V07 W02 V03 P07 V04 V05 B06 W03读。 - 所有者的规矩:未知只是过渡状态。V07 R[0] 现在写“聚合方式为‘全部’时,结果混合记未知(间歇)”。各轮都过了完整性规则时,混合是看到了的事实:哪几轮通过、哪几轮失败都清楚,不缺事实,也没有哪一步能把它变成别的结论,所以不该记未知。R[1] 对 k-of-n 按阈值给判定,k 等于次数时就是“全部”,R[0] 的未知和它也对不上。
-
对照模型的复核第 2 节第 3 条:V07 没进引擎。上真实台架的设计第 5 节写“一个 S 只派发一次”;同一批写的
gateway-request-ids.md第 10 条把dispatch.bytes:<S>改成按尝试记,第 13 条加逐台只读探测,第 16 条在结果归属认证以后给逐用例的通过和失败。这一件在它们之上按轮做。 - 集成者先做(模型文字归集成者),开分支前提交:
- V07 R[0] 改成:每一轮先看它合不合期望的结局;聚合方式为“全部”时,各轮都合期望才合期望;有一轮不合就是不合;既有合又有不合的,标“间歇”,附观测分布。间歇的原因(被测对象、环境、执行上下文)只作假设,不进归责(V04 R[0])。
- 限定标记加
intermittent(间歇),归 V07,这一件用它。 - V07 R[5] 的默认次数:所有者 10-21 定了,决定表第 19 行按推荐(
node tools/show-element.ts --pending):验证与复现默认 3 次,Web 默认首轮通过、失败再重跑。所以:- 加一个“工作类”轴,归 V07,取值:验证、复现、Web;
- 默认的重复策略:验证和复现是 3 次、聚合方式“全部”;Web 是首次通过、2 次(首轮通过就停,失败再跑一次);
- 工作流包声明自己的工作类,没写重复策略的要求项按工作类取默认;包没声明工作类的才是一轮;
- case-compile 的派发那一行照旧写它自己的次数,写了的以写的为准。
- 上真实台架的设计第 5 节那一句:次数只来自冻结的重复策略和效果表的次数预算。
- 分支和工作树:
v07-repetition,目录circle-hub-v07-repetition。从 hub-redesign 开出;等 hub-unknown-exits(第 10 条把派发结局接进动态层)、dispatch-gateway(gateway-request-ids 第二步)、d03-p11-boundary(写声明和预算)和w10-criterion-change(同改contracts/src/pack.ts、run.ts、validation.ts、evaluate.ts、text.ts)合并以后,由集成者开出并通知。 - 可以改的路径(行号照现在的写,合并以后以函数为准):
contracts/src/pack.ts(RequirementTemplate 的repetition,工作流的工作类)、contracts/src/run.ts(RequirementSummary 带出它)、contracts/src/validation.ts(动态层结果的轮次和观测分布),照生成器重新生成contracts/generated/**;hub/runs/packs/validate.ts;hub/runs/packs/ports.ts:只改packSummary;hub/runs/engine/start.ts:只改requirementSummary。两处都带出生效的重复策略(第 1 条);hub/runs/engine/repetition.ts(新,纯函数)、terminals.ts的dynamicLayer、evaluate.ts里动态层取派发结局的那一段、README.md;hub/dispatch/**(按轮派发);hub/server/cli-job.ts:只改output()和状态那一行(逐轮列出);hub/server/text.ts、console/pages.ts(显示观测分布);tests/acceptance/oracle/**的动态层规则;- 对应的测试。
- 规则:同前(不推送、不建 PR、不发布、不部署;不碰 7420、钥匙串、环境配置文件和任何真实系统;测试只用合成数据,版本线 10.6 以后,地址只用 192.0.2.0/24 和 2001:db8::/32;
git commit -s)。所有者的规矩:- 未知只是过渡状态,写明缺的事实和下一步动作;
- 枚举只来自生成的词表:聚合方式用 aggregation 轴,终态用 dynamic_terminal 轴;
- Hub 只核验,不生成内容,不调用模型:每一轮派发的都是核验过的同一份字节;
- 核心里没有产品的字。
- 验证:
npx tsc --noEmit;node tools/gen-contracts.ts --check;node --test --test-concurrency=1对contracts/**、hub/runs/**、hub/dispatch/**、hub/server/**、tests/acceptance/oracle/**。每条先写改前失败、改后通过的测试。
要做的
- 重复策略的形状(V07 DEF、W02 F[6]):
- RequirementTemplate 加可选的
repetition:次数(1 到 10,上限写进 README);聚合方式;k(只在 k-of-n 时写,1 ≤ k ≤ 次数);是否换新上下文;是否先证基线;时间窗(秒,可选)。 - 只许写在声明了动态层的要求项上:静态检查不重复(架构第 1 节)。
- 没写的,按工作流声明的工作类取默认(集成者先做的那一条);工作流也没声明工作类的,就是一轮:次数 1、聚合方式“全部”,结论照样写“1/1”。
- RequirementSummary 带出生效的那一份(写的,或者默认的,标明是哪种),模型和客户端看得到。摘要有两处在拼:
start.ts的requirementSummary和ports.ts的packSummary,两处都要带。 - 测试:发布校验和合约逐条正反例;三种工作类的默认值各一;写了的盖过默认值;两处摘要给出的相同;现有的包不改照样读。
- RequirementTemplate 加可选的
- 按轮派发(B06 F[0]):
- 一个条目的每一轮是一条单独的效果,意图键的次序就是轮次。dispatch-gateway 已把
dispatch.bytes:<S>改成按尝试记,这一件再按轮分:同一(S,轮次)至多派发成功一次,尝试照它的规则。轮次不超过冻结的次数,也不超过效果表那一行的次数预算,超了被效果前边界拒绝(d03-p11)。 - 首次通过:有一轮通过就停,后面的轮不派发。
- 换新上下文:每轮取新的网关租约和会话,不沿用上一轮的。
- 先证基线(P07 R[1]):每轮之前,在同一个网关租约里做环境核对和逐台只读探测(dispatch-gateway 第 13 条)。不过的,这一轮记未运行,理由码
integrity_unproven,出口是重跑这一轮;不算失败。 - 时间窗:从第一轮开始计。窗外才开始的轮不派发,但留在分母里,记未运行,理由码
budget_exhausted(时长预算用完),出口是开新修订重跑(W06 R[0])。这样 k 等于次数的 k-of-n 在窗外有轮时判不了通过,写明缺哪几轮。 - 谁跑第 2 到 n 轮:
- 一次
circle-hub job dispatch就是一个作业,在同一条命令里按次序跑完冻结策略的全部轮次,每一轮都重新过效果前边界。 - 进程中途退出以后,
job resume只读、只对账已经开始的轮,不开新轮。 - 后面的轮只由新的一次
job dispatch接着开,从下一轮起,照样每轮过效果前边界。
- 一次
job status逐轮列出。- 测试:
- 桩网关上三轮;首次通过在第二轮停;
- 换新上下文时三轮的租约号各不相同;
- 基线不过的那一轮;窗外的轮在分母里;
- 同一(S,轮次)再派发被拒;
- 第 1 轮和第 2 轮之间进程退出:
job resume不开第 2 轮,新的job dispatch从第 2 轮接着跑。
- 一个条目的每一轮是一条单独的效果,意图键的次序就是轮次。dispatch-gateway 已把
- 汇总(
repetition.ts,按聚合方式的一张表,satisfies Record<Aggregation, …>):- 输入:逐轮的动态层终态(已过完整性规则,V03 R[5]),加这个要求项期望的结局。
- 每一轮先判它合不合期望,照
terminals.ts的meets()。期望通过时,通过合、失败不合;期望失败(对照或反向的用例)时,带期望码的失败合、通过不合。 - 汇总按“合不合”算:
- 全部:各轮都合 → 终态取合期望的那个。有一轮不合 → 终态取不合期望的那个,码取第一次不合的(首因不丢);既有合又有不合 → 同时标
intermittent,要求项不满足。 - k-of-n(R[1]):合的轮数 ≥ k → 合期望的终态;不合的轮数 > 次数 − k → 不合期望的终态;否则缺判定。
- 首次通过(R[2]):有一轮合 → 合期望的终态,之前不合的轮照样列在分布里;各轮都不合 → 不合期望的终态;否则缺判定。
- 缺判定(有轮是无判定、未运行、未完成,又定不下来):取其中最弱的,写明缺哪几轮,出口是重跑这几轮(hub-unknown-model 的 exit)。
- 全部:各轮都合 → 终态取合期望的那个。有一轮不合 → 终态取不合期望的那个,码取第一次不合的(首因不丢);既有合又有不合 → 同时标
- 观测分布(R[3]):次数,各终态的个数,逐轮列表(轮次、终态、码、合不合期望),全部保留。
- 测试:
- 每种聚合方式的表格用例:全合、全不合、间歇、缺轮;
- 每张表都加期望失败的几行:期望失败时,三轮全失败是满足;两次失败一次通过是间歇、不满足;
- 性质测试:k 等于次数的 k-of-n,对任意轮次序列和任意期望,都和“全部”给出同样的终态和满足状态。
- 完整性和目标自报(V03 R[5]、D02 R[6]):
- “结果按派发身份归属”在这个网关版本上没认证时,每一轮都是无判定,汇总也是无判定(完整性未证明),出口是认证这条前提(管理员,dispatch-gateway 第 12 条)。
- 目标逐轮的报告另外汇总成一条观察主张,带“目标对本次派发的报告”,也写观测分布,例如“目标报告:3 次里 2 次通过、1 次失败(间歇)”。这是确定的观察,不满足只收事实的要求项。
- 测试:认证和没认证各一。
- 间歇的归责(V04 R[0]、R[1]、F[5]):
- 只有汇总的终态不合期望时才带归责(V04 R[1]),记
unattributed(待归因)。 - 被测对象缺陷、环境、执行上下文三种原因写成假设集,经 hub-unknown-exits 第 4 条加的 V08 记录写,不进归责。
- 测试:合期望的间歇不带归责;不合期望的带
unattributed,并有一份假设集。
- 只有汇总的终态不合期望时才带归责(V04 R[1]),记
- 显示(展示规则 16):答复和控制台写观测分布,例如“3/3 次未见失败”“间歇:3 次里 1 次失败(第 2 次)”。动态层没运行时,静态的“通过”旁边写规则@版本和动态层的状态,不用“未上设备”这类领域词。测试:
text.test.ts、console.test.ts各几条。 - oracle:
tests/acceptance/oracle的动态层规则加上汇总,差分测试照新规则;引擎 README 的终态一节同步。
不做:两次运行之间的自动比较。V07 R[4] 只约束比较怎么做,Hub 现在没有运行之间的比较,决定 35 第 13、16 项也没要。以后加比较的地方要照 R[4] 写“重复策略不同,不可比”,README 记一句。
完成后在终端里回报:提交号、测试数量、没做完或拿不准的地方。