Repository navigation
fix(lint,metadata-protocol,metadata-core)!: os lint and the react-page props check refuse the retired list-view filterableFields by name, and its residue readers go - #24878
Conversation
…is reported by name, and its residue readers go Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D6F9axfoPzR7t8G1J7Ytzz
Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D6F9axfoPzR7t8G1J7Ytzz
…root Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D6F9axfoPzR7t8G1J7Ytzz
Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D6F9axfoPzR7t8G1J7Ytzz
…lterablefields-residue
📓 Docs Drift CheckThis PR changes 3 package(s): 8 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 8 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 17 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 536f482721b7102c61ea1fb4c0782f059b008b45 && git checkout 536f482721b7102c61ea1fb4c0782f059b008b45
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin a7199ef9744edf0c3ef0e381bb95a328545a3da9 43782da0bec22abe83f102b9d8edcfe2dfa12f72 && git checkout -B drift-repro a7199ef9744edf0c3ef0e381bb95a328545a3da9 && git merge --no-ff 43782da0bec22abe83f102b9d8edcfe2dfa12f72
node scripts/docs-audit/affected-docs.mjs --json a7199ef9744edf0c3ef0e381bb95a328545a3da9
|
…lterablefields-residue
…ed view-level api provider Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D6F9axfoPzR7t8G1J7Ytzz
Closes #24728
Clause-②: yes (narrowing)
What this does
@objectstack/spec18 retired the list view'sfilterableFieldswith aretiredKey()tombstone (#24640), soos validateandos buildrefuse it at the parse.os lintnever parses, and a react page's source is parsed against no list-view schema, so the lint package still treated the key as a live field position. This PR removes every residue reader on the card's list, and turns the two that judge authoring input into a refusal by name that carries the tombstone's prescription.os lint(list views).validate-list-view-field-refs.tsno longer walksfilterableFields(it is gone from the severity mapPOSITIONSand the dotted-path mapDOTTED_AXIS). Instead every list-view rung that still carries the key reports a new rule,list-view-key-retired(error, at...filterableFields), whatever the key names and whether or not the object binding resolves. Before, on a JSON/YAML/raw source, a valid name passedos lintsilently and a stale one was reported aslist-view-field-unknown. The prescription is READ fromListViewSchema's tombstone description ([REMOVED] ...), never retyped: the message carries its verdict head, the hint its "Delete the key" sentence, cut by the existingretiredKeyRemedyhelper, the way the permission-residue rule already does it. The rule id is exported from the package root asLIST_VIEW_KEY_RETIRED(the package's ownrule-id-barrel-exportstest requires it). The keys reported are one frozen list,LIST_VIEW_RETIRED_KEYS_REPORTED = ['filterableFields']: the retired keys this rule used to read as field positions.React-page props (done first, per triage).
REACT_FIELD_SPECS.ListView.fieldsno longer listsfilterableFields. The ListView block now carriesretiredSchemaProps, built from the same list and the same tombstone reader. Writing the prop is refused asreact-prop-retired(error) with "is retired and no prop replaces it" plus the tombstone's verdict head and remedy. The old "covers the legacy filterableFields shorthand" test is replaced: a valid name and a stale name both get exactly onereact-prop-retiredand nopage-field-unknown, the hint equals the remedy read from the tombstone, and auserFilterslit control is not refused.The other residue readers.
validate-field-consumers.ts:filterableFieldsleavesBEHAVIOUR_SEGMENTS.rule-explanations.ts:os explain list-view-field-unknownandlist-view-field-dottedno longer name it as a checked position.metadata-protocol/src/metadata-diagnostics.ts: the dead walk is deleted, folded into thetabsretirement comment beside it.metadata-core/src/object-schema-fls-references.ts:LIST_VIEW_NAME_LISTS.filterableFieldsis deleted. A body that still carries the key now goes the unclassified way and fails closed. Measured with a one-off probe againstapplyObjectSchemaMask(caller may readidandtitle): a list view whosefilterableFieldsnames the deniedsecret_scoreis dropped whole, and one naming onlytitleis served unchanged. Output:{"b":{"label":"B","columns":["title"],"filterableFields":["title"]}}. No denied name leaks.objectql/src/metadata-diagnostics.test.ts(the array-shaped-fields case now usesuserFilters.fields) and the lint field-refs tests (FULL_LIST_VIEW, the per-position case table, the dotted filter-position case).The ratchet.
RESIDUEinpackages/spec/src/ui/view-list-filterable-fields-retirement.test.tsis now empty. All four entries left in this PR. The new pin filepackages/lint/src/list-view-filterable-fields-retired.test.tsauthors the key as a key on purpose, so it joinsEXCLUDEDby name with its reason, beside the spec pin it twins. The walk's offender list is[]and its anti-vacuity floors still hold (38/38 tests pass).Classification (changeset
.changeset/24728-filterable-fields-residue.md)@objectstack/lintminor,@objectstack/metadata-protocolpatch,@objectstack/metadata-corepatch. BREAKING (an authoring narrowing), shippedminorunder the launch-window convention.os validate,os buildandos lintonly, not on the page save door. A react page writing the ListView element'sfilterableFieldsprop used to pass all three commands whenever its names resolved. It is now refused. On list views,os lintnow fails a raw source thatos validatealready refused.LIST_VIEW_KEY_RETIRED.Clause-②: yes (narrowing). That follows the precedent of the two list-view door refusals that added an exported rule id (list-view-object-outside-closure,list-view-object-unknown).Clause-②: no. It was written before the rule id existed, and this PR carries the corrected line instead of copying it.not-required (already-registered view-list-filterable-fields-removed, list-view-filterable-fields-retired). The key's tombstone, D2 conversion and D3 entry already exist (from spec(ui): ListViewSchema.filterableFields is described as the userFilters.fields shorthand, but its one renderer reads it as the Filter panel whitelist; retire or redefine (objectui#13047) #24640, same unreleased major), and this PR adds no key, conversion or stored shape. The changeset carries the FROM → TO table and the one-line fix.Verification (final head
7077ebc775, the merge oforigin/main81120caac8)pnpm --filter @objectstack/lint test: 151 files / 6994 tests passed.typecheck(tsc +check:test-typecheck): pass.5c3a09b412(before the merge, which touched neither package):pnpm --filter @objectstack/metadata-core test: 18 files / 780 passed, plus typecheck.pnpm --filter @objectstack/metadata-protocol test: 251 files / 20828 passed (3 files / 19 tests skipped), plus typecheck.pnpm --filter @objectstack/objectql typecheck: pass, andsrc/metadata-diagnostics.test.ts: 10/10.pnpm --filter @objectstack/spec exec vitest run src/ui/view-list-filterable-fields-retirement.test.ts: 38/38.pnpm --filter @objectstack/spec check:generated: "All 14 generated artifacts are up to date" (spec built first).node scripts/pm/dispatch-gates.mjs --commands(92 commands): all 92 run on7077ebc775, each exit 0, and--ranreconciliation answered "92 derived, 92 run, 0 NOT-MEASURED, 0 UNRUN". Among them:check:adr-0087-registration("ADR-0087 exemption (already-registered)"),check-changeset-no-major,check-empty-changeset,check:nul-bytesandcheck:cross-package-test-inputs.os lintregistry:runAuthoringRules('lint', { normalized })on an unparsed stack whose list view carriesfilterableFields: ['status']returns exactly onelist-view-key-retirederroratviews[0].list.filterableFields(pinned in the new test file). A spawnedos lintCLI run was NOT MEASURED: the CLI package was not built in this worktree.Acceptance notes
packages/lint/src/reference-integrity-suite.tscomments (around lines 56, 272 and 300) still listfilterableFieldsamong the positions the field-refs member walks. They are stale prose outside this claim's file surface, and no behaviour depends on them. Carrier: none.retiredKey()tombstones onListViewSchema(pageName,tabs,responsive,performance,striped,bordered,virtualScroll) are equally unjudged byos linton a raw source and by the react-page props check. They were never field positions in this rule, so nothing here ever gave them a wrong answer. Whether the renderer still reads any of them as a react prop is NOT MEASURED. Extending to them is one entry each inLIST_VIEW_RETIRED_KEYS_REPORTED. Carrier: none.os explainfor the two list-view binding verdicts, and the whole-collection docblocks say what is now true #24858 also editspackages/lint/src/rule-explanations.tsandvalidate-list-view-field-refs.test.ts. Whichever lands second mergesorigin/mainand keeps both sides. No other open PR touches these files (read over all 13 open PRs' file lists).Generated by Claude Code