Skip to content

feat(spec)!: 收紧 automation/ 主体剩余九个可授权形状的未知键(#4001 批 11) - #4974

Merged
xuyushun441-sys merged 5 commits into
mainfrom
claude/issue-4001-automation-batch11
Aug 3, 2026
Merged

feat(spec)!: 收紧 automation/ 主体剩余九个可授权形状的未知键(#4001 批 11)#4974
xuyushun441-sys merged 5 commits into
mainfrom
claude/issue-4001-automation-batch11

Conversation

@xuyushun441-sys

@xuyushun441-sys xuyushun441-sys commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Part of #4001

批 11:automation/ 主体剩余九个 strip 站点(重测报告 comment 5165088968 的批次表 A 第 11 行)。零猜测项,无 needs_decision。

改了什么

文件 站点 动作
automation/flow.zod.ts 6 FlowNode.connectorConfig / .position / .inputSchema / .waitEventConfig / .boundaryConfigFlow.errorHandlingstrictObject
automation/time-relative-trigger.zod.ts 1 TimeRelativeTriggerSchemastrictObject.refine 保留)
automation/flow-function.zod.ts 1 FlowFunctionDeclarationSchemastrictObject
automation/webhook.zod.ts 1 WebhookSchemastrictObject + ADR-0010 信封

刻意留开、且已在代码与测试里就地钉住(不是漏网):FlowVersionHistorySchema(本文件唯一的 wire 形状)与 node config 槽位(ADR-0018)。两处都写了理由,让下一轮扫荡在这里停下而不是「把文件做完」。

三件值得单独看的

一、flow.zod.ts 是本战役第 17 条发现出现在它自己的文件里

四个外壳(flow / node / edge / variable)在第一步就关了,内层六个块没关。于是闸门会拒绝节点级的 nodee:,却让

connectorConfig: { connectorId: 'rest', actionId: 'get', params: { id: '{record.id}' } }

干净通过 —— executor 读的是 input ?? {},整张映射输入变成空对象,调用成功、什么也没带。写守卫的人站在哪扇门,就把门装在哪。

这里有一处必须说准,因为最顺口的例子是错的:写错一个必填键(connectorID / attachedToRef)从来都是响的 —— 必填键随即读作缺失。.strip 吞掉的是可选的那一半:输入映射、重试预算、interrupting: falserequired: true —— 恰恰是作者用来收紧行为的那些键,被无声换回宽松默认值。三处 history 文案与测试都按这个事实写,而不是按更好听的那个(自查发现,单独一个 commit 改正)。

二、webhook(p) 解出来是「spec-only」的反面,而且必须同时补信封

台账原行写 authorable (p) / 「spec-only (#3461)」。实测三个 parse 门,其中一个是 boot

  1. defineWebhook()
  2. defineStack({ webhooks })StackSchemaz.array(WebhookSchema));
  3. plugin-webhooksbootstrapDeclaredWebhooksbootstrap-declared-webhooks.ts:114)在物化进 sys_webhook 前逐条 .parse()失败即 warn + 跳过

第 3 条同时是信封必须同批落地的原因:两条元数据加载路径都对每一个类型applyProtection,所以随包加载的 webhook 到达 boot 解析时已经带着 _packageId / _provenance.strip 把它们悄悄丢掉;只收紧而不声明,会把每一个随包发布的 webhook 变成 redeploy 之后消失的订阅,只留一行 warn。这正是注册类型批次还过八次的「信封欠债」—— webhook 不是注册类型(BUILTIN_METADATA_TYPE_SCHEMAS 里没有它),所以守那八个的不变量测试从来没往这边看过。

顺带:strictness 会沿 .extend() 传到 integration/connector.zod.tsWebhookConfigSchema(对着真 zod 验过,不是推断),已在 connector.test.ts 就地钉住。

三、time-relative-trigger 的收紧落在 BIND 时,不只是授权时

它是 #4852 让其可见的那个文件。实测 TimeRelativeTriggerPlugin.start()binding.config.timeRelativesafeParsetime-relative-trigger.ts:164)。而这个描述符住在刻意开放的 node config 槽位下面,所以它是唯一的键闸门。行为差:{ …valid, offsetDay: 7 } 以前会绑上一个每天跑、但作者的收窄被丢掉的 sweep,并报告「已配置」;现在拒绝绑定,warning 里带着键名和改法。

flow-function 则相反,只在授权时绑(boot 读的是 normalizeFlowFunctionEntry,不是 parse)—— 这条写进了代码,因为一次收紧不该宣称自己够不到的射程。它仍然值得做,理由恰是让它初看多余的那一点:那个 reader 按构造只取两个键、忽略其余,所以拼错的 effect 先被 schema 丢掉、再被 reader 不去找 —— 函数照常注册、照常运行,它的写入被计为零,正好让 #4354 的 broken-sweep 查询在最该响的那次运行上保持沉默。

别名表:每一条都是仓里的实测拼法,不是设想的错别字

先跑了一遍全仓 AST 普查(按 flow-node / flow / webhook / functions-entry 形状定位真实载荷,而不是按键名瞎抓 —— 按键名抓 handler 会得到 490 个命中,没有一个是这个 schema 的载荷),再据实策展:

写了 该写 那个词的出处(本仓)
errorHandling.backoffMs retryDelayMs shared/retry-policy.zod.ts#4661 收敛后的正统拼法,且它给 retryDelayMs 立了墓碑)
errorHandling.initialDelayMs / maxDelayMs retryDelayMs / maxRetryDelayMs integration/connector.zod.ts RetryConfigSchema
boundaryConfig.attachedToRef / cancelActivity attachedToNodeId / interrupting BPMN 2.0 自己的属性名(本块 JSDoc 就宣称 BPMN 对齐,且 bpmn-interop.zod.ts 存在就是为了导入第三方定义)
webhook.object_name / active object / isActive sys_webhook 的列名(mapWebhookToRow 的 remap),从行反向重写元数据的人正是这条路径
timeRelative.field / filters / objectName dateField / filter / object record-change 触发器与 CRUD 节点 config 的既有拼法

两处刻意不给改名,给处方 —— 改名在这两处是错的:

  • inputSchema.optional:与 required 极性相反。只说「你是不是想写 required」而不说往哪边翻,就是本战役自己撤回过的那四条「自信写错的处方」。
  • errorHandling.maxAttempts:connector RetryConfigmaxAttempts 含首次尝试maxRetries 不含。裸改名会静默少跑一次,所以写成 maxRetries: ( maxAttempts - 1 )

同理,waitEventConfig.timeout 的处方指向 timerDuration绝不指向墓碑 timeoutMs —— 那是第 7 条发现(triggerPhrasetriggerPhrases → 墓碑)的形状。webhookextraKeys 也因此故意不列 events:它同时是本表的别名目标,列进去会让基面作者被走两次拒绝、走进一个基面不接受的键 —— 第 7 条经由手写 extraKeys 而非 shape 到达的新入口(acceptsNothing 守的是前者,后者无人守)。

先证红,再信绿

  • 变异对照:把 strictObject 的返回改成 z.object(shape)(strip),四个文件一次覆盖 → 19 条断言报红,恢复后 helper 与 origin/main 逐字节相同git diff 空)。即每一条新断言都真的依赖这次收紧,没有一条是恒真的。
  • 台账闸门两个方向各诱发一次:行内数字错一位 → `automation/flow.zod.ts` declares 2 strip of 11, found 1 of 11;把已归零的 webhook.zod.ts 行塞回去 → has NO strip sites left, but still has a rowheader says 58 strip, rows sum to 59。恢复后绿。
  • .extend() 继承:先用独立 zod 探针证明 .strict() 与 error map 都会被 .extend() 带走,再据此写 extraKeysconnector.test.ts 的钉子 —— 台账第 16 条发现(.extend() 陷阱)反向验证。

ADR-0087:三个示例应用的构建产物逐条按新契约 parse

不是读源码,是读 dist/objectstack.json —— 过了 defineStack、转换层与 handler lowering 之后、运行时真正拿到的那份形状。

### app-showcase
  flows 29 · nodes 122 · webhooks 1 · timeRelative 1 · function decls 0 (1 lowered string refs)
  closed nested blocks seen: connectorConfig=4 waitEventConfig=2 (total 6)
  ✓ 0 unknown-key rejections
### app-crm
  flows 1 · nodes 8 · errorHandling=1
  ✓ 0 unknown-key rejections
### app-todo
  flows 4 · nodes 21
  ✓ 0 unknown-key rejections

### negative controls — the probe must go RED on an injected key
  ✓ RED as required — flow node `position.left`
  ✓ RED as required — flow `errorHandling.backoffMs`
  ✓ RED as required — webhook `active`
  ✓ RED as required — timeRelative `offsetDay`

一条如实说明:三个 app 的 functions 都写成裸 handler,所以构建产物里没有声明记录(只有 lowered string ref),FlowFunctionDeclarationSchema 这条在产物侧无覆盖 —— 覆盖来自单测与 defineStack 那扇门。顺带核实过 CLI 的 lowerCallables 确实把声明记录原样保留进产物,而 mergeRuntimeModule 在任何人解析之前就把 callable 装回记录里,所以 schema 永远不会看到 lowered 形态(artifact-function-declarations.test.ts 已就地钉住)。一度怀疑这里有 effect 在构建后丢失的缺口,实测不成立,故未立单。

三个 validate 全过:✓ Validation passed(showcase 903ms / crm 271ms / todo 247ms)。

台账 + 连续两轮串行同步(已发生,已解)

本批单独作用:automation/ 剩余 strip −9 站点 / −3 文件flow.zod.ts 7 → 1,另三个文件归零、行由 #4852 反向闸删除)。

批 9(#4925)与批 10(#4973)先后落 main,本分支各做了一轮同步。两次冲突都在同一段,且第二次正是批 10 就地写下的那个形状

波次 删行 其他改动
批 9 (#4925) builtin-node-config(8) · schemaless-node-config(4) · io-node-config(2)
批 10 (#4973) control-flow(5) · state-machine(6)
批 11(本 PR) flow-function(1) · time-relative-trigger(1) · webhook(1) flow.zod.ts 7 → 1

每个 PR 都只按自己的删除量去减表头。于是 git 把干净合并(互不重叠),只留表头冲突 —— 而紧挨着的小计行不冲突任何东西,干净地合并成一个两边都错的数。表头 44(本分支)/ 42(main),小计 18 / 16,各自对自己的分支都是对的。

双方全留,表头与小计一律从存活行重算:存活行 = execution 13 + etl 10 + flow 1 + bpmn-interop 5 + node-executor 4 → 表头 33 strip of 75,可授权 7 of 33check:strictness-ledger 是裁判,实跑:

✓ strictness ledger: 67 file(s) across 5 triaged director(ies) — site counts match, …
✓ remaining-strip map: 42 open file(s) / 289 strip site(s) across 4 director(ies) — counts match, …

批 10 那段散文已改写成「逐波次表格 + 机械化规则」,并记上这是同一天内第三次,免得下一批第四次重新发现它。

顺带一个里程碑:三批合流后,automation/ 的可授权 strip 只剩 etl.zod.ts 一个文件 7 个站点(批 12 的目标)。其余 26 个全是 wire —— 包括 flow.zod.ts 最后那个 FlowVersionHistorySchema,这也是为什么该文件还有行却已经 0 可授权,不该被读成未完成的工作

os-regen 四步两轮都全走(⛔ 未 rebase / 未 force-push)。第二轮驱动把 authorable-surface.jsonreferences/integration/connector.mdx 记进 os-regen-pending 而非文本合并,整体重生成后 pre-commit 校验为 current 并清除标记。断言两边条目共存:批 10 的 control-flow / state-machine 参考页与它的 21 条 TryCatch/Loop/StateNode/Transition authorable-surface 条目,和本分支的 automation/Webhook:_packageId / :protection 及两张参考页并存;合并产物里唯一的删除属于 main 自己的 connector.rateLimitConfig 退役(#4911/#4947),不属于任何一批。

验证

本批改动本身(合并前):

  • @objectstack/spec 全量 295 文件 / 7393 用例通过tsc --noEmit 干净
  • 下游回归 @objectstack/lint / @objectstack/metadata / @objectstack/runtime 全绿(runtime 80 文件 / 1094 用例)
  • 全仓 pnpm build 71/71

合并批 10 后复验(§10:main 动的是 packages/spec,与本 diff 同包,故重跑全量):

  • check:generated 8/8
  • 十个 spec 闸门全绿 —— liveness empty-state react-declaration-parity skill-examples variant-docs strictness-ledger exported-any dual-source-exports 逐个实跑 PASS
  • @objectstack/spec 297 文件 / 7474 用例通过tsc --noEmit 干净

gen:docs 重生成的参考页已按 #3746 的坑逐行核对 —— 页面 description / frontmatter 零变动,没有内部注释漏进公开参考页。

一处顺带的文档更正

content/docs/automation/flows.mdxwaitEventConfig 行把 timeoutMs / onTimeout 列为成员 —— 这两个键 17 就退役了(#4158),手写文档没跟上。就在本次收紧的那个块上,留着等于教作者写会被拒绝的键,故一行改掉。⛔ content/docs/releases/ 零触碰。

衍生(均实核存在,已立单,本 PR 不修)

claude added 2 commits August 3, 2026 17:29
…keys (#4001 batch 11)

zod's default `.strip` discards an undeclared key and parses on. Batch 11 closes
the nine remaining shapes in `automation/`'s main body, each rejection naming the
surface, the key, and — where the word is recognisable — the canonical spelling.

`flow.zod.ts`: the four OUTER shapes were closed earlier; their six nested
authoring blocks were not, so the gate rejected `nodee:` at node level while
`connectorConfig: { connectorID }` parsed clean and dispatched against an
undefined connector id. Now strict: `FlowNode.connectorConfig` / `.position` /
`.inputSchema` / `.waitEventConfig` / `.boundaryConfig`, `Flow.errorHandling`.
Deliberately still open, now pinned in code AND tests so a later sweep stops
rather than "finishing" the file: the node `config` slot (ADR-0018) and
`FlowVersionHistorySchema` (emitted, not authored — its `definition` is
`FlowSchema`, so the authored half is gated anyway).

Every alias is a real in-repo spelling of the same knob on a neighbouring
surface, taken from an AST census over the repo's own payloads, not guessed:
`backoffMs` from `shared/retry-policy.zod.ts` (#4661), `initialDelayMs` /
`maxDelayMs` from connector `RetryConfig`, `attachedToRef` / `cancelActivity`
from BPMN 2.0. Two cases get a prescription instead of a rename because a rename
would be wrong: `inputSchema.optional` is the opposite polarity of `required`,
and `errorHandling.maxAttempts` counts the first attempt while `maxRetries` does
not — renaming it alone would quietly run one attempt fewer.

`time-relative-trigger.zod.ts`: the schema #4852 made visible (its only site was
line-wrapped, the old counter read zero, and a zero-site file is skipped by the
coverage walk). It sits under the open node `config` slot, so it is the only key
gate there is — and it is `safeParse`d at BIND time, so `offsetDay` beside a
valid mode used to bind a sweep with the author's narrowing discarded and report
itself configured.

`flow-function.zod.ts`: binds at authoring only (boot reads
`normalizeFlowFunctionEntry`), stated in the code rather than implied. That is
why it matters: the reader takes two keys and ignores the rest by construction,
so a misspelled `effect` was dropped and then not looked for — the function ran
and its writes were counted as none, keeping #4354's broken-sweep query silent.

`webhook.zod.ts`: the ledger's `(p)` resolved to the opposite of "spec-only" —
three parse doors, one of them `bootstrapDeclaredWebhooks` at BOOT, which warns
and SKIPS on failure. Hence the ADR-0010 envelope in the same commit:
`applyProtection` stamps `_packageId`/`_provenance` on every type, so closing the
shape without declaring them would have turned every package-shipped webhook
into a skipped subscription after a redeploy. Strictness also rides `.extend()`
onto the connector `WebhookConfigSchema` — verified against real zod and pinned
in `connector.test.ts`.

Ledger: `automation/` 67 → 58 strip; three rows reached zero and were deleted by
the #4852 reverse pin. Gate re-proved red in both directions before trusting it,
and every new assertion was proved to depend on the tightening by neutering
`strictObject` (19 red, restored byte-identical).

Part of #4001

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ehu85kbvMcrNTUJjwxvLJ9
`gen:docs` only — the property tables for `automation/Webhook` and the
`integration/WebhookConfig` extension gain the `protection` block and the seven
`_lock*`/`_provenance`/`_package*` rows. Checked for the #3746 trap: no page
description or frontmatter moved, so no internal comment leaked onto a public
reference page.

Part of #4001

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

vercel Bot commented Aug 3, 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 3, 2026 6:22pm

Request Review

claude added 2 commits August 3, 2026 17:49
Self-review against the actual behaviour, before the claim shipped. The
`connectorConfig` / `boundaryConfig` / `position` / `inputSchema` prose named a
slip on a REQUIRED key (`connectorID`, `attachedToRef`) as the silent case. It
never was: a required key spelled wrong then reads as MISSING, which zod has
always rejected loudly. Nothing was silent about it.

What `.strip` actually swallowed is the OPTIONAL half — the mapped `input` map
(dispatched as `input ?? {}`: a successful connector call carrying nothing),
BPMN's `cancelActivity: false` (so `interrupting` fell to its `true` default and
a NON-interrupting event cancelled the host anyway), `optional: false` (so
`required` fell to false and `validateNodeInputSchemas` had nothing to require),
a canvas hint beside x/y. I.e. exactly the keys an author adds to CONSTRAIN
behaviour, replaced by a permissive default.

The corrected version is the stronger argument as well as the true one, and
getting it wrong is the failure mode this campaign has already paid for four
times (the withdrawn guidance prescriptions): rejection prose is behaviour, not
documentation. Fixed in the schemas, the module comment, the tests and the
ledger row; a test now pins the required-key case as loud so the distinction
cannot quietly re-blur.

Part of #4001

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ehu85kbvMcrNTUJjwxvLJ9
Ledger conflict was expected and is the three-way `automation/` header the
dispatch note warned about: 批 9 (#4925) landed on main while this branch was
open, and both sides edit the same section. Resolved by keeping BOTH sides' row
edits and recomputing the header from the merged rows rather than taking a side:

  批 9  removed builtin-node-config (8) / schemaless-node-config (4) /
        io-node-config (2), and rewrote their triage notes
  批 11 removed flow-function (1) / time-relative-trigger (1) / webhook (1),
        and dropped flow.zod.ts 7 → 1

  header  67 → 44 strip of 75   (13+10+1+6+5+5+4, summed from the rows)
  authorable  41 → 18           (etl 7 + state-machine 6 + control-flow 5)

`check:strictness-ledger` arbitrates that arithmetic and passes; the header was
NOT copied from either side.

os-regen four-step ran in full: merge → `git checkout origin/main --` every
`merge=os-regen` path → `pnpm install --frozen-lockfile` + rebuild spec +
`check:generated --fix` (regenerated `content/docs/references/**` only) → assert
BOTH sides survive. Sibling entries verified present after the wholesale
regeneration: 批 9's NotifyConfig / HttpConfig / Script node-config pages and
#4922's `data/SortNode` are all in `authorable-surface.json` beside this
branch's `automation/Webhook:_packageId` / `:protection`.

Merged-tree verification (§10: main touched packages/spec, the same package as
this diff, so the full suite was re-run rather than scoped):
  check:generated 8/8 · all 8 pure audits PASS (incl. strictness-ledger)
  @objectstack/spec 297 files / 7450 tests · tsc --noEmit clean

Part of #4001

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ehu85kbvMcrNTUJjwxvLJ9
@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling size/l labels Aug 3, 2026
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/spec.

106 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/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/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/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/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/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/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/spec)
  • content/docs/ui/actions.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.

Second serial sync. One conflict, the same `automation/` section as last time,
and it arrived exactly as 批 10 predicted in the paragraph it left there.

Resolution — both waves' rows kept, header and subtotal recomputed from the
SURVIVING rows rather than resolved in favour of a side:

  surviving rows  execution 13 · etl 10 · flow 1 · bpmn-interop 5 · node-executor 4
  header          44 (HEAD) / 42 (main)  ->  33 strip of 75
  subtotal        18 (HEAD) / 16 (main)  ->  7 authorable of 33

Both incoming numbers were right against their own branch and wrong against the
merge: mine counted 批 10's deletions as still present, main's counted mine.
That is the third instance in one day of the shape 批 10 wrote down — the header
CONFLICTS and gets attention, while the subtotal line conflicts with nothing and
merges clean while being wrong on both sides. The paragraph is rewritten as a
per-wave table plus the rule stated mechanically, so the next batch does not
have to rediscover it a fourth time. `check:strictness-ledger` arbitrates, and
passes.

Milestone worth noting in the ledger prose: with 批 9 + 批 10 + 批 11 merged,
`automation/`'s authorable strip is **etl.zod.ts alone** (7 sites). The other 26
are wire — including `flow.zod.ts`'s last site `FlowVersionHistorySchema`, which
is why that file still has a row while having 0 authorable left and must not be
read as unfinished work.

os-regen four-step ran in full. The driver deferred `authorable-surface.json`
and `references/integration/connector.mdx` this time (recorded in
os-regen-pending) rather than text-merging them. checkout origin/main for every
`merge=os-regen` path -> install + rebuild spec -> `check:generated --fix`
(regenerated `content/docs/references/**` only) -> assert BOTH waves survive:
批 10's control-flow/state-machine reference pages and its 21
TryCatch/Loop/StateNode/Transition authorable-surface entries coexist with this
branch's `automation/Webhook:_packageId` / `:protection` and its two pages.
The only deletions in the merged artifacts belong to main's own
`connector.rateLimitConfig` retirement (#4911/#4947), not to either batch.

Verification on the merged tree:
  check:generated 8/8 · all 8 pure audits PASS
  check:strictness-ledger: 42 open file(s) / 289 strip site(s) — counts match
  @objectstack/spec 297 files / 7474 tests · tsc --noEmit clean

Part of #4001

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ehu85kbvMcrNTUJjwxvLJ9
@github-actions github-actions Bot added size/xl and removed size/l labels Aug 3, 2026
@xuyushun441-sys
xuyushun441-sys marked this pull request as ready for review August 3, 2026 18:26
@xuyushun441-sys
xuyushun441-sys added this pull request to the merge queue Aug 3, 2026
Merged via the queue into main with commit c87ef70 Aug 3, 2026
26 checks passed
@xuyushun441-sys
xuyushun441-sys deleted the claude/issue-4001-automation-batch11 branch August 3, 2026 18:43
xuyushun441-sys pushed a commit that referenced this pull request Aug 3, 2026
The merge of origin/main resolved `authorable-surface.json` to this
branch's side, silently dropping the 16 rows #4974 (#4001 批 11) added
for `automation/Webhook` and `integration/WebhookConfig` — main's own
committed baseline had them. Regenerating via `gen:schema` (the gate's
own proof path, never a hand edit) restores both sides: the sibling's
webhook rows and this branch's `ui/DashboardWidget:responsive [RETIRED]`.

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

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

Labels

documentation Improvements or additions to documentation size/xl tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants