Repository navigation
automation: ActionDescriptor.supportsPause / isAsync 是零读者的声明字段 —— 引擎判定「暂停」的唯一事实是 execute() 返回的 suspend: true #5703
Description
Activity
发现分诊轮判级(#4949 纪律):持有(
finding留)。为什么还留着:事实成立(
ActionDescriptor.supportsPause/isAsync三仓零非测试读者,引擎判"暂停"的唯一事实是engine.ts:4256的if (result.suspend),#3801 的 resume 闸门也不看它),但处置是退役一个已发布的 spec 声明字段 —— 属 breaking,须走 ADR-0049 enforce-or-remove 的完整路线(ADR-0087 转换 + 生成基线 + 文档 + pin 测试),而 v17 的退役窗已随 #4938 批次收口。今天无用户可达伤害:全部 6 个 pausing 执行器都在本仓内且声明都正确,声明与事实暂时同向。重启条件:v18 列车的退役批开列时一并测量与判定 —— 与 #5295(
ServerEvent*/ServerCapabilities/ServerStatus零消费者,08-05 已按同一理由持有、同一重启条件)同批处理,两单是同一形态(spec 侧幸存声明 + 零读者 + 退役属 breaking),分开判会得出不一致的口径。⚠️ 另一条可先行的路(若 services 车道认为值得):把「声明与事实不同向」变成门可见 —— 注册时校验supportsPause与执行器实际是否返回suspend的一致性(即 #5561 那条告警的同族),这不需要退役任何字段,可独立立单。本轮不代拆。本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
- added a commit that references this issue
on Aug 6, 2026 存量裁决轮(维护者 2026-08-06 委托,session_01LeEfA7CFwbJb7JJmXm2KM3):维持持有,但记录一处前提更正——「零读者」已过时:#5561(PR #5725,06:03Z 前合入)已在 engine.ts:1388 落地按
supportsPause下判词的告警,其 TSDoc 明写「#5703 tracks the runtime half」。本单现追踪的是 runtime 半边(execute 返回 suspend 而声明 false 时告警静默 fail-open);今天仓内 6 个 pausing 执行器声明皆正确、无第三方执行器,无人可撞。重启条件:services 车道投资一致性校验,或第三方 pausing 执行器面出现。
Generated by Claude Code
Findings triage (#4949 discipline): hold —
findingretained,domain:specunchanged.Stale-premise check. The 08-06 08:06Z re-grading already corrected the body's "zero readers" premise: #5561 / PR #5725 landed a registration-time warning that does judge on
supportsPause(engine.ts:1388), so what this issue now tracks is strictly the runtime half — an executor whoseexecute()returnssuspend: truewhile its descriptor leavessupportsPauseat the.default(false), which the warning cannot see and which still reachesresumeAuthority's fail-open default. That scoping still holds this round; no new commit changes it.One state change worth recording, because it moves the restart condition: #5561 is now
pm:on-hold(it was open and active when the previous restart condition was written). Both of that condition's clauses therefore need re-reading:- "services 车道投资一致性校验" — the nearest vehicle for that investment was the automation:
resumeAuthoritydefaults to'any', so every future pausing node ships fail-open — ADR-0044 says this is "tracked separately" and nothing tracks it #5561 family, and it is now parked. So this clause is not merely unfired, it currently has no carrier. Treat it as live only if the services lane opens a consistency-check issue in its own right. - "第三方 pausing 执行器面出现" — unfired. All six pausing executors remain in-repo (
screen,wait,subflow,map,approval,approval_revise), all declaresupportsPause: truecorrectly, and no example app registers node executors. Declaration and fact are still pointing the same way, so nobody can be hurt today.
Restart condition, re-anchored to the surviving carrier: the v18 retirement batch, processed together with #5295 (
ServerEvent*/ServerCapabilities/ServerStatus, held 08-05 on the same grounds). Both are the same shape — a survivingpackages/specdeclaration with no production reader, whose removal is breaking and so owes the full ADR-0049 enforce-or-remove route (ADR-0087 conversion, generated baselines, docs, pin tests). Judging them apart would produce inconsistent verdicts on one question, which is why they stay batched. The v17 retirement window closed with the #4938 batch, so neither can move before that train.Unchanged and still available as an independent path if the services lane wants it: making declaration-vs-fact gate-visible (validate at registration that a descriptor claiming no pause never returns
suspend) retires nothing and needs no window. ⛔ Not split out by this seat — that is the lane's call, and the transfer protocol runs through the target queue, not through this thread.本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
- "services 车道投资一致性校验" — the nearest vehicle for that investment was the automation:
os-project-manager commented
on Aug 8, 2026 CollaboratorMore actionsFindings sweep (maintainer-authorized one-off, 2026-08-07 — registered on #6015): promoted to the queue as a retirement card.
ActionDescriptor.supportsPause/isAsynchave zero non-test readers across three repos while the engine's only pause fact isresult.suspend— declared-but-inert fields under the maintainer's standing tight default (today's family rulings: #6247 retire, #5488 flip-to-false). ADR-0049 remove side unless a reader is found at claim time.finding→pm:queue.
Generated by Claude Code
os-project-manager commented
on Aug 8, 2026 CollaboratorMore actionsBundled into sweep card #6486 (ADR-0049 zero-consumer retirements, 5 members). Keeps
pm:queuebut is excluded from batch selection while #6486 is open — claim the sweep card, not this one; it closes viaFixeswhen that PR merges.
Generated by Claude Code
Maintainer ruling (2026-08-08): Option A — close this card; successor filed as #6667.
The card's premise ("zero readers in all three repos") expired while it sat: #5561 / PR #5725 landed warnIfResumeAuthorityUndeclared (engine-side wording keyed on supportsPause), the check-resume-authority-declared.mjs CI gate, dedicated tests, and TSDoc. supportsPause is now an enforced input, not an inert declaration — retiring it would delete an enforcement surface the maintainer just shipped. isAsync, taken alone, still has zero readers; its disposition moves to the successor so it gets decided on fresh measurements at pickup time, not today's reading.
Successor #6667 carries the two remaining pieces: the runtime consistency check (executor suspend result vs declared supportsPause — the blind spot the authoring-time gate does not cover) and the isAsync decision.
Closing as not planned: the retirement this card proposed will not happen.
Maintainer directive (verbatim, covering all 14 inbox cards): 「你的建议全部接受」. Recorded by PM session session_01JaVVMrSxt7Tgi1uwEuDtH7.
Generated by Claude Code
发现于 #5561 第一步(注册时对未声明
resumeAuthority的 pausing executor 打告警)的前提重验。observation-class:今天没有用户会撞到,单独立单只为把事实记下来。事实(origin/main @ 6ddb2ec)
ActionDescriptor.supportsPause与ActionDescriptor.isAsync(均在packages/spec/src/automation/node-executor.zod.ts,均.default(false))在 framework / objectui / cloud 三仓没有任何非测试读者。仓库范围内对.supportsPause/.isAsync的读取只有 3 处断言:packages/spec/src/automation/node-executor.test.ts:174(读默认值)、:218(读 legacyWAIT_EXECUTOR_DESCRIPTOR)packages/plugins/plugin-approvals/src/approval-node.test.ts:100packages/services/service-automation/src/engine.ts:4256的if (result.suspend)。resolveResumeAuthority(engine.ts:2708)只沿 alias 走到 canonical 后读resumeAuthority,supportsPause全程不参与。为何是 observation-class
今天全部 6 个 pausing 执行器都在本仓内,且
supportsPause: true声明都正确 ——screen(builtin/screen-nodes.ts:50)、wait(builtin/wait-node.ts:166)、subflow(builtin/subflow-node.ts:54)、map(builtin/map-node.ts:53)、approval(plugin-approvals/src/approval-node.ts:114)、approval_revise(approval-revise-node.ts:79)。仓内没有第三方 pausing 插件,示例应用也不注册任何节点执行器,所以这个字段今天错不了。为何仍值得记
#5561 第一步的裁决把告警的触发条件定在
supportsPause: true。一旦有代码开始按这个字段下判词,它就从「无人读的声明」变成安全判定的输入 —— 而它当前不被任何执行路径校验:一个execute()返回suspend: true、却把supportsPause留在默认false的执行器,既不会被那条告警点名,又照样拿到resumeAuthority的 fail-open 默认。这就是 declared 不等于 enforced(Prime Directive #10)在同一个节点上的第二层,且正好落在 #5561 想堵的那条缝上。两条路(只记录,不在本单裁)
按 ADR-0049 enforce-or-remove 择一:
engine.ts:4256的result.suspend处对照该节点类型描述符的supportsPause,不一致就拒绝/告警(把描述符声明变成运行时可反驳的事实)。content/docs/references/automation/node-executor.mdx,那就在 TSDoc 里写清「声明供设计器/文档使用,运行时不校验」,别让下一个作者以为它是闸门输入。Refs #5561、#3801、#3823。