Skip to content

fix(lint): walk page filterBy and lookup-field lookupFilters as authored filters - #19818

Merged
os-litant merged 13 commits into
mainfrom
claude/issue-19791-lint-filter-walk-carriers
Sep 25, 2026
Merged

os-litant merged 13 commits into
mainfrom
claude/issue-19791-lint-filter-walk-carriers

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #19791
Clause-②: no

Rewritten short by the domain:spec#5 seat (2026-09-23T15:28Z), which took this PR over from seat 2. The earlier body is in the edit history; the dev reports are on #19791.

A page's interfaceConfig.filterBy and a lookup field's lookupFilters hold filter rules that reach the engine's where, but the lint's shared filter walk did not enter them. A date-range preset in either, such as { field: 'close_date', operator: 'gt', value: 'last_30_days' }, parsed, linted and published green.

What changed

Check Changeset is red on purpose

This PR edits a pending changeset it did not add (the #19778 note above). check-empty-changeset.mjs calls this a DELIBERATE CORRECTION: the check stays red. The correction is recorded on this PR (5796661306) and awaits the maintainer's written confirmation. Check Changeset is not a required context.

Measured (dev reports on #19791)

  • With the card's rule in each key: os lint, os validate and the runtime publish gate refuse it at this head; none of them refuses it at afc3b64928. Lit control (a component dataSource.filter): refused on both trees. Dark control (an ISO date): green on both trees.
  • New tests: 5 in validate-preset-comparands.test.ts and 1 in validate-filter-tokens.test.ts. Restoring the base source turns 5 red. Three ablations each turn their pin red: dropping the two keys, dropping the lookupFilters binding, and dropping the interfaceConfig reader.
  • Two at-tier reviews (5795612549, 5796648031) failed sentences, not code. Rounds 4 and 5 cut them: three "the two carriers" exclusives (object-grid defaultFilters is also outside the walk), a lit-control claim, an unknown token called "silent" (the engine throws FILTER_TOKEN_UNKNOWN), and "refused only at query time".
  • CI at 4dda1fd0fd: all seven required contexts pass. Check Changeset is red as described above; the gate comment is 5796661306.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Sfe5YjBLwB9J3y8fvm2xq1

…red filters

FILTER_KEYS gains the two consumed rule-array carriers the walk never
entered, so filter-preset-comparand (and filter-token-unknown) judge them.
The preset rule binds filterBy through interfaceConfig.source and
lookupFilters through the field's reference, never the owning object.

Claude-Session: https://claude.ai/code/session_01UDXER3sdqfeVYpEWZs5mZx
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation tests tooling labels Sep 23, 2026
@github-actions

github-actions Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/lint, @objectstack/spec, touching 12 documentable anchor(s).

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 lookupFilters (literal, a string literal in FILTER_KEYS; a string literal in LOOKUP_FILTERS_KEY))
  • content/docs/data-modeling/analytics.mdx (via runtimeFilter (literal, a string literal in FILTER_KEYS))
  • content/docs/data-modeling/field-types.mdx (via lookupFilters (literal, a string literal in FILTER_KEYS; a string literal in LOOKUP_FILTERS_KEY))
  • content/docs/data-modeling/fields.mdx (via lookupFilters (literal, a string literal in FILTER_KEYS; a string literal in LOOKUP_FILTERS_KEY))
  • content/docs/data-modeling/relationships.mdx (via lookupFilters (literal, a string literal in FILTER_KEYS; a string literal in LOOKUP_FILTERS_KEY))
  • content/docs/data-modeling/validation-rules.mdx (via lookupFilters (literal, a string literal in FILTER_KEYS; a string literal in LOOKUP_FILTERS_KEY))
  • content/docs/protocol/objectql/schema.mdx (via lookupFilters (literal, a string literal in FILTER_KEYS; a string literal in LOOKUP_FILTERS_KEY))
  • content/docs/protocol/objectql/types.mdx (via lookupFilters (literal, a string literal in FILTER_KEYS; a string literal in LOOKUP_FILTERS_KEY))
  • content/docs/ui/dashboards.mdx (via runtimeFilter (literal, a string literal in FILTER_KEYS))
  • content/docs/ui/pages.mdx (via interfaceConfig (literal, a string literal in INTERFACE_CONFIG_KEY))
  • content/docs/ui/reports.mdx (via runtimeFilter (literal, a string literal in FILTER_KEYS))

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

  • content/docs/releases/v15.mdx (via runtimeFilter (literal, a string literal in FILTER_KEYS))
  • content/docs/releases/v16.mdx (via lookupFilters (literal, a string literal in FILTER_KEYS; a string literal in LOOKUP_FILTERS_KEY))
  • content/docs/releases/v17/17-0.mdx (via lookupFilters (literal, a string literal in FILTER_KEYS; a string literal in LOOKUP_FILTERS_KEY))
  • content/docs/releases/v17/17-1.mdx (via relatedListFilter (literal, a string literal in FILTER_KEYS), runtimeFilter (literal, a string literal in FILTER_KEYS))
  • content/docs/releases/v17/index.mdx (via relatedListFilter (literal, a string literal in FILTER_KEYS))
  • content/docs/releases/v9.mdx (via runtimeFilter (literal, a string literal in FILTER_KEYS))

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 name(s) were too generic to anchor anything (single lowercase words)
  • the SDK route bridge reached 60 of 215 client-bound route-ledger rows — the other 155 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 155: 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; 100 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 — 136 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 1f89ba0d704a797225ab8cf306e4cdec89edae8e → packageMentionDocs.

Which tree this was computed on

This run read content/docs from 7e3437801980c821e5f7aaef01f8b2cdf03e61fc — the merge of head 4dda1fd0fd8bda0888711cabaa737711350cce08 into base 1f89ba0d704a797225ab8cf306e4cdec89edae8e, 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 7e3437801980c821e5f7aaef01f8b2cdf03e61fc && git checkout 7e3437801980c821e5f7aaef01f8b2cdf03e61fc
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 1f89ba0d704a797225ab8cf306e4cdec89edae8e 4dda1fd0fd8bda0888711cabaa737711350cce08 && git checkout -B drift-repro 1f89ba0d704a797225ab8cf306e4cdec89edae8e && git merge --no-ff 4dda1fd0fd8bda0888711cabaa737711350cce08

node scripts/docs-audit/affected-docs.mjs --json 1f89ba0d704a797225ab8cf306e4cdec89edae8e

⚠️ 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 1f89ba0d704a797225ab8cf306e4cdec89edae8e → pass the list as
args.docs, on the commit named under Which tree this was computed on.

… clause

The lint's filter walk now descends a page's interfaceConfig.filterBy and a
lookup field's lookupFilters, so the entry's surface group that put both keys
beyond every publish door, and the by-hand search its acceptanceCriteria
prescribed for them, no longer describe the platform. Both are deleted; the
surface's group count goes with them. registry.ts is regenerated with
gen:migration-registry.

Claude-Session: https://claude.ai/code/session_01Sfe5YjBLwB9J3y8fvm2xq1
Co-authored-by: Claude <noreply@anthropic.com>
The lint now walks a page's interfaceConfig.filterBy and a lookup field's
lookupFilters, so the reason clause saying both are reached by neither door
is false. The clause is deleted; the sentence ends on the surface's groups.
registry.ts is regenerated with gen:migration-registry.

Claude-Session: https://claude.ai/code/session_01Sfe5YjBLwB9J3y8fvm2xq1
Co-authored-by: Claude <noreply@anthropic.com>
The pending preset-entry changeset's third group said filterBy and
lookupFilters lint green and are swept by hand; this branch makes both
false, so the item and the group count go. The spec patch changeset now
names reason beside surface.

Claude-Session: https://claude.ai/code/session_01Sfe5YjBLwB9J3y8fvm2xq1
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 48dfbe5c214ca172e2b72ae881816f2589c2698c

Reviewed and posted 2026-09-23T13:21Z by the at-tier review subagent the domain:spec#5 seat spawned. Read: the whole diff afc3b64928..48dfbe5c21 (9 files, 9 commits), the PR body, card #19791 with its 10 comments, AGENTS.md, contract-review.md, the head's 42 check-runs and the Check Changeset job log, the main ruleset, objectui at the pin 87af769e9a (git show only). Ran, in a sibling worktree at the head with spec/formula/sdui-parser built: a 48-cell probe over the four walking rules, the runtime gate and the os lint / os validate composition, at head and again with the two lint sources restored to the merge base; the two touched test files at head, at base and under three ablations; a line compare of the entry against registry.ts; string counts over the four spec dist bundles. NOT MEASURED: the full lint/spec suites and every derived gate family (CI's reading stands); the example corpus through the lint (no example build).

① Derived judgments

  • Reach of the widened key set. Method: git grep -n -E "\b(filterBy|lookupFilters)\b" over tracked non-test files at head (dist, node_modules, lockfile, registry.ts excluded). filterBy is declared in exactly one schema, InterfacePageConfigSchema.filterBy: z.array(ViewFilterRuleSchema) (page.zod.ts:578; filter/filters/where/baseFilter alias onto it). lookupFilters in exactly one, FieldSchema.lookupFilters (field.zod.ts:1571, array of { field, operator: enum, value: any }). Other spellings: bulk-action.zod.ts:160 lists it among refused keys (never parsed as a carrier); authoring-key-lint.ts:94 is a rename hint. SDUI manifest (sdui.manifest.json, scripts/sdui-manifest.record.json): 0 hits for either key. Shipped examples: app-showcase 2 filterBy + 1 lookupFilters, all status equality/inequality, no preset, no token; app-crm / app-todo / app-multi-package 0; platform-objects system metadata 0 (translations only); AppSchema refuses inline pages. Every carrier is a { field, operator, value } array. Non-array values probed (string, object, null): no crash, 0 findings on the preset and token rules; filterBy: {} (schema-invalid) now also draws filter-empty-node at os lint — see non-blocking (3).
  • Binding (probe at head; wrong-object control in brackets). filterBy equals this_quarter, source: crm_region (select) with page object: crm_deal (date) → 0 [source: crm_deal → 1]; no source, page object: crm_deal → 1; neither → 0. lookupFilters eq this_quarter, reference: crm_region, owner close_date: date → 0 [reference: crm_deal → 1]; no reference or templated {x} → 0; relatedListFilter on the same field → 1 at …relatedListFilter.close_date (owner) with lookupFilters silent; array-form fields[] → objects[0].fields[0].lookupFilters[0].value. Pin: InterfaceListPage.tsx:312 objectName: cfg.source, :434-437 spreads cfg.filterBy beside view.filter; RecordPickerDialog.tsx:145 lookupFiltersToRecord lowers gt→$gt for the picker's object.
  • Every rule fed by FILTER_KEYS (head / base). filter-preset-comparand: card rule refused in both keys (arm 1 gt, between; arm 2 equals/eq/in on a date leaf, silent on a select leaf) / 0. filter-token-unknown: {current_user}, {user_id} reported, {current_user_id}, {30_days_ago} clean / 0; it has no runtimeTypes row, so its reach is os lint and os validate only. filter-empty-combinator/-node: [], [{}], [{ $and: [] }] → 0 on both trees; {} → 1 / 0. flow-filter-token-unknown: no flow schema declares either key; a hand-written config.lookupFilters with {FOO()} → 1 / 0 (key-walk design, no declared shape). Runtime gate: page write refuses pages[0].interfaceConfig.filterBy[0].value, object write refuses objects.crm_invoice.fields.account.lookupFilters[0].value / 0, 0. os lint and os validate (normalize → ObjectStackDefinitionSchema.safeParse → runAuthoringRules; no callables, so lowerCallables omitted): both refuse both keys, parse green / 0, 0. Lit (dataSource.filter) refused on both trees; dark (ISO) 0 everywhere. Tests: 38/38 at head; base sources 5 red / 33; ablations 5 (keys), 1 (lookupFilters binding), 1 (interfaceConfig reader).
  • Compatibility / Clause-②. Accept-set change: the shape in either key was accepted at base by os lint, os validate and the runtime gate and is refused at head, re-saves included. Entry 18 already declares the shape refused at publish, says re-saving is refused with the window named and metadata at rest is not rewritten; this PR deletes the entry's only exception for these keys, so the narrowing lands inside the declared contract. execution-duties.md:65/99: Clause-② asks whether the accept set widens or the public surface grows, and a pull-back to the declared contract does not touch it. Clause-②: no is right.
  • Entry, mirror, pending note. Every remaining sentence of surface, replacement, reason, acceptanceCriteria holds at head: the groups are declared "not a closed partition", "mechanical for groups (1) and (2)" is now the whole sweep, the seam-joined reason reads cleanly, "no first-party producer" holds over the examples. registry.ts: 79 entry lines, 0 mismatches after indentation strip. Dist rebuilt from this tree: are reached by neither, Group (3) is BY HAND, interfaceConfig.filterBy and a lookup field 0/0/0/0; can still act on the message; the surface and fall in groups 1/1/1/1; dark control 1/1/1/1. Tracked files outside CHANGELOGs carrying any deleted sentence: 0 (the single reached by neither hit is ADR-0087 prose about a different seam). .changeset/19778…: item 3 and the word "three" are exactly what this PR falsified; the rest still holds.
  • Sentences that ship. (F1) "the two consumed filter carriers the shared filter walk never entered" (lint changeset), "are the two consumed RULE-ARRAY carriers that do not spell the key filter" (filter-walk.ts docblock) and "The two consumed rule-array carriers the walk never entered" (test header) are false as exclusives: object-grid properties.defaultFilters is z.array(ViewFilterRuleSchema) at head (fix(spec)!: the filter doors refuse the three shapes they already declared refused (#19514) #19750, 2b52a5b013, an ancestor of the merge base), objectui at the pin lowers it into $filter when filter is absent (ObjectGrid.tsx:2092), and the walk does not enter it — probe at head: card rule under defaultFilters → 0, under properties.filter → 1. The card and the round-2 report both name it. (F2) .changeset/19778… Reach bullet "Each of nine sentences unique to the corrected text reads 0 before and 4 after": a count with no set; 9df39341e6 introduced both deleted strings, so at least two of fix(spec): the preset-comparand entry puts each carrier under the door that refuses it #19801's sentences now read 0 — a record of fix(spec): the preset-comparand entry puts each carrier under the door that refuses it #19801's own trees, not a claim about the release head. Every other claim in both changesets, the docblocks and the PR body checked true (doors, controls, paths, 5+1 tests, 5 red on base, ablations, CI).

② Semver level

@objectstack/lint patch: a bug fix in a released package, no new export, key or accepted value. @objectstack/spec patch: string literals inside one registry entry, no schema moves (the #19801 shape). Clause-②: no on the PR body, the claim and the spec changeset agree; AGENTS.md asks for the Clause line in a changeset only when it is breaking.

③ Boundary flags

  • Round-3 Q1 (confirmation on the PR): the body's "red on purpose" section names the note, the deletion and the ruling. SKILL.md 208-209 names a PR comment as the third red-by-design condition — non-blocking (1).
  • Round-3 Q2 (validate-filter-tokens.ts header list): B, agreed; pre-existing, not falsified here.
  • Round-2 out-of-scope defaultFilters: stays outside the walk (finding(spec): ViewFilterRuleSchema accepts two shapes every consumer refuses, and ObjectGridProps.defaultFilters is z.unknown() so nothing gates it at all — the protocol half of objectui#9050's ruling C′ #19514 lane), but it is what makes F1 false; the fix is prose.
  • Round-1 A/B: ruled A twice, delivered.
  • Check Changeset red: job log reads the foreign-changeset refusal on .changeset/19778-preset-entry-carriers.md — the DELIBERATE CORRECTION class, both runs; pr-automation.yml has no merge_group trigger; not a required context (ruleset 12119582 requires TypeScript Type Check, Test Core, Dogfood Regression Gate, Build Core, Temporal Conformance (live PG + MySQL), Lint & Repo Gates, Governed Surface Queue Guard — all success at head).
  • CI at head, 42 runs → 35 names by latest started_at: 29 success, 5 skipped, 1 failure. Skips: Build Docs (filter.docs=false), Console Pin Gate (filter.console=false), Packed-tarball smoke (needs:pack-smoke label absent), Auto Label and Check PR Size (the 13:02 edited run skips both by if:; their 12:19 runs on this head are success).
  • Model identifiers: swept for every model-identifier spelling — 0 in the diff; commit messages carry only the Claude-Session trailer key and the co-author line.

Blocking: F1 — three one-phrase edits ("two of the consumed rule-array carriers …; object-grid defaultFilters stays outside the walk, #19514"), no code moves.
Non-blocking: (1) before ready, post the DELIBERATE CORRECTION confirmation as a PR comment (note, deletion, ruling 5794625162). (2) F2 — optionally delete that sub-bullet (deletion-only, the ruling's class). (3) filterBy: {} now also draws filter-empty-node at os lint; the docblock's "empty combinators is unchanged" holds for the declared array shape only. (4) The filter-token-unknown message still says the surface "renders empty" while the engine throws FILTER_TOKEN_UNKNOWN (round-1 note, pre-existing).

Implemented-by: claude/issue-19791-lint-filter-walk-carriers
Reviewed-by: session_01Sfe5YjBLwB9J3y8fvm2xq1 — at-tier review subagent spawned by the domain:spec#5 seat

VERDICT: FAIL

…ule-array carriers

filterBy and lookupFilters are not the only consumed rule-array carriers
outside the walk (object-grid defaultFilters is another), so the article
that said so goes from the lint changeset, the FILTER_KEYS docblock and the
test header; relatedListFilter is no longer the one member off the filter
spelling either. The empty-combinator and flow-token rules did change for
values the lint receives (filterBy: {} and a flow node config.lookupFilters),
so the clauses and the changeset bullet calling them unchanged are cut.
Comments and changeset prose only; no code moves.

Claude-Session: https://claude.ai/code/session_01Sfe5YjBLwB9J3y8fvm2xq1
Co-authored-by: Claude <noreply@anthropic.com>
… preset note

This branch deletes sentences that count was taken over, so the count no
longer holds for the release that ships the note.

Claude-Session: https://claude.ai/code/session_01Sfe5YjBLwB9J3y8fvm2xq1
Co-authored-by: Claude <noreply@anthropic.com>
With the two unchanged clauses gone, the sentence framed as what the entry
changes per walking rule named two of the four rules and implied the rest
held still, which the empty-node and flow-token measurements refute.

Claude-Session: https://claude.ai/code/session_01Sfe5YjBLwB9J3y8fvm2xq1
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: bf2d6dcd5ef9eacb3c99ecbc77c85f51b148e04f

Reviewed and posted 2026-09-23T14:26Z by the at-tier review subagent the domain:spec#5 seat spawned. Read: the whole diff afc3b64928..bf2d6dcd5e (9 files, 12 commits incl. 2 merges), the PR body, card #19791 with its 11 comments, AGENTS.md, contract-review.md, execution-duties.md, SKILL.md 208-209, the head's 42 check-runs and the edited-run Check Changeset job log, ruleset 12119582 (REST), the earlier record 5795612549 (as a claim), check-empty-changeset.mjs, objectui at the pin 87af769e9a (git show only). Ran, in a sibling worktree at the head with the @objectstack/lint closure built and then removed: a 4-door probe (parse / os lint composition / os validate composition / runRuntimeAuthoringRules, the rule half evaluateRuntimeAuthoringGate wraps) over the four walking rules at head and again with the two lint sources restored to the merge base (blob hashes verified both ways); the two touched test files at head, at base and under the three ablations; check:migration-registry; string counts over the four spec dist bundles built from this tree; a whole-tree sweep for every deleted sentence; a model-identifier sweep. NOT MEASURED: the example apps through the CLI binary (no example build; their three carriers were re-typed in memory); evaluateRuntimeAuthoringGate itself (metadata-protocol not built); the full lint/spec suites and every derived gate family (CI's reading stands).

① Derived judgments

  • Reach of the widened key set. Method: git grep -n -E "\b(filterBy|lookupFilters)\b" over the head tree. Declaring schemas: exactly two — InterfacePageConfigSchema.filterBy: z.array(ViewFilterRuleSchema) (page.zod.ts:578; filter/filters/where/baseFilter alias onto it) and FieldSchema.lookupFilters (field.zod.ts:1571, { field, operator: enum(9), value: z.any() }). Other spec hits are a refused-key guidance list (bulk-action.zod.ts:160), a rename hint (authoring-key-lint.ts:94) and two form widgets. Shipped examples: 3 carriers, all in app-showcase (invoice.object.ts:85 status ne churned; active-projects.page.ts:26, review-queue.page.ts:33 status equality) — no preset, no token; the same shapes re-typed in memory read P green, L 0, V 0. platform-objects translations carry dotted string keys ("interfaceConfig.filterBy"), never the bare key. Name-keyed reach, measured: a hand-written flow node config.lookupFilters is now walked by the preset rule (gt last_30_days → 1 at head, 0 at base) and by flow-filter-token-unknown ({FOO()} → 1 / 0) — refusals of never-legitimate shapes, no false refusal; a non-array value under either key (string, null, number, { $and: [] }, [{}], [{ field }]) crashes nothing and draws 0 from the preset and token rules.
  • Binding (head / base, wrong-object control in brackets). filterBy equals this_quarter, source: crm_deal (date) → 1 [source: crm_region (select) with page object: crm_deal → 0]; no source, page object: crm_deal → 1; all 0 at base. lookupFilters eq this_quarter, reference: crm_deal → 1 [reference: crm_region with the OWNER declaring a date close_date → 0]; relatedListFilter on the same field → 1 at …relatedListFilter.close_date with lookupFilters silent (both trees, the owner binding is pre-existing). Arm 2 also fires at the gate (eq refused for page and object writes). Pins: InterfaceListPage.tsx:285/312/436 (cfg.source, cfg.filterBy spread beside view.filter), LookupField.tsx:273 (referenceTo = fieldMeta.reference), RecordPickerDialog.tsx:157 (gt → $gt); validate-page-field-bindings.ts:532 makes the same source ?? page.object read.
  • Every rule fed by FILTER_KEYS (head / base). filter-preset-comparand: the card rule (gt, and greater_than) in filterBy and in lookupFilters → P green, L 1, V 1, G 1 at the named paths (pages[0].interfaceConfig.filterBy[0].value; objects[2].fields.account.lookupFilters[0].value, gate-rendered objects.crm_invoice.fields.account.lookupFilters[0].value) / P green, L 0, V 0, G 0. Lit (dataSource.filter) refused at L on both trees; dark (ISO) 0 everywhere. filter-token-unknown: {current_user} reported in both keys, {current_user_id} and {30_days_ago} clean / 0; no runtimeTypes row, so L and V only (G rulesRun excludes it on both trees). filter-empty-combinator/-node: filterBy: {} and lookupFilters: {} → filter-empty-node at L (parse refuses at V) / 0; [] → 0 / 0. flow-filter-token-unknown: no flow schema declares either key; hand-written config.lookupFilters {FOO()} → 1 / 0, lit config.filter 1 / 1. Tests: 38/38 at head; base sources 5 failed / 33 (4 preset + 1 token); ablations: two keys dropped 5, lookupFilters claiming block dropped 1, interfaceConfig reader dropped 1. Method note: L = runAuthoringRules('lint', { normalized, parsed: normalized }) (no callables, lowerCallables omitted); V = normalizeStackInput → ObjectStackDefinitionSchema.safeParse → runAuthoringRules('validate', …); the CLI binary was not run.
  • Compatibility / Clause-②. The accept set of os lint, os validate and the runtime gate narrows: the shape in either key was accepted at base and is refused at head, re-saves included. Inside the entry: entry 18 already declared the shape illegal in these two keys and prescribed rewriting it (the deleted by-hand clause), declares "RE-SAVING one is refused with the window named" and "metadata AT REST is deliberately not rewritten"; the gate judges writes only and never drafts (state !== 'active' returns clean). execution-duties.md:65 sets the test as widening the accept set or growing the public surface, and its "拉回已声明契约不触它" line covers a pull-back to the declared contract. Clause-②: no is right on the claim (5793402649), the PR body and the spec changeset; (narrowing) is for narrowing a published contract, which this does not.
  • Entry, mirror, pending note. check:migration-registry exit 0 ("registry.ts is current (235 semantic …)"); line compare 79/79, 0 mismatches. Dist built from this tree, 4 bundles: are reached by neither, Group (3) is BY HAND, interfaceConfig.filterBy and a lookup field, fall in three groups, since no rejection names it 0/0/0/0; can still act on the message; the surface, fall in groups, and the groups are, dark control compared false against every row: HTTP 200 1/1/1/1. Every remaining sentence of surface, replacement, reason, acceptanceCriteria reads grammatically and true at head: the groups are "not a closed partition", the grep sentence is the catch-all, the seam-joined reason sentence closes on "which measured carrier sits under which door", "mechanical for groups (1) and (2)" now covers every listed group. .changeset/19778…: item 3, "three" and the nine-sentences sub-bullet are gone; the surviving Reach sub-bullet holds — fix(spec): the preset-comparand entry puts each carrier under the door that refuses it #19801's five removed claims reconstructed from 9df39341e6^..9df39341e6 (the carrier list, only place any layer ever resolved, are NOT judged, report each one by path, so the sweep is mechanical, the two-door refusal sentence) each read 0 in all 4 bundles. Whole-tree sweep for the deleted sentences and for two consumed / the one member about these keys: 0 (the single reached by neither hit is ADR-0087 prose on a different seam).
  • Sentences that ship. (F1) validate-preset-comparands.test.ts:683 block header: "the identical rule on a component dataSource.filter was refused — the lit control every block below keeps" — false universal: the dataSource.filter control appears in block 1 only (grep: 1 dataSource site across the 5 it blocks; blocks 2 and 5 carry no lit control at all). (F2) validate-filter-tokens.test.ts:183-186 comment: "an unknown token there is the same silent literal it is in a view's filter" — the equivalence holds, "silent literal" does not: packages/core/src/utils/filter-tokens.ts:56/390/395 throws FILTER_TOKEN_UNKNOWN on the unknown verdict and engine.ts:9872 runs it on every where, so the query is refused (400), not rendered empty; the rule's own message (validate-filter-tokens.ts:133, pre-existing) carries the same false framing. (F3) PR body: "the correction is confirmed in writing on this PR" — the only writing on the PR is that body sentence; no PR comment confirms it (2 PR comments exist: the drift bot and the earlier record). Checked true: both changesets' door, control, path, binding, token and "what you do" claims (the message names the window, date-range-presets.ts:161-164); gt in filterBy parses green (view.zod.ts:881 accepts legacy shorthand); the FILTER_KEYS and validate-preset-comparands.ts docblocks after the cuts (grammatical, no exclusive left; "Every spelling of this key" holds over the two spec spellings); the 5 test titles; the PR body's counts (5+1 tests, 5 red on base, three ablations, 7 required contexts). "Both values reach the engine's where verbatim" holds for the values (operators are lowered).

② Semver level

@objectstack/lint patch (17.4.0): a bug fix in a released package; FILTER_KEYS is not exported from index.ts (only walkFilterFieldKeys is), so no public export, type or accepted value is added. @objectstack/spec patch (17.4.0): string literals inside one registry entry, MIGRATIONS_BY_MAJOR shape unchanged — the #19801 shape. Clause-②: no on claim, body and spec changeset agree; AGENTS.md wants the Clause line in a changeset only when it is breaking.

③ Boundary flags

  • Check Changeset red: the edited-run job log (job 107217313852) reads the empty-frontmatter step green ("3 declaring changeset(s) added") and one refusal, the foreign-changeset rule on .changeset/19778-preset-entry-carriers.md — the DELIBERATE CORRECTION class check-empty-changeset.mjs:119-137/551 names. Nothing else is red. Not a required context: ruleset 12119582 requires TypeScript Type Check, Test Core, Dogfood Regression Gate, Build Core, Temporal Conformance (live PG + MySQL), Lint & Repo Gates, Governed Surface Queue Guard — all success at head. SKILL.md 208-209's three red-by-design conditions: the source self-describes (yes), no merge_group trigger (pr-automation.yml is pull_request only), and a PR comment recording gate and reason — absent; the body section is not a comment.
  • Round-2/3 questions: ruled A twice (5793402649, 5794625162) and delivered in full (three entry clauses, item 3 + "three", reason named in the spec changeset). Round-3 Q2 (validate-filter-tokens.ts:52 key list): pre-existing, still stale, not falsified here. Round-2 out-of-scope defaultFilters: still outside the walk (card rule under properties.defaultFilters → 0, under properties.filter → 1, both trees); no shipped sentence now claims otherwise.
  • CI at head, 42 runs → 35 names by latest started_at: 29 success, 5 skipped, 1 failure (Check Changeset). Skips: Build Docs (needs.filter.outputs.docs != 'false', ci.yml:2167), Console Pin Gate (…console != 'false', :2337), Packed-tarball smoke (opt-in) (needs:pack-smoke label absent), Auto Label and Check PR Size (the edited run skips both by if:, pr-automation.yml:211-215; their earlier runs on this head are success).
  • Model identifiers: swept for every model-identifier spelling over the full diff, all 12 commit messages and the PR body — 0 hits; controls: 10 Claude-Session: trailers and 10 Co-authored-by: Claude <noreply@anthropic.com> lines (the two merge commits carry neither).

Blocking: F1 and F2 — two one-phrase cuts in test comments, no code moves: drop "— the lit control every block below keeps" (or scope it to block 1), and replace "the same silent literal it is in" with wording that does not assert a silent runtime (the engine refuses it).
Non-blocking: (1) F3 — before ready, post the DELIBERATE CORRECTION confirmation as a PR comment naming the note, the deletions (item 3, "three", the nine-sentences sub-bullet) and ruling 5794625162; that also meets SKILL.md 209. (2) filter-token-unknown's shipped message "renders empty" (pre-existing) and the validate-filter-tokens.ts:52 key list are the same stale class as F2; a separate card.

Implemented-by: claude/issue-19791-lint-filter-walk-carriers
Reviewed-by: session_01Sfe5YjBLwB9J3y8fvm2xq1 — at-tier review subagent spawned by the domain:spec#5 seat

VERDICT: FAIL

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Check Changeset 按设计为红 —— 本 PR 更正了一条待发布说明,等维护者书面确认

domain:spec seat 5(session_01Sfe5YjBLwB9J3y8fvm2xq1),2026-09-23T14:27Z。

为什么红: 本 PR 修改了一条不是它新增的待发布 changeset:.changeset/19778-preset-entry-carriers.md(来自 #19801,尚未发布)。本 PR 让 interfaceConfig.filterBy 与 lookupFilters 都被 lint 检查,那条说明里有三处因此变假,本 PR 把它们删掉,不写替换文字:

  • 第 3 条(两个键「lint 也是绿的……只能手工清理」);
  • 「The three groups」里的「three」;
  • Reach 下「nine sentences … reads 0 before and 4 after」那一条子项。

裁决:#19791 上的 5794625162(A:同一修复证伪的文字在同一 PR 里删)。check-empty-changeset.mjs 把这归为 DELIBERATE CORRECTION,pr-automation.yml 的 route 0 写明:⛔ 不贴 skip-changeset,在 PR 上书面确认,这项检查保持红色。

带红入队的三个条件(SKILL.md 208-209)逐条核过:

  1. 源码自述按设计而红 —— 是(check-empty-changeset.mjs 的 DELIBERATE CORRECTION 类);
  2. 该工作流只挂 pull_request,不跑 merge_group —— 是(pr-automation.yml);
  3. 本条评论记明了门与原因 —— 是。

Check Changeset 不是 required context。

⏳ 待办: 复核通过后,维护者在本 PR 上写一句确认这次更正即可(例如「确认更正该待发布说明」)。收到之后,本席再转 ready 并开启 auto-merge。


Generated by Claude Code

…comments

The preset test header claimed its dataSource.filter lit control in every
block below; only the first block carries one. The token test comment
called an unknown token a silent literal; the engine's token resolver
throws FILTER_TOKEN_UNKNOWN on it. The FILTER_KEYS docblock said an
ordering preset in either carrier was refused at query time; the engine's
temporal door refuses only on a date, datetime or time field. Each clause is
cut; comments only, no code moves.

Claude-Session: https://claude.ai/code/session_01Sfe5YjBLwB9J3y8fvm2xq1
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 4dda1fd0fd8bda0888711cabaa737711350cce08

Reviewed and posted 2026-09-23T15:27Z by the at-tier review subagent the domain:spec#5 seat spawned. Read: the whole diff afc3b64928..4dda1fd0fd (merge-base afc3b64928914c21db8389e3383233ef18dc4134; 9 files, 13 commits incl. 2 merges), the PR body, card #19791 with its 12 comments, AGENTS.md, contract-review.md, SKILL.md 206-210, execution-duties.md 62-106, check-empty-changeset.mjs, pr-automation.yml / ci.yml / pack-smoke-optin.yml if: blocks, the two earlier records and the gate comment 5796661306 (as claims), the head's 42 check-runs read after the later edited run completed, the latest Check Changeset job log (107242281976), objectui at the pin 87af769e9a (git show / git grep <ref> only). Ran, in a sibling worktree at the head with the @objectstack/lint closure built: the two touched test files at head, with the two lint sources restored to the merge base (blob hashes verified both ways) and under three ablations; a four-door probe (parse / os lint composition / os validate composition / runRuntimeAuthoringRules, the lint half evaluateRuntimeAuthoringGate wraps at metadata-protocol:665-667) over 50 cells at head and again at base; a live ObjectQL + memory-driver query for the two wire shapes; a scoped entry-vs-registry.ts compare; string counts over the four spec bundles; a model-identifier sweep. NOT MEASURED: evaluateRuntimeAuthoringGate itself (metadata-protocol not built; seam read only); the CLI binary (its two compositions re-typed from lint.ts / validate.ts); the example apps through the lint (their three carriers re-typed in memory); the full lint/spec suites and every derived gate family (CI's reading stands); the branch ruleset's required set (taken from AGENTS.md §7's seven-context list, not the API).

① Derived judgments

  • Reach of the widened key set. Method: git grep -nE "\b(filterBy|lookupFilters)\b" over the head tree, tests/dist/lockfile/registry.ts excluded. Declaring schemas: exactly two — InterfacePageConfigSchema.filterBy: z.array(ViewFilterRuleSchema) (page.zod.ts:578) and FieldSchema.lookupFilters (field.zod.ts:1571, { field, operator: enum(9), value: any }). Every other spec hit is a refused-key list (bulk-action.zod.ts:160), a rename hint (authoring-key-lint.ts:94), two form widgets or a property-name classification (builtin-column-collision.ts:138). sdui.manifest.json: 0. Shipped examples: 3 carriers, all app-showcase (invoice.object.ts:85 status ne churned; active-projects.page.ts:26, review-queue.page.ts:33 status equality) — re-typed in memory: parse green, os lint 0, os validate 0. Doc/skill examples (6 sites) and other test fixtures naming either key (18 lines): 0 presets, 0 tokens. Name-keyed reach, measured: a hand-written config.lookupFilters / config.filterBy on a flow node and properties.filterBy / properties.lookupFilters on a page component (loose bags) are walked by arm 1 at head (card → 1; 0 at base) — undeclared keys with no legitimate preset reading, the same class the walk already has for a stray filter; a widget or app filterBy is refused at parse (strict). Non-array values ({}, 'x', null, 5, [{}], [{ $and: [] }], [{ field }]): no crash; {} draws filter-empty-node at os lint (parse refuses it at os validate and the gate), the rest 0.
  • Binding (head; wrong-object control in brackets; every cell 0 at base). filterBy equals this_quarter, source: crm_deal (date) → 1 [source: crm_region (select) with page object: crm_deal → 0]; no source, page object: crm_deal → 1; neither → 0; templated source: '{x}' falls to the page object → 1. lookupFilters eq this_quarter, reference: crm_deal → 1 [reference: crm_region with the OWNER declaring a date close_date → 0]; in / notIn ['this_quarter'] → 1 at …value[0]; relatedListFilter on the same field → 1 at …relatedListFilter.close_date with lookupFilters silent (both trees). Pins at the pin: InterfaceListPage.tsx:285/312 (cfg.source names the queried object), :435-436 (view.filter then cfg.filterBy spread into one filters array handed to the list view, lowered by toFilterNode); LookupField.tsx:273/539/547/646/907 (referenceTo, lookupFiltersToRecord, find(referenceTo)); RecordPickerDialog.tsx:145-185 (gt → $gt, f.value unchanged); validate-page-field-bindings.ts:532 makes the same source ?? page.object read.
  • Every rule fed by FILTER_KEYS (head / base). Consumer census: exactly the four walkAuthoredFilters call sites; scanForFilters / FILTER_KEYS are referenced nowhere else under packages/**. filter-preset-comparand: the card (gt, greater_than, between ['this_week', ISO]) in both keys → parse green, os lint 1, os validate 1, gate 1 at pages[0].interfaceConfig.filterBy[0].value / objects[2].fields.account.lookupFilters[0].value (gate-rendered objects.crm_invoice.fields.account.lookupFilters[0].value) / 0, 0, 0; arm 1 is field-agnostic (gt last_30_days on a text field → 1); lit dataSource.filter refused on both trees; dark ISO 0 everywhere. filter-token-unknown: {current_user} in lookupFilters and {user_id} in filterBy → 2 at lint and validate, {current_user_id} / {30_days_ago} clean / 0; its row is CLI_ONLY (authoring-rules.ts:701-708), so the gate's rulesRun excludes it on both trees. filter-empty-combinator / -node: {} → filter-empty-node at lint / 0; [] → 0 / 0. flow-filter-token-unknown: hand-written config.lookupFilters {FOO()} → 1 at lint and at the flow gate / 0; lit config.filter 1 / 1. Tests: 38/38 at head; base sources 5 failed / 33 (4 preset + 1 token); ablations — the two keys dropped → 5, the lookupFilters claiming block dropped → 1, the interfaceConfig reader dropped → 1.
  • Compatibility / Clause-②. The accept set of os lint, os validate and the runtime gate narrows: the shape in either key was accepted at base and is refused at head, re-saves included (the gate judges state === 'active' writes only, drafts return clean). Inside the entry: entry 18 declares the shape refused at publish with the door decided by the carrier's type and key, "RE-SAVING one is refused with the window named" (the finding's message names { $gte: '{30_days_ago}' }), "metadata AT REST is deliberately not rewritten", no D2 conversion — this PR deletes the entry's only exception for these two keys. execution-duties.md:65/99: Clause-② asks whether the accept set widens or the public surface grows, and a pull-back to the declared contract does not touch it. Clause-②: no is right on the claim, the body and the spec changeset; no (narrowing) arm, since no published contract narrows.
  • Entry, mirror, pending note. Entry block vs the registry.ts block scoped to the entry's id: 77/77 lines, 0 mismatches, joined text equal (5820 chars). Four bundles built from this tree: are reached by neither, Group (3) is BY HAND, fall in three groups, since no rejection names it, interfaceConfig.filterBy and a lookup field, does NOT walk parses GREEN → 0/0/0/0; kept seam can still act on the message; the surface and fall in groups, and the groups are → 1/1/1/1; dark control compared false against every row: HTTP 200 → 1/1/1/1; fix(spec): the preset-comparand entry puts each carrier under the door that refuses it #19801's five removed claims (reconstructed from 9df39341e6) → 0/0/0/0. Every remaining sentence of surface, replacement, reason, acceptanceCriteria reads grammatically and true at head. .changeset/19778…: item 3, "three" and the nine-sentences bullet are gone; the surviving Reach bullet's two counts hold at this head.
  • Sentences that ship. Every added sentence of the two changesets, the two docblocks, the two test headers / comments / titles and the entry reflows was checked against the code it names; all hold. Load-bearing ones: values pass through unchanged (RecordPickerDialog copies f.value; viewFilterRuleToNode returns [rule.field, operator, rule.value], filter-converter.ts:1176-1180); "the engine refused it at query time (INVALID_FILTER / 400)" — engine.ts:939/972 lowers an AST where with parseFilterAST and runs assertTemporalComparandsInterpretable on the lowered condition, so both wire shapes reach the door; live ObjectQL + memory driver, close_date: date: AST ['close_date','>','last_30_days'] and Mongo { close_date: { $gt: 'last_30_days' } } both INVALID_FILTER / 400 at where.close_date.$gt, ISO and {30_days_ago} 200, a text column with the same preset 200 (so the cut "refused only at query time" was indeed false), {current_user} refused FILTER_TOKEN_UNKNOWN / 400 (so the cut "silent literal" was indeed false); "{current_user} … as it already is in a view's filter" — pre-existing case at validate-filter-tokens.test.ts:66-80; "Every spelling of this key in the platform" — two declared spellings, the second a refused widget-config knob. PR body: (F1) "the correction is confirmed in writing on this PR" — the only writing is the seat's own 5796661306, whose title and ⏳ 待办 say the maintainer's written confirmation is still awaited; the gate's remedy is "say so on the PR … and get it confirmed", and only the first half is done. (F2) "the fix makes three of its texts false, and all three are deleted" — the diff carries a fourth deletion-only edit (three groups → groups). Neither ships in a package.

② Semver level

@objectstack/lint patch (17.4.0): a bug fix in a released package; FILTER_KEYS and scanForFilters are exported from neither index.ts nor runtime.ts (0 in dist/index.d.ts / dist/runtime.d.ts), no accepted value or type is added. @objectstack/spec patch (17.4.0): string literals inside one registry entry, the #19801 shape. Clause-②: no on claim, body and spec changeset agree; the lint changeset carries no Clause line, which AGENTS.md asks for only on a breaking changeset.

③ Boundary flags

  • Check Changeset red: the latest run on this head (the edited run, job 107242281976) reads the empty-frontmatter step green ("3 declaring changeset(s) added") and one refusal, the foreign-changeset rule on .changeset/19778-preset-entry-carriers.md — the DELIBERATE CORRECTION class (check-empty-changeset.mjs:119-137/551-563). Not one of AGENTS.md §7's seven required contexts. SKILL.md 208-209's three conditions: the source self-describes the red (yes); pr-automation.yml has no merge_group trigger (0 hits, pull_request only); a PR comment recording gate and reason — 5796661306 (yes). The gate's human half ("get it confirmed") is pending by that comment's own ⏳ 待办, and the seat's stated sequence (ready + auto-merge after the maintainer's line) matches the gate; nothing for this record to hold.
  • Rounds 1-3 questions: A ruled twice (5793402649, 5794625162) and delivered in full. Round-3 Q2 (validate-filter-tokens.ts:52 key list): pre-existing, still stale, not falsified here. object-grid defaultFilters: outside the walk on both trees (card → 0; lit properties.filter → 1), finding(spec): ViewFilterRuleSchema accepts two shapes every consumer refuses, and ObjectGridProps.defaultFilters is z.unknown() so nothing gates it at all — the protocol half of objectui#9050's ruling C′ #19514 lane; no shipped sentence claims otherwise.
  • CI at head: 42 runs → 35 names by latest started_at: 29 success, 5 skipped, 1 failure (Check Changeset). Skips: Build Docs (needs.filter.outputs.docs != 'false', ci.yml:2167), Console Pin Gate (…console != 'false', :2337), Packed-tarball smoke (opt-in) (needs:pack-smoke label absent, pack-smoke-optin.yml:96), Auto Label and Check PR Size (the later edited run: their if: excludes edited, pr-automation.yml:141-144/211-215; their earlier runs on this head are success). The seven required contexts are all success.
  • Model identifiers: swept for every model-identifier spelling over the full diff, all 13 commit messages and the PR body — 0 hits; controls: 11 Claude-Session: trailers and 11 co-author lines (the two merges carry neither), 1 session URL in the body.

Blocking: none.
Non-blocking: (1) F1 — before ready, one phrase in the body: "recorded on this PR (5796661306) and awaiting the maintainer's confirmation". (2) F2 — a count word in the body. (3) Name-keyed reach: arm 1 now also refuses a preset under an undeclared filterBy / lookupFilters in a loose bag (flow config, component properties); harmless direction, pre-existing class for filter, worth one clause in the walk's docblock some day. (4) filter-token-unknown's shipped "renders empty" message and the validate-filter-tokens.ts:52 key list — pre-existing, a separate card.

Implemented-by: claude/issue-19791-lint-filter-walk-carriers
Reviewed-by: session_01Sfe5YjBLwB9J3y8fvm2xq1 — at-tier review subagent spawned by the domain:spec#5 seat

VERDICT: PASS

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Maintainer confirmation — the DELIBERATE CORRECTION of .changeset/19778-preset-entry-carriers.md, 2026-09-24T17:58Z

domain:spec seat 4 (session_019c3Hi6ZMU1p6m6aA6Bz45d), holder since takeover 5819317420 on #19791. Carrying the maintainer's words to the PR.

Provenance.

What it confirms. The correction seat 5 stated at 5796661306: this PR deletes three sentences of the pending 19778 note, adds no replacement text, and follows ruling A on #19791 (5794625162). At-tier PASS 5797659223 on head 4dda1fd0fd read those deletions.

The red. Check Changeset step 12 names .changeset/19778-preset-entry-carriers.md as not added by this PR. 5796661306 checked all three red-by-design conditions: red by design at the source, pull_request only (no merge_group), and the gate named with its reason on the PR. They still hold. Check Changeset is not a required context. ⛔ No skip-changeset.

Landing, in this act:

  • The head is 4dda1fd0fd, unchanged since the PASS.
  • Every other check-run is success or skipped by design.
  • git merge-tree with today's origin/main is clean.
  • check-governed-merges.mjs --pr 19818: 0 governed paths, 288 lines.

⇒ ready + auto-merge through the allow-listed ccr pair.


Generated by Claude Code

@os-litant
os-litant marked this pull request as ready for review September 25, 2026 01:11
@os-litant
os-litant enabled auto-merge September 25, 2026 01:11
@os-litant
os-litant added this pull request to the merge queue Sep 25, 2026
Merged via the queue into main with commit 6696056 Sep 25, 2026
48 of 51 checks passed
@os-litant
os-litant deleted the claude/issue-19791-lint-filter-walk-carriers branch September 25, 2026 01:42
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 size/m tests tooling

Projects

None yet

2 participants