Skip to content

feat(types)!: retire FilterUISchema.filters[].operator on the filter-ui node (objectui#10611) - #10760

Merged
objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-10611-filter-ui-operator-retired
Sep 27, 2026
Merged

objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-10611-filter-ui-operator-retired

Conversation

@objectstack-fleet

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

Copy link
Copy Markdown
Contributor

Fixes #10611
Clause-②: yes

What changes

FilterUISchema.filters[].operator is retired from the filter-ui node on both published faces and on the docs page (ADR-0049 enforce-or-remove). The renderer never read it.

  • TS face (packages/types/src/views.ts): the member is now operator?: never. Its docblock says why and carries a @deprecated tag.
  • zod mirror (packages/types/src/zod/views.zod.ts): the seven-member z.enum is now a retirementTombstone(). One guidance string serves as both the parse-time issue message and the .describe() metadata. The refusal is invalid_type at the entry's own path (filters.N.operator). No replacement key is named, because nothing in this component implements operators.
  • Docs (content/docs/components/complex/filter-ui.mdx): the Schema block no longer lists operator. A new short section, "Retired: filters[].operator", states the retirement in prose. The page adds no new fence and leaves the JSON Configuration block untouched.
  • Changeset: minor for @object-ui/types, with the breaking semantics stated. It is not major, because of the version-alignment rule.
  • Pin: packages/types/src/__tests__/filter-ui-operator-retired-10611.test.ts.
    • (a) Every retired enum member, plus greater_than and a nonsense id, is refused. The check runs at safeValidateSchema (the door objectui validate / objectui check run) and on the mirror, and expects ONE issue { code: 'invalid_type', path: ['filters', 1, 'operator'] }. The message equals the published describe string, and the key stays declared.
    • (b) Lit control: the same entries without operator parse at both doors.
    • (c) Control: an undeclared entry key is stripped in silence. That is why a tombstone was used and the member was not deleted.
    • (d) The TS twin: Equal pins plus one @ts-expect-error, judged by tsc -p tsconfig.test.json.

Measured before retiring (the card's stop condition)

The stop condition was a real producer that writes operator on a filter-ui filters[] entry, or a reader that honours it. None was found.

H1, declaration. Confirmed on origin/main 1422a920ed, the branch point. The TS member is in the FilterUISchema filters element type. The mirror is the z.enum(['equals', 'contains', 'startsWith', 'gt', 'lt', 'between', 'in']).optional() in the FilterUISchema filters element.

H2, no reader. Measured with a render probe, not a grep. The probe was a throwaway test file, deleted and not committed. It used a real SchemaRenderer and the real registry: a module-scope import '../index' of @object-ui/plugin-view. The node was one filter-ui with a number entry and a text entry, and ONLY filters[0].operator varied: absent / gt / greater_than / startsWith / between / zz_nonsense_op. Each reading was taken from:

  • the DOM before and after typing 7 and ab;
  • the host onChange calls;
  • the window event detail.

Result: 6 variants gave 1 distinct reading. The payload was { values: { qty: 7 } }, then { values: { qty: 7, name: 'ab' } }, and the host calls were the same records. There was no operator anywhere. Control: type: 'text' on the same entry gave a different reading.

Source side, as a corroboration and not as the instrument:

  • FilterUI.tsx has no operator token and no ...filter / ...schema spread. The entry is read only for type, field, label, placeholder and options.
  • git log -S operator over the file returns 0 commits. The lit control, -S notifyViewHandlerChannels over the same file, returns 1.
  • ⚠️ The checkout is shallow (the graft is at 328ad7a419), so this history reading covers that window only. The present-tree probe above is the load-bearing reading.

Producer census. Every in-repo filter-ui author was read, and none writes operator:

  • the catalog components-complex-filter-ui/filter-ui.json;
  • the registration defaultProps and designer inputs;
  • the phase2-schemas fixture;
  • the plugin-view tests;
  • the check-doc-expression-carriage control fixture.

Other places checked:

  • FilterUISchema importers: only plugin-view's FilterUI.tsx, plus tests.
  • The RecordPickerDialog renderFilterBar docblock bridge: it passes RecordPickerFilterColumn, whose members are field / label / type / options, with no operator.
  • skills/**: 0 filter-ui / FilterUI hits.
  • objectstack origin/main e2c4e12: filter-ui in 0 files (control: object-grid in 53). The one FilterUI mention is prose in an ADR.

H3, tombstone form. The filters[] element is a plain z.object. It strips an undeclared key and is neither .passthrough() nor strict. Deleting the member would therefore have dropped an authored value in silence. Pin block (c) measures this on a misspelling.

H4 / H5. The docs Schema block is rewritten. No designer input, skills text or example names the key, so nothing is split out.

Verification (at e0fdfb5647, the first commit; the code and test logic are byte-identical at the final head, see Patch round 1)

Command Reading
pnpm exec vitest run packages/types/src/__tests__/filter-ui-operator-retired-10611.test.ts 16 passed (16)
pnpm exec vitest run --maxWorkers=2 packages/types/ Test Files 246 passed (246), Tests 5343 passed (5343)
pnpm exec vitest run --maxWorkers=2 packages/plugin-view/ Test Files 51 passed (51), Tests 485 passed (485)
pnpm --filter @object-ui/types type-check (incl. tsc -p tsconfig.test.json) exit 0
pnpm exec turbo run build --filter='@object-ui/plugin-view^...' --concurrency=2 15 successful, 15 total
pnpm --filter @object-ui/plugin-view type-check (against the rebuilt dist) exit 0

Consumer direction. @object-ui/types is upstream, and its downstream consumer that types FilterUISchema is @object-ui/plugin-view alone. Both packages were run and both are green, as listed above.

Ablation and reverse verification. Each leg ran through ablation-replace.mjs (the anchor must hit, and the restore is proven by blob == HEAD and an empty git diff HEAD).

  • Mirror: the tombstone was reverted to the old enum. The pin went 10 failed / 6 passed: every (a) refusal and the one-string check went red, and (b), (c) and (d) stayed green. The file was restored to blob 9b06cc60f1de.
  • TS face: ?: never was reverted to the old union, and tsc -p tsconfig.test.json exited 2. It reported TS2344 on assertionOperatorRetired, TS2578 on the unused @ts-expect-error, and also TS2322 from zod-mirror-parity.test.ts on views.zod.ts#FilterUISchema (the parity ratchet sees the pair drift). The file was restored to blob 3a0237a738ed.
  • Cross-package: a probe const zzProbe10611: FilterConfig = { ..., operator: 'gt' } was planted in plugin-view and run through tsc --noEmit. It exited 2 with TS2322: Type 'string' is not assignable to type 'undefined', which proves plugin-view reads the rebuilt .d.ts. The file was restored to blob 651baa8e1956. The first attempt at this leg was refused by the tool (its replacement kept the anchor, so the mutation never landed). It is declared here and did not count.

Gates (each exit code captured before any pipe). Every one of these exited 0:

  • node scripts/check-changeset-presence.mjs
  • node scripts/check-changeset-no-major.mjs
  • node scripts/check-changeset-overwrite.mjs
  • node scripts/check-changeset-fixed.mjs
  • pnpm check:new-line-citations (0 new citations)
  • pnpm check:control-bytes
  • pnpm check:spec-symbols
  • pnpm check:test-path-roots
  • pnpm check:changeset-claims
  • pnpm check:pending-changeset-literals
  • pnpm type-check:coverage
  • pnpm check:doc-types
  • pnpm check:doc-fences
  • pnpm check:doc-example-ids
  • pnpm docs:check-links
  • node scripts/check-doc-expression-carriage.mjs
  • pnpm check:component-surface-parity
  • pnpm check:designer-field-key-parity
  • pnpm check:prompt-keys
  • pnpm check:handler-key-reads
  • node scripts/check-governed-queue-guard.mjs --test over the five paths, which answered NOT GOVERNED.

ESLint, as a proven narrowing. The run was eslint --no-inline-config --format json over the three lintable touched files (views.ts, views.zod.ts, the pin). Three facts make this narrowing a measurement:

  • The population is the root eslint.config.js, which packages/types' eslint . resolves to.
  • The JSON output counts 3 files, 0 errors, 6 warnings. All six are pre-existing no-explicit-any hits on untouched views.ts members, and this diff adds no any.
  • The config has no parserOptions.project / projectService, so type-aware linting is off and this diff cannot move a verdict on an untouched file.

Patch round 1 (final head 671407f3fb)

The at-tier review 5853796261 of e0fdfb5647 said FAIL on prose only. The changeset and the pin header said a nonsense operator id 「type-checked, parsed green」, which was false: the old seven-member enum refused it (invalid_value), and the TS union did not admit it. REWORK 5853806677 asked for exactly that fix.

  • Commit 8eb899fd9d rewrites the two texts. operator: 'gt', a member of the old enum, type-checked and parsed green; a nonsense id was refused and did not type-check; and both rendered and emitted what a filter without it does. The emit sentence is now exact: a host onChange function receives the bare record, and only the authored window event's detail is { values }. The pin's AUTHORED docblock now says the render reading sampled a subset. Every changed pin line is a comment, and the changeset front matter is byte-identical.
  • Commit 671407f3fb merges origin/main 0896838deb, with no conflict and no hand edit.
  • Re-run at 671407f3fb, each exit 0:
    • the pin, 16 of 16;
    • packages/types/, 246 files and 5343 tests;
    • pnpm --filter @object-ui/types type-check;
    • check-changeset-presence, check-changeset-no-major, check:changeset-claims, check:new-line-citations and check:control-bytes.
  • The at-tier delta re-review 5856250843 of 671407f3fb says PASS. CI at that head: 40 success, 3 skipped.

Acceptance notes

  • NOT MEASURED locally: pnpm check:doc-snippets, pnpm check:doc-examples (exit 2, precondition not met). They need the 34-package build their --build-filter names. The fence this PR edits is plaintext, and it is the one block check:doc-fences lists for this file in its declared debt (unchanged at 1), so it is outside the snippet gate's judged population. CI runs both.
  • Not applicable: the Spec Main Shape Gate. FilterUISchema is not spec-derived: @objectstack/spec does not name filter-ui, and the diff adds or moves no spec import. check:spec-symbols is green.
  • Not owed and not run: check:sdui-registration-pins and check:readme-exports. They need a console build or a whole-tree build, and the diff touches no registration and no README.
  • Observation: the docs Schema block's type union omits multi-select, which both faces declare and FilterUI renders. It under-teaches but invites no wrong metadata. It is pre-existing and outside this card. The director seat's review record 5856250843 attaches a carrier card for it.

Session: https://claude.ai/code/session_014fWVhLzhxR8qrFsJ5o8TYW


Generated by Claude Code

…ui node

filter-ui never read a per-filter operator: the renderer picks the control
from `type` and emits `{ values }` only, with no matching of its own. The key
is now a `?: never` tombstone on the TS face and a retirementTombstone() on
the zod mirror, refused by name at the entry's own path. The docs Schema
block drops it and states the retirement.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014fWVhLzhxR8qrFsJ5o8TYW
@github-actions

github-actions Bot commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

changeset-claim-re-read

⚠️ 6 pending changeset(s) describe a file this change touches

Their bodies publish verbatim into the CHANGELOG at the next release, so this is a request to re-read them against your diff — addressed here because you are the one seat that can answer it without re-deriving anything.

⛔ Nothing here blocks, and nothing here is a verdict on your change. This gate exits 0, is not a required context, and judges name resolution, never meaning: it asked whether a pending body names a file you touched. "Is this sentence still true?" is the one question it will not answer, and the one you are being asked to answer.

.changeset/6594-headercolor-mirror-enum.md

  • names packages/types/src/views.ts → packages/types/src/views.ts — edited by this change

    The nearest precedent is objectui#5853 (.changeset/5853-tablecolumn-type-canonical-union.md), which narrowed TableColumn.type on the same three-ends pattern and exported a TABLE_COLUMN_TYPES tuple for the zod mirror to build its enum from. That shape is not available here and the difference is structural, not a preference: packages/types/src/views.ts is a type-only module, so a tuple there would add a runtime export to the package barrel (a value export cannot ride the barrel's export type block) and a runtime import edge from the zod entry into views.js. finding(types): TableColumn.type disagrees three ways — interface declares 8 literals, zod mirror accepts any string, renderer's live read set handles values outside the union via an as any cast #5853 had a second reason to export — producers needed its normalizeTableColumnType() at their emit seam — and headerColor has no producer that needs a runtime value. The literals are therefore written on each half and the anti-drift guarantee is carried by the pin above, which also covers the third end a shared tuple could not reach: the renderer, in a package @object-ui/types must not depend on.

.changeset/7287-resolve-title-field-shared-ladder.md

  • names views.ts → packages/types/src/views.ts — edited by this change

    def.primaryField — a DetailViewSchema key (@object-ui/types views.ts), read off an OBJECT def and ranked ABOVE the canonical nameField ADR-0079 Phase 2 made the pointer (AGENTS.md Commandment #0.1). No producer can put it there: @objectstack/spec's object schema is a strictObject that answers unrecognized_keys: ['primaryField'], and ObjectSchema.create() throws — which is why objectstack#6326 deleted the identical read from two lint rules. A census across both repos found zero object payloads carrying it (the only writers are three test fixtures), and primaryField appears in zero files of the shipped @objectstack/spec@17.2.0 dist against 68 for nameField. Same shape as the undeclared objectDef.titleField read objectui#6531 measured and Five more consumer-side reads of the undeclared object-level titleField survive #6531 — in ObjectView view-config fallbacks and a useRecordSearch memo key #6557 removed. DetailViewSchema.primaryField is untouched and still honoured by DetailView's own header — it is a view key, and on a view it is legitimate.

.changeset/7344-handler-string-any-mirrors.md

.changeset/7586-primary-field-consumer-reads.md

  • names views.ts → packages/types/src/views.ts — edited by this change

    primaryField is a DetailViewSchema key (@object-ui/types views.ts) — a view key, which DetailView.resolveDisplayTitle reads off schema and is welcome to. Read off an object def it is undeclared: @objectstack/spec's object schema is a strictObject answering unrecognized_keys: ['primaryField'], and ObjectSchema.create() throws. primaryField appears in zero files of the shipped @objectstack/spec@17.2.0 dist, against 68 for the canonical nameField. objectstack#6326 removed the identical read from two lint rules; objectui#7287 / PR fix(plugin-detail): resolveTitleField delegates to the shared ADR-0079 ladder #7585 removed it from resolveTitleField. These two survived it — and three of this repo's own changelogs already called the probe "not a spec property — always undefined" while the code kept honouring it.

.changeset/7735-zod-mirrors-stop-authoring-defaults.md

  • names views.zod.ts → packages/types/src/zod/views.zod.ts — edited by this change

    What changed. All 41 .default() call sites under packages/types/src/zod/ are removed — layout.zod.ts 22, crud.zod.ts 11, form.zod.ts 5, views.zod.ts 2, app.zod.ts 1. @object-ui/components reconciles the third face objectui#8229 found: flex's registration defaultProps.align seeded 'center', the value its own renderer never applies, so a designer-made node laid out differently from a hand-authored one; it now seeds 'start'.

.changeset/9511-record-id-is-a-string.md

  • names views.ts → packages/types/src/views.ts — edited by this change

    The three authorable keys, each on BOTH faces. ObjectFormSchema.recordId (objectql.ts + zod/objectql.zod.ts), DetailViewSchema.resourceId (views.ts + zod/views.zod.ts) and DetailSchema.resourceId (crud.ts + zod/crud.zod.ts). ⚠️ The crud pair is DetailSchema, not DetailViewSchema, and it reaches the same renderer — not by symbol but by data flow: plugin-detail registers the 'detail' node type onto DetailView. A read that follows TypeScript symbols alone finds two keys and is incomplete.

  • names zod/views.zod.ts → packages/types/src/zod/views.zod.ts — edited by this change

    The three authorable keys, each on BOTH faces. ObjectFormSchema.recordId (objectql.ts + zod/objectql.zod.ts), DetailViewSchema.resourceId (views.ts + zod/views.zod.ts) and DetailSchema.resourceId (crud.ts + zod/crud.zod.ts). ⚠️ The crud pair is DetailSchema, not DetailViewSchema, and it reaches the same renderer — not by symbol but by data flow: plugin-detail registers the 'detail' node type onto DetailView. A read that follows TypeScript symbols alone finds two keys and is incomplete.

Read the paragraph, not the line: both false halves of the objectui#8617 claim sat in one paragraph, and correcting either alone would have left it asserting the same wrong thing.

If a claim did go false, correct the body. That is precedented and prose-only, frontmatter untouched; check-changeset-overwrite.mjs will report the correction as its own case 2 ("correcting a declaration on purpose … legitimate"), which is the intended shape — one gate asks for the read, the other records the write.

Not covered, stated so nobody reads this as more: a born-false claim that spells no line address at all (objectui#9495 coordinated one by ORDINAL — "a grep finds that member first" — and deciding that means reading what the sentence means), a claim spelled as a symbol or a package rather than a backticked file name, and a file named ambiguously.

Compared the checked-out tree with 0896838de (merge-base with origin/main): 4 file(s) changed outside .changeset/, read against 1576 pending declaration(s) that publish a body (2164 pending in total). · run

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 329 chunks) 3066.1 KB 3104.5 KB
Main entry chunk (gzip) 148.3 KB 350 KB
Entry file index-DjcehrjV.js —
Status PASS —

The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it.


📦 Bundle Size Report

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 16.57KB 6.15KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
auth (ActiveOrganizationStorage.js) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.17KB 10.58KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.39KB 1.21KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 8.52KB 3.45KB
auth (index.js) 3.63KB 1.64KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 27.13KB 7.95KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 554.92KB 132.66KB
core (index.js) 9.52KB 3.79KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 223.93KB 62.31KB
fields (index.js) 259.29KB 65.64KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 2.59KB 1.22KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.24KB 2.27KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.40KB 12.91KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 39.28KB 11.09KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 6.62KB 2.45KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 5.52KB 2.10KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 13.52KB 4.88KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.24KB 2.16KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.33KB 3.07KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 16.01KB 3.93KB
plugin-calendar (index.js) 51.65KB 14.69KB
plugin-charts (index.js) 82.37KB 22.57KB
plugin-chatbot (index.js) 198.40KB 47.22KB
plugin-dashboard (index.js) 134.11KB 35.62KB
plugin-designer (index.js) 216.25KB 44.39KB
plugin-detail (index.js) 233.23KB 61.74KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 157.08KB 40.13KB
plugin-gantt (index.js) 169.75KB 41.96KB
plugin-grid (index.js) 218.12KB 59.72KB
plugin-kanban (index.js) 48.43KB 15.11KB
plugin-list (index.js) 114.70KB 28.42KB
plugin-map (index.js) 22.90KB 7.62KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.55KB 11.99KB
plugin-timeline (index.js) 30.91KB 9.05KB
plugin-tree (index.js) 10.58KB 3.72KB
plugin-view (index.js) 87.83KB 22.01KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.66KB 3.50KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 116.21KB 38.14KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.03KB 1.86KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.78KB 2.09KB
sdui-parser (codegen.js) 6.58KB 2.74KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 5.78KB 2.56KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (kanban-quick-add.js) 3.89KB 1.87KB
sdui-parser (parse.js) 25.28KB 7.80KB
sdui-parser (provenance.js) 3.66KB 1.82KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 18.27KB 6.20KB
types (ai.js) 4.11KB 2.06KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 1.00KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.93KB 1.49KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 4.74KB 2.25KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 5.00KB 2.39KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 2.52KB 1.31KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 17.15KB 6.32KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: e0fdfb5647ed51ed65d51e0bc6b5aec454379e71

① Derived judgments

  • Refusal at the door. objectui validate and objectui check call safeValidateSchema (packages/cli/src/commands/validate.ts, check.ts), which is AnyComponentSchema.safeParse; the filter-ui literal selects FilterUISchema, whose filters[] element now carries retirementTombstone(guidance) = z.never({ error: guidance }).optional().describe(guidance). Probe on zod 4.4.3 (the pinned version): operator set to gt, greater_than or zz_nonsense_op is refused as exactly one issue { code: 'invalid_type', path: ['filters', 1, 'operator'] } with message === description. The message names the card, why nothing reads the key, and the remedy (remove it). The pin's block (a) asserts the same envelope at both doors; the pin matches the CI unit include (packages/**/*.test.ts) and all eight Test shards are green.
  • Strip vs tombstone. The element is z.array(z.object({...})), not .passthrough() and not strict; probe: a misspelled operatr parses green and is gone after parse (keys ['field','type']). So a plain deletion would have been a silent accept; the tombstone is the right form, consistent with the body / children tombstones already on the same schema and with the helper's own docblock.
  • Producer / reader census (re-derived, lit controls). FilterUI.tsx reads entries by name only (type, field, label, placeholder, options); there is no ...filter or ...schema spread, and operator lives on an array element, so the SchemaRenderer node-key spread cannot carry it separately. grep operator in packages/plugin-view/src hits only view-filter rules ({ field, operator, value } on named views / FilterBuilder), a different vocabulary. Every in-repo filter-ui author (catalog filter-ui.json, registration defaultProps and inputs, phase2-schemas, RecordPickerDialog bridge whose columns are field/label/type/options, expression-carriage fixture, docs) writes no operator. objectstack origin/main e2c4e125: filter-ui 0 files, control object-grid 56; FilterUISchema 0 hits. No producer, no reader; the stop condition did not fire.
  • Docs. The Schema block now lists field / label? / type / options? / placeholder?, all true to the TS face. The "Retired" prose is true: the renderer emits via notifyViewHandlerChannels(onChange, schema.onChange, nextValues, { values }), and the key is refused when validated.
  • Pin can fail; ablations cohere. 16 tests = 9 it.each + 2 + 2 + 1 + 2. Mirror reverted to the enum ⇒ 9 refusals fail, the one-string test throws on issuesOf(r)[0], "stays DECLARED" passes ⇒ 10/6 as claimed. TS reverted ⇒ TS2344 on assertionOperatorRetired, TS2578 on the unused directive, parity TS2322 on views.zod.ts#FilterUISchema (the ratchet row exists) all follow. Cross-package TS2322 string → undefined is the expected widened message.
  • Scope. Five files, all inside the claim's file surface; FilterUI.tsx untouched. All 43 check runs are success or path-skipped; every required context (Lint, Type Check, Build & E2E, Build Docs, Changeset Declaration, Test, Spec Main Shape Gate, Governed Surface Queue Guard) is success. Merge base 1422a920ed as the PR body states.
  • Defect (blocking, prose). Changeset line "so operator: 'gt', or a nonsense id, type-checked, parsed green through objectui validate" is born false for the nonsense id: the pre-change mirror was z.enum([...]) and the TS member the same union, so zz_nonsense_op / greater_than were refused (invalid_value, probe above) and did not type-check; only the render reading was identical. The same false clause is in the pin header ("type-checked, parsed green"). The views.ts docblock ("rendered and emitted exactly what a filter without it does") is the true form.
  • Nit, non-blocking: "emits { values } only (to a host onChange function and to the authored window event)" — the host function receives the bare record; only the window detail is { values }. Substance (no operator anywhere) holds.

② Semver level

minor for @object-ui/types with a BREAKING banner, major refused per the version-alignment rule; Changeset Bump Policy, Changeset Declaration and Changeset Fixed Group Check all green. Every other changeset sentence is true (seven-member enum, plain object strips, invalid_type at filters.N.operator, no replacement key, one-time census recorded on the PR, pin path exists). The one false clause is the "nonsense id … type-checked, parsed green" sentence above; because a changeset publishes verbatim into the CHANGELOG and published CHANGELOG paragraphs are never re-addressed, it is listed as blocking.

③ Boundary flags

  • (a) The model-named Co-Authored-By: Claude Opus 5.5 trailer cannot reach main. Ruleset main: merge_queue.merge_method = SQUASH; repo settings squash_merge_commit_title = PR_TITLE, squash_merge_commit_message = PR_BODY; the PR body carries no model name. Empirical control: PR feat(types,core,data-objectstack)!: the three surviving record ids are strings (objectui#10078) #10733's four commits all carried that exact trailer and its squash 7b395d8c56 on main carries only the author-derived Co-authored-by: Claude <noreply@anthropic.com> that GitHub appends to every squash here; a grep of the last 300 main commits finds zero model-named trailers. The trailer survives only in the PR's own commit, which the branch deletion after merge retires.
  • (b) multi-select missing from the docs type union pre-exists on main (docs line lacks it, views.ts has it) and is outside the card, so deferring it was correct; it under-teaches and invites no wrong metadata. But "carrier: none" means nothing owns it now — the PM seat should file a docs card or it is lost.
  • Other: the PR is correctly still draft (dispatched-PR rule ②); NOT GOVERNED paths; Fixes #10611 closes only the intended card.

Implemented-by: claude/issue-10611-filter-ui-operator-retired
Reviewed-by: session_014fWVhLzhxR8qrFsJ5o8TYW

Blocking: (1) .changeset/10611-filter-ui-operator-retired.md clause "operator: 'gt', or a nonsense id, type-checked, parsed green through objectui validate" is false for the nonsense id (old enum refused it with invalid_value; old union did not type-check it) — restate as: 'gt' type-checked and parsed green, a nonsense id was refused by the enum, and both rendered identically; (2) the same clause in the pin header of filter-ui-operator-retired-10611.test.ts. Prose only; no code or test logic change needed.

VERDICT: FAIL


Generated by Claude Code

… truthfully

The changeset and the pin header said an authored `operator: 'gt'`, "or a
nonsense id", type-checked and parsed green before the retirement. That is
false for the nonsense id: the old mirror was a seven-member z.enum and the
old TS member the same union, so a non-member was refused (invalid_value) and
did not type-check. Both now say that 'gt' type-checked and parsed green, a
nonsense id was refused by the enum, and both rendered and emitted exactly
what a filter without it does.

The emit sentence is made exact too: a host onChange function receives the
bare field -> value record; only the authored window event's detail is
{ values }. The AUTHORED docblock no longer credits the one-time render
reading with values it did not sample.

Prose and comments only; no code or test logic changes, and the changeset
front matter is byte-identical.

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

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 329 chunks) 3066.4 KB 3104.5 KB
Main entry chunk (gzip) 148.3 KB 350 KB
Entry file index-Bc0YniPQ.js —
Status PASS —

The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it.


📦 Bundle Size Report

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 16.57KB 6.15KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
auth (ActiveOrganizationStorage.js) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.17KB 10.58KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.39KB 1.21KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 8.52KB 3.45KB
auth (index.js) 3.63KB 1.64KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 27.13KB 7.95KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 554.94KB 132.67KB
core (index.js) 9.57KB 3.81KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 223.93KB 62.31KB
fields (index.js) 259.29KB 65.64KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 2.59KB 1.22KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.24KB 2.27KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.40KB 12.91KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 39.28KB 11.09KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 6.62KB 2.45KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 5.52KB 2.10KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 13.52KB 4.88KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.24KB 2.16KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.33KB 3.07KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 16.01KB 3.93KB
plugin-calendar (index.js) 51.65KB 14.69KB
plugin-charts (index.js) 82.37KB 22.57KB
plugin-chatbot (index.js) 198.40KB 47.22KB
plugin-dashboard (index.js) 134.11KB 35.62KB
plugin-designer (index.js) 216.25KB 44.39KB
plugin-detail (index.js) 233.23KB 61.74KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 157.44KB 40.24KB
plugin-gantt (index.js) 169.75KB 41.96KB
plugin-grid (index.js) 218.12KB 59.72KB
plugin-kanban (index.js) 48.43KB 15.11KB
plugin-list (index.js) 114.70KB 28.42KB
plugin-map (index.js) 22.90KB 7.62KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.55KB 11.99KB
plugin-timeline (index.js) 30.91KB 9.05KB
plugin-tree (index.js) 10.58KB 3.72KB
plugin-view (index.js) 87.83KB 22.01KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.66KB 3.50KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 116.21KB 38.14KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.03KB 1.86KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.78KB 2.09KB
sdui-parser (codegen.js) 7.50KB 3.05KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 6.16KB 2.71KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (kanban-quick-add.js) 3.89KB 1.87KB
sdui-parser (parse.js) 25.28KB 7.80KB
sdui-parser (provenance.js) 3.66KB 1.82KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 18.27KB 6.20KB
types (ai.js) 4.11KB 2.06KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 1.00KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.93KB 1.49KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 4.74KB 2.25KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 5.00KB 2.39KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 2.52KB 1.31KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 17.15KB 6.32KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review ABSENT at the new head 671407f3fb, so this PR stays draft and out of the queue. domain:spec#1 @ objectui · session_014fWVhLzhxR8qrFsJ5o8TYW · 2026-09-27T10:56Z.

  • Where the PR stands. The at-tier record 5853796261 says FAIL at head e0fdfb5647, on prose only: a changeset clause and the pin header wrongly said a nonsense operator id type-checked. The prose patch round (REWORK 5853806677, then the dev's report on the card) moved the head to 671407f3fb. That round rewrites those two texts, makes the emit sentence exact and merges main. CI at 671407f3fb is green on every required context.
  • Why no record. The isolated at-tier delta re-review could not start: its model returned HTTP 429, 「reached your Fable limit」. Under the contract-review rule, a reviewer that cannot start means the review is absent. The PR carries needs:contract-review and stays draft, out of the queue. The only bypass is the maintainer reviewing it personally.
  • Next. The seat retries the delta re-review once the at-tier quota answers again. The review is ⛔ never waived, and it is ⛔ never done below tier.

Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 671407f3fb07611e0de767ce55c39ee7693bae88

① Derived judgments

Scope of this record: the hop e0fdfb5647 → 671407f3fb after record 5853796261 (FAIL, prose only) — commit 8eb899fd (two files, +21 / −13: the changeset and the pin's header comments) and merge commit 671407f3fb of origin/main 0896838deb, whose tree equals git merge-tree of its two parents, so it carries no hand edit. The three-dot file set is the same five files as at the FAIL head; the increment grew by the eight prose lines of 8eb899fd (+217 → +225). The FAIL record's derived judgments on the unchanged code — refusal at the door with one invalid_type issue at filters.N.operator, tombstone rather than strip, the producer/reader census, the docs Schema block, the 16-test pin and its ablations, scope — are adopted here unchanged; measured first-hand by the director seat on the fetched refs. What is re-judged is the two prose sites the FAIL named blocking, and its nit.

  1. Blocking item (1) is fixed and the new sentence is true. .changeset/10611-filter-ui-operator-retired.md now reads: "operator: 'gt', a member of that enum, type-checked and parsed green through objectui validate; a nonsense id was refused by the enum and did not type-check; and both rendered and emitted exactly what a filter without it does." That is the restatement the FAIL asked for, and it matches the pre-change faces the FAIL measured (the mirror's seven-member z.enum refused zz_nonsense_op with invalid_value; the TS union did not admit it). The sentence also now says the TypeScript face carried "the same union", which is the true before-state.
  2. Blocking item (2) is fixed the same way. The pin's header (filter-ui-operator-retired-10611.test.ts:13-26) carries the same corrected sentence, and the AUTHORED list's comment no longer claims the render reading covered every member: "sampled a subset of these (it lists which)". The test body is untouched: the fix commit's two hunks in this file are comment lines only; the nine-member AUTHORED list and the 16 tests are the ones the FAIL ablated.
  3. The nit is fixed exactly. "a host onChange function receives that bare record, and only the authored window event wraps it, as detail: { values }" is what notifyViewHandlerChannels(onChange, schema.onChange, nextValues, { values }) does; the changeset and the pin header both say it now.
  4. No other published text moved. content/docs/components/complex/filter-ui.mdx, views.ts, views.zod.ts are byte-identical to the FAIL head across the hop (the two guide pages in the two-dot diff are main's own edits carried by the merge, outside this PR's file set).
  5. Mergeability and CI. git merge-tree --write-tree origin/main refs/pull/10760/head at 17b323e5ca exits 0 with no conflict. Check runs on 671407f3fb: 40 success, 3 skipped (dependabot, the two coverage rows), 0 red; every required context is green.

② Semver level

Unchanged from 5853796261: minor on @object-ui/types with a BREAKING banner (major refused by the version-alignment rule); Changeset Bump Policy, Declaration and Fixed Group Check green. Every changeset sentence now reads true, the one false clause having been the blocking item above. The PR body's Clause-②: yes is the spelling objectui's retirement bodies use for a public-surface removal (#10759's body spells the same convention out); under either reading the grade is minor + BREAKING, so no gate outcome turns on it.

③ Boundary flags

  • (a) Model-named commit trailer: adopted from the FAIL record's ③(a) — the squash on main carries the PR body, not the commits, and the branch retires with the merge.
  • (b) Docs type union lacks multi-select (pre-existing, outside the card): the FAIL asked the PM seat for a carrier. The director seat attaches a carrier card with this record (filed, or an existing one if the board already holds it) so "carrier: none" stops being true; nothing in this PR changes for it.
  • The seat's ABSENT note 5855221809 waited on at-tier quota; this record is that delta re-review, rendered by the director seat at tier, so the seat's retry is not needed.
  • Fixes #10611 closes only the intended card; NOT GOVERNED paths.

Implemented-by: claude/issue-10611-filter-ui-operator-retired
Reviewed-by: session_01AsCNgFBs8HCjwhyHQsFbx3

VERDICT: PASS

Rendered at tier by the director seat (summon #30 续) on the fetched head. Not a governed path; the landing pre-checks are met on this head (fresh PASS, CI green, no conflict), so needs:contract-review comes off with this record and ready + auto-merge follow through the relay.


Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review September 27, 2026 13:27
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Sep 27, 2026
Merged via the queue into main with commit 17cc3a3 Sep 27, 2026
45 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-10611-filter-ui-operator-retired branch September 27, 2026 13:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

2 participants