Skip to content

feat(spec): referenceDeletedWhen beside referenceVia marks a pointer's target as platform-deleted - #23759

Merged
objectstack-fleet[bot] merged 6 commits into
mainfrom
claude/issue-23735-reference-deleted-when
Oct 16, 2026
Merged

objectstack-fleet[bot] merged 6 commits into
mainfrom
claude/issue-23735-reference-deleted-when

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #23735

Clause-②: yes

The spec half of objectstack-ai/objectui#12489 ruling 6203737086, letter A (maintainer 「A (推荐)」): FieldSchema gains referenceDeletedWhen: { field, value } beside referenceVia. On rows where the sibling select field field holds the option value, the record the pointer names was deleted by the platform's own assertion; a renderer draws the tombstone from that option's own label, reads nothing and links nothing.

What changed

  • packages/spec/src/data/field.zod.ts: the key, directly after referenceVia, as a closed strictObject (field: snake_case; value: string). Refusal 1 in the FieldSchema superRefine beside the referenceVia checks: the key on a field that declares no referenceVia. The message names the field and the option.
  • packages/spec/src/data/object.zod.ts: refuseDishonestReferenceDeletedWhen, in the ObjectSchema superRefine beside refuseNonPictureImageField (the parse-time sibling door), not in create() only. One located custom issue at fields.FIELD.referenceDeletedWhen.field or .value when field is the declaring field itself, is undeclared, is not a select, is a multiple: true select, or declares no inline options (a picklist-backed select); or when value is not one of the sibling's option values (the declared set is listed). Every door refuses it: ObjectSchema.create(), defineStack, raw .parse() and the save door (getMetadataTypeSchema('object')).
  • packages/spec/src/data/field.form.ts: a composite form row beside referenceVia (the currencyConfig face), gated data.type == 'text'.
  • packages/spec/liveness/field.json: a planned row, drilled to field / value. It names both carriers: the producer plugin-approvals: sys_approval_request.record_id declares referenceDeletedWhen on cancel_reason = record_deleted (objectui#12489 letter A) #23736 (sys_approval_request.record_id with { field: 'cancel_reason', value: 'record_deleted' }) and the consumer objectui#12489 step 4. There is no authorWarn, following the field.settledWhen precedent.
  • Regenerated: authorable-surface/data.json, content/docs/references/** (3 pages), the strictness-ledger counts, and liveness/state-counts/field.md.
  • .changeset/23735-reference-deleted-when.md: @objectstack/spec minor; @objectstack/metadata-core, @objectstack/driver-sql and @objectstack/platform-objects patch (commit 645116bef; this line amended by the seat to match the changeset).

Outside the claimed file surface (forced by the widening, measured)

A new FieldSchema key reaches every exhaustive per-key table and census pin. Each one below went red, or would have, without its line:

  • packages/metadata-core/src/object-schema-fls-references.ts: FIELD_REFERENCE_POSITIONS is pinned against the live FieldSchema shape. The key is classified deletedWhen: the predicate is deleted whole when its field names a field the caller cannot read (value is an option, never a field). This has a new pin in object-schema-fls-references.test.ts.
  • packages/drivers/driver-sql/src/builtin-column-collision.ts: FIELD_KEY_STORAGE_CLASS classifies it presentation (no DDL reads it).
  • packages/platform-objects translation catalogs: the form row's three labels and help texts, hand-translated in zh-CN, ja-JP and es-ES (check:i18n green, source-hash entries dropped). Two catalog census pins moved: 669 → 672 and 8 → 10.
  • Census pins: metadata-protocol /meta/types field property count 79 → 80, and lint shipped-form predicate counts 88 → 89 and 65 → 66.

No plugin-approvals or platform-objects object file was touched; that is #23736. No objectui file was touched.

Verification (head d13e56398, after merging origin/main a869ea636)

  • @objectstack/spec: test 680 files / 20771 passed; typecheck exit 0; check:generated "All 14 generated artifacts are up to date" after a real (DTS) build; check:liveness exit 0.
  • New pins field-reference-deleted-when.test.ts: 15 passed. Ablation: the value check disabled through scripts/ablation-replace.mjs gave 3 failed / 12 passed, and the file was restored with blob equal to HEAD (c7916c270c23) and an empty git diff HEAD.
  • Consumers: @objectstack/objectql 427 files / 8148 passed (pre-merge head); @objectstack/metadata-protocol 236 files / 20577 passed; @objectstack/lint 139 files / 6771 passed; @objectstack/metadata-core 18 files / 728 passed plus typecheck; @objectstack/platform-objects 70 files / 1091 passed plus typecheck; @objectstack/driver-sql collision pin 11 passed plus typecheck.
  • dispatch-gates --commands: 113 families derived. 110 exited 0. 3 are NOT MEASURED locally: check:skill-examples (exit 3) and check:dual-build-cjs-loads (exit 3) refused a prerequisite, and check:dts-closure (exit 1) reported missing .d.ts in 48 packages that this container had built with OS_SKIP_DTS. That is local dist state, not a tree finding. CI builds fresh and runs all three.

Acceptance notes

  • The sibling check needs inline options. A picklist-backed select is refused, because its values are not declared on the object and the option cannot be checked at parse. A multiple: true select is refused, because "holds that value" has no single reading on an array.
  • Extensions (ObjectExtensionSchema) are not judged: the check reads the authored object's own field map, as imageField does.

Generated by Claude Code

…orm row, generated artifacts, changeset

Claude-Session: https://claude.ai/code/session_01LSSHP4Yb97YuFXXzj85HMJ
Co-authored-by: Claude <noreply@anthropic.com>
…age tables; bump field census pins

Claude-Session: https://claude.ai/code/session_01LSSHP4Yb97YuFXXzj85HMJ
Co-authored-by: Claude <noreply@anthropic.com>
…n zh-CN, ja-JP and es-ES; bump catalog census pins

Claude-Session: https://claude.ai/code/session_01LSSHP4Yb97YuFXXzj85HMJ
Co-authored-by: Claude <noreply@anthropic.com>
…s for the referenceDeletedWhen classification

Claude-Session: https://claude.ai/code/session_01LSSHP4Yb97YuFXXzj85HMJ
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 4 package(s): @objectstack/driver-sql, @objectstack/metadata-core, @objectstack/platform-objects, @objectstack/spec, touching 13 documentable anchor(s). ⚠️ 3 changed file(s) yielded no anchor (packages/spec/authorable-surface/data.json, packages/spec/liveness/field.json, packages/spec/liveness/state-counts/field.md), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

11 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:

  • content/docs/concepts/metadata-driven.mdx (via FieldSchema (symbol, a top-level const), ObjectSchemaBase (symbol, a top-level const object))
  • content/docs/data-modeling/external-datasources.mdx (via FieldSchema (symbol, a top-level const))
  • content/docs/data-modeling/field-types.mdx (via FieldSchema (symbol, a top-level const))
  • content/docs/data-modeling/validation-rules.mdx (via FieldSchema (symbol, a top-level const))
  • content/docs/deployment/troubleshooting.mdx (via FieldSchema (symbol, a top-level const))
  • content/docs/deployment/validating-metadata.mdx (via FieldSchema (symbol, a top-level const))
  • content/docs/getting-started/quick-reference.mdx (via FieldSchema (symbol, a top-level const))
  • content/docs/kernel/contracts/data-engine.mdx (via FieldSchema (symbol, a top-level const))
  • content/docs/protocol/backward-compatibility.mdx (via FieldSchema (symbol, a top-level const))
  • content/docs/protocol/objectql/types.mdx (via FieldSchema (symbol, a top-level const))
  • content/docs/protocol/objectui/concept.mdx (via FieldSchema (symbol, a top-level const))

⛔ 2 release-owned page(s) also name something this change touched. These are read-only:

  • content/docs/releases/v17/17-0.mdx (via FieldSchema (symbol, a top-level const))
  • content/docs/releases/v17/17-1.mdx (via FieldSchema (symbol, a top-level const))

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.

What this run could not see
  • 3 changed file(s) yielded no anchor (packages/spec/authorable-surface/data.json, packages/spec/liveness/field.json, packages/spec/liveness/state-counts/field.md) — pages documenting those are invisible to this run
  • 1 name(s) were too generic to anchor anything (single lowercase words)
  • the SDK route bridge reached 54 of 206 client-bound route-ledger rows — the other 152 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 152: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 97 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 143 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 140238a47b892ef9234052e44267ec3739fa79c2 → packageMentionDocs.

Which tree this was computed on

This run read content/docs from f4739bdc34be3247940a422881e90bd6f0e29ece — the merge of head 645116bef8e07c81784acad61568ac89b561d046 into base 140238a47b892ef9234052e44267ec3739fa79c2, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin f4739bdc34be3247940a422881e90bd6f0e29ece && git checkout f4739bdc34be3247940a422881e90bd6f0e29ece
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 140238a47b892ef9234052e44267ec3739fa79c2 645116bef8e07c81784acad61568ac89b561d046 && git checkout -B drift-repro 140238a47b892ef9234052e44267ec3739fa79c2 && git merge --no-ff 645116bef8e07c81784acad61568ac89b561d046

node scripts/docs-audit/affected-docs.mjs --json 140238a47b892ef9234052e44267ec3739fa79c2

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs 140238a47b892ef9234052e44267ec3739fa79c2 → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对 · ACCEPT · PR #23759 @ 645116bef8e07c81784acad61568ac89b561d046 (#23735) · domain:spec seat 1 · os-elon-musk · session session_01HjR8RUwTPQ3TgbfKihmxp9 · 2026-10-16T01:00Z

Reviewer of record. Every item below was checked against GitHub, not against the report (os-dev-report on #23735).

  • Shape:
    • Draft, base main. The first line is Fixes #23735, then Clause-②: yes, matching claim 6204194958 and the changeset.
    • 23 files, +578/−15, none governed. Assignee os-elon-musk.
  • Ruling item 1 (6203737086), read in the diff:
    • FieldSchema.referenceDeletedWhen is a closed strictObject (field snake_case, value string), directly after referenceVia.
    • Refusal 1 sits in FieldSchema's superRefine: the key without referenceVia.
    • Refusal 2 is refuseDishonestReferenceDeletedWhen in ObjectSchema's superRefine, beside refuseNonPictureImageField. Each of its five arms (self, undeclared, not a select, multiple: true, no inline options) and the out-of-set value adds one located custom issue at fields.FIELD.referenceDeletedWhen.field|value. The message names the field, the object and the option, with one prescription.
    • It runs at parse, so create(), defineStack, raw .parse() and the save door all refuse.
  • The report's three questions, the seat's calls: all three A.
    • The multiple: true and picklist-backed refusals stay. The ruling names "a select sibling and one of its declared options". The one named producer, cancel_reason, is a single select with inline options. Widening later is free; narrowing later would break.
    • The liveness row is planned without authorWarn, following the settledWhen precedent: the authoring half is enforced now.
    • The Zod custom issue shape stays. The save door maps it into its 422 envelope.
  • Outside the claimed surface, accepted: a new FieldSchema key reaches every exhaustive per-key table and census pin, and each edit names the pin that reds without it. The claim's file surface is amended on spec(field): referenceDeletedWhen beside referenceVia, a declared predicate on a sibling select field that marks the referenced record as platform-deleted (objectui#12489 letter A) #23735 in this round.
    • metadata-core FIELD_REFERENCE_POSITIONS: the predicate is deleted from a served field when its field names a field the caller cannot read (FLS). It has a new pin.
    • driver-sql FIELD_KEY_STORAGE_CLASS: presentation, so no DDL reads it.
    • The form-row labels in four locale catalogs (zh-CN / ja-JP / es-ES hand-written).
    • Census pins: metadata-protocol 79→80, lint 88→89 and 65→66, catalogs 669→672 and 8→10.
  • Changeset: @objectstack/spec minor; metadata-core, driver-sql and platform-objects patch. The sentences were checked against the diff (the five refusal arms, "nothing that parsed before is refused", the per-package classification). The PR body's changeset line said @objectstack/spec only, because the widening commit 645116bef came after pr_create. The seat amended that one line in this act, to match the changeset.
  • Consumers (spec lane rule), real readings in the report:
    • objectql: 8148 passed;
    • metadata-protocol: 20577 passed;
    • lint: 6771 passed;
    • metadata-core: 728 + 53;
    • platform-objects: 1091;
    • driver-sql collision: 11.
    • Ablation of the value refusal: 3 red, restored.
  • Out of scope: an ObjectExtensionSchema-added field is not judged (the imageField precedent). No producer exists, so Acceptance notes only.
  • CI on this head at this act: 34 success, 5 skipped, 1 pending. Not yet read as green.
  • Before the queue: a CONTRACT_REVIEW_TIER contract review (face packages/spec/src/**, and the widening the Clause-②: yes declares) by an isolated at-tier reviewer, and every check green on the head.

Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 645116bef8e07c81784acad61568ac89b561d046
Local-runs: none
Scope: packages/spec/src/data/field.form.ts, packages/spec/src/data/field.zod.ts, packages/spec/src/data/object.zod.ts + packages/spec/src/data/field-reference-deleted-when.test.ts, packages/spec/src/shared/strict-object.ts, packages/spec/liveness/field.json, packages/spec/liveness/README.md, packages/metadata-core/src/object-schema-fls-references.ts, packages/metadata-core/src/object-schema-fls-references.test.ts, packages/drivers/driver-sql/src/builtin-column-collision.ts, packages/drivers/driver-sql/src/builtin-column-collision.test.ts, .changeset/23735-reference-deleted-when.md

Inputs: card #23735 (body and all 3 comments: triage 6204123641, the dispatch claim 6204194958, the os-dev-report 6205248708), the ruling 6203737086 on objectstack-ai/objectui#12489 (letter A), the PR body, its 23-file list, the merge-base diff against main at this head (merge base a869ea636, 23 files, +578/-15), and the check-runs on this head. Code read at this head through the contents API. The rest of the diff (docs references, strictness-ledger counts, catalogs, census-pin test files, authorable-surface and state-counts artifacts) is the lane seat's ACCEPT at TIER_DEFAULT.

① Derived judgments

  1. FieldSchema accept set widens by one optional key — right. referenceDeletedWhen is a closed strictObject of field (snake_case string) and value (string), placed directly after referenceVia. An unknown key inside it is refused with one located issue at ['referenceDeletedWhen'] naming the key (pinned). Its aliases entry (option, equals to value; sibling to field) was read in strict-object.ts: a curated near-miss answer consulted before the distance fallback that steers the refusal MESSAGE only; the key stays refused. No tolerated alias, no ?? fallback (Prime Directive Add comprehensive test suite for Zod schema validation #12 holds). The authorable surface gains exactly data/Field:referenceDeletedWhen; the strictness ledger counts one more strict site (157 to 158, strict 80 to 81) — consistent.
  2. Refusal, field half — right and located. In the FieldSchema superRefine, beside the two referenceVia checks: referenceDeletedWhen present and referenceVia undefined gives one custom issue at ['referenceDeletedWhen'] whose message names the sibling field and the option the author wrote and prescribes referenceVia or removal (pinned, message asserted on both names). On a non-text field or beside reference, the existing referenceVia refusals fire alongside, each at its own path.
  3. Refusal, sibling half — right, at parse, at every door. refuseDishonestReferenceDeletedWhen sits in ObjectSchemaBase.superRefine beside refuseNonPictureImageField (read at 3040-3046). One custom issue per offending field at ['fields', FIELD, 'referenceDeletedWhen', 'field' or 'value'], six branches: the declaring field itself; an undeclared sibling; a non-select (its type named); a multiple: true select; a select with no inline options; a value outside the declared set (the set listed). Only a picklist-backed select reaches the no-options branch — FieldSchema already refuses a select with neither options nor picklist, and options: [], and picklist together with options — so that message's claim is exact. Every message names the declaring field, the object and the sibling; the option is named where it is the defect or cannot be checked (value and picklist branches) and the path leaf tells the author which half to fix on the others — judged sufficient against the card's "naming the field and the option". Doors: create() parses through ObjectSchemaBase.parse (read at 3494-3569), defineStack and the save door getMetadataTypeSchema('object') resolve to the same schema; the new test pins the refusal at ObjectSchema.safeParse, create(), the save door and the stack door (15 pins). CI Test Core is green on this head, and the dev's recorded ablation of the value branch went 3 red / 12 green and was restored byte-equal.
  4. Form — right. One composite row beside referenceVia, gated data.type == 'text', the currencyConfig face (read at field.form.ts 106-118): two text sub-rows field and value. The three locale catalogs carry its three labels and help texts; check:i18n rides in Lint & Repo Gates, green.
  5. Liveness — planned, right; not live. The row names the producer (plugin-approvals: sys_approval_request.record_id declares referenceDeletedWhen on cancel_reason = record_deleted (objectui#12489 letter A) #23736, sys_approval_request.record_id with { field: 'cancel_reason', value: 'record_deleted' }) and the consumer (objectui#12489 step 4), children field and value planned, no authorWarn. The README (read at this head) grades a declared key not yet read planned, makes authorWarn an opt-in on planned only, and refuses live without a reader; the settledWhen precedent row is planned with no authorWarn. Spec property liveness check-run green. State-counts planned 3 to 5 is the row plus its two children.
  6. No other accept set moved. metadata-core FIELD_REFERENCE_POSITIONS gains referenceDeletedWhen: deletedWhen — a served-projection scrub (REMOVE when field names a denied field; a non-object value goes the unclassified over-mask way). It is forced by the closed-against-live-spec pin classifies every FieldSchema key (test 662-664) and pinned in both directions (denied sibling deleted, readable sibling kept). It accepts nothing new and exports no new symbol. driver-sql FIELD_KEY_STORAGE_CLASS gains referenceDeletedWhen: 'presentation', forced by classifies EVERY FieldSchema key, and invents none (test 43-51); no DDL reads the key, so presentation is the right class. Both are value-level entries in exported tables; neither widens an input accept set or a public API.
  7. Governed surfaces: none in the file list; head repo equals base repo; the PR is a draft with auto-merge unarmed. The review is owed by face (packages/spec/src/**).

② Semver level

  • The changeset .changeset/23735-reference-deleted-when.md declares @objectstack/spec minor and @objectstack/metadata-core, @objectstack/driver-sql, @objectstack/platform-objects patch, body Clause-②: yes, no narrowing arm, no ADR-0087 marker needed (nothing that parsed before is refused; the key is new). That matches what the diff publishes: all four are published packages (private unset in their package.json at this head) whose src/ moved; lint and metadata-protocol move test files only. yes takes at least minor; met.
  • Clause-②: yes agrees across the claim (6204194958), the PR body and the changeset.
  • Drift noted, not a contract defect: the PR body's "What changed" bullet still reads "@objectstack/spec minor" alone and its Verification heading cites head d13e56398; the changeset-only commit on this head added the three patch lines after pr_create. The dev's report flags it for the seat to amend the body line.

③ Boundary flags

  • Deviation 1 (file surface widened to object.zod.ts, tests, the liveness row, the metadata-core and driver-sql tables, the catalogs, the census pins): answered — each widening is either the sibling half the claim's own refusal requires or a pin the key moved (① items 3, 4, 6). No plugin-approvals, platform-objects object or objectui file was touched.
  • Deviation 2 (changeset widened after pr_create; PR body line stale): answered in ②; the body amendment is the seat's.
  • Deviations 3 (footer form) and 4 (detached primary checkout): process notes with no contract bearing.
  • Q1 (refuse a multiple: true select and a picklist-backed select, beyond the ruling's letter): A, keep both. The ruling binds "a select sibling and one of its declared options"; a picklist's options are not declared on the object, so the parse cannot check the option, and an array column has no single reading of "holds that value". Narrowing later would be breaking, widening later is a minor. The one named producer (cancel_reason, a single select with inline options holding record_deleted) passes, pinned.
  • Q2 (liveness row without authorWarn): A — ① item 5.
  • Q3 (zod custom plus path, no envelope status): A — the save door maps the issues into its 422 envelope, the imageField precedent; the pins assert code, path and the named subjects.
  • Out-of-scope finding (ObjectExtensionSchema-added fields are not judged by refuseDishonestReferenceDeletedWhen): escalated to the lane seat as a card candidate, not a FAIL. Read at this head: ObjectExtensionSchema.fields is z.record(z.string(), FieldSchema), so an extension CAN author the key (the field half still fires there), and its own superRefine runs only refuseForeignTreeReference. The imageField precedent's justification ("an extension cannot declare the key") does not transfer; what does transfer is referenceVia's own precedent (its sibling check runs at create() only, extensions unjudged). The sibling may live on the base object, so the honest seam is where an extension's fields fold into the owning object — outside this card and outside the ruling's letter. The key's .describe() claim "any other shape is refused at parse" is exact for the object doors and over-broad for the extension door by exactly the margin referenceVia's already is; no producer extends an object with either key today. A follow-up card covering both keys at that seam is the right carrier.
  • Liveness verdict for the new key: planned — right (① item 5).
  • Check-runs on this head, read at 2026-10-16T01:07Z: every completed run is success or skipped; the five required contexts (Lint & Repo Gates, TypeScript Type Check, Test Core and all six shards, Build Core, Governed Surface Queue Guard) are success; Spec property liveness and both Check Changeset runs success; nothing in_progress.

Implemented-by: claude/issue-23735-reference-deleted-when
Reviewed-by: session_01HjR8RUwTPQ3TgbfKihmxp9

VERDICT: PASS

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:data size/l tests tooling

Projects

None yet

2 participants