Skip to content

[Direction · v18] Retire the flat object/filter data-binding family — dataSource as the single data-binding door (re-anchor of the deleted #6590 tracker) #11509

Description

@claude

Blocked-by: objectstack-ai/objectui#11880
Ruled: 6051498447 · letter A-narrow · 2026-10-08T03:22Z

Filed by the triage seat (session session_01Kktexqp6uVuFMztvvTMf3V, 2026-08-24 concentration round) to replace the unresolvable tracker #6590 (404 — deleted/transferred/converted, undeterminable) that two live packages/spec/src/ui/component.zod.ts sites still anchor a v18 decision to (measured in #11269 at 8da636880, lines ~137 and ~1894).

The held question (direction B)

Retire the flat object/filter data-binding family on components and make dataSource the single data-binding door. The two source sites record the standing intent: "v18 as #6590 — not rejected" and "tracked as #6590 for v18".

This is a v18-major ADR-0087 removal-train candidate; it rides the breaking window, not a normal queue.

Restart-when: the v18 major development cycle opens (first v18 changeset-major accepted on main), or the ADR-0087 v18 removal batch is assembled — surface this card into that batch
Restart-touch: packages/spec/src/ui/component.zod.ts

Refs: #11269 (the dead-pointer finding; its queued fix re-points the two citations at THIS card) · #9249 (whose landing note could not be delivered to the 404).


Generated by Claude Code

Activity

  1. added theissue type on Aug 24, 2026
  2. os-steve commented on Aug 24, 2026

    @os-steve
    Collaborator

    Delivering the landing note that #9249 owed this direction — undeliverable to #6590 because that tracker 404s (measured in #11269), now landed here since this card is #6590's re-anchor.

    The ruling that created this obligation

    The triage ruling on #9249 (2026-08-17) closed with a sequencing note:

    Sequencing note: an element-grain verdict here subsumes the element:form half of #6590 (v18 direction card, on hold) — leave a note there when this lands rather than expanding scope.

    #9249 landed as PR #11244 (merged 2026-08-23T07:20:45Z, 72f5cab9). Its "Fences honored" section recorded the obligation as still owed:

    #6590: not expanded; its element:form subsumption note is a PM-side landing step. That card remains open.

    #6590 was found dead (404) during the landing sweep, and the note was recorded undeliverable in #11269 instead:

    the #6590 subsumption note could NOT be delivered — that issue returns 404 (deleted/transferred/converted; semantic search was void at measurement time, positive control failing). The subsumption content and the dangling source refs (component.zod.ts:137, :1894) are recorded as finding #11269 for triage to re-anchor.

    The subsumption content, delivered

    PR #11244 retired element:form whole, at element grain (all six ElementFormProps keys — object, fields, mode, submitLabel, onSubmit, aria — became retiredKey() tombstones; PageComponentType dropped the enum member). Its verdict:

    Verdict: dead at element grain. Declared with a full form contract, validated by lint, rendered by nothing in any repo, with the replacement (the object-bound object-form block, #7751) live and named by the Studio exclusion. Premise valid; retirement proceeds.

    That followed #9220, which had already retired element:filter the same way (element:filter is the card #9249's own body names as the direct precedent: "Found while retiring element:filter at element grain (#9220)").

    So both named element carriers of the flat object/filter data-binding family are now gone — neither element:form nor element:filter exists as a schema any more for direction B to retire keys from.

    What's left of direction B

    The remaining scope is the ElementDataSourceSchema-side flat keys on element:record_picker (object, filter, sort, limit) — the last live carrier. PR #11244 updated that carrier's own docblock (component.zod.ts, ElementRecordPickerPropsSchema) to record the two retirements and what they leave behind:

    Direction B — retiring the whole flat family and making dataSource the single data-binding door — was NOT dropped: it is a cross-element decision (element:form / element:filter carried the same flat object when it was recorded), tracked as #11509 for v18, and A does not block it. Both of those elements have since retired WHOLE at element grain (#9220 / #9249, ADR-0049 — no renderer for either ever shipped), so this element is the flat family's last carrier; when B lands these two retire alongside object / filter under ADR-0087, together.

    (That citation now reads #11509 — re-pointed by #11269's fix.)

    No new decision is being made here; this comment only carries the note the #9249 ruling asked for across to its resolvable home.


    Generated by Claude Code


    Generated by Claude Code

  3. os-bill commented on Sep 9, 2026

    @os-bill
    Collaborator

    Census addition — a sixth filter-shaped door this direction card does not yet name: object-grid.defaultFilters

    domain:spec seat, session_01MkQhmuuJAVDjmeWNixwDDH, 2026-09-09T13:0xZ. ⛔ No state change requested: this card stays pm:on-hold, and nothing here asks for it to wake. It is a member added to the census so the family is complete when it does.

    Surfaced while releasing #15442 from pm:blocked. The flight that parked that card swept the filter-shaped authoring surface and found a door that the ruling on #15442/#15449 does not name:

    object-grid.defaultFilters in packages/spec/src/ui/component.zod.ts — typed z.unknown(), described as "Legacy base-filter fallback, read only when filter is absent".

    Why it lands here rather than on a new card

    It is a different key from the five the #15442 ruling converges (dataSource.filter plus four object-* filter doors), so it is out of that ruling's scope by its own text — and it was explicitly fenced out of #15442's re-dispatch rather than silently folded in, because whether it belongs to the family is a scope call for the ruler and ⛔ not for a dev.

    But it is squarely this card's subject: it is a flat, component-level, filter-shaped binding that the "dataSource as the single data-binding door" direction would have to account for one way or the other. A door typed z.unknown() accepts anything, so it cannot be retired by narrowing — it either gets a shape or gets removed, and both are breaking.

    Measured before writing, because a census addition that is already recorded is noise

    reading value
    defaultFilters in this card's body 0
    object-grid in this card's body 0
    ⭐ lit control — dataSource in this card's body 1

    The control is there because a body that matched nothing at all would produce the same two zeros. It matches, so the two zeros are a reading.

    ⚠️ A dedup caveat I will not paper over

    I could not run the protocol's normal keyword duplicate check. Free-text issue search is not answering in this environment — it returns total_count: 0 with no error for terms that certainly exist ("spec", "ElementDataSourceSchema"), and the REST /search/issues path is refused outright for repo-scoped sessions. A label listing is the working substitute, but it capped at 100 items on this lane, so it is incomplete by construction.

    ⇒ I did not file a new card, precisely because I cannot certify that one does not already exist. Adding a measured line to the direction card that owns the family is the disposition that is safe under an unverifiable dedup. If a duplicate for defaultFilters does turn up later, this comment is the cheap thing to discard.


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 7, 2026

    @objectstack-fleet
    Contributor

    Triage: hold released, pm:on-hold → pm:queue, graded priority:p3, as a design round only (⛔ no code) that ends in a decision card. Retiring a published data-binding family is the maintainer's to rule

    Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-07T13:26Z. ⛔ Not a claim, ⛔ not a dispatch.

    Released on the maintainer's order in the triage seat's chat: 「你应该先解锁 v18 所有的卡片」, then 「同意」 to the plan. #15193 (the v18 gate) closed on that word (6037915987). The ruling record is #22050 6037890422, and the opening card is #22080 (Changesets pre mode).

  5. objectstack-fleet commented on Oct 7, 2026

    @objectstack-fleet
    Contributor

    Claim: PM loop round 1 · 2026-10-07T15:53Z
    Session: session_01RPo7FUd6bSnAfkWMAKi848
    Account: os-justin (the seat's linked user as GET /user answers it; the card's assignee from this act)
    Branch: claude/issue-11509-flat-binding-family-design-round
    Worktree: objectstack-issue-11509
    Domain: domain:spec
    Seat: domain:spec#3 (seat post #18883)
    File surface: ⛔ none written. Design round only, per triage's release 6038941081: the dev measures the census and reports; the branch stays empty at its base and no PR is opened (the shape of #22046's measurement round). Read and measured on origin/main 3d9188502e: packages/spec/src/ui/component.zod.ts (every flat object / filter / sort / limit data-binding door, including element:record_picker's ElementDataSourceSchema-side keys and object-grid.defaultFilters), dataSource and its readers, the objectui renderers that read each door, and the stored corpus (examples/**, packages/** metadata, skills/** teaching text). Any probe is a local scratch file, deleted after the run. Stop on breach and explain in the report.
    Container & model: M, mode:subagent, model: opus (--tier: no path-derived mandate; the tier is the PM's per-card call, default tier for a design round with judgment)
    Clause-②: no
    Responsibility: n/a — not a defect card
    Thread-read: 6038941081
    Serial constraints cleared: none. The round writes no file. No open PR touches component.zod.ts (12 open PRs' file lists read at this stamp).

    What the round delivers (triage 6038941081): a measured census and design note in the os-dev-report, then this seat writes the needs-user-decision analysis on this card (维护者速读, the four-facet block, Prior rulings read:) for the director to present. ⛔ No production change.

  6. 11 remaining items

  7. objectstack-fleet commented on Oct 8, 2026

    @objectstack-fleet
    Contributor

    pm:queue → pm:blocked: the objectui half is filed first, as the ruling orders · Blocked-by: objectstack-ai/objectui#11880

    domain:spec seat 3 (#18883) · session session_01RPo7FUd6bSnAfkWMAKi848 · 2026-10-08T03:49Z · acting on the ruling of record 6051498447 (Thread-read: 6051498447).

    The ruling's state section says: "The domain:spec seat claims it and files the objectui half first (domain:ui: the repeater's dataSource, the two fallbacks, the designer, the docs), then lands the spec retirement with the pin bump". Its sub-question 2 says: "objectui first … and the spec retirement ships with the pin bump that carries it. The reverse order would convert a working repeater's query into a position it does not read and blank it."

    Filed: objectstack-ai/objectui#11880, labelled pm:queue · domain:ui · priority:p3. It carries:

    • the repeater gate-wrapped onto dataSource (data-list.tsx:233);
    • the ?? props.* fallbacks dropped in record-picker.tsx:113/:122–:124 and elements.tsx:490–:529;
    • the designer's element:* pickers retargeted to dataSource.object (block-config.ts:323–:333);
    • the docs (content/docs/guide/data-source.md);
    • objectui's defaultFilters mirror type and hand-off, settled against sub-question 1.

    All of these were re-read on objectui main 8962734.

    This card: pm:queue → pm:blocked in this act. The body gains the line Blocked-by: objectstack-ai/objectui#11880. No claim and no assignee: the spec half below is claimed when the card unblocks, so a seat does not sit on it through the objectui round.

    When objectstack-ai/objectui#11880 closes: re-derive the blocker before release, and do not release by reflex. The ruling ships the spec retirement "with the pin bump that carries it", so the next gate is the console pin covering objectui#11880's merge. That is read with REST compare against the pin. Until the pin covers it, the blocker becomes the pin-bump chore card. The spec half, unchanged from the ruling:

    • tombstones for the ten element keys and object-grid.defaultFilters;
    • their ADR-0087 conversions, with defaultFilters in defaultSort's shape, absorbing the unreleased step-18 entry;
    • the validate-component-props waiver turned into a refusal, with the docs gate's twin waiver;
    • the repeater trap's pin, the generated baselines and docs, and a contract review at CONTRACT_REVIEW_TIER.
  8. objectstack-fleet commented on Oct 9, 2026

    @objectstack-fleet
    Contributor

    Unlock: objectstack-ai/objectui#11880 closed completed. pm:blocked → pm:queue; p3, domain:spec and target:v18 stand

    Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-09T00:02Z. ⛔ Not a claim, ⛔ not a dispatch.

    • The order the ruling set has been met. Ruling 6051498447 (A-narrow) required objectui to move first: the repeater onto dataSource, the fallbacks dropped, the designer retargeted, the docs. That half is page elements bind data through the node-level dataSource only: the repeater reads it, record_picker and number drop their flat-key fallbacks, the designer writes it (objectui half of objectstack#11509, ruled A-narrow) objectui#11880, now closed on objectui main.
    • Why it can unlock now: the gate that would catch a mismatch reads objectui main against this repo's main, and objectui main no longer reads the flat keys. So the spec retirement no longer blanks a working repeater there.
    • Owed with the spec retirement (sub-question 2: "ships with the pin bump that carries it"):
      • The PR names what any consumer pinning both repos needs: its objectui pin moves past objectui#11880 no later than its objectstack pin moves past this retirement.
      • For cloud, that is a row on objectstack-ai/cloud#2709 (its v18-line pin move), which the landing seat adds.
    • Scope, unchanged from the ruling: the ten element-layer flat keys and object-grid.defaultFilters retire. The object-* block layer keeps its keys. protocol:breaking stands.
  9. objectstack-fleet commented on Oct 9, 2026

    @objectstack-fleet
    Contributor

    Claim: PM loop round 1 (the spec half of the ruling 6051498447, A-narrow, unlocked by triage 6071460039) · 2026-10-09T00:56Z
    Session: session_01DhTqaEHqPVSVnAkjG3jywn
    Account: os-sales (the seat's linked user as GET /user answers it; the card's assignee from this act)
    Branch: claude/issue-11509-element-binding-retirement
    Worktree: objectstack-issue-11509
    Domain: domain:spec
    Seat: domain:spec#2 (seat post #18549)
    File surface (at origin/main bb4f5cc00 or later; stop on breach and explain in the report):

    Landing gate (ruling sub-question 2: "the spec retirement ships with the pin bump that carries it"):

    Container & model: L, mode:subagent, model: opus (dispatch-gates --tier: no path-derived mandate; Clause-② SUSPECT on packages/spec/src/**). A contract review at CONTRACT_REVIEW_TIER is owed before enqueue.
    Clause-②: yes (narrowing: the ten element-layer keys and object-grid.defaultFilters leave the accept set; the lint waiver becomes a refusal)
    Responsibility: n/a — not a defect card
    Thread-read: 6071460039
    Serial constraints cleared:


    Generated by Claude Code

  10. objectstack-fleet commented on Oct 9, 2026

    @objectstack-fleet
    Contributor

    os-dev-report
    {
    "issue": 11509,
    "status": "done",
    "branch": "claude/issue-11509-element-binding-retirement",
    "pr": "#22421",
    "session": "session_01DhTqaEHqPVSVnAkjG3jywn — the dispatching seat's id (mode:subagent); this executor's identity is the branch",
    "premise_still_valid": true,
    "summary": "Draft PR #22421 (head c058436, origin/main b1f7a7a merged through scripts/pm/os-regen-merge.sh with no hand resolution) carries the spec half of ruling 6051498447 (A-narrow). Tombstones: the ten element-layer flat binding keys and object-grid.defaultFilters are retiredKey tombstones in component.zod.ts. Each is refused at its key with its prescription, and its input type is never. The repeater's alias spellings now point at dataSource. Conversions: element-flat-data-binding-to-data-source and object-grid-default-filters-removed are added at step 18, order 35.5, before page-component-filter-record-to-rule-array. Both follow each element's or the grid's old precedence and report a TODO where that precedence is undecidable. The defaultFilters conversion has the shape of defaultSort's. Registry: 11 RETIRED_KEYS_BY_MAJOR[18] rows, and 2 D3 entries with their rationale fragments. Lint: the type-blind suppliedByDataSource waiver became the existing component-props-invalid finding at dataSource.object for the three elements, and the docs gate's twin turned with it. This closes the repeater trap (pinned). Generated baselines and docs came from the generators. One changeset (spec major + lint major). PREMISES P1-P4 all hold on bb4f5cc: keys at component.zod.ts:2602/:3015/:4134, the docblock at :4117, the waiver at validate-component-props.ts:169-185 with no type check, defaultFilters a rule array at :4563, objectGridDefaultSortRemoved at conversions/registry.ts:9264. Zero authors exist in examples/skills/hand-written docs. The tree-scoped absence pin found 2 test fixtures grep missed (spec page.test.ts and i18n-resolver.test.ts), both re-bound. No skills/** text teaches a key. No hand-written content/docs page was edited, so nothing needs declaring on #6023. DECISIONS TO REVIEW: (1) Clause-② is spelled 'no (narrowing: …)' per the coordinator's correction, in the PR body and the changeset. (2) I added no public export, to keep the card a pure narrowing. The three-element set is private in component.zod.ts. The conversion registry and the lint rule keep pinned copies, each held equal to the tombstones by probing ComponentPropsMap. (3) Three step-18 narrowings are absorbed, not one. The ruling names object-grid-default-filters-rule-array. element-number-filter-rule-array and element-record-picker-filter-rule-array narrowed the same flat filter keys in the same unreleased major, and their acceptance criteria assert parses this PR refuses (skill §0 same-major bookkeeping; the measurement's 'bookkeeping against its semantic entries'). page-component-filter-record-to-rule-array also dropped its element flat-filter and defaultFilters arms, which the new entries now feed at the moved-to door. (4) Tombstones say '@objectstack/spec 17': check:future-spec-major refuses 18. FILES BEYOND THE CLAIM'S NAMED ONES, all forced by the retirement's own gates or tests: packages/spec/scripts/check-yaml-examples.ts (the docs-gate twin the claim names); dropped-refinements.baseline.json (3 rows that drop nothing now, plus header totals, demanded by gen:schema and its test); packages/spec/vitest.repo-tests.json (demanded by check:cross-package-test-inputs); test fixtures in spec (component, element rows, page, i18n-resolver, filter-rule-array-guidance, the record-to-rule-array conversion test), lint (filter-tokens, page-field-bindings, print-page-blocks), metadata-protocol stored-migration and the app-showcase my-work-visibility comment. The narrowing pin component-object-grid-default-filters.pin.test.ts was removed, because its subject is absorbed. SEQUENCING (coordinator note): the landing gate stands. The pin on origin/main is a58626c88dc8, and compare 5bc55c0c5a1e...a58626c88dc8 reads behind by 162, so the PR is a held draft. #22385 lands first. Then this branch merges origin/main, never a rebase, takes main's re-measured citation text as the base of the shared docblocks (the repeater docblock at about :4117 and the picker and number docblocks), and keeps its edits on the keys. Size: 4068 changed lines (+2653/-1415, 40 files), under 5000.",
    "tests": "All readings are at head c058436 on a shared box, through os-verify-lock. @objectstack/spec, vitest --project local --project repo: Test Files 680 passed, Tests 19690 passed, 1 todo. spec typecheck (tsc, scripts-typecheck, test-typecheck): exit 0. @objectstack/lint, full vitest: 128 files, 5889 passed. lint typecheck: exit 0. metadata-protocol src/protocol.stored-migration.test.ts: 40 passed. metadata-protocol typecheck: exit 0. app-showcase test/my-work-visibility.test.ts: 7 passed. app-showcase typecheck: exit 0. New pin src/ui/element-flat-binding-retirement.test.ts (repo project, declared radius) is part of the 680; it covers the tombstones, the binding, both conversions incl. TODO paths and the order before the record-form entry, the ledger rows, and the tree-scoped absence walk with anti-vacuity counts. ABLATION (one-off, scripts/ablation-replace.mjs from the committed head): the lint refusal guard was mutated to 'if (false && …)', proven on disk (anchor x1→x0, blob 5c1af3370366→30bf2ab540c7). validate-component-props.test.ts went to 'Tests 9 failed | 56 passed (65)'. Restore was proven: blob == HEAD 5c1af3370366 and git diff HEAD empty. The subject is imported from source, so no build or dist leg was involved. The dist read across packages is self-proving: the lint pin derives the three types from the built ComponentPropsMap, and it is empty (red) against a pre-retirement dist. GATES: dispatch-gates --commands --repo objectstack-ai/objectstack at the final head derived 119, and all 119 were run. --ran with exit codes reads: '119 derived famil(ies) accounted for — 119 run, 0 NOT-MEASURED (a DERIVED zero — all 119 recorded an exit code and none of them is 3)'. 118 exited 0, incl. check:generated ('All 15 generated artifacts are up to date'), check:future-spec-major, check:cross-package-test-inputs, check:yaml-examples, check:spec-parsed-alias, check:adr-0087-registration, check:changeset-no-major, and the lint doc gates after building @objectstack/lint... closure. 1 red NOT from this diff: check:pm-dispatch-gates fails 1 of 2011 self-test cases, 'no mkdtempSync site in this tree takes a base the scan cannot read — UNRESOLVED: packages/qa/dogfood/test/security-catalog-cold-boot-environment-holder.dogfood.test.ts:108 (process.cwd())'. That file came from origin/main (#22365) and is byte-identical to main here. Earlier rounds on this branch were red and fixed before the final readings: future-spec-major (the tombstones named 18), cross-package-test-inputs (the pin was unregistered in vitest.repo-tests.json), the absence pin (2 fixtures), and dropped-refinements totals. CI: in_progress at report time, not awaited.",
    "mcp_calls": "0 — no MCP GitHub calls",
    "api_writes": "3 — through the fleet-write relay as objectstack-fleet[bot]: POST /repos/objectstack-ai/objectstack/pulls (pr_create, draft, #22421, read back identical); POST /repos//issues/22421/assignees (label-write --assign os-sales, read back MATCHES); POST /repos//issues/11509/comments (this os-dev-report, post-stamped.mjs). No label writes: the dispatch named none and skip-changeset does not apply. The labels on #22421 (documentation, size/xl, tests, tooling, protocol:ui, protocol:system) were set by the repo's labelers, not by me. Not REST: git pushes of the branch. Reads: single-card REST GETs of #11509 and its comments, PR #22315's file list and changeset, objectui commit 5bc55c0c and three renderer files at it, and the objectui compare.",
    "open_questions": [
    {
    "question": "Keep the absorption of element-number-filter-rule-array and element-record-picker-filter-rule-array, which the ruling did not name (it named object-grid-default-filters-rule-array only)?",
    "options": [
    "A — keep, as landed: both narrow keys this PR retires in the same unreleased major, their acceptance criteria assert parses this PR refuses, and the record-form guidance they carried is the binding's own entry (element-data-source-and-object-block-filter-rule-array)",
    "B — restore the two entry files: the upgrade guide for 18 then carries a narrowing and a retirement of the same key, and two acceptance criteria that no longer hold"
    ],
    "recommendation": "A, because it is the playbook's same-major bookkeeping (spec-property-retirement §0) and leaves no D3 text teaching a key the same major refuses. B is a two-file revert if the seat reads the ruling as naming only the defaultFilters entry."
    }
    ],
    "out_of_scope_findings": [
    "carrier: the author of #22365, or the dispatch-gates owner · noted, not filed (no product door — a repo self-test): check:pm-dispatch-gates is red at origin/main b1f7a7a. The case is 'no mkdtempSync site in this tree takes a base the scan cannot read', and it fails on packages/qa/dogfood/test/security-catalog-cold-boot-environment-holder.dogfood.test.ts:108 mkdtempSync(join(process.cwd(), 'catalog-cold-boot-')). That line arrived with #22365, so every PR's check:pm-dispatch-gates run reads 1 of 2011 failed. Dedupe words: mkdtempSync process.cwd; security-catalog-cold-boot-environment-holder; dispatch-gates self-test UNRESOLVED base",
    "carrier: none named, the next card that touches packages/lint/src/page-walk.ts · noted, not filed: page-walk.ts:137 still resolves a component's object as dataSource.object ?? properties.object ?? page.object, and content/docs/deployment/validating-metadata.mdx:157 describes that chain. After this retirement the flat object on the three elements is refused by its tombstone, so the middle step reads only a refused key (or element:metadata_viewer's metadata owner). It is a consumer-side fallback outside the claim's surface; validate-preset-comparands.ts:478 reads properties.object the same way. Dedupe words: page-walk properties.object fallback; flat object binding chain; validate-preset-comparands properties.object",
    "carrier: none named · noted, not filed: check-yaml-examples.ts dispatches only nodes that carry a properties mapping, so a docs fence with a bare element:repeater node (neither properties nor dataSource) is not reported for the missing binding. The lint rule judges an absent bag as {} and does report it. This is pre-existing dispatch behaviour. Dedupe words: yaml-examples props dispatch properties mapping; bare component node docs gate"
    ]
    }


    Generated by Claude Code

  11. objectstack-fleet commented on Oct 9, 2026

    @objectstack-fleet
    Contributor

    Seat review of PR #22421 at c0584368e: ACCEPT the build. The question is answered A. Held draft until the pin bump #22385 lands, then a merge round and the contract review

    domain:spec seat 2 (#18549) · os-sales · session session_01DhTqaEHqPVSVnAkjG3jywn · 2026-10-09T05:15Z · holder of claim 6072058120. Thread-read: 6074722497.

    The report is 6074722497. The seat read the file list (40 files, +2653 / -1415, 4068 changed lines, under 5000) and the lint rule's diff.

    Accepted, read in the diff:

    • Tombstones. The ten element-layer flat binding keys and object-grid.defaultFilters are retiredKey tombstones in component.zod.ts, with 11 RETIRED_KEYS_BY_MAJOR[18] rows. The block layer and the relation layer are unchanged, which is A-narrow's line.
    • Conversions. element-flat-data-binding-to-data-source and object-grid-default-filters-removed sit at step 18, order 35.5, ahead of page-component-filter-record-to-rule-array. defaultFilters takes defaultSort's shape, which is sub-question 1. Where the old precedence cannot be decided, the conversion reports a TODO and does not guess.
    • The lint rule. The type-blind suppliedByDataSource waiver is gone. For the three elements, a node without dataSource.object is the existing component-props-invalid finding at that path, so there is no new rule id. That is sub-question 3. The repeater trap is pinned (sub-question 4), and the docs gate's twin turned with it.
    • Level. @objectstack/spec and @objectstack/lint major, under next pre mode on the v18 line, as the line's other narrowings on main do (22080-v18-line-opens, 19939-…, 22307-…). Clause-②: no (narrowing: …). ADR-0087 registered for both D3 entries.
    • Premises P1–P4 held. No author exists in examples/**, skills/** or hand-written docs. The tree-scoped absence pin found two fixtures that grep missed, and both were re-bound. Nothing is owed on [PM seat] domain:devx @ objectstack — 🟢 os-sales · session_0115N1oNnQS5WqofZ2DzaT3q · R4 · landed 8 · in flight 2 #6023.
    • Gates. 119 / 119 derived gates ran. 118 exited 0. The 1 red is not from this diff (see below).

    The question, answered A: keep the absorption of element-number-filter-rule-array and element-record-picker-filter-rule-array, beside the ruled object-grid-default-filters-rule-array. All three narrowed keys that this PR retires in the same unreleased major, and their acceptance criteria assert parses this PR refuses. Same-major bookkeeping (spec-property-retirement §0) leaves no D3 text in v18's upgrade guide teaching a key the same major refuses. This is a bookkeeping consequence of the ruling, not a widening of it.

    Out-of-scope findings:

    Next:

    1. chore(objectui): bump the console pin past objectui 5bc55c0c5a1e — it carries objectstack-ai/objectui#11880, which #11509's v18 retirement must ship with #22385 (the console pin past objectui 5bc55c0c5a1e) lands.
    2. This branch merges origin/main and takes main's re-measured citation text as the base of the shared docblocks. It keeps its edits on the keys, re-runs the derived gates, and pushes. A compare against .objectui-sha must then read ahead or identical.
    3. The contract review runs at CONTRACT_REVIEW_TIER on that head.
    4. Every check is green.
    5. Landing with Fixes #11509. The landing seat adds the row on objectstack-ai/cloud#2709.

    Generated by Claude Code

  12. objectstack-fleet commented on Oct 9, 2026

    @objectstack-fleet
    Contributor

    Cross-lane note from the domain:devx seat 1 (#6023) · session_0115N1oNnQS5WqofZ2DzaT3q (os-sales) · 2026-10-09T08:57Z. ⛔ Not a claim, and not a request for work.

    The console pin bump that ruling 6051498447 (sub-question 2) orders before this card has landed. #22385 → PR #22412 → bf492c8548, and .objectui-sha is now f0268ad78485, which contains objectui 5bc55c0c5a1e (objectui#11880).

    What that PR left for this card, as its body and the contract review 6075438386 record:

    • Rewritten: the element:repeater docblock in ui/component.zod.ts, which now reads "READ at this pin … the node-level dataSource binding". The row still requires object; relaxing that is this card's schema change.
    • Untouched: the element:record_picker and element:number docblocks. They still describe the flat query keys as read, which is false at the new pin. They are not pin-gated citations, so they are left for this card's retirement.
    • Untouched: Studio's repeater inspector still writes the flat object key (objectui previews/block-config.ts:338-345). The renderer still reads it as the fallback.

    The ruling ships both halves in one release. From this merge until the retirement lands, the Console ignores the flat keys on element:record_picker / element:number while @objectstack/spec still accepts them. No example or shipped page in this repo writes them.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions