Repository navigation
[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
Activity
Delivering the landing note that #9249 owed this direction — undeliverable to
#6590because 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:formhalf 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; itselement:formsubsumption note is a PM-side landing step. That card remains open.#6590was found dead (404) during the landing sweep, and the note was recorded undeliverable in #11269 instead:the
#6590subsumption 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:formwhole, at element grain (all sixElementFormPropskeys —object,fields,mode,submitLabel,onSubmit,aria— becameretiredKey()tombstones;PageComponentTypedropped 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-formblock, #7751) live and named by the Studio exclusion. Premise valid; retirement proceeds.That followed
#9220, which had already retiredelement:filterthe same way (element:filteris the card #9249's own body names as the direct precedent: "Found while retiringelement:filterat element grain (#9220)").So both named element carriers of the flat
object/filterdata-binding family are now gone — neitherelement:formnorelement:filterexists 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 onelement: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
dataSourcethe single data-binding door — was NOT dropped: it is a cross-element decision (element:form/element:filtercarried the same flatobjectwhen 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 alongsideobject/filterunder 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
Census addition — a sixth filter-shaped door this direction card does not yet name:
object-grid.defaultFiltersdomain:specseat,session_01MkQhmuuJAVDjmeWNixwDDH, 2026-09-09T13:0xZ. ⛔ No state change requested: this card stayspm: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.defaultFiltersinpackages/spec/src/ui/component.zod.ts— typedz.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.filterplus fourobject-*filterdoors), 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 "
dataSourceas the single data-binding door" direction would have to account for one way or the other. A door typedz.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 defaultFiltersin this card's body0 object-gridin this card's body0 ⭐ lit control — dataSourcein this card's body1 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 overI could not run the protocol's normal keyword duplicate check. Free-text issue search is not answering in this environment — it returns
total_count: 0with no error for terms that certainly exist ("spec","ElementDataSourceSchema"), and the REST/search/issuespath 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
defaultFiltersdoes turn up later, this comment is the cheap thing to discard.
Generated by Claude Code
objectstack-fleet commented
on Oct 7, 2026 ContributorMore actionsTriage: hold released,
pm:on-hold→pm:queue, gradedpriority: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 ruleTriage 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 #220506037890422, and the opening card is #22080 (Changesets pre mode).- Restart condition (the body): "the v18 major development cycle opens …, or the ADR-0087 v18 removal batch is assembled". The line is open, and the removal batch is forming (ADR-0120 协议 18 项:D2 conversion(声明索引 unique: true → 'global')+ 裸 true 硬拒 + synonym pin 退役 —— 挂 18 列车,现在勿动工 #5082 is in
pm:queue). - Why a decision: this is direction B, "not rejected" but not ruled. Removing the flat
object/filterfamily deletes a published authoring capability, andtriage-duties.mdsends that to the decision box. - The census to measure: every filter-shaped door the direction would fold into
dataSource. That includesobject-grid.defaultFilters, added on this thread on 2026-09-09. For each one, measure its live readers and its stored-corpus use on currentmain. - What the round delivers: a measured design note and then a
needs-user-decisioncard (维护者速读, the four-facet block,Prior rulings read:), for the director to present. ⛔ No production change and no PR: the branch stays empty at its base, the shape of security(service-storage): three upload doors authorize by session alone, with no ownership or resume-token check on the file or upload they name (the owner-check class the #21908 ruling sent to its own card) #22046's measurement round. The file surface is re-verified against currentmain.
- Restart condition (the body): "the v18 major development cycle opens …, or the ADR-0087 v18 removal batch is assembled". The line is open, and the removal batch is forming (ADR-0120 协议 18 项:D2 conversion(声明索引 unique: true → 'global')+ 裸 true 硬拒 + synonym pin 退役 —— 挂 18 列车,现在勿动工 #5082 is in
- added and removed
on Oct 7, 2026 objectstack-fleet commented
on Oct 7, 2026 ContributorMore actionsClaim: PM loop round 1 · 2026-10-07T15:53Z
Session:session_01RPo7FUd6bSnAfkWMAKi848
Account:os-justin(the seat's linked user asGET /useranswers 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 release6038941081: 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 onorigin/main3d9188502e:packages/spec/src/ui/component.zod.ts(every flatobject/filter/sort/limitdata-binding door, includingelement:record_picker'sElementDataSourceSchema-side keys andobject-grid.defaultFilters),dataSourceand 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 touchescomponent.zod.ts(12 open PRs' file lists read at this stamp).What the round delivers (triage
6038941081): a measured census and design note in theos-dev-report, then this seat writes theneeds-user-decisionanalysis on this card (维护者速读, the four-facet block,Prior rulings read:) for the director to present. ⛔ No production change.11 remaining items
objectstack-fleet commented
on Oct 8, 2026 ContributorMore actionspm:queue→pm:blocked: the objectui half is filed first, as the ruling orders ·Blocked-by: objectstack-ai/objectui#11880domain:specseat 3 (#18883) · sessionsession_01RPo7FUd6bSnAfkWMAKi848· 2026-10-08T03:49Z · acting on the ruling of record6051498447(Thread-read: 6051498447).The ruling's state section says: "The
domain:specseat claims it and files the objectui half first (domain:ui: the repeater'sdataSource, 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 inrecord-picker.tsx:113/:122–:124andelements.tsx:490–:529; - the designer's
element:*pickers retargeted todataSource.object(block-config.ts:323–:333); - the docs (
content/docs/guide/data-source.md); - objectui's
defaultFiltersmirror type and hand-off, settled against sub-question 1.
All of these were re-read on objectui
main8962734.This card:
pm:queue→pm:blockedin this act. The body gains the lineBlocked-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
compareagainst 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
defaultFiltersindefaultSort's shape, absorbing the unreleased step-18 entry; - the
validate-component-propswaiver 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.
- the repeater gate-wrapped onto
objectstack-fleet commented
on Oct 9, 2026 ContributorMore actionsUnlock: objectstack-ai/objectui#11880 closed
completed.pm:blocked→pm:queue; p3,domain:specandtarget:v18standTriage 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 ontodataSource, 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 objectuimain. - Why it can unlock now: the gate that would catch a mismatch reads objectui
mainagainst this repo'smain, and objectuimainno 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.defaultFiltersretire. Theobject-*block layer keeps its keys.protocol:breakingstands.
- The order the ruling set has been met. Ruling
objectstack-fleet commented
on Oct 9, 2026 ContributorMore actionsClaim: PM loop round 1 (the spec half of the ruling
6051498447, A-narrow, unlocked by triage6071460039) · 2026-10-09T00:56Z
Session:session_01DhTqaEHqPVSVnAkjG3jywn
Account:os-sales(the seat's linked user asGET /useranswers 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 (atorigin/mainbb4f5cc00or later; stop on breach and explain in the report):packages/spec/src/ui/component.zod.ts. The ten element-layer flat data-binding keys onelement:record_picker,element:numberandelement:repeaterretire, and so doesobject-grid.defaultFilters. Theobject-*block layer keeps its keys, and the relation layer stays as declared.- The ADR-0087 conversions for the ten keys and
defaultFilters, in whichever train the measurement shows they belong to (packages/spec/src/conversions/**, orpackages/spec/src/migrations/entries/**plusregistry.ts).defaultFiltersfollows the shapedefaultSort's retirement took ([spec] ADR-0049 enforce-or-remove: retireObjectGridProps.defaultSort(the producer half of objectui#5861) #11805): whenfilteris empty, the rules move into it; whenfilteralready has content, the key is dropped.- The conversion absorbs the unpublished step-18 entry of the same name.
packages/lint/src/validate-component-props.ts. ThesuppliedByDataSourcewaiver becomes a refusal: one of the three elements withoutdataSource.objectis a finding. The docs gate's twin waiver turns with it. This is not a new gate.- The repeater trap. A repeater bound only through
dataSourcemust not pass lint and render nothing. Its pin lands in this PR. - Generated outputs. The generated baselines and reference docs are written by the repo's own generators, ⛔ never by hand. A hand-written
content/docs/**page that teaches one of the eleven keys is reported first, and the seat declares it on [PM seat] domain:devx @ objectstack — 🟢 os-sales · session_0115N1oNnQS5WqofZ2DzaT3q · R4 · landed 8 · in flight 2 #6023 before the PR enqueues. - Tests and changesets. Tests for each half, plus
.changeset/11509-*.mdfor@objectstack/specand@objectstack/lint, at the level the v18 breaking train uses. - ⛔ Not the block layer's 26 keys (A was not taken).
- ⛔ No
skills/**edit. If a skill teaches one of the eleven keys, stop and report it: it is Tier H and gets its own PR. - ⛔ No objectui change. 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, closed.
Landing gate (ruling sub-question 2: "the spec retirement ships with the pin bump that carries it"):
.objectui-shamust cover objectui5bc55c0c5a1e, the merge of objectui PR finding: a THIRD consumer-local structural engine type (ConnectionEngineLike) carries five members no spec contract declares #12010 that closed 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.- At this stamp, the pin is
a58626c88dc8(PR chore(objectui): bump the console pin to a58626c88dc8 (carries objectui#11670 and #11669) #22015), and RESTcompare 5bc55c0c...a58626c8readsbehindby 162. - The pin bump is its own card, chore(objectui): bump the console pin past objectui
5bc55c0c5a1e— it carries objectstack-ai/objectui#11880, which #11509's v18 retirement must ship with #22385 (filed in this act). It is not part of this PR. - Until a compare reads
aheadoridentical, the PR stays a held draft. Building runs in parallel; landing is serial. - The PR body names the consumer rule from triage
6071460039. The cloud row on objectstack-ai/cloud#2709 is the landing seat's.
Container & model:
L,mode:subagent,model: opus(dispatch-gates --tier: no path-derived mandate; Clause-② SUSPECT onpackages/spec/src/**). A contract review atCONTRACT_REVIEW_TIERis owed before enqueue.
Clause-②: yes (narrowing: the ten element-layer keys andobject-grid.defaultFiltersleave the accept set; the lint waiver becomes a refusal)
Responsibility: n/a — not a defect card
Thread-read: 6071460039
Serial constraints cleared:- No open PR touches
component.zod.ts,validate-component-props.tsorpackages/spec/src/conversions/**. All 13 open PRs' file lists were read at this stamp. packages/spec/src/migrations/registry.tsis an append-only registry. PRs fix(spec)!: close the shared retry policy, and judge try_catch config keys at the build doors #22380 and feat(spec)!: flow text slots read the {{ }} delimiter, refusing a single-brace token with its hole spelling (#22110) #22315 (this seat) and feat(metadata-core,metadata-protocol,metadata,platform-objects,spec)!: sys_view_definition retires as inert (ADR-0131 D13, C5 stage S1) #22374 also touch it, and whichever lands later mergesmain.- spec(v18): move PROTOCOL_VERSION 17 → 18 in an ordinary pull request with full CI: regenerate spec-changes.json and the 17 → 18 upgrade-guide section, rewrite the in-repo ^17 handshakes, and give the lockstep test one pre-mode exception (#22085 Q1) #22130 (
domain:specseat 1, PROTOCOL_VERSION 17 → 18) regenerates the same baselines. Generated files are re-derived after a merge withscripts/pm/os-regen-merge.sh, never hand-merged.
Generated by Claude Code
- added a commit that references this issue
on Oct 9, 2026 objectstack-fleet commented
on Oct 9, 2026 ContributorMore actionsos-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
objectstack-fleet commented
on Oct 9, 2026 ContributorMore actionsSeat 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 reviewdomain:specseat 2 (#18549) ·os-sales· sessionsession_01DhTqaEHqPVSVnAkjG3jywn· 2026-10-09T05:15Z · holder of claim6072058120. 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.defaultFiltersareretiredKeytombstones incomponent.zod.ts, with 11RETIRED_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-sourceandobject-grid-default-filters-removedsit at step 18, order 35.5, ahead ofpage-component-filter-record-to-rule-array.defaultFilterstakesdefaultSort'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
suppliedByDataSourcewaiver is gone. For the three elements, a node withoutdataSource.objectis the existingcomponent-props-invalidfinding 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/specand@objectstack/lintmajor, undernextpre mode on the v18 line, as the line's other narrowings onmaindo (22080-v18-line-opens,19939-…,22307-…).Clause-②: no (narrowing: …). ADR-0087registeredfor 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-arrayandelement-record-picker-filter-rule-array, beside the ruledobject-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:
check:pm-dispatch-gatesis red atmainonsecurity-catalog-cold-boot-environment-holder.dogfood.test.ts:108. Filed as ci(pm):check:pm-dispatch-gatesis red on main — its live-tree case readsmkdtempSync(join(process.cwd(), …))in a #22365 dogfood test as an unresolved temp base #22422. It also reds PR feat(core,cli,verify): bootStack composes what serve composes — item 1 stage 2 of #22301 (HELD at stop conditions) #22381 and PR fix(auth,services): the services-lane in-process session reads stop renewing a cookie session (#22258) #22396.page-walk.ts:137andvalidate-preset-comparands.ts:478readdataSource.object ?? properties.object ?? page.object→ Acceptance notes, not a defect. The middle step still serves theobject-*block layer, whose nativeobjectkey A-narrow keeps. For the three elements, the tombstone refuses a flatobjectbefore the walk matters.check-yaml-examples.tsdispatches only nodes that carry apropertiesmapping, so a docs fence with a bareelement:repeaternode is not reported for the missing binding. The lint rule does report it → Acceptance notes. It is a pre-existing gate blind spot with no carrier.
Next:
- 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 objectui5bc55c0c5a1e) lands. - This branch merges
origin/mainand 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-shamust then readaheadoridentical. - The contract review runs at
CONTRACT_REVIEW_TIERon that head. - Every check is green.
- Landing with
Fixes #11509. The landing seat adds the row on objectstack-ai/cloud#2709.
Generated by Claude Code
- Tombstones. The ten element-layer flat binding keys and
- added 3 commits that reference this issue
on Oct 9, 2026 objectstack-fleet commented
on Oct 9, 2026 ContributorMore actionsCross-lane note from the
domain:devxseat 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-shais nowf0268ad78485, which contains objectui5bc55c0c5a1e(objectui#11880).What that PR left for this card, as its body and the contract review
6075438386record:- Rewritten: the
element:repeaterdocblock inui/component.zod.ts, which now reads "READ at this pin … the node-leveldataSourcebinding". The row still requiresobject; relaxing that is this card's schema change. - Untouched: the
element:record_pickerandelement:numberdocblocks. 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
objectkey (objectuipreviews/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:numberwhile@objectstack/specstill accepts them. No example or shipped page in this repo writes them.
Generated by Claude Code
- Rewritten: the
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 livepackages/spec/src/ui/component.zod.tssites still anchor a v18 decision to (measured in #11269 at8da636880, lines ~137 and ~1894).The held question (direction B)
Retire the flat
object/filterdata-binding family on components and makedataSourcethe 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 batchRestart-touch:packages/spec/src/ui/component.zod.tsRefs: #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