You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
spec+executor: a wait node with no waitEventConfig parses clean and suspends forever with success: true — require the block (and timerDuration for timers) at the contract, retire the executor's ?? 'timer'; declare http_request.method / screen.mode defaults per the executor (objectui#9354's objectstack half) #17928
Filed by the director seat (decision batch #127 item 5, ruled by the maintainer on 2026-09-13; ruling recorded on objectui#9354). ⛔ Not claimed, ⛔ not dispatched. Graded here because the ruling names the priority and the landing point.
The ruling this card executes
Maintainer, verbatim (live PM chat, 2026-09-13T05:5xZ), to decision batch #127 presented as 1B·2A·3B·4B·5C′: 「16678 具体解释,计划用哪个字段判断经理。其他同意」 — item 5 (C′) is covered by 「其他同意」. C′, as presented: the protocol is the source of truth; a designer never invents a default the protocol does not apply; a default the protocol should have is declared by the protocol; a required key has no "unset behaves as". The objectui half (the designer's two required-enum declarations are deleted now) is objectui#9354; this card is the objectstack half.
Inside a present block, eventType is REQUIRED for both wait.waitEventConfig and boundary_event.boundaryConfig (objectui#9109's table, rows 9–10, installed spec 17.4.0). So the contract refuses an omitted key but accepts an omitted block — two documents, two verdicts, and the accepted one is the silent one.
HttpConfigSchema.method is z.string().optional() with no default; ScreenConfigSchema.mode is an optional enum with no default (same table, rows 7–8). What the executors apply for an absent value is NOT MEASURED (PR objectui#9279's own caveat: "the installed spec's Zod applies no default is NOT the runtime applies no default").
A — the contract stops accepting the silent shape (packages/spec)
FlowNodeSchema: waitEventConfig is required when type: 'wait'; boundaryConfig is required when type: 'boundary_event'. With eventType already required inside each block, a wait / boundary node then always says what it waits for.
WaitEventConfigSchema: timerDuration is required when eventType: 'timer' (a timer with no duration is the forever-hang; refuse it at authoring with a remedy naming the key).
Accept-set narrowing ⇒ Clause-②: no; changeset under the launch-window convention (minor, BREAKING banner); ADR-0087 semantic migration entry: a stored wait node with no block has no lossless conversion (the author's intent is unknown) ⇒ structured TODO naming the node id.
B — the executor follows the contract (packages/services/service-automation)
wait-node.ts: the ?? 'timer' fallback and the ?? {} block fallback are retired; a node that reaches execute without the block (a stored pre-migration document) fails the run loudly with a named error — ⛔ never suspends with success: true. The comment "a wait node without one is a VALID TIMER WAIT" is deleted with the reversal named.
Read boundary_event's executor on an absent block; apply the same treatment if it defaults silently.
Pin both directions: absent block ⇒ named failure; present timer block with duration ⇒ job scheduled, waitUntil written.
C — the two optional keys get the default the executor actually applies, or none
Read what the http_request executor sends when method is absent. If it sends GET (the universal HTTP default), HttpConfigSchema.method declares .default('GET') and the reference page renders it; if it refuses or does something else, that is recorded and the key stays default-free (objectui then deletes its declaration).
Same for screen.mode and 'create'.
⛔ The two required enums (wait.eventType, boundary_event.eventType) get NO default here: the maintainer ruled that a required key has no "unset behaves as", and the designer's declarations for them are deleted on the objectui side (objectui#9354).
Cross-domain declaration
Landing points: packages/spec/src/automation/** (A, C) and packages/services/service-automation/src/builtin/wait-node.ts (+ the boundary executor) (B). Routed domain:spec — the protocol decides and the executor follows it — with the service-automation file face declared in the claim comment per the cross-domain exception path; ⛔ not two PRs that could land the executor change without the contract change or vice versa.
After A+B: a wait node with no block is refused at parse with a message naming waitEventConfig; a stored one fails the run with a named error; a timer wait with no timerDuration is refused at parse.
After C: objectui's declared-default ledger (UNBACKED_REGISTER, PR objectui#9279) re-measures the two optional rows against the adopted spec and the entries are removed in the version-adoption PR; the register must read 0 for http_request.method / screen.mode once the spec carries whatever this card declares.
objectui#9354 is notified on landing (its two remaining declarations follow this card's answer for C).
priority:p1 per the triage escalation on objectui#9109 / objectui#9354 (silent forever-hang reachable from the designer's default state); type Bug; pm:queue.
Filed by the director seat (decision batch #127 item 5, ruled by the maintainer on 2026-09-13; ruling recorded on objectui#9354). ⛔ Not claimed, ⛔ not dispatched. Graded here because the ruling names the priority and the landing point.
The ruling this card executes
Maintainer, verbatim (live PM chat, 2026-09-13T05:5xZ), to decision batch #127 presented as
1B·2A·3B·4B·5C′: 「16678 具体解释,计划用哪个字段判断经理。其他同意」 — item 5 (C′) is covered by 「其他同意」. C′, as presented: the protocol is the source of truth; a designer never invents a default the protocol does not apply; a default the protocol should have is declared by the protocol; a required key has no "unset behaves as". The objectui half (the designer's two required-enum declarations are deleted now) is objectui#9354; this card is the objectstack half.What is measured, and by whom
waitnode with nowaitEventConfigparses clean and suspends forever, silently, answeringsuccess: true. Triage's source reading onorigin/main(packages/services/service-automation/src/builtin/wait-node.ts,execute; measurement request(flow executor): what does await/boundary_eventnode with NO config block do at run time? — the parse contract accepts it, and objectui's inspector already advertises it as a timer #17843 comment 5651444086): the block is optional at the contract, the executor applieseventType ?? 'timer'with a comment declaring that intended,timerDurationis absent so nowaitUntilis written and no job is scheduled, the onlywarnfires only when no job service exists, and the node returns{ success: true, suspend: true }.wait/boundary_eventnode with NO config block do at run time? — the parse contract accepts it, and objectui's inspector already advertises it as a timer #17843 stays open for the real run and its result is this card's first acceptance line.eventTypeis REQUIRED for bothwait.waitEventConfigandboundary_event.boundaryConfig(objectui#9109's table, rows 9–10, installed spec 17.4.0). So the contract refuses an omitted key but accepts an omitted block — two documents, two verdicts, and the accepted one is the silent one.HttpConfigSchema.methodisz.string().optional()with no default;ScreenConfigSchema.modeis an optional enum with no default (same table, rows 7–8). What the executors apply for an absent value is NOT MEASURED (PR objectui#9279's own caveat: "the installed spec's Zod applies no default is NOT the runtime applies no default").boundary_event's executor on an absentboundaryConfigis NOT MEASURED (measurement request(flow executor): what does await/boundary_eventnode with NO config block do at run time? — the parse contract accepts it, and objectui's inspector already advertises it as a timer #17843 read thewaitbranch only).What lands
A — the contract stops accepting the silent shape (
packages/spec)FlowNodeSchema:waitEventConfigis required whentype: 'wait';boundaryConfigis required whentype: 'boundary_event'. WitheventTypealready required inside each block, a wait / boundary node then always says what it waits for.WaitEventConfigSchema:timerDurationis required wheneventType: 'timer'(a timer with no duration is the forever-hang; refuse it at authoring with a remedy naming the key).Clause-②: no; changeset under the launch-window convention (minor, BREAKING banner); ADR-0087 semantic migration entry: a storedwaitnode with no block has no lossless conversion (the author's intent is unknown) ⇒ structured TODO naming the node id.B — the executor follows the contract (
packages/services/service-automation)wait-node.ts: the?? 'timer'fallback and the?? {}block fallback are retired; a node that reachesexecutewithout the block (a stored pre-migration document) fails the run loudly with a named error — ⛔ never suspends withsuccess: true. The comment "a wait node without one is a VALID TIMER WAIT" is deleted with the reversal named.boundary_event's executor on an absent block; apply the same treatment if it defaults silently.waitUntilwritten.C — the two optional keys get the default the executor actually applies, or none
http_requestexecutor sends whenmethodis absent. If it sendsGET(the universal HTTP default),HttpConfigSchema.methoddeclares.default('GET')and the reference page renders it; if it refuses or does something else, that is recorded and the key stays default-free (objectui then deletes its declaration).screen.modeand'create'.wait.eventType,boundary_event.eventType) get NO default here: the maintainer ruled that a required key has no "unset behaves as", and the designer's declarations for them are deleted on the objectui side (objectui#9354).Cross-domain declaration
Landing points:
packages/spec/src/automation/**(A, C) andpackages/services/service-automation/src/builtin/wait-node.ts(+ the boundary executor) (B). Routeddomain:spec— the protocol decides and the executor follows it — with theservice-automationfile face declared in the claim comment per the cross-domain exception path; ⛔ not two PRs that could land the executor change without the contract change or vice versa.Acceptance
wait/boundary_eventnode with NO config block do at run time? — the parse contract accepts it, and objectui's inspector already advertises it as a timer #17843's real run confirms (or refutes) the silent hang; if refuted, section B narrows to whatever the run shows and objectui#9354's p1 is re-graded by triage.waitnode with no block is refused at parse with a message namingwaitEventConfig; a stored one fails the run with a named error; a timer wait with notimerDurationis refused at parse.UNBACKED_REGISTER, PR objectui#9279) re-measures the two optional rows against the adopted spec and the entries are removed in the version-adoption PR; the register must read 0 forhttp_request.method/screen.modeonce the spec carries whatever this card declares.Relations
pm:queuep1) · objectui#9109 (the ledger, PR objectui#9279 in flight) · measurement request(flow executor): what does await/boundary_eventnode with NO config block do at run time? — the parse contract accepts it, and objectui's inspector already advertises it as a timer #17843 (the measurement request; stays open for the real run) · objectui#9277 / objectui#9278 (same ledger, other direction; ⛔ not folded).Blocked-by:line: nothing mechanical holds this card. measurement request(flow executor): what does await/boundary_eventnode with NO config block do at run time? — the parse contract accepts it, and objectui's inspector already advertises it as a timer #17843's run is an input, not a gate — section A is right whether or not the run reproduces the hang, because the contract already refuses the omitted key inside a present block.priority:p1per the triage escalation on objectui#9109 / objectui#9354 (silent forever-hang reachable from the designer's default state); type Bug;pm:queue.Generated by Claude Code