Skip to content

fix(spec): app 表单摘掉八个已退役的墓碑键输入,#3786 对账门改判「真实可授权面」(#5280) - #5318

Merged
os-zhuang merged 3 commits into
mainfrom
claude/issue-5280-form-tombstone-reconciliation
Aug 4, 2026
Merged

fix(spec): app 表单摘掉八个已退役的墓碑键输入,#3786 对账门改判「真实可授权面」(#5280)#5318
os-zhuang merged 3 commits into
mainfrom
claude/issue-5280-form-tombstone-reconciliation

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Fixes #5280

前提核验(origin/main @ de113a4,带阳性对照)

三条都成立,但范围比单子写的大:issue 点名三个键(sharing / embed / mobileNavigation),按范围第 3 条全量扫下来,app.form.ts 一共在提供八个 retiredKey() 墓碑键。

app.sharing:          in shape=true innerType=never isRetired=true
app.embed:            in shape=true innerType=never isRetired=true
app.mobileNavigation: in shape=true innerType=never isRetired=true
app.navigation:       in shape=true innerType=union isRetired=false   ← 阳性对照
app.label:            in shape=true innerType=string isRetired=false  ← 阳性对照

form offers ∩ retired: ["version","homePageId","mobileNavigation","objects","apis","sharing","embed","aria"]

safeParse sharing:          success=false :: `App.sharing` was removed in @objectstack/spec 17.0.0 …
safeParse embed:            success=false :: `App.embed` was removed in @objectstack/spec 17.0.0 …
safeParse mobileNavigation: success=false :: `App.mobileNavigation` was removed in @objectstack/spec 17.0.0 …
control (no retired key):   success=true

另外五个(version / homePageId / objects / apis / aria)与点名的三个同类同因:都是 17.0.0 的 retiredKey() 墓碑,处方都落在别的层(manifest.version;navigation 首项 + isDefault;defineStack({ objects });defineStack({ apis });渲染 DOM 的组件),没有一个部分映射到 App 自身的活键,所以八个的摘除都是机械操作,按范围第 3 条「发现的一并修」同 PR 处理。

1) 表单(范围 1+3)

八个 { field: … } 输入全部移除,按套件惯例在原位留注释说明能力去向。另有两个分区描述本身还在宣传已退役能力(Content 的 "Objects and APIs this app uses."、Access & sharing 的 "…and how it can be embedded."),一并订正为真实语义。

2) 门谓词(范围 2 —— 本单真正的价值)

#3786 的断言用 key ∈ shape 判「Zod accepts」。retiredKey() 按设计把键留在 walked shape 里(退役套件的 liveness 行正因为键还在才保留),于是墓碑键对该断言永远为真 —— 门绿着,作者拿到 422。

谓词收紧为「∈ shape 且不是墓碑」,双向都改:

  • form-only 拆成两条独立断言,失败信息分得清「未声明 → 静默丢弃」与「墓碑 → 硬失败」。后者更响也更早,原断言的措辞("silently stripped on save")只覆盖了两种失败里的一种。
  • zod-only 把墓碑键排除出「必须提供或立 ledger」的集合 —— 墓碑键的唯一正确处置就是不提供。此前 object.fields.conditionalRequired 没被要求回填,纯属被一条无关的 subset ledger 条目挡住,是运气不是设计。
  • ledger 自检(omit 的存在性、subset 的非空性)改用 authorable 键计数,免得墓碑撑住一条已失效的豁免。

检测器判 schema 节点(optional 内层是否 z.never),不匹配键名 —— 键名清单本身就是 #3786 要消灭的手抄列表。这是 build-schemas.ts 里 JSON Schema 侧 isRetired()({ "not": {} })的 zod 侧孪生。union 取安全方向:只要有一个成员仍把该键声明为活键,就不算退役。

3) RED-first 实证(方向先预测,后运行)

预测:谓词收紧、表单未改时,app 那条用例,恰好点名八个键;其余类型与两条 nested 方向不变。实测一致:

 ❯ src/system/metadata-form-zod-reconciliation.test.ts (41 tests | 1 failed)
     × app: every field the form offers is a key the author may write

AssertionError: app: offered by the form but RETIRED in the Zod (retiredKey tombstone —
filling the control hard-fails the save)…: expected [ 'apis', 'aria', 'embed', …(5) ] to deeply equal []
+   "apis", "aria", "embed", "homePageId", "mobileNavigation", "objects", "sharing", "version"

 Tests  1 failed | 40 passed (41)

摘掉输入后 41 passed (41)

自检钉在合成 schema 上而非当期某个墓碑:墓碑会随版本退场(retired-key.ts 写的约两个大版本),锚在活墓碑上的自检要么烂尾,要么在锚被删的那一版悄悄空转 —— 一条什么都不过滤却依旧报绿的门。四条自检覆盖:墓碑留在 shape 里(即 key ∈ shape 为何是错谓词)、值被硬拒且带处方、按节点而非键名判定、union 成员仍 live 时不算退役。

4) 全量扫(范围 3)

17 个 *.form.ts 全部在册(METADATA_FORM_REGISTRY 覆盖),顶层 + 手写 nested 列表一起扫。修复后:

tombstone keys still offered by ANY form: 0
app form final fields: name,label,description,icon,active,isDefault,navigation,areas,defaultAgent,branding,requiredPermissions
app tombstones still in shape (必须保留 —— 墓碑路线): version,homePageId,objects,apis,sharing,embed,mobileNavigation,aria

其余带墓碑的类型(field / view / dashboard / action / agent / skill / flow)的表单没有在提供它们,本单无需改动。未删除任何墓碑,只删表单控件 —— liveness 行依赖键继续留在 shape 里。

5) i18n

表单输入变动会带走抽取键,四个 *.metadata-forms.generated.ts 按 merge 模式重生成(纯删除,每个 bundle 8 组 field 键)。两个分区描述的 leaf 值按「bundle 值可手写」的惯例手工订正 —— merge 模式不会用源文覆盖已有值,不改的话渲染出来的仍是旧文案(zh-CN 的 basics/navigation 甚至点名「版本」「首页」两个已退役键)。

验证

命令 结果
vitest run src/system/metadata-form-zod-reconciliation.test.ts 41 passed (41)
pnpm --filter @objectstack/spec test 308 files / 7959 tests passed
pnpm --filter @objectstack/spec check:generated 9/9 up to date
pnpm check:i18n OK(9 包全部 in sync)
pnpm check:i18n-coverage OK(660 baselined,none new)
pnpm --filter @objectstack/spec --filter @objectstack/platform-objects typecheck Done
pnpm --filter @objectstack/cli test 69 files / 626 tests passed
pnpm --filter @objectstack/lint test 57 files / 1198 tests passed
pnpm --filter @objectstack/platform-objects test 9 files / 266 tests passed
node scripts/check-nul-bytes.mjs OK(5343 文件,无裸 NUL)

消费半径按门的调用方扫过(不是按改动的包):METADATA_FORM_REGISTRY 的消费方是 packages/cli 的 i18n 抽取/覆盖率、packages/lint 的翻译引用校验、packages/platform-objects 的 bundle,三者的测试都跑过。

git merge origin/main(合入 #5289 / #5293 / #5296 / #5302 / #5303),生成物整体重生成而非文本合并,合并后全部门重跑并确认兄弟 PR 的条目仍在。

范围外发现


🤖 Generated with Claude Code

https://claude.ai/code/session_01ErbEDVAg1No9gdg1pgDAGB


Generated by Claude Code

claude added 2 commits August 4, 2026 18:38
`app.form.ts` 仍在给作者渲染八个 `retiredKey()` 墓碑键的输入控件 ——
`version` / `homePageId` / `objects` / `apis` / `sharing` / `embed` /
`mobileNavigation` / `aria`(issue 只点了后三个,全量扫出八个)。墓碑是
`z.never().optional()`,填进去不是静默丢弃,是整条 save 硬失败并抛出该键
的退役处方。八个控件全部移除,按套件惯例在原位留注释说明能力去向。

真正的价值在门这一侧:#3786 的对账断言用 `key ∈ shape` 判定「Zod 接受该
键」。在 `retiredKey()` 出现之前这两件事同义,之后不是了 —— 墓碑**按设计**
把键留在 walked shape 里(退役套件的 liveness 行正因为键还在才保留),于是
八个墓碑键对该断言永远为真,门绿着而作者拿到 422。

谓词收紧为「∈ shape 且不是墓碑」,双向都改:
- form-only 方向拆成两条独立断言,失败信息能分清「未声明→静默丢弃」与
  「墓碑→硬失败」,后者更响也更早;
- zod-only 方向把墓碑键排除出「必须提供或立 ledger」的集合 —— 墓碑键的唯一
  正确处置就是不提供。此前 `object.fields.conditionalRequired` 不被要求回填
  纯属被一条无关的 `subset` ledger 条目挡住,是运气不是设计;
- ledger 的 `omit`/`subset` 自检改用 authorable 键计数,避免墓碑撑住一条
  已失效的豁免。

检测器判 **schema 节点**(optional 内层是否 `z.never`),不匹配键名 —— 键名
清单本身就是 #3786 要消灭的手抄列表。这是 `build-schemas.ts` 里 JSON Schema
侧 `isRetired()`(`{ not: {} }`)的 zod 侧孪生。四条合成 schema 上的自检把
机制钉住(含 union 成员仍 live 时不算退役的安全方向),不依赖任何当期墓碑,
免得墓碑随版本退场后这条门悄悄变空转。

RED-first 实证:谓词收紧、表单未改时,`app` 那条用例红,恰好点名八个键;
摘掉输入后 41/41 绿。

表单输入变动会带走 i18n 抽取键,四个 metadata-forms bundle 按 merge 模式
重生成(纯删除 8 组);两个分区描述原文仍在宣传已退役能力(zh-CN 的
basics/navigation 甚至点名「版本」「首页」),按 bundle 值可手写的惯例一并
订正为真实语义。

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

vercel Bot commented Aug 4, 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 4, 2026 10:01pm

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation protocol:system tests protocol:ui tooling labels Aug 4, 2026
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

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

107 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/platform-objects, @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/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/platform-objects, @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.

@os-zhuang
os-zhuang marked this pull request as ready for review August 4, 2026 22:02
@os-zhuang
os-zhuang enabled auto-merge August 4, 2026 22:02
@os-zhuang
os-zhuang added this pull request to the merge queue Aug 4, 2026
Merged via the queue into main with commit f1cc3a3 Aug 4, 2026
25 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-5280-form-tombstone-reconciliation branch August 4, 2026 22:24
os-zhuang pushed a commit that referenced this pull request Aug 4, 2026
Second relay merge: #5300 / #5304 / #5306 / #5308 / #5318 / #5326 / #5327.
Textually clean, but the os-regen driver defers generated artifacts rather than
text-merging them, so `json-schema.manifest.json` again came out holding this
branch's pre-merge side — this time still listing `ui/EmbedConfig` and
`ui/NotificationAction`, both retired by #5300. Reset the deferred artifacts to
`origin/main`, rebuilt from the merged tree, regenerated wholesale.

Post-regen assertions (a silent one-side drop is exactly what this catches):
api-surface delta vs `origin/main` is exactly this PR's four additions and ZERO
removals; manifest delta is one addition (`ui/ViewItemWire`) and zero removals;
every sibling retirement stays removed (`ui/EmbedConfig`, `ui/NotificationAction`,
`system/HttpServerConfig`, `ui/Animation`, `ui/ZIndex`) and every sibling
addition stays present (`FilterArray` ×7, `EmailProvider` ×2).
`check:authorable-surface` (+ its #5304 `.base.json` anchor) is green and the
anchor file is byte-identical to `origin/main` — not hand-edited.

`metadata-form-zod-reconciliation.test.ts` co-edited with #5280/#5318 and merged
SEMANTICALLY, not by taking a side: #5318 rewrote the docblock, imports, helpers
and test bodies, while this PR's only edit is `unwrap`'s `pipe` case, so the two
did not overlap textually — but they do interact, and in the direction that
matters. #5318's `isRetiredAt` / `authorableKeysOf` both route through
`unwrap`/`keysOf`, and `view`'s root is now a `z.preprocess` pipe. Measured both
ways: without this PR's #4488-style fix `unwrap(view root)` resolves to
`transform` and `keysOf` returns NULL, so #5318's brand-new tombstone assertions
would be VACUOUS on `view` (and the pre-existing key-bearing assertion would
fail outright); with it, 89 keys. Both PRs' assertions are live on every type.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ErbEDVAg1No9gdg1pgDAGB
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Aug 6, 2026
…ack-ai#5074) (objectstack-ai#5319)

* feat(spec)!: split ViewItemSchema into an authoring gate and a wire variant (objectstack-ai#5074)

`ViewItemSchema` carried two contracts at once: the authoring surface
`defineViewItem()` and Studio's view-create form parse, AND member 1 of the
`ViewMetadataSchema` union that `saveMetaItem` validates every persisted `view`
body against. The wire role needed Studio's round-trip keys through, so the
shape stayed open — and `defineViewItem({ …, confg: {…} })` parsed clean,
handing back a ViewItem with no view configuration at all.

Per the maintainer's ruling (option A, 2026-08-04):

- `ViewItemSchema` is strict on both arms — the authoring gate.
- `ViewItemWireSchema` is the `.strip()` wire variant and is member 1 of
  `ViewMetadataSchema`, with `isPinned` / `sortOrder` DECLARED on it instead of
  surviving because nobody closed the member. Both are built from one
  `viewItemArmShape()`, so the two postures cannot drift into two
  transcriptions (a `discriminatedUnion` cannot be `.extend()`ed).

The scope addendum's hard requirement was recursive-effective openness, which a
posture flip cannot deliver: `.strip()` re-opens a member's TOP level only, so
the console-decorated NESTED blocks were still reached at full strictness.
`stripViewConsoleDecorations` (+ the declared `VIEW_CONSOLE_ROW_DECORATIONS`
vocabulary) removes them at the wire door before the union runs — the
write-path mirror of `stripReadDecorations`. That let both blocked sites close:

- `ViewFilterRuleSchema` — objectstack-ai#5114's hotfix was explicitly provisional; retired.
- `ListView.sort[]` — 批 18's revert (objectstack-ai#5070); the `direction → order` alias
  (objectstack-ai#4721, a silently REVERSED sort) comes back with it.

`id` is still not declared anywhere: it is a React list key, and declaring it
would teach an AI author to emit a UUID (批 18 Q1, rejected on record).

Two gate walkers went silent on `view` under a preprocess-rooted registration —
the exact blind spot objectstack-ai#4488 already fixed in `check-liveness.mts` — and are
fixed the same way here. A gate that stops covering a type is worse than one
that fails.

Fixes objectstack-ai#5074

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

* chore(spec): regenerate baselines after merging origin/main (objectstack-ai#5074)

The os-regen merge driver defers generated artifacts rather than text-merging
them, so `json-schema.manifest.json` came out of the merge holding this
branch's pre-merge side — which still listed `system/HttpServerConfig`,
`ui/Animation` and `ui/ZIndex`, all retired by the objectstack-ai#5289/objectstack-ai#5293 chain. Reset the
deferred artifacts to `origin/main`, rebuilt, and regenerated wholesale.

Asserted after regenerating, because a silent one-side drop is exactly what
this step exists to catch: the api-surface delta vs `origin/main` is exactly
this PR's four additions and ZERO removals; the manifest delta is one addition
(`ui/ViewItemWire`) and zero removals; the sibling retirements
(`HttpServerConfigSchema`, `ui/Animation`, `ui/ZIndex`) all stay removed.

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

* chore(spec): regenerate baselines after merging origin/main (spec 车道接力)

Second relay merge: objectstack-ai#5300 / objectstack-ai#5304 / objectstack-ai#5306 / objectstack-ai#5308 / objectstack-ai#5318 / objectstack-ai#5326 / objectstack-ai#5327.
Textually clean, but the os-regen driver defers generated artifacts rather than
text-merging them, so `json-schema.manifest.json` again came out holding this
branch's pre-merge side — this time still listing `ui/EmbedConfig` and
`ui/NotificationAction`, both retired by objectstack-ai#5300. Reset the deferred artifacts to
`origin/main`, rebuilt from the merged tree, regenerated wholesale.

Post-regen assertions (a silent one-side drop is exactly what this catches):
api-surface delta vs `origin/main` is exactly this PR's four additions and ZERO
removals; manifest delta is one addition (`ui/ViewItemWire`) and zero removals;
every sibling retirement stays removed (`ui/EmbedConfig`, `ui/NotificationAction`,
`system/HttpServerConfig`, `ui/Animation`, `ui/ZIndex`) and every sibling
addition stays present (`FilterArray` ×7, `EmailProvider` ×2).
`check:authorable-surface` (+ its objectstack-ai#5304 `.base.json` anchor) is green and the
anchor file is byte-identical to `origin/main` — not hand-edited.

`metadata-form-zod-reconciliation.test.ts` co-edited with objectstack-ai#5280/objectstack-ai#5318 and merged
SEMANTICALLY, not by taking a side: objectstack-ai#5318 rewrote the docblock, imports, helpers
and test bodies, while this PR's only edit is `unwrap`'s `pipe` case, so the two
did not overlap textually — but they do interact, and in the direction that
matters. objectstack-ai#5318's `isRetiredAt` / `authorableKeysOf` both route through
`unwrap`/`keysOf`, and `view`'s root is now a `z.preprocess` pipe. Measured both
ways: without this PR's objectstack-ai#4488-style fix `unwrap(view root)` resolves to
`transform` and `keysOf` returns NULL, so objectstack-ai#5318's brand-new tombstone assertions
would be VACUOUS on `view` (and the pre-existing key-bearing assertion would
fail outright); with it, 89 keys. Both PRs' assertions are live on every type.

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Aug 6, 2026
…摆纠偏、飞行中重叠、预期红停放 (objectstack-ai#5441) (objectstack-ai#5501)

* docs(pm-dispatch,os-dev): 串行接力一夜沉淀的六条缺口补进 SKILL —— 接力模式、锚点措辞、裁决传播扫描、停摆纠偏、飞行中重叠、预期红停放 (objectstack-ai#5441)

2026-08-04/05 夜 spec 车道以串行接力连落 10 个 PR(objectstack-ai#5304objectstack-ai#5365),六个情形是
现行 SKILL 没有覆盖、靠现场即兴的,各有实付学费。按 issue 注明的落点章节逐条插入:

- 第 7 步「入队与落地」新增平行小节「串行接力」:每棒一整圈(auto-merge 由 PM 挂、
  dev 永不碰,ready 与 auto-merge 顺序不可反且每棒各走一次)、相邻棒同文件交接语义
  而非文本(objectstack-ai#5318/objectstack-ai#5319 实例)、两棒散文互锁由 PM 指派分工(objectstack-ai#5323objectstack-ai#5365objectstack-ai#5335)。
- 「入队与落地 A」新增锚点断言措辞:authenticity = baseRev 是 origin/main 祖先 且
  keys 与该 commit 逐行一致;baseRev 允许滞后;⛔ 不得要求 baseRev == merge-base
  (那会教唆手改锚点,即 objectstack-ai#4650 攻击自身)。四步序的第 3 步补上「先 commit merge」,
  并引用 objectstack-ai#5370 / objectstack-ai#5371 两个新陷阱(仅引用,不实现)。
- 第 5 步派发词 + 第 7 步 review 新增「裁决传播 = 全仓 pin 扫描」:翻 pin 一轮翻完
  且必须保留承重(objectstack-ai#5322 裁决、objectstack-ai#5365 的 REST 层漏翻)。
- 第 6 步 Collect 的 subagent 半边新增停摆纠偏:watcher 永不触发,中途状态即停摆
  信号,第三次视为不可靠改走接手协议。生产端半边同步落到 os-dev.md 资源纪律第 6 条。
- 第 5 步 same-day churn 新增姊妹段「飞行中范围重叠」:每轮读 origin/main 时对每个
  在飞 dispatch 做相交判断,相交即预警(objectstack-ai#5322 × objectstack-ai#5335 实例)。
- 「入队与落地 B」新增依赖 PR 的预期红停放:draft 停放 + 签名级预期红清单 + 解除
  条件,新签名才是真问题(objectstack-ai#5365 的 REST 红即由此识别)。

仅改 `.claude/` 内部 agent 协议文本,不发布任何包;六条落点之外未动任何段落。

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

* docs(pm-dispatch): 停摆纠偏第三条的交叉引用改指「step 5」—— 接手协议在第 5 步,不在第 6 步之下

自查发现的方向错误:「Handing off an interrupted dev」小节是第 5 步的子节
(SKILL.md:839),而新增段落写在第 6 步(:923),原文写「below」会把读者指向
第 6 步之后的 Cloud mode 段。同段里对 cloud-mode ~2h 阈值的「below」是对的,保留。

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

* docs(pm-dispatch): 飞行中重叠一段的时间戳改用可核验值 —— objectstack-ai#5335 的 merged_at 是 23:49:44Z,不是 00:0xZ

issue objectstack-ai#5441 正文写「objectstack-ai#5335 在 00:0xZ 合入」,核 GitHub API 的 merged_at 与 main 上
squash 提交的 committer date,两者一致给出 2026-08-04T23:49:44Z。改写成「起飞后
32 分钟合入(merged_at 2026-08-04T23:49:44Z)」,把不可核验的钟点换成可核验的
时间差 + 权威字段;起飞时刻 23:17Z 沿用 issue 的记述(无仓内产物可核,且非承重)。

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

---------

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

Projects

None yet

2 participants