Skip to content

docs(spec): a form section / page component gates visibility only — say so, and tell disabled where it belongs (#7887) - #8199

Merged
os-zhuang merged 2 commits into
mainfrom
claude/issue-7887-section-component-editability-boundary
Aug 12, 2026
Merged

docs(spec): a form section / page component gates visibility only — say so, and tell disabled where it belongs (#7887)#8199
os-zhuang merged 2 commits into
mainfrom
claude/issue-7887-section-component-editability-boundary

Conversation

@os-zhuang

@os-zhuang os-zhuang commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Fixes #7887

The ruling being implemented

Maintainer ruling of 2026-08-12 (comment 5271005260), operative sentence, verbatim:

Ruling: boundary, not gap. FormSectionSchema / PageComponentSchema gate visibility only; editability lives on fields. No disabled / readonly / disabledWhen slot is added to those shapes, and no alias row is registered for them — adding one would declare a key the runtime does not honour, the exact ADR-0049 class being retired elsewhere.

So this PR adds no key and no alias row. It documents the boundary on both shapes and gives the existing rejection a guidance string naming where the key does belong.

Before, on a section:

Unrecognized key(s) on this view/page schema: `disabled`. Before ADR-0089 D3a these
were dropped silently, shipping inert metadata; a mis-layered or stale key is now a
loud parse error.

After:

Unrecognized key(s) on this view/page schema: `disabled`.
  • Editability is a FIELD-level concern. This shape gates VISIBILITY only — a
    deliberate boundary, not a missing key (#7887): a section / page component has no
    read-only semantics of its own to enforce. Write `readonly: true` (or the
    conditional `readonlyWhen` predicate) on the form field(s) inside it instead; to
    hide the whole section or component, use `visibleWhen`. Before ADR-0089 D3a these
    were dropped silently, shipping inert metadata; a mis-layered or stale key is now
    a loud parse error.

It points at readonlyWhen and never at disabledWhen — verified on origin/main, not inherited from the card: data/field.zod.ts renames disabled to readonly and its own comment records that "a field has readonlyWhen, not disabledWhen" (#7832). A prescription naming disabledWhen would hand the author their next rejection. One pin asserts the prescription text contains readonlyWhen and another asserts it never contains disabledWhen.

Where the guidance landed, and why not the obvious place

VISIBILITY_STRICT_OPTIONS is shared by three shapes: FormSectionSchema, PageComponentSchema, and FormFieldSchema. Filing the boundary family in that shared table is one line shorter and is wrong in three separate ways, all of them measured rather than argued (I ran the counterfactual — the set hoisted into the shared table — and reverted it):

  1. It silently destroys the one correct pointer in the family. strictUnknownKeyError consults exact guidance, then guidanceSets, then aliases, and a set match continues past the rename channel. FormFieldSchema answers disabled through its own aliases: { disabled: 'readonly' } row, and readonly is real there. Measured on the counterfactual: the sentence Did you mean disabledreadonly? disappears, and a field author is redirected away from the surface where the key they want actually lives.
  2. alias-integrity.test.ts goes red — the [finding] alias-integrity cannot see an alias row made unreachable by a guidanceSet — a vis-shaped alias on VISIBILITY_STRICT_OPTIONS surfaces would be dead code with no gate saying so #7889 reachability check, which landed this morning:
    "this view/page schema": alias `disabled` -> `readonly` is unreachable — guidanceSet
    `…` already matches `disabled` and consumes it before the alias table is ever consulted
    
  3. alias-integrity.test.ts's [spec] Fold the three hand-written unrecognized_keys error maps into strictObject guidance — requires a set-keyed guidance form, and closes the alias-integrity gate's blind spot (#6416 direction 2) #6619 check goes red tooreadonly is a declared key on FormFieldSchema, so a shared set listing it is a dead member on that surface by construction.

The existing comment at view.zod.ts's FormFieldSchema strict-options block already rejected shared-table filing for the alias case, in the same direction ("filed there it would name a key two of its three surfaces do not accept"). This is that rule read from the other end, and the comment is extended to say so rather than contradicted.

So: a new VISIBILITY_ONLY_STRICT_OPTIONS (the shared options plus the boundary set) is taken by the two shapes that gate visibility and nothing else. FormFieldSchema keeps the bare options. The prescription text is written once, filed on exactly two surfaces.

Set membership covers disabled, disabledWhen, readonly, readOnly, readonlyWhen, editable. None of them matches VISIBILITY_KEY_PATTERN (/vis|conceal|hidden|show.?when/i), so the two sets on the table never contend and declaration order is not load-bearing — pinned, so it cannot quietly become load-bearing later.

…and why the table is package-internal

The options table lives in a new packages/spec/src/shared/editability-boundary.ts that the shared/index.ts barrel deliberately does not re-export — the same posture as strict-object.ts and alias-probe.ts, the machinery it belongs to.

It was first written into shared/visibility.ts, which the barrel does re-export wholesale, and check:api-surface caught that (+ VISIBILITY_ONLY_STRICT_OPTIONS (const), 1 added / 0 breaking) — a repo-wide gate that a package-scoped typecheck does not reach. Two fixes were available: regenerate the api-surface snapshot, or keep it internal. Internal is right here, and not merely because it is tidier:

  • StrictObjectOptions, the const's own type, is not public (it lives in the unbarrelled strict-object.ts). A published value of an unpublished type is an export no consumer can annotate or usefully extend.
  • It keeps the card's claim exactly true one level out: nothing observable moves except the sentence an author reads. check:api-surface now reports "public API surface + factory signatures unchanged ✓", and export-origins is byte-identical to main — this PR touches no committed generated artifact.

VISIBILITY_STRICT_OPTIONS being public is a pre-existing accident of visibility.ts carrying the runtime normalizeVisibleWhen helper; not touched here.

Acceptance invariance

The lane's admission criterion, evidenced five ways:

  • The rejected set does not move. All six spellings are still rejected on both shapes; the pins assert it per key with a message saying so.
  • The accepted set does not move. A representative section (name/label/description/collapsible/columns/visibleOn/fields) and a representative page component (type/id/label/properties/className/visibility) both still parse, and the ADR-0089 fold still produces the same output keys.
  • FormFieldSchema's message is byte-for-byte what it was — captured before the change and after, identical.
  • The generated schema surface is unchanged. A full pnpm --filter @objectstack/spec build runs gen:schema, which rewrites authorable-surface.base.json and the JSON-schema artifacts; the tree was clean afterwards. Nothing about the accepted surface moved for it to record.
  • The public API surface is unchanged, per check:api-surface above.

New pins — packages/spec/src/shared/editability-boundary.test.ts

Each asserts on a real safeParse error, never on the options table (a row filed in a table nothing consults is the dead-entry shape alias-integrity.test.ts exists for, and only reading the message back cannot pass that way):

Pin What it catches
disabled on section/component reaches the boundary text, rendered as the template bullet the guidance being filed on a table the shape does not use, or the prescription channel being bypassed
the whole family (six spellings) reaches it a member quietly dropped from the set
one prescription per message for a body carrying three of them someone converting the set to N exact guidance entries — same text, three copies of the paragraph
the history sentence still comes last a regression of #5955's ordering caused by the new set
the text names readonly: true and readonlyWhen a rewrite that loses the destination and leaves a bare "this is not the place"
the prescription never contains disabledWhen the card's own most likely wrong turn — pointing at a key no field surface declares
visibleWhen is named and really parses on both shapes prose making a claim the schema does not honour
FormFieldSchema still emits the rename and NOT the boundary text the shared-table hoist, i.e. the whole design decision above
no editability key matches VISIBILITY_KEY_PATTERN a future widening of the pattern making set order decide which prescription an author sees
no alias row exists for any of the six the half of the ruling that forbids alias rows
every spelling still rejected; representative section/component still parse; an unrelated typo still gets no bullet acceptance drift in either direction, and the set over-claiming beyond its family

visible-when-alias-guidance.test.ts §3's assertions are unchanged and green by construction — this card added no disabled-ish key, which is exactly what those pins measure. Only that block's prose moved: it said disabled "stays uncurated", which is no longer true for the two shapes the ruling covers (SelectOptionSchema, out of the ruling's scope, stays bare). The test name now reads "so no alias row is filed", which is the claim the assertions actually make.

Changeset

patch, confirmed rather than inherited. The criterion is whether the prose reaches a consumer; measured:

  • Parse-reachable error string — YES. Demonstrated above and pinned. This alone settles it: an author reads this text.
  • dist .d.ts hover — YES. The boundary paragraphs are JSDoc on the two exported schema consts, FormSectionSchema and PageComponentSchema.
  • Generated reference page — NO, measured. content/docs/references/ui/view.mdx is built by build-docs.ts from the file-level doc block plus per-property .describe() text; a schema's own JSDoc is not rendered. Grepping the page for existing FormSectionSchema docblock text ("Closed under ADR-0089 D3a") returns nothing, while a per-key .describe() string hits. No top-level .describe() was added for it: it would not reach that page either, and it would move authorable-surface.base.json for no consumer gain.

One reachable consumer is enough, and no metadata that parses today parses differently, so patch is right. No public export is added, so there is nothing additive for the bump to cover.

Scope

data/object.zod.ts is untouched and no part of the visible/showWhen symmetry question is implemented — that is #7816's, per the cross-seat note there. SelectOptionSchema is also untouched: the ruling names two shapes, and a per-option disabled is a genuinely different question (a disabled select option is a real UI concept, unlike a read-only section). Recorded as an observation for the PM to route, not fixed here.

Verification

Re-run in full after the api-surface fix:

  • pnpm --filter @objectstack/spec test — 386 files / 10218 tests, green.
  • pnpm --filter @objectstack/spec typecheck — green.
  • pnpm --filter @objectstack/spec check:api-surface — "public API surface + factory signatures unchanged ✓" (after a full dts build; OS_SKIP_DTS=1 is not valid for this gate, per AGENTS.md §9).
  • pnpm --filter @objectstack/spec check:export-origins — current, 5021 exports, artifact byte-identical to main.
  • alias-integrity / strict-object / visible-when-alias-guidance / ui/view / ui/page — green.
  • Reverse verification: the shared-table counterfactual, red in all three predicted places (listed above), reverted with git checkout and re-run green.
  • Gates: check:nul-bytes, check:adr-anchors, check:changeset-gate-self-tests, check:docs-audit-scope, check:merge-driver, check:release-body, check:spec-parsed-alias, check:i18n, @objectstack/lint check:doc-formula-expressions — all exit 0.

Generated by Claude Code

…t in the rejection (#7887)

`FormSectionSchema` / `PageComponentSchema` gate visibility only; editability
lives on fields (maintainer ruling, 2026-08-12). No slot and no alias row is
added — the rejection now carries a guidance string naming the field-level
`readonly` / `readonlyWhen` pair instead of refusing bare.

Filed as `VISIBILITY_ONLY_STRICT_OPTIONS` on those two shapes rather than in the
shared `VISIBILITY_STRICT_OPTIONS`: the third consumer, `FormFieldSchema`,
answers `disabled` through its own rename row, and a guidanceSet consumes a key
before the rename channel is ever reached.

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

vercel Bot commented Aug 12, 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 12, 2026 8:35pm

Request Review

@github-actions

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/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 @objectstack/spec)
  • content/docs/kernel/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/data-service.mdx (via @objectstack/spec)
  • content/docs/kernel/runtime-services/email-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/examples.mdx (via @objectstack/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 @objectstack/spec)
  • content/docs/kernel/runtime-services/sms-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx (via @objectstack/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/permissions/system-context.mdx (via packages/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/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/field-grouping-and-order.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)

7 release-owned page(s) also reference the affected code. These are read-only:

  • 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/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

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.

#7887)

`check:api-surface` (repo-wide TypeScript Type Check job) went red: exporting
`VISIBILITY_ONLY_STRICT_OPTIONS` from `shared/visibility.ts` put it in the
public barrel and moved the package's API surface.

Moved to a new `shared/editability-boundary.ts`, which the barrel deliberately
does not re-export — the same posture as `strict-object.ts` and
`alias-probe.ts`. `StrictObjectOptions`, the const's own type, is not public
either, so a published value of that type is one no consumer could annotate.
The public API surface and `export-origins` now both read unchanged, which is
also the card's own claim one level out.

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

Copy link
Copy Markdown
Contributor Author

Pushed 82443539check:api-surface fix.

Took option 2 (keep it package-internal), not the snapshot regeneration. The barrel does re-export shared/visibility.ts wholesale, which is how the const became public in the first place — but the same directory already holds strict-object.ts and alias-probe.ts, which the barrel deliberately omits. Moving the table to a new shared/editability-boundary.ts in that group is one file and three import lines; nothing was contorted for it.

What tipped it past "slightly better fit":

  • StrictObjectOptions — the const's own type — is not public. It lives in the unbarrelled strict-object.ts, so a published VISIBILITY_ONLY_STRICT_OPTIONS is a value no external consumer can annotate, extend, or do anything with. Publishing it would have been an obligation with no reachable use.
  • The card's claim is that nothing observable changes, and it is now literally true at both levels: check:api-surface reports "public API surface + factory signatures unchanged ✓", and export-origins/shared.json is back to byte-identical with main. This PR now touches no committed generated artifact at all — the one-line export-origins diff from the first push is gone.

(VISIBILITY_STRICT_OPTIONS itself is public, but that reads as an accident of visibility.ts also carrying the runtime normalizeVisibleWhen helper rather than an API commitment. Not touched.)

The PR body's placement section now covers both decisions — which table the guidance goes in, and why the table is internal — and the changeset gained a sentence saying the public surface does not move.

Re-ran after the change: full @objectstack/spec suite (386 files / 10218 tests) green, typecheck green, check:api-surface green (needs a real dts build — OS_SKIP_DTS=1 is explicitly wrong for it, per the gate's own message and AGENTS.md §9), check:export-origins green, and all nine gates from the first pass exit 0. Still draft, auto-merge untouched.

Taking the process note: check:api-surface joins my standing pass whenever a card adds or removes an export — and the more general lesson is that --filter <pkg> typecheck is not the same instrument as the repo-wide TypeScript Type Check job, which runs package check:* steps my scoped run never reaches.


Generated by Claude Code

@github-actions

Copy link
Copy Markdown
Contributor

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

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

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

  • Dogfood Regression Gate (3/3) — 失败步骤: Boot example apps and exercise real user flows

    �[41m�[1m FAIL �[22m�[49m �[30m�[46m isolated �[49m�[39m test/federated-phantom-share-grant.dogfood.test.ts�[2m > �[22m[#8119] federated phantom anchor: single-record gates + share posture�[2m > �[22m
    

历史信号:

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

分诊清单:

  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

Queue-failure receipt — requeuing ONCE, and this is the record of why. domain:spec-surface seat (#6298), session session_016YBUGvukaeVu9DjKdsHJa9.

Queue build 31641136083 ejected this PR. Signature:

FAIL test/federated-phantom-share-grant.dogfood.test.ts
  > [#8119] federated phantom anchor: single-record gates + share posture
  > PHASE 2 — no share row may be minted on a phantom anchor
  > over real HTTP the envelope is code SHARING_NOT_ENABLED + status 422

AssertionError: expected undefined to be 'SHARING_NOT_ENABLED'
  test/federated-phantom-share-grant.dogfood.test.ts:311:25

Triaged before requeuing, not after:

  1. Not this PR's package. The diff is JSDoc plus a package-internal unknown-key guidance table in @objectstack/spec. The failure is the code field of a plugin-sharing REST refusal envelope. There is no path from one to the other — and note which half failed: line 309's expect(res.status).toBe(422) passed, so the refusal fired correctly and only the envelope's code key was absent.
  2. Why this PR's own CI did not run it. The test file arrived on main in b8c95a64 (PR fix(plugin-sharing): refuse a share row on a federated phantom owner anchor, with the single-record gate behaviour measured (#8119) #8209, plugin-sharing's SINGLE-record write gates still read the phantom owner_id on federated objects (the three hasOwnerField consumers #7858 did not touch) #8119) at 20:33:37Z. This branch's base is 6b702480, which predates it, and PR-side CI runs the affected subset — so the queue build (base = main + this diff) is the first run of this test against this branch. Dogfood Regression Gate (3/3) was green on the PR side for exactly that reason, and that green is not evidence either way.
  3. Not a known-flaky signature. Searched every triage comment in the repo from today for this test name: no other PR has been ejected by it. This is the first sighting, so the "known elsewhere ⇒ flaky, do not requeue" branch does not apply.

That leaves the third branch of the lane's queue-triage rule — cause not established as either mine or a known flake — whose action is one requeue, receipted here.

The commitment that makes a single requeue honest: if the same signature ejects this PR again, I will not requeue a second time. I will file it as a flaky/broken-test finding against the owning lane and leave this PR out of the queue until that is resolved. Two consecutive identical ejections is evidence about main, not about this branch, and burning a third full-queue rebuild for the whole fleet to re-learn it is not a cost I get to impose.

Also notified the domain:identity seat on #8119 — that test is theirs, it is 40 minutes old, and they were active on the card minutes ago. If it is red on main rather than batch-dependent, they will know faster than a second requeue would tell me.


Generated by Claude Code

Merged via the queue into main with commit a18abf3 Aug 12, 2026
28 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-7887-section-component-editability-boundary branch August 12, 2026 21:34
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 protocol:ui size/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[finding] disabled has no vocabulary at all on FormSectionSchema / PageComponentSchema — no readonly/disabled/disabledWhen key to point an author at

2 participants