Skip to content

feat(spec,automation): flow 的 update_record / delete_record 可以声明批量意图 multi - #5485

Merged
os-zhuang merged 2 commits into
mainfrom
claude/issue-5393-flow-bulk-intent
Aug 5, 2026
Merged

feat(spec,automation): flow 的 update_record / delete_record 可以声明批量意图 multi#5485
os-zhuang merged 2 commits into
mainfrom
claude/issue-5393-flow-bulk-intent

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Fixes #5393

前提复核(rule 6,对 origin/main @ ed0d2aa)

issue 的三条事实全部成立,逐条实测:

  • DeleteRecordConfigSchema / UpdateRecordConfigSchema(packages/spec/src/automation/builtin-node-config.zod.ts)是 strictObject,前者只声明 objectName / filter,后者只多一个 fields —— 任何批量意图拼法都被 unrecognized_keys 拒。
  • packages/services/service-automation/src/builtin/crud-nodes.ts 的两个执行器调用 data.update / data.delete 时不传 options.multi
  • 引擎契约不变:resolveEngineDeleteDispatch(标量 where.id → 按 id;否则 options.multideleteMany;否则抛 Delete requires an ID or options.multi=true),update 侧在 engine.ts 有同款内联 throw。

所以谓词批量写从任何 app 的任何 flow 都不可达,而节点描述符写着 Delete Records / Delete records matching a filter. —— declared ≠ enforced(PD #10)。按在册裁定 A 实现。

改了什么

spec —— 两个 config 各声明一个同名键 multi(z.boolean().optional(),默认 false):

  • 缺省 / false:执行器传 multi: false,写入必须以标量 id 点名一行,谓词(含 id: { $in: [...] })由引擎拒绝。拒绝即契约,不是要绕过的缺陷。
  • true:执行器传 options.multi: true,落到 driver.updateMany / deleteMany,步骤的 acted 指标报出命中行数。
  • 名字复用引擎既有的词(EngineUpdateOptions.multi / EngineDeleteOptions.multi)—— 一概念一名(PD Add comprehensive test suite for Zod schema validation #12),从节点 config 到 driver 调用全程可 grep,不发明第二个词。

guidance(#4001 纪律,两道门都写) —— bulk / all / multiple 拿到点名处方,options: { multi: true } 被当作写错层回答(那是引擎的 options 包,不是节点 config)。这四个拼法是 #5225 诊断期真喂过 safeParse 的,编辑距离从它们中的任何一个都够不到 multi,没有这些条目拒绝就只会报个键名。同一份处方复制到 service-automation 引擎的注册门(FLOW_NODE_UNKNOWN_KEY_GUIDANCE),因为注册是作者在 boot 时撞到的第一道门,而 #4001 的发现正是:检测面会随默认值翻转自动泛化,处方不会

描述符表单 —— 两个节点的 configSchema 各加 multi,所以 form ↔ Zod 台账对得上,键在 Studio 里可授权,而不是只能手写元数据。

执行器 —— multi: cfg.multi === true每次调用上都写出来,而不是 true 时才 spread:multi: false 是让引擎拒绝谓词写的那一半契约,调用点的读者应该直接看见问的是哪一半,而不是从一个缺席的键推断。

packages/objectql 零改动。#3810 的抹除守卫零改动,并新增用例钉住它:声明 multi 不会解除它。

测试

新增 packages/services/service-automation/src/builtin/crud-bulk-intent.test.ts(10 例)。它的 delete 替身以 assertEngineDeleteDispatch(从 @objectstack/objectql import 的生产者自己的判定)开头,所以在任何输入上都不可能比真引擎松 —— 包括手抄守卫必漏的 id: { $in: [...] }(看着像 id,其实是谓词)。check-engine-double-contract 已把该文件认作 pinned

这正是 issue 点名的 #5197 盲点:run-summary.test.ts 的内联 async delete() { return false; } 既接受真引擎拒绝的谓词删除,又因为零参而躲过门禁的 arity 判定(isEngineDeleteShape 要求引擎的 (object, options) 形状),连被发现都做不到。

为此给 @objectstack/service-automation 加了 @objectstack/objectql devDependency —— 无环:objectql 的传递依赖闭包(12 包)不含 service-automation,turbo run build --filter=@objectstack/service-automation --dry 正常解析。scripts/engine-double-contract.baseline.json 里 8 条 service-automation 条目的 why 原本写着「不依赖 objectql,加依赖是另一次可评审动作」—— 那句话被本 PR 变成假的,所以按 plugin-auth 的 #3585 先例把它们改成 MEASURED 记述,并给 crud-filter-guard.test.ts 多留一句:它有几条 #3810 fixture 断言谓词删除成功,真引擎会拒;#5393 之后那是可表达的,所以将来 pin 它时那些 fixture 应该multi: true,而不是删掉。

update 侧刻意不 pin,并在文件头写明原因:objectql 没有导出 update 的判定函数(engine.ts 里是内联 throw),门禁自己的文件头也把 "update's twin dispatch" 列为待抽取后再覆盖的切片。所以 update 用例只断言执行器交给引擎的 options 包——执行器的全部义务——并明确不对引擎会不会接受它发表第二份意见;在 fake 里手抄一份 update 判定,恰恰是那道门禁存在的理由。已另开 issue 记录。

反向验证(方向是先判定后跑的:红)

预判:把执行器的 multi 接线撤掉,multi: true 的用例应当变红,因为替身钉在生产者判定上,谓词删除会拿到引擎真实的拒绝。实测撤线后 10 例中 7 例红:

AssertionError: expected { where: { stage: 'stale' }, …(1) } to match object { multi: false }
AssertionError: expected false to be true // Object.is equality
AssertionError: expected { where: { id: 'd2' }, …(1) } to match object { where: { id: 'd2' }, multi: false }
Tests  7 failed | 3 passed (10)

三例仍绿,各有诚实的理由,其中一条据此改强了:「multi: false 写出来与不写是同一个拒绝」原本只断言拒绝本身,而拒绝在接线前后都成立 —— 它会穿过本文件存在的意义所在的那次 revert 保持绿。已补上对 options 包的断言。另两条(#3810 守卫、描述符表单)本就与执行器接线无关,绿在两边是设计使然,不是空断言。

命令与真实输出

pnpm --filter @objectstack/spec test                 → Test Files 310 passed  / Tests 7941 passed
pnpm --filter @objectstack/service-automation test   → Test Files  56 passed  / Tests  675 passed
pnpm --filter @objectstack/lint test                 → Test Files  58 passed  / Tests 1229 passed
pnpm --filter @objectstack/objectql test             → Test Files 118 passed  / Tests 1911 passed
pnpm --filter @objectstack/metadata-protocol test    → Test Files  42 passed  / Tests  388 passed
pnpm --filter @objectstack/cli test                  → Test Files  79 passed  / Tests  767 passed
pnpm --filter @objectstack/spec typecheck            → Done

消费半径按规则的调用方扫过,不是按被改的包:CRUD node config 被 cli(validate/lint/migrate)、lint、metadata-protocol(canonicalization)、studio flow-builder 一并消费,全部跑过。cli 首轮 30 红,原因是新 worktree 里 @objectstack/setup 等依赖没构建(Failed to resolve entry for package),pnpm --filter '@objectstack/cli^...' build 后 79/79 全绿 —— 与本改动无关。

门禁:

check:generated                → ✓ All 9 generated artifacts are up to date
check-engine-double-contract   → OK — 23 pinned, 32 in the DEBT ledger, 1 exempt
check-nul-bytes                → OK (5457 files; no raw C0 control bytes)
check-i18n-bundles             → OK (9 packages, all in sync)
check-i18n-coverage            → OK (12 configs, 660 baselined, none new)
check:merge-driver / check:adr-anchors / check:durability-log-level /
check:startup-registry-verdict / check:type-check-coverage /
check:published-files / check:release-notes / check:stall-guard / … → OK

生成物随行:authorable-surface.json(+2 键)、content/docs/references/automation/builtin-node-config.mdx(+2 行),两者都由 gen:schema / gen:docs 整体重生成,未手改。strictness 台账重生成后无变化(往已 strict 的 shape 上加键不动计数)。

两处刻意留下的行为,写在这里而不是留给下一个读者

  1. multi: true 且没有 filter = 按声明清空整个对象。 引擎的派发表本就把「multi 且完全没有谓词」列为合法,Flow node filters silently blank date macros: the template engine consumes {…} before the query engine sees it #3810 的守卫按「作者写过的条件被抹掉」判定而不是按「filter 为空」判定(那是它注释里的原话,也有专门用例钉住)。flow 的 delete_record / update_record 无法表达批量意图 —— 节点 schema 无键、执行器不传 options.multi,谓词批量写对所有 flow 平台级不可达,而节点描述符宣称支持 #5393 之前这条路径不可达,现在可达了,但它是显式、可 grep 的声明。是否要在 authoring 期加告警,已另开 issue 交 PM 定级,不在本 PR 内发明。
  2. update_record 的破坏性并不比 delete_record 低多少(谓词 update 覆盖整表字段),但它的测试替身在结构上不能被绑到生产者契约。同上,另开 issue。

范围外发现(PD #10,均已建单、未指派)

后续

#5225(showcase 清扫流)挂 Blocked-by 本单,本单落地后由它以声明批量意图收尾。示例目录本 PR 未动。


Generated by Claude Code

claude added 2 commits August 5, 2026 12:47
…record (#5393)

`UpdateRecordConfigSchema` / `DeleteRecordConfigSchema` are strictObjects and
neither declared any spelling of bulk intent, while the CRUD executors never
passed `options.multi`. The data engine accepts a write only when `where.id` is
a scalar or `options.multi` is truthy and throws otherwise, so a predicate
update/delete was unreachable from any flow in any app — while the node
descriptors advertised "Delete records matching a filter." Declared != enforced
(PD #10); #5225's showcase sweep flow was the site it surfaced at.

Adds `multi` (boolean, default false) to both config contracts and wires the
executors to forward it as `options.multi`. One name for one concept (PD #12):
`multi` is the engine's own word for it, so the concept is greppable from node
config to driver call. The engine's rejection path is untouched — refusing an
undeclared predicate write IS the contract.

- spec: `multi` on both schemas, with `bulk`/`all`/`multiple` prescriptions and
  a wrong-layer answer for `options: { multi: true }` (edit distance reaches
  `multi` from none of them); the same curation is copied to the registration
  door in service-automation's engine, per #4001's finding that detection
  generalizes for free while prose does not.
- descriptors: `multi` declared on both designer forms, so the form<->Zod
  ledger reconciles and the key is authorable in Studio, not only by hand.
- tests: `crud-bulk-intent.test.ts`, whose delete double opens with
  `assertEngineDeleteDispatch` from @objectstack/objectql — the producer's own
  predicate — so it cannot accept a call the real engine refuses. That is the
  #5197 blind spot closed for this file: `run-summary.test.ts`'s zero-parameter
  `async delete() { return false }` accepts predicate deletes AND is invisible
  to check-engine-double-contract's arity test. Needed a devDependency on
  @objectstack/objectql (acyclic — objectql's closure does not contain
  service-automation); the eight service-automation baseline entries citing
  that missing dep as their blocker are updated to say so.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018fxLGQdatPbBUvCgiVxg6D
@vercel

vercel Bot commented Aug 5, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Aug 5, 2026 1:49pm

Request Review

@github-actions github-actions Bot added size/l documentation Improvements or additions to documentation dependencies Pull requests that update a dependency file tests tooling labels Aug 5, 2026
@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/service-automation, @objectstack/spec.

109 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/agents.mdx (via @objectstack/spec)
  • content/docs/ai/skills-reference.mdx (via @objectstack/spec)
  • content/docs/ai/skills.mdx (via @objectstack/spec)
  • content/docs/api/client-sdk.mdx (via @objectstack/spec)
  • content/docs/api/environment-routing.mdx (via @objectstack/spec)
  • content/docs/api/error-catalog.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-client.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-server.mdx (via @objectstack/spec)
  • content/docs/api/index.mdx (via @objectstack/spec)
  • content/docs/automation/approvals.mdx (via @objectstack/spec)
  • content/docs/automation/connectors.mdx (via @objectstack/spec)
  • content/docs/automation/flows.mdx (via @objectstack/service-automation, @objectstack/spec)
  • content/docs/automation/hook-bodies.mdx (via packages/spec)
  • content/docs/automation/hooks.mdx (via @objectstack/spec)
  • content/docs/automation/index.mdx (via @objectstack/spec)
  • content/docs/automation/webhooks.mdx (via @objectstack/spec)
  • content/docs/automation/workflows.mdx (via @objectstack/spec)
  • content/docs/concepts/architecture.mdx (via @objectstack/spec)
  • content/docs/concepts/design-principles.mdx (via packages/spec)
  • content/docs/concepts/index.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-driven.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-lifecycle.mdx (via packages/spec)
  • content/docs/concepts/north-star.mdx (via @objectstack/spec)
  • content/docs/data-modeling/analytics.mdx (via @objectstack/spec)
  • content/docs/data-modeling/drivers.mdx (via @objectstack/spec)
  • content/docs/data-modeling/external-datasources.mdx (via @objectstack/spec)
  • content/docs/data-modeling/field-types.mdx (via @objectstack/spec)
  • content/docs/data-modeling/fields.mdx (via @objectstack/spec)
  • content/docs/data-modeling/formulas.mdx (via @objectstack/spec)
  • content/docs/data-modeling/index.mdx (via @objectstack/spec)
  • content/docs/data-modeling/objects.mdx (via @objectstack/spec)
  • content/docs/data-modeling/queries.mdx (via @objectstack/spec)
  • content/docs/data-modeling/schema-design.mdx (via @objectstack/spec)
  • content/docs/data-modeling/seed-data.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation-rules.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation.mdx (via @objectstack/spec)
  • content/docs/deployment/cli.mdx (via @objectstack/spec)
  • content/docs/deployment/tenancy-modes.mdx (via @objectstack/spec)
  • content/docs/deployment/troubleshooting.mdx (via @objectstack/spec)
  • content/docs/deployment/validating-metadata.mdx (via @objectstack/spec)
  • content/docs/getting-started/build-with-claude-code.mdx (via @objectstack/spec)
  • content/docs/getting-started/common-patterns.mdx (via @objectstack/spec)
  • content/docs/getting-started/examples.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-reference.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx (via @objectstack/spec)
  • content/docs/getting-started/your-first-project.mdx (via @objectstack/spec)
  • content/docs/kernel/cluster.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/auth-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/cache-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/data-engine.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/index.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/metadata-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/storage-service.mdx (via packages/spec)
  • content/docs/kernel/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/email-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/queue-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/sharing-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/sms-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx (via packages/spec)
  • content/docs/kernel/services-checklist.mdx (via @objectstack/service-automation, @objectstack/spec)
  • content/docs/kernel/services.mdx (via @objectstack/spec)
  • content/docs/permissions/authorization.mdx (via @objectstack/spec)
  • content/docs/permissions/permission-sets.mdx (via @objectstack/spec)
  • content/docs/permissions/permissions-matrix.mdx (via @objectstack/spec)
  • content/docs/permissions/positions.mdx (via @objectstack/spec)
  • content/docs/permissions/rls.mdx (via @objectstack/spec)
  • content/docs/permissions/sharing-rules.mdx (via @objectstack/spec)
  • content/docs/plugins/adding-a-metadata-type.mdx (via @objectstack/spec)
  • content/docs/plugins/development.mdx (via @objectstack/spec)
  • content/docs/plugins/index.mdx (via @objectstack/spec)
  • content/docs/plugins/packages.mdx (via @objectstack/service-automation, @objectstack/spec)
  • content/docs/protocol/backward-compatibility.mdx (via @objectstack/spec)
  • content/docs/protocol/diagram.mdx (via packages/spec)
  • content/docs/protocol/kernel/config-resolution.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/http-protocol.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/i18n-standard.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/index.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/lifecycle.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/plugin-spec.mdx (via @objectstack/spec)
  • content/docs/protocol/knowledge.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/query-syntax.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/schema.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/security.mdx (via packages/spec)
  • content/docs/protocol/objectql/state-machine.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/actions.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/concept.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/layout-dsl.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/record-alert.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx (via @objectstack/spec)
  • content/docs/releases/implementation-status.mdx (via @objectstack/service-automation, @objectstack/spec)
  • content/docs/releases/index.mdx (via @objectstack/spec)
  • content/docs/releases/v12.mdx (via @objectstack/spec)
  • content/docs/releases/v13.mdx (via @objectstack/spec)
  • content/docs/releases/v16.mdx (via @objectstack/spec)
  • content/docs/releases/v17.mdx (via @objectstack/spec)
  • content/docs/releases/v9.mdx (via @objectstack/service-automation, @objectstack/spec)
  • content/docs/ui/actions.mdx (via @objectstack/spec)
  • content/docs/ui/apps.mdx (via @objectstack/spec)
  • content/docs/ui/create-vs-edit-form.mdx (via @objectstack/spec)
  • content/docs/ui/dashboards.mdx (via @objectstack/spec)
  • content/docs/ui/forms.mdx (via @objectstack/spec)
  • content/docs/ui/index.mdx (via @objectstack/spec)
  • content/docs/ui/public-data-collection.mdx (via @objectstack/spec)
  • content/docs/ui/setup-app.mdx (via @objectstack/spec)
  • content/docs/ui/translations.mdx (via @objectstack/spec)
  • content/docs/ui/views.mdx (via @objectstack/spec)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

⛔ merge queue 构建失败 — 先分诊,再决定要不要重排

队列构建 31015413774 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集),
所以失败的测试可能在本 PR 没碰过的包里 —— 那不是重排能修的。每次盲目重排都会让排在后面的所有 PR 重建一轮。

失败的 job(日志抽取,best effort):

  • Test Core (3/3) — 失败步骤: Run this shard's tests

    �[41m�[1m FAIL �[22m�[49m src/commands/serve-email-config-parity.contract.test.ts�[2m > �[22ma config the schema accepts reaches the plugin intact�[2m > �[22mspreads defaultTemplateContext OVER the re
    

历史信号:

  • 本 PR 过去 24h 无队列失败记录(首次)。
  • 过去 24h 队列共有 9 个失败构建(不含本次)。

分诊清单:

  1. 失败测试在本 PR 改动的包里 → 真回归,修 PR。
  2. 失败测试与本 PR 无关 → 在其他 PR 的同类评论里搜同名测试;出现过 ⇒ flaky 实锤,开 issue 修/隔离那条测试。修好前重排只会再烧一轮全队列。
  3. 两者都不是 → 可能与同组 PR 语义冲突;等前面的 PR 落地或失败出队后再重排一次即可,不要连续重排。

Generated by Claude Code · merge-queue-triage workflow (#4859)

Copy link
Copy Markdown
Contributor Author

分诊(spec 车道 PM):第 3 型同批连坐,非本 PR 回归,非 flaky。 失败测试 serve-email-config-parity.contract.test.ts 不在本 PR 改动内 —— 本次构建链在 #5465 之后,踩的是 #5465×#5498(appName 优先级翻转)的语义互锁,定因见 #5465 的分诊#5465 已出队对齐中;队列会自动把本 PR 重建到不含它的基线上,无需人工重排。flaky 检索者请勿把本次计入该测试的 flaky 记录。


Generated by Claude Code

Merged via the queue into main with commit 168f60f Aug 5, 2026
26 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-5393-flow-bulk-intent branch August 5, 2026 14:51
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Aug 6, 2026
…te node (objectstack-ai#5225) (objectstack-ai#5534)

`InquiryPurgeFlow`'s `purge` node deletes by the predicate
`{ status: 'closed' }` but declared no bulk intent. The data engine accepts a
write without `options.multi` only when `filter` names ONE row by a scalar
`id`, so every run of this flow failed on that node:

  Node 'purge' failed: delete_record(showcase_inquiry) failed:
  Delete requires an ID or options.multi=true

with `acted: 0` — identically on both paths, the declarative endpoint
`POST /api/v1/apps/showcase/inquiries/purge` and the built-in trigger route
`POST /api/v1/automation/showcase_inquiry_purge/trigger`. The delete half of
the CRUD quartet `src/coverage.ts` claims this flow demonstrates had therefore
never executed once (declared != enforced, PD objectstack-ai#10); objectstack-ai#5112's boot probes are
what finally reached it.

The fix is a DECLARATION, not a rewrite. Until objectstack-ai#5393 (PR objectstack-ai#5485) no spelling of
bulk intent existed on the node config at all, which is why the third triage
round correctly refused a get-then-loop-then-delete-by-id rewrite as a PD objectstack-ai#5
workaround and escalated instead. `filter` stays: `multi: true` with an absent
or empty filter is a declared whole-object delete, and this node is meant to be
objectstack-ai#5482's zero-warning sample for exactly that distinction.

Verified on a real `--fresh` boot, both probes, with row counts:

  endpoint  selected 2 -> purge acted 2, success true, 4 rows -> 2 (both
            `closed` rows gone, both non-closed survived)
  trigger   selected 3 -> purge acted 3, success true, 5 rows -> 2

Reverse-verified by stripping the declaration and rebooting: both probes
returned to the byte-identical original failure above with `acted: 0` and the
row count unchanged.

The new example test states the rule as a two-sided invariant over EVERY
`delete_record` / `update_record` node rather than asserting one node, and
walks ADR-0031 structured containers — `showcase_task_crm_sync`'s `catch`
region holds an `update_record` a flat scan of `flow.nodes` misses.


Claude-Session: https://claude.ai/code/session_016FNvXhtSdnEGEfLEsMmvxh

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation size/l tests tooling

Projects

None yet

2 participants