Repository navigation
fix(service-automation): a run summary node row carries its steps warnings, so a refused notify channel shows in the trigger response - #33438
Conversation
…fy summary row Red on origin/main: the trigger response's summary.nodes[] notify row carries no warning when its only channel was refused. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016WV4cykhsWAtSL6Sr4VWFG
…ode rows A notify step whose only channel was refused warned on its step, but its row in summary.nodes[] read as a clean success with acted: 0, so a caller reading the trigger response could not tell nothing was delivered. summarizeRun now folds each node's step warnings onto its row (distinct texts, first-seen order, bounded per node with a counted overflow entry), and FlowRunNodeSummarySchema declares the optional `warnings` member in the step log's own shape. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016WV4cykhsWAtSL6Sr4VWFG
…d changeset Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016WV4cykhsWAtSL6Sr4VWFG
📓 Docs Drift Check4 anchor(s) derived from 2 changed package(s); no hand-written page names any of them. What this run could not see
Coarse fallback — 172 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 47ef06f73b2843ff1db4e15aec0deda8a8a4e410 && git checkout 47ef06f73b2843ff1db4e15aec0deda8a8a4e410
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 9499dcc530a3dd8c0eee872f9483b96127ac8bfe c14afda2e91048a917253ec3c1b3d4b6c5a9b7a9 && git checkout -B drift-repro 9499dcc530a3dd8c0eee872f9483b96127ac8bfe && git merge --no-ff c14afda2e91048a917253ec3c1b3d4b6c5a9b7a9
node scripts/docs-audit/affected-docs.mjs --json 9499dcc530a3dd8c0eee872f9483b96127ac8bfe |
|
domain:server#5 · os-elon-musk · session_016WV4cxHwXNcGcAHNerZsom Request: review · area A5 · head c14afda · 2026-11-14T21:47Z Contract review (Clause-② yes, widening: optional |
|
Contract-review-claim: session_016WV4cxDxAYxdtDhtR1kQQe · head c14afda · 2026-11-14T21:48Z review#2 (server area pilot, A5). |
Contract reviewServed-tier: review#2 (server area pilot) · area A5 · Fixes #33341 · published schema face ( ① Derived judgments
② Semver level
③ Boundary flags
④ Design judgmentRulings on the two questions from the os-dev report (comment 6884319460 on #33341):
Nits (none blocking):
Implemented-by: VERDICT: PASS Nits only, so this is the final round. |
|
domain:server#5 · os-elon-musk · session_016WV4cxHwXNcGcAHNerZsom ACCEPT · area A5 · head c14afda · 2026-11-14T21:52Z
|
⛔ merge queue 构建失败 — 先分诊,再决定要不要重排队列构建 43645264458 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集), 分类: 失败的 job(日志抽取,best effort):
跨 PR 相同签名(24h,按失败测试文件聚合):
历史信号:
分诊清单:
Generated by Claude Code · merge-queue-triage workflow (#4859) |
Requested by Elon · project thread
Fixes #33341
Clause-②: yes (widening)
Metadata-protocol: added
Skills-docs: none — the added member is a field of the run summary the platform answers; no metadata author writes it, and no skill teaches the summary's node rows
维护者速读
summary.nodes[]的每个节点行,现在会带上该节点步骤产生的告警(warnings,字符串数组);spec 的FlowRunNodeSummarySchema同步声明这个可选字段。notify节点唯一的渠道被拒(如未注册的push)时,步骤日志里有告警,但触发接口返回的摘要里该行只显示success、acted: 0,调用方看不出其实谁都没通知到。packages/services/service-automation/src/run-summary.ts(折叠与上限,nodeWarnings);packages/spec/src/automation/execution.zod.ts(新字段与描述);packages/services/service-automation/src/builtin/notify-delivery-outcome.integration.test.ts(末尾新 describe)。pnpm --filter @objectstack/service-automation exec vitest run src/builtin/notify-delivery-outcome.integration.test.ts,预期 12 个用例全绿,其中新 describe 的 4 个用例断言摘要行带有点名'push'的告警。What changes
@objectstack/spec:FlowRunNodeSummarySchemagainswarnings?: string[], the same element shape asExecutionStepLogSchema.warnings. Optional and additive: absent when no execution of the node raised a warning, never[].@objectstack/service-automation:summarizeRunfolds every node's stepwarningsonto that node's row, distinct texts in first-seen order. The list is bounded per node (MAX_NODE_SUMMARY_WARNINGS = 5, not exported from the package entry) because the summary's detail is sized by the flow's static shape, which is what keeps a long sweep's persistedsummary_jsonunder its byte cap; past the bound a final entry says how many distinct warnings were left out, and the step log keeps each execution's own.notify's: acreate_record/update_recordwhose requested fields were stripped now says so on its row too. One fold over the step log covers the whole class instead of anotifyspecial case.status, every counter, the run's outcome and flow control. A refused channel is still a successful step, as Flow notify step records success when its only channel was refused and nothing was delivered #32143's fix decided.packages/spec/authorable-surface/automation.json(+1 key) andcontent/docs/references/automation/execution.mdx, both fromcheck:generated --fix.authorable-surface.base.jsonis untouched..changeset/33341-notify-summary-row-warning.md:minorfor both packages, with both declaration lines.The trigger door serves the engine's result verbatim (
deps.success(result),packages/runtime/src/domains/automation.ts), so the engine'srun.summaryis the trigger response'ssummary; the same summary rides a flow door's400 FLOW_FAILEDdetails and the persisted run row.Why
The run already stopped claiming a false success (#32143), but a caller reading only the trigger response's summary still saw a notify row with
status: 'success',acted: 0and no reason, so it could not tell "nothing to send" from "the only channel was refused". The card asks for the warning on that row, in the shape other nodes already use for warnings (the step log'swarnings).Metadata-protocol is
addedand notnonebecauseFlowRunNodeSummaryis on the spec's authorable-surface baseline, and the changeset gate refusesnonebeside a movedauthorable-surface/file. Clause-② isyes (widening): an optional member added to a published response schema.Tests
All readings on head
c14afda2e9.AutomationEngine.executewith the realMessagingService, outbox and dispatcher): the new describe innotify-delivery-outcome.integration.test.tswent red, 3 failed / 9 passed (12),AssertionError: Target cannot be null or undefined.on the row'swarnings; the CONTROL case (registered channel, no warning) stayed green.notify-delivery-outcome.integration.test.ts(durable path, inline path, partial delivery, control); each parses the summary throughFlowRunSummarySchema, so an undeclared member would be stripped and the case would go red. 5 cases inrun-summary.test.ts(distinct first-seen fold, absent on other rows and on skipped nodes, a failed execution's warnings, the bound with its overflow entry, a list exactly at the bound). 3 cases inpackages/spec/src/automation/execution.test.ts(kept through a parse, absent stays absent, a non-string entry is refused at['warnings', 0]).scripts/ablation-replace.mjs: anchorif (warnings) node.warnings = warnings;1 → 0, blobbacf67bb→ef6fbf30; 8 failed / 51 passed (59), every new warning pin red and the control green. Restored: blob == HEADbacf67bb,git diff HEADempty. The tests importrun-summary.tsfromsrc, so no dist leg.Suite readings (os-verify-lock VERDICT lines)
pnpm --filter @objectstack/service-automation test: Test Files 281 passed (281), Tests 3916 passed (3916), VERDICT command-exit 0.pnpm --filter @objectstack/service-automation typecheck(tsc + check:test-typecheck): exit 0.pnpm --filter @objectstack/spec test: Test Files 840 passed (840), Tests 26868 passed, 1 todo (26869), VERDICT command-exit 0.pnpm --filter @objectstack/spec typecheck: exit 0.pnpm --filter @objectstack/runtime typecheck+vitest runofflow-failed-inner-refusal,endpoint-flow-dispatch-status,automation-trigger-paused-run,automation-runs-unknown-flow: Test Files 4 passed (4), Tests 39 passed (39), VERDICT command-exit 0.eslint --no-inline-configover the five touched source and test files: exit 0.Acceptance notes
@objectstack/runtime(the trigger door and the typedFlowFailureDetailsbuilder) was re-run locally, its typecheck plus the four test files that read the summary. Every other dependent is left to CI'sTest CoreandTypeScript Type Check. Aturbo ls --affectedset would be blind to tests that read another package's source from disk, and the repo-root suites are not on that graph at all.origin/mainbefore opening: the branch is 9 commits behind, none touchingpackages/spec/src/automation,run-summary.ts, the authorable-surface or the reference docs (read withgit diff HEAD...origin/mainon those paths); the merge queue tests the merged tree.subflowchild's warnings stay on the child's own run row, as itsskippedgates do; the parent'ssubflowrow carries only warnings its own step raised.Verification
Derived gates (dispatch-gates --commands at c14afda, 8 paths vs merge base b462444)
dispatch-gates --ran: 109 accounted for, 107 run, 2 NOT MEASURED, 0 UNRUN.check:skill-examples(spec), reason: exit 3 PREREQUISITE NOT MET, it compiles the skill examples against built@objectstack/client/@objectstack/client-reactdeclarations, and this container has not built them.check:dual-build-cjs-loads, reason: exit 3 PREREQUISITE NOT MET, it loads 38 packages' built CJS entries and needs a fullpnpm build.Lint & Repo Gateson this PR.pnpm --filter @objectstack/spec check:generatedafter--fix: 14 of 14 artifacts current (it had namedcheck:docsstale once, regenerated above);check:authorable-surfaceandcheck:api-surfacegreen.Human Minimum
packages/specholds no runtime logic.pnpm lintpasses (eslint run over the touched files; the repo-wide run is CI's).main, one pull request.packages/spectouched: its generated artifacts are regenerated and committed.content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.Seat:
domain:server#5 · os-elon-musk · session_016WV4cykhsWAtSL6Sr4VWFG, dispatched to an os-dev subagent on claim 6883603057.Generated by Claude Code