Skip to content

docs(spec): 修正 SYNC_ARCHITECTURE.md 的 L3 Connector 示例并为其加编译门 (#5515) - #5603

Merged
os-zhuang merged 2 commits into
mainfrom
claude/issue-5515-sync-arch-l3-sap
Aug 5, 2026
Merged

docs(spec): 修正 SYNC_ARCHITECTURE.md 的 L3 Connector 示例并为其加编译门 (#5515)#5603
os-zhuang merged 2 commits into
mainfrom
claude/issue-5515-sync-arch-l3-sap

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Fixes #5515

前提复核(先于实现)

origin/main(5acb93add)逐条核对,四条缺陷全部仍在,前提成立:

一处需要更正的前提细节(不影响结论,但影响修法与钉法):issue 正文把 sourceField 说成"schema 里挂了 curated alias 的被拒键",引用的是 connector.test.ts:1028。那行的 curated alias registry 属于 ./dataImportFieldMappingSchema(一个 strictObject),不是 ConnectorFieldMappingSchema。后者是普通 z.object,实测:

ConnectorFieldMappingSchema.safeParse({ sourceField: 'a', targetField: 'b', dataType: 'string' })
→ success: false,issues 只有 path ['source'] 和 ['target'] 两条 "expected string, received undefined";
  'sourceField' 这个词在整个 error 里一次都没出现

也就是说这个键在连接器面上是被静默丢弃的,作者只会被告知"少了 source/target",永远不会被告知他写的词有问题 —— 比 issue 描述的情形更难自查。这一条已按事实钉在新门里(见下)。

改了什么

1. 文档示例的四处修正(packages/spec/docs/SYNC_ARCHITECTURE.md)

原写法 改成 依据
fieldMappings[].sourceField / targetField source / target shared/mapping.zod.ts 的基协议规范拼写
transform: { type: 'custom', function: … } transform: { type: 'javascript', expression: 'value / 100' } 五个真实联合成员里语义最近的一个;裸字符串是 ExpressionInput 简写,parse 后包成 { dialect, source }
webhooks[].retryPolicy: { … } 删除,原地留一行墓碑注释 WebhookSchemastrictObject,已为该键挂了 #3494 的 curated guidance:投递重试归消息 outbox 的固定排程所有,没有等价键。同时点明它与下方 retryConfig 不是一回事(后者管连接器发出的调用)
const sapConnector: Connector const sapConnector: ConnectorInput(import 改 import type) 裸名是 z.infer(parse 结果),作者形状是 z.input

第四条按派单裁定只改示例注解;connector.zod.ts 20 个 z.infer 裸名别名翻到 #4963 确立的 X / XParsed house convention 是独立 appetite,本 PR 不动,已另立 #5551。示例上方新增一段散文说明作者形状 / parse 形状的区别,并如实点出它与上文 L2 的不对称(L2 的裸 ETLPipeline 是作者形状),指向 #5551

顺带把 Migration Guide 两段 L3 草图的注解也改成 ConnectorInput,否则同一篇文档会教两种注解。它们仍用裸 ... 省略,不是 TypeScript,不进编译门。

2. 新编译门 packages/spec/src/integration/connector-author-shape.test.ts

automation/etl-author-shape.test.ts 的兄弟门,由拥有该示例的 schema 所在文件持有。四组断言:

  • 分类 + 反空洞:文档里含 Connector 的块必须是 3 个,其中 2 个是 ... 省略草图、1 个是完整示例。选择器匹配为空会让下面的编译断言在空程序上通过 —— 门失效的经典形态。
  • 逐字编译:把 L3 块连 import 行一起丢给 ts.createProgram(strict: true,@objectstack/spec/* 映射到 src/*/index.ts,types: ['node'] —— 示例真的读 process.env.SAP_CLIENT_ID!),要求零诊断;附一个必须失败的 harness 自检探针。
  • 反向验证(方向先于运行声明):把四处缺陷各自放回一个本来正确的 ConnectorInput 字面量,每个必须以具名诊断变红(不是"有诊断"),再配一个三处规范拼写同时为绿的对照组 —— 没有对照,那三处红说明不了问题出在拼写上。
  • 运行期措辞:编译门守类型面,这组守 parse 面,两者不冗余 —— 作者写错时被告知了什么,是"可自查的错误"和"神秘的错误"之间的差别,而这三个键的告知方式各不相同:retryPolicy 是 key 判决(unrecognized_keys + 点名 [P2] Aspirational-config disposition: reconcile-or-prune the still-dead props from the 2026-06 liveness audit (Theme / Translation / Job / Webhook) #3494 + "There is no replacement");sourceField 是静默剥离 + 缺 source/target;'custom' 是 value 判决(消息列出五个真实成员)。

同时更新了兄弟门里那段现在已经过时的分类注释(它写着"L3 那段报四条诊断,filed as #5515, not fixed here")。

3. 块数钉子

文档的 ```typescript 总块数没有变化,仍是 6(改的是已有块,没有增删),etl-author-shape.test.tstoBe(6) 钉子原样成立,无需调整。

验证

先证红 —— 新门跑在未修改的文档上,复现出 issue 里的四条诊断,逐字一致:

FAIL  src/integration/connector-author-shape.test.ts > compiles the `sapConnector` example verbatim
AssertionError: the L3 example must compile clean: expected 'TS2322: ...' to be ''

+ TS2322: Type 'string' is not assignable to type '{ dialect: "cel" | "cron" | "template"; source?: string | undefined; ... }'.
+ TS2353: Object literal may only specify known properties, and 'sourceField' does not exist in type
          '{ source: string; target: string; required: boolean; syncMode: ... }'.
+ TS2322: Type '"custom"' is not assignable to type '"map" | "lookup" | "constant" | "cast" | "javascript"'.
+ TS2353: Object literal may only specify known properties, and 'retryPolicy' does not exist in type
          '{ name: string; url: string; method: ...; timeoutMs: number; isActive: boolean; ... }'.

 Test Files  1 failed (1)
      Tests  1 failed | 12 passed (13)

注意这一跑里其余 12 项(反向验证探针、运行期措辞、ConnectorInput vs Connector 那组)已经全绿 —— 它们描述的是 schema 的既有事实,不依赖文档改没改,所以红的只有"示例本身"这一项,正是应有的方向。

后证绿(修完文档):

pnpm --filter @objectstack/spec exec vitest run \
  src/integration/connector-author-shape.test.ts \
  src/automation/etl-author-shape.test.ts \
  src/integration/connector.test.ts --maxWorkers=2

 Test Files  3 passed (3)
      Tests  79 passed (79)

全量:

pnpm --filter @objectstack/spec test --maxWorkers=2
 Test Files  315 passed (315)
      Tests  8023 passed (8023)

pnpm --filter @objectstack/spec typecheck
 tsc --noEmit  ✓
 check:test-typecheck: OK — 79 file(s) / 691 error(s) held in test-typecheck-debt.json
 (新增的测试文件零错误,不进 debt 账本)

node scripts/check-nul-bytes.mjs
 OK (scanned 5501 tracked text file(s); no raw ASCII control bytes)

changeset

无。packages/spec/docs/** 不在该包 package.jsonfiles 白名单里(只发 dist / json-schema / src/**/*.zod.ts 等),本 PR 没有任何 runtime / schema 行为变化,是文档 + 测试。按约定走 skip-changeset 标签,不放空 changeset。

派单外发现(均已另立 issue,本 PR 不修)

侧查(issue 的"未验证"一节,已完成)

  • content/docs/references/integration/connector.mdx:grep sourceField / targetField / custom / retryPolicy —— 零命中,无同类缺陷。(该目录是生成产物,本 PR 未触碰。)
  • connector.zod.ts 自己的 @example:该文件 @example 块数为 0,无从出错。
  • shared/mapping.zod.ts 的两处 @example 用的就是 source / target + { type: 'cast', targetType: 'string' },是对的。
  • content/docs/** 其余 retryPolicy 命中(automation/retry-policy.mdxsystem/job.mdx 等)属于另外几个真实存在的 RetryPolicySchema,与 webhook 的退役键无关。

侧查结论:无需修改、无需重新生成任何 content/docs/references/**

风险

低。改动面是一份不随包发布的仓内设计文档 + 一个新测试文件 + 一段兄弟测试的注释;无 schema、无运行时、无生成产物。唯一的行为性影响是新门从此会对这份文档的 L3 段变红 —— 那正是它存在的意义。


Generated by Claude Code

…d gate it (#5515)

The `sapConnector` example taught four spellings `integration/connector.zod.ts`
turns down. Measured with the compiler API before the fix, verbatim:

  TS2353  'sourceField' does not exist in '{ source: string; target: string; ... }'
  TS2322  '"custom"' is not assignable to
          '"map" | "lookup" | "constant" | "cast" | "javascript"'
  TS2353  'retryPolicy' does not exist in the webhook shape
  TS2322  'string' is not assignable to '{ dialect: "cel"|"cron"|"template"; ... }'

Fixed in the document:

  - fieldMappings[].sourceField/targetField -> source/target, the canonical
    spelling of the base protocol in shared/mapping.zod.ts.
  - transform { type: 'custom', function } -> { type: 'javascript', expression },
    the nearest real member of the five-way discriminated union. The bare
    string is ExpressionInput shorthand and parses to { dialect, source }.
  - webhooks[].retryPolicy removed. WebhookSchema is a strictObject and
    already carries a curated tombstone for it (#3494): delivery retries are
    owned by the messaging outbox on a fixed schedule. There is no equivalent
    key, so the block becomes a comment saying why -- and saying that the
    sibling `retryConfig` is a different thing (the connector's own calls).
  - the annotation is now ConnectorInput (z.input), which is what an author
    writes. The bare `Connector` is z.infer on this file, so it is the shape a
    parse RETURNS. Flipping this file's 20 aliases to the #4963 X / XParsed
    house convention is a real but separate appetite -- filed as #5551 -- and
    is deliberately NOT done here.

New gate: packages/spec/src/integration/connector-author-shape.test.ts, a
sibling of automation/etl-author-shape.test.ts (#4963 / PR #5514) owned by the
schema that owns the example. It compiles the L3 block verbatim, import line
included, with a harness self-test against vacuity; classifies the document's
three `Connector` blocks (two Migration-Guide sketches elide with a bare `...`
and are not TypeScript); restores each of the four defects as a probe that must
go red with a named diagnostic; and pins what the schema SAYS at runtime for
each -- a curated tombstone for `retryPolicy`, a silent strip plus missing
`source`/`target` for `sourceField` (the curated alias for that word lives on
./data's ImportFieldMappingSchema, not this one), a value verdict naming the
five members for 'custom'.

The document's total ```typescript block count is unchanged at 6; the sibling
gate's pin holds.

Fixes #5515

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 9:26pm

Request Review

@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation tests labels Aug 5, 2026
@os-zhuang os-zhuang added skip-changeset PR has no user-facing published change; bypasses the changeset gate and removed documentation Improvements or additions to documentation tests labels Aug 5, 2026 — with Claude
@github-actions github-actions Bot added documentation Improvements or additions to documentation tests labels Aug 5, 2026
@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @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/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/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/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/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/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.

Copy link
Copy Markdown
Contributor Author

PM 预记(session_018fxLGQdatPbBUvCgiVxg6D):本 PR 的 ESLint job 将因 #5604(main 侧 check:engine-double-contract 断裂,#5584 遗留,与本 diff 无关)而红——验收时不计入本单质量账,#5604 修复落地后合 main 重跑。Check Changeset 已按 tests/docs-only 路线走 skip-changeset,最新一跑放行。


Generated by Claude Code

@os-zhuang
os-zhuang marked this pull request as ready for review August 5, 2026 22:15
@os-zhuang
os-zhuang added this pull request to the merge queue Aug 5, 2026
Merged via the queue into main with commit 93a61be Aug 5, 2026
25 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-5515-sync-arch-l3-sap branch August 5, 2026 22:27
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/m skip-changeset PR has no user-facing published change; bypasses the changeset gate tests

Projects

None yet

2 participants