Skip to content

feat(types): export ObjectTreeSchema from the root barrel (objectui#9550) - #9685

Merged
os-sales merged 3 commits into
mainfrom
claude/issue-9550-objecttree-root-barrel
Sep 17, 2026
Merged

os-sales merged 3 commits into
mainfrom
claude/issue-9550-objecttree-root-barrel

Conversation

@os-sales

@os-sales os-sales commented Sep 17, 2026

Copy link
Copy Markdown
Collaborator

Fixes #9550

ObjectTreeSchema is now a named export of the @object-ui/types root barrel.

WARNING — angle-bracket-shaped tokens are spelled out in WORDS throughout this body: GitHub's body sanitizer deletes them, including inside backticks and fenced blocks (AGENTS.md, the section on GitHub rewriting the bytes you write into an issue or PR body). So "an EXTRACT of ObjectQLComponentSchema narrowed to the object-tree tag", never the literal TypeScript spelling — a table written to show that idiom would otherwise render as if it showed nothing.

What changed — seven files after patch round 2, one of them a single line of product code

⚠️ This table is the count: every file in the diff has a row, so the heading cannot drift from the diff without a row going missing. (It drifted twice before — 「three」 while the head touched five, then 「five」 while the head touched seven — because a later commit added files after the figure was written.)

file what
packages/types/src/index.ts one name added to the existing explicit export type list that re-exports from ./objectql.js, placed in union-arm order between ObjectMapConfig and ObjectGanttSchema
packages/types/src/__tests__/object-tree-root-barrel-9550.test.ts the pin (new file)
.changeset/9550-object-tree-root-barrel.md @object-ui/types minor
packages/plugin-tree/src/ObjectTree.tsx patch round 1 — the module-local narrowing alias replaced by a type-only named import of ObjectTreeSchema at both read sites (ObjectTreeProps.schema, getTreeConfig); the now-false justification paragraph deleted; the objectui#8651 shadowing warning KEPT, its ruling sentence verbatim and its leading clause re-pointed (a byte-for-byte keep would itself have gone false)
.changeset/9550-plugin-tree-import-object-tree-schema.md patch round 1@object-ui/plugin-tree patch (new file)
.changeset/8655-object-tree-props-schema-typed.md patch round 2 — prose-only correction of a pending, unreleased entry that this merge would otherwise falsify; frontmatter byte-identical; the overwrite gate's declared case 2
packages/plugin-tree/src/ObjectTree.schemaTyped-8655.test.ts patch round 2comments only; the executable content is proven unchanged by a comment-masked line-sequence hash with two lit controls, ⛔ not by a line-aligned diff (which reports a false difference from the longer comment block's offset)

Premise re-verified on this branch point, not relayed from the card

Base 72f55c9ec1. Occurrence counts in packages/types/src/index.ts BEFORE the repair, each zero standing beside controls that read non-zero under the same query:

probe hits
ObjectTreeSchema 0
ObjectGridSchema (control) 2
ListViewSchema (control) 3
BreadcrumbSchema (control) 1
ZZZ_ABSENT_CONTROL (absent-token control) 0

The declaration reads 2 in objectql.ts and the zod barrel reads 1, so the instrument was lit in both directions. The card's second premise also holds: the package's exports map declares ., ./base, ./complex, ./data, ./data-display, ./feedback, ./form, ./internal/retired-field-keys, ./layout, ./navigation, ./overlay and ./zod — there is no ./objectql subpath, so the root barrel was the only route and it did not carry the name.

One more measurement worth having: nothing in this workspace star-re-exports @object-ui/types (export * from that specifier: zero hits across every .ts / .tsx). That is what makes this addition unable to collide with any downstream barrel — the failure mode an additive export can otherwise have.

The file fence held — nothing under another PR's hold was touched

packages/types/src/objectql.ts and packages/types/src/zod/objectql.zod.ts are held by open PR objectui#9540 at a frozen head. Neither is in this diff. The ObjectTreeSchema declaration already existed in objectql.ts; this PR publishes it from the barrel and does not edit, move or re-declare it. Leg b4 of the pin asserts exactly that: objectql.ts still declares the interface and index.ts declares nothing by that name.

The pin, and the reverse verification that proves it can fail

The repair has two enforcement halves and the pin covers both, because a pin that only covered one would be green on half a regression.

  • legs a1 / a2 / a3 — the type level, erased by the compiler and therefore silent under pnpm test. Their enforcement is tsc -p tsconfig.test.json, the third leg of this package's type-check script, which CI runs as its own job. a2 is the interesting one: it asserts the imported name and the EXTRACT idiom are the SAME declaration, using the house invariant type-equality helper rather than assignability. That idiom is the measured "before" — the seat delivering objectui#8655 had to write it because the name could not be imported.
  • legs b1 / b2 / b3 / b4 — the source scan, which is the half that runs under vitest. Deliberately not a dist/ read: this repo's per-PR test job runs pnpm test with no build step ahead of it, so a test needing a fresh dist/ would be vacuously absent-or-red on a cold cache. package-exports-manifest.test.ts and combobox-option-root-barrel-7697.test.ts record that same constraint for this package; the new file follows them rather than re-litigating it.

Reverse verification (run from the committed fix, restored afterwards; the direction was predicted as RED before the run and RED is what it read):

leg result
mutation landed on disk anchor occurrences before 1, after 0; blob hash differs from the HEAD blob
vitest exit 1 — 1 failed / 6 passed, b1 failing with "expected [...] to include 'ObjectTreeSchema'"
tsc -p tsconfig.test.json exit 2 — TS2724 on the import ("has no exported member named ObjectTreeSchema") plus the a1/a2 equality assertions inverting
restore git checkout HEAD on the path, git diff HEAD empty, blob hash byte-identical to the HEAD blob

Only 1 of the 7 tests reds under mutation, which is the expected shape and not a weakness: b2/b3/b4 pin properties the mutation does not move, and a1/a2/a3 are erased at runtime — they red in the tsc column instead.

Gates — exit codes captured to disk before any pipe

⚠️ The table below is the ROUND 0 reading (@object-ui/types only: 199 files / 4663 tests). Patch round 1 re-ran the owed gates across both packages — 215 files / 4757 tests, all green — so this table is a true record of round 0 and ⛔ not a reading of the current head.

gate exit
pnpm --filter @object-ui/types run lint 0 (0 errors, 288 pre-existing warnings)
pnpm --filter @object-ui/types run type-check 0 (all three tsc legs)
pnpm exec vitest run packages/types/ 0 — 199 files, 4663 tests
pnpm exec vitest run on the new test file 0 — 7 tests, non-zero pass count confirmed
pnpm exec turbo run build --filter=!@object-ui/site 0 — 43/43
pnpm changeset:check 0
node scripts/check-changeset-presence.mjs 0
pnpm check:changeset-claims 0 (report-only)
pnpm check:pending-changeset-literals 0
pnpm check:readme-exports 0
pnpm check:dist-completeness 0
pnpm check:component-surface-parity 0 (report-only)
pnpm check:entry-guard 0
pnpm check:unreferenced-sources 0
pnpm check:spec-symbols 0
pnpm check:self-import 0
pnpm check:control-bytes 0
pnpm check:test-path-roots 0
pnpm check:new-line-citations 0 (report-only, 0 new)
pnpm check:esm-specifiers 0
pnpm check:node-esm-load 0
pnpm check:published-dist 0
pnpm check:published-tsconfig-exclude 0

Two readings that deserve their names rather than a bare number:

  • check:readme-exports exits 1 on an unbuilt tree — "type entry ./dist/index.d.ts is not on disk, run pnpm build first", 36 of 40 packages unbuilt in a fresh worktree. That is PRECONDITION NOT MET, not a finding: it names packages/data-objectstack and reports 0 fabricated names. After the full build it exits 0 with 542 self-imports judged real. The pre-build 1 is recorded here so nobody re-derives it and reads it as a regression.
  • pnpm lint and pnpm type-check at the repo root are turbo run across every package — a whole-farm run that belongs to CI. They were narrowed to @object-ui/types, declared: the diff touches one package; no workspace package star-re-exports @object-ui/types (measured zero, above), so no other package's resolution can change; and the change is purely additive to a type-only re-export list, which cannot remove or retype anything a consumer already resolved. The full workspace build ran anyway and is green, which exercises every package's own tsc emit.
  • scripts/pm/check-half-states.mjs is a scheduled board patrol, not a per-PR gate on this diff (its pull_request leg fires only for changes to the patrol itself). Not run; not owed.

Acceptance notes — two things for the reviewer; ⭐ the second one IS now repaired here (patch round 1)

  1. BreadcrumbSchema's TS-side status, which the card flagged as NOT MEASURED, is now MEASURED: it is CLEAN. The name is on the root barrel's ./navigation.js re-export clause, declared in navigation.ts, with BreadcrumbItem and NavigationSchema as lit controls on the same list and an absent token reading false. So the card's option 2 finds nothing to repair on the TypeScript side — objectui#7917's other name never had this gap. Nothing filed, because there is nothing to file.

  2. SUPERSEDED BY PATCH ROUND 1 — the stale comment IS repaired in this PR. ⚠️ The text below is kept as the record of what this note said when the PR was opened; ⛔ do not read it as the current state.

    What changed and why: the at-tier contract review returned FAIL on exactly this point, and it was right. The triage grading on objectui#9550 had already ordered the repair in its 修法边界 section — 「decision(plugin-tree): ObjectTreeProps declares schema: any, so two cast reads are structurally UNANSWERABLE — the one class-(d) half with no carrier among the seven (objectui#8327) #8655 那份手抄件在补导出之后应当删掉并改为 import,⛔ 否则第二权威照旧存在,而这张卡看起来已经修好了」 — and the dispatching seat's order failed to carry that line and then fenced plugin-tree out explicitly. The narrowing was the seat's error, ⛔ not the implementer's. The fence was amended and the repair taken in this PR: packages/plugin-tree/src/ObjectTree.tsx now takes a type-only named import of ObjectTreeSchema from @object-ui/types at both read sites, the module-local narrowing alias is gone (ObjectQLComponentSchema occurrences in that file: 0), the false justification paragraph is deleted, and the still-true objectui#8651 shadowing warning is kept — with its ruling sentence verbatim and its leading clause re-pointed, because a byte-for-byte keep would itself have become false once the file imports that name. A @object-ui/plugin-tree patch changeset rides along.

    Original note 2, as written when this PR was opened — ⛔ no longer true

    A comment in packages/plugin-tree/src/ObjectTree.tsx goes stale the moment this merges, and it is deliberately NOT repaired here. Its docblock states, as a measured reason for choosing the narrowing idiom, that the TS barrel "omits it ... So the name cannot be imported today." After this PR that sentence is false. The triage seat asked for the hand-written spelling to be replaced by an import once the export landed. It is out of this PR's declared file surface and out of the dispatch's ruling zone, which fixed the ask at the one name — so it is reported rather than taken unilaterally. It needs its own card.

    ℹ️ objectui#9687 was filed by the seat for this repair while the fence was believed correct; it is superseded and will be closed as a duplicate once this PR lands.

Not done here, on purpose: the card's option 3, a gate over barrel completeness for every declared node schema. That is a wider design with its own review, and a gate arriving unrequested inside a one-symbol repair is scope taken unilaterally. objectui#9526 is the sibling card in the same family; if that gate is ever built, this pin becomes one of its regression cases rather than its substitute.

Governed surface: this diff touches none of them (AGENTS.md, CLAUDE.md, .claude/, skills/, docs/adr/), so it does not need the governed-surface approval before it is readied. It DOES carry clause 2 — a symbol added to a published barrel — so an at-tier contract review runs first.

维护者速读(草稿)

改了什么。 @object-ui/types 这个包的「总目录」(根 barrel)原本漏掉了一个名字:ObjectTreeSchema —— 树形表格这个组件的类型定义。它本身一直存在、一直被联合类型用着、zod 那一面也导出了,唯独 TypeScript 这一面没往外摆,所以谁都 import 不到。这次就是补上这一行,外加一个防止它再次消失的测试和一份 changeset。

为什么改。 缺口不是「少一行」这么静态:objectui#8655 那一轮因为导不到这个名字,只能在插件里手写一份等价的类型表达式。一个导不出来的类型,每被需要一次就会被手抄一次,而手抄件今天对、明天就开始漂 —— 这正是 objectui#6349 那张 burn-down 卡在清的形状。补上导出,是把「第二权威」的源头关掉。

风险与代价(含回滚)。 风险接近于零,方向是纯新增:没有任何东西被删除、改类型或收窄,原来的写法照旧可用;全仓没有任何包用 export * 转发这个包,所以新增的名字不可能和别人撞名。发版影响是 @object-ui/types 走一个 minor、@object-ui/plugin-tree 走一个 patch(按本仓约定,破坏性变更也不写 major)。回滚就是回退本 PR:七个文件(两轮补丁后),产品代码是 packages/types一行导出plugin-tree 里把本地别名换成具名 import 的类型替换(该替换经实测为类型不变式:_PropIsThePublishedNode 这条跨包 pin 断言两种拼法同一,且把它改成别的已发布类型会让 tsc 变红)。没有数据迁移、没有运行时行为改变。发版影响是 @object-ui/types 一个 minor@object-ui/plugin-tree 一个 patch

席位意见。 (留空,待受权席位填写)

你要做的。 只有一件:确认「往已发布的包里新增一个公开名字」这件事本身可以接受(条款②的 at-tier 契约评审)。⭐ 补丁轮更新:开 PR 时 Acceptance notes 第 2 条说 plugin-tree 里那段会因本次合并变成假话的注释「不在本 PR 修」—— 那条已作废。达档契约复核判 FAIL,而且判得对:分诊在卡上本来就写明了「补导出之后应当把那份手抄件改成 import,否则第二权威照旧存在,而这张卡看起来已经修好了」,是派发席漏带了这句并把 plugin-tree 围了出去。围栏已修订,该修复已在本 PR 内完成,并随附一个 @object-ui/plugin-tree 的 patch changeset。⇒ 合并后不会留下假话,也不需要再另开卡。


Generated by Claude Code

…#9550)

`ObjectTreeSchema` was the one arm of `ObjectQLComponentSchema` that the
root barrel of `@object-ui/types` did not name, so no TypeScript consumer
could import it: the declaration lives in `objectql.ts`, the union applies
it, and the zod barrel re-exports it, while the package publishes no
`./objectql` subpath to reach around the barrel.

The repair is one name added to the existing explicit named re-export
list. The declaration is not moved or edited - it is held by another open
pull request and only published from here.

`object-tree-root-barrel-9550.test.ts` pins the repair on both halves: the
type-level legs (enforced by `tsc -p tsconfig.test.json`) assert the name
resolves off the root barrel and is the SAME declaration as the
`Extract<ObjectQLComponentSchema, { type: 'object-tree' }>` spelling a
consumer was forced into, and the source legs (enforced under vitest)
assert the list stays explicit rather than becoming a wildcard and that
the declaration stays in `objectql.ts`.

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

github-actions Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

changeset-claim-re-read

⚠️ 2 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/6051-gantt-flat-config-declared-keys.md

  • names packages/types/src/index.tspackages/types/src/index.ts — edited by this change

    GanttConfig itself gains nine members and is a published type, exported by name from packages/types/src/index.ts: lockField, objectField, summaryExtent, defaultCollapsedDepth, borderColorField, dependencyTypes, timeZone, exportFileName, interactions. The entry file's diff is empty only because the export list already named the type — the widening happened at the declaration.

.changeset/8253-export-tree-view-config.md

  • names plugin-tree/src/ObjectTree.tsxpackages/plugin-tree/src/ObjectTree.tsx — edited by this change

    What was wrong. tree is a host-composition-only view type — ruled deliberate on objectui#5321, it is a member of neither ObjectViewSchema.defaultViewType nor NamedListView.type, so the branch runs only when a host passes a views prop. On that path a per-view tree block is read at four sites, and its only description anywhere was a module-local, non-exported interface TreeConfig inside plugin-tree/src/ObjectTree.tsx. The live host is the console: it stores view records and passes them as views, and its create-view dialog offers tree. So a real consumer wrote this block with no type to write it against, and a misspelled parentFeild was admitted by the views entry's [key: string]: any, stored, read by nobody and reported by nothing. Declared ≠ enforced on a surface a non-author re-writes.

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 claim that was born false (a changeset this change adds is excluded by construction), 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 5f8190c8c (merge-base with origin/main): 4 file(s) changed outside .changeset/, read against 1120 pending declaration(s) that publish a body (1627 pending in total). · run

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 329 chunks) 3048.9 KB 3104.5 KB
Main entry chunk (gzip) 145.7 KB 350 KB
Entry file index-Ckww2Jo5.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.69KB 6.21KB
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) 25.05KB 9.16KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.18KB 10.59KB
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.41KB 1.23KB
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.46KB 3.43KB
auth (index.js) 3.19KB 1.44KB
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) 26.08KB 7.56KB
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) 545.84KB 130.66KB
core (index.js) 8.94KB 3.59KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 215.98KB 59.97KB
fields (index.js) 249.27KB 62.92KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 1.22KB 0.64KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.22KB 2.26KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 32.15KB 10.49KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 38.83KB 10.95KB
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) 2.53KB 0.85KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 4.39KB 1.66KB
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.39KB 3.10KB
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) 14.81KB 3.63KB
plugin-calendar (index.js) 49.92KB 14.22KB
plugin-charts (index.js) 71.33KB 19.90KB
plugin-chatbot (index.js) 195.34KB 46.51KB
plugin-dashboard (index.js) 131.44KB 34.65KB
plugin-designer (index.js) 215.94KB 44.33KB
plugin-detail (index.js) 253.29KB 65.88KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 136.71KB 34.16KB
plugin-gantt (index.js) 167.62KB 41.26KB
plugin-grid (index.js) 212.64KB 57.91KB
plugin-kanban (index.js) 46.41KB 14.49KB
plugin-list (index.js) 112.73KB 27.69KB
plugin-map (index.js) 21.48KB 6.99KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.41KB 11.93KB
plugin-timeline (index.js) 30.07KB 8.74KB
plugin-tree (index.js) 10.58KB 3.72KB
plugin-view (index.js) 85.04KB 21.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) 104.82KB 34.67KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.63KB 2.18KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 6.58KB 2.74KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 5.66KB 2.50KB
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) 14.82KB 4.99KB
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) 4.73KB 2.28KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
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) 14.04KB 5.36KB
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

Copy link
Copy Markdown
Collaborator Author

At-tier contract review record — PR #9685 / card objectui#9550 — FAIL

Adopted VERBATIM by the domain:spec @ objectui execution seat (session_01UanLVj6xvbS6puBCewLr8L), per 「逐字采纳或整体作废,没有第三种」. ⛔ Not one finding was softened, dropped or re-ranked. ⭐ The seat agrees with the verdict and the blocking item is this seat's own error, not the implementer's — see the REWORK note on the card.

Tier, from the reviewer's OWN transcript (⛔ not get_session): message.model reads claude-fable-5-1, 84 of 84 — at CONTRACT_REVIEW_TIER. Firing control: the three os-dev implementer transcripts in the same session read claude-opus-5 (137 / 147 / 152). ⇒ the field discriminates.

Isolation: the reviewer got the card, existing rulings and the PR only — ⛔ never the dispatch order, ⛔ never this seat's conclusions, ⛔ never the implementer's report as an input.


VERDICT: FAIL

Served-tier: CONTRACT_REVIEW_TIER
Head reviewed: bdb519c55784b13441c220eab1832c2816434fb7 (base 72f55c9ec118946d3a7f839013b27d87f78c77d3; origin/main at review time 61b7553469, with zero commits between base and main touching packages/types or packages/plugin-tree, so main-side readings below stand for the base).
Implemented-by: mode:subagent, branch claude/issue-9550-objecttree-root-barrel (Claim comment 5713271918, session session_01UanLVj6xvbS6puBCewLr8L)
Reviewed-by: isolated contract-review subagent (no session; adopted by the dispatching seat). The card's Claim, the PR and this review share one protocol identity; that was not treated as evidence of anything — the diff was judged, and every reading below was re-taken in an isolated clone under the review's own scratchpad directory, never in the shared checkouts.

What I measured

# reading value source / control
1 ObjectTreeSchema in packages/types/src/index.ts @ base 0 git show origin/main:…; controls in the same file, same query: Grid 2 · Form 2 · View 2 · Map 1 · Gantt 1 · Calendar 1 · Kanban 2 · Chart 1 · Gallery 1 · DataTable 1 · ListView 3 · ObjectQLComponentSchema 3; absent token ZZZ_ABSENT_CONTROL 0
2 arms of export type ObjectQLComponentSchema in objectql.ts 12, 11 on the barrel, Tree the only miss awk over the union at base
3 export type { … } from './objectql.js'; clauses in index.ts 1 (lines 424–469 at base); the only other ./objectql.js line is an import type at 786; export * lines in index.ts: 0; the root barrel does not re-export the zod barrel grep on the base file
4 export clause of every sibling all 11 sit in that one type-only named clause; the diff adds the 12th name to the same clause between ObjectMapConfig and ObjectGanttSchema; count at head 1 PR diff + grep -c at head in clone
5 files in the diff 3 (+256/−0): index.ts +1, new test +222, new changeset +33. packages/types/src/objectql.ts and packages/types/src/zod/objectql.zod.ts: absent git diff --stat base..head in clone, and PR files API (3 entries)
6 @object-ui/types exports keys 12 keys, no ./objectql package.json at base
7 new test at head, vitest exit 0, 7/7 isolated clone, pnpm install --frozen-lockfile exit 0
8 tsc -p tsconfig.test.json at head exit 0, 0 errors packages/types in clone
9 ablation (delete the ObjectTreeSchema, barrel line; count 0; 1 deletion) vitest exit 1 — `1 failed 6 passed, b1("expected [ 'HttpMethod', … ] to include 'ObjectTreeSchema'");tscexit **2** — **8** errors, all in the new file (TS2724 at the import, 7×TS2322 on a1/a2); restore:git status --porcelain` 0 lines, count back to 1
10 full packages/types suite at head 199 files / 4663 tests pass, exit 0 clone
11 gates in clone check-changeset-presence 0 (1 changeset for 2 published source files); check-pending-changeset-literals 0; changeset:check 0 (no major); eslint on the new file 0 (0 output lines) clone
12 export * … from '@object-ui/types' across *.ts/*.tsx 0 control: files importing from '@object-ui/types' 697
13 changeset level precedent .changeset/7697-combobox-option-root-barrel.md and 9406-types-root-barrel-two-names.md both '@object-ui/types': minor for the identical shape; AGENTS.md §9 forbids major mechanically git show at main
14 new changeset cites its own card 9550 occurrences in body: 0 (file name only) controls: 7697's cites itself 1×, 9406's 3×; 7 of the 40 newest 9xxx-* changesets also lack a self-cite, so no gate reads this
15 tree-wide ObjectTreeSchema mentions at main 16 files (control: ObjectGanttSchema 47 files); every one read in context for a claim that depends on the name being unreachable git grep -c
16 open PRs touching packages/plugin-tree/src/** 0 of 13 open PRs (file lists read for 9688 · 9683 · 9682 · 9540 · 9686 · 9391 · 9584 · 9488 · 8941 · 9592 · 9378 · 5400/first 100). #8941 touches packages/plugin-tree/package.json only PR files API
17 PR #9540's objectql.ts patch touches ObjectGallerySchema.filter and an ObjectChartSchema docblock; not the ObjectTreeSchema interface → the new test's b4/a1 are not coupled to it PR files API
18 type-leg enforcement wiring tsconfig.test.json includes src/**/*.test.ts; type-check script runs it as its 3rd leg; ci.yml runs pnpm type-check and pnpm test --shard; turbo test depends on ^build only files at main
19 docs enumeration control packages/types/README.md names Gantt/Map/Grid 0 times (Kanban 1); content/docs does not list the family as an import surface → no README/doc parity is owed by this change grep at main
20 ObjectTree.schemaTyped-8655.test.ts reads ObjectTree.tsx only to extract schema.* reads (schemaReads(mask(readRepo(TREE_READER)))); it does not pin the Extract idiom file at main

What I checked and found

1. Does the diff do what the card asks — no less, no more? The card (as graded in comment 5710385032, "修法边界: 补一行导出") asks for option 1, one name on the root barrel. The product change is exactly that one line, in the right clause, in union-arm order. Option 3 (a gate) was not built. Option 2's unmeasured item (BreadcrumbSchema) was measured and reported, not changed — I confirm it is on the ./navigation.js clause (count 1 at base). But the same grading ruling also says, in its repair-boundary section: "并请顺手核一次:#8655 那份手抄件在补导出之后应当删掉并改为 import,⛔ 否则第二权威照旧存在,而这张卡看起来已经修好了." The PR does not do this, reports it as out of scope, and closes the card with the closing keyword. That is "less" than the card as ruled — see Blocking item 1.

2. Published surface. Measured, not assumed (rows 3–4): all eleven present arms are exported by a single type-only export type { … } from './objectql.js' named clause; the new name is added to that same clause, so it ships as exactly the same kind of thing — a type-only named re-export, no runtime edge, dist/index.js unaffected. Nothing star-re-exports the package (row 12), so no downstream barrel can collide. Under 创业阶段不扩散: this is completion of an already-published family with measured pull (objectui#8655 had to write the Extract workaround), not speculative widening.

3. Frozen files. packages/types/src/objectql.ts and packages/types/src/zod/objectql.zod.ts are absent from the diff (row 5). The new test reads objectql.ts (b4), which is not a mutation, and #9540's patch to that file does not touch the pinned interface (row 17). Constraint respected.

4. Is the pin real? Yes, and I proved it rather than trusting the PR body: with the one line reverted, the runtime leg b1 (a source scan of index.ts, not a dist/ read) fails under vitest, and the type legs a1/a2 fail under tsc -p tsconfig.test.json, which CI runs (rows 9, 18). a2 is the valuable assertion: invariant equality between the barrel name and the Extract spelling, so a forked declaration cannot pass. Size: 222 lines, ~70 of docblock; a3/b2/b3 are lit controls and structural guards, b4 pins that the declaration did not move. That is in line with the house siblings (7697 test 225 lines, 9406 409, 8784 584) — not padding, though the docblock could lose a third without losing a reading.

5. Changeset. Right package (@object-ui/types), right level (minor, matching both precedents for this exact shape; major is forbidden here, row 13), presence/literal/no-major gates all 0 (row 11). Prose checked claim by claim: 12 arms / 11 exported (row 2) — true; zod barrel exports it via objectui#7917 — true (index.zod.ts count 1, 7917 changeset pending); no ./objectql subpath, pinned by package-exports-manifest.test.ts — true (that test asserts the exports map); the 8655 Extract idiom — true (verbatim in ObjectTree.tsx and its changeset); the three pinned properties — match a2, b3, b4. One gap: the body never cites objectui#9550 (row 14) while citing four other cards — non-blocking.

6. Does anything this merge makes false go unrepaired? Yes — one live-reading claim. Of the 16 files naming ObjectTreeSchema (row 15), exactly one states, as a present-tense measured reason, that the name is unreachable: packages/plugin-tree/src/ObjectTree.tsx, docblock above the module-local Extract alias:

"Extract off ObjectQLComponentSchema, and NOT a named import, for a measured reason: … the TS barrel's export type { … } from './objectql.js' block omits it … So the name cannot be imported today. ⛔ That omission is NOT repaired here: it is a published-surface addition on another package and belongs to whoever files it."

On merge every sentence of that paragraph inverts, nothing re-derives it (AGENTS.md #9), and the triage ruling on this very card named this exact site as the thing to close in the same stroke. The PR knows this (its acceptance note 2) and leaves it, citing the Claim's file fence and the absence of an open-PR intersection for plugin-tree — I ran that intersection (row 16): no open PR touches packages/plugin-tree/src, so the fence has no serial-constraint reason to exist for that file. A second, historical instance: the pending .changeset/8655-object-tree-props-schema-typed.md (unreleased — packages/plugin-tree/CHANGELOG.md mentions 8655 zero times) says "the TS barrel does not export ObjectTreeSchema" and will publish verbatim into the same release as this PR's entry; the changeset-claim-re-read bot did not flag it because the file is not named in backticks. That one is narrative-of-the-time and the new changeset cross-references 8655 the way 7697's precedent does — non-blocking.

Blocking items

  1. Repair the claim this merge falsifies, in this PRpackages/plugin-tree/src/ObjectTree.tsx. Replace the module-local Extract alias with a type-only named import of ObjectTreeSchema from @object-ui/types and use the imported name at its two read sites (ObjectTreeProps.schema, getTreeConfig's parameter), delete the now-false "Extract … NOT a named import, for a measured reason … cannot be imported today" paragraph, and keep the still-true "Deliberately NOT spelled ObjectTreeSchema locally" shadowing note (now satisfied by importing rather than aliasing). Add a '@object-ui/plugin-tree': patch changeset (published src/ changes, so check-changeset-presence will demand a declaration; the emitted .d.ts swaps an Extract alias for a named reference, type-identical per this PR's own a2). Re-run packages/plugin-tree/src/ObjectTree.schemaTyped-8655.test.ts (it does not pin the idiom, row 20, so it should stay green) and pnpm --filter @object-ui/plugin-tree run type-check. Measured prerequisites are already met: the file is disjoint from all 13 open PRs (row 16), and the imported type equals the Extract (row 9, a2). This is what the card's grading ruling asked for in so many words; if the dispatching seat instead insists on keeping the fence, the PR must not close the card until a follow-up card exists and is cited from the PR body — but note that alternative still ships the false paragraph and does not clear AGENTS.md 完善设计器的每一个细节 #9; only a maintainer ruling could accept it.

Non-blocking observations (not gating)

Scratchpad: the review's own directory (clone at head, vitest.head.log, vitest.ablated.log, tsc.head.log, tsc.ablated.log, vitest.types-all.log, gate logs). Nothing under /home/user/objectui or /home/user/objectstack was written, checked out, or run against.


⚠️ Departures from verbatim, disclosed rather than hidden. GitHub's sanitiser deletes tag-shaped fragments from a stored body even inside backticks, so four spellings were rendered as words: the reviewer's scratchpad path placeholder; the Extract type application in Blocking 1 and in row-6's heading (written as "the module-local Extract alias"); and the closing-keyword phrase in check 1. ⛔ No finding, count, verdict or ranking was altered — only spellings that would otherwise have been silently eaten.

— Record posted by PM domain:spec @ objectui · session session_01UanLVj6xvbS6puBCewLr8L · 2026-09-17T11:54Z


Generated by Claude Code

…ng it (objectui#9550)

`ObjectTree` typed its node by narrowing the published union on the
`object-tree` tag and binding that to a module-local alias. The spelling was
forced, not chosen: the name it wanted was declared in `@object-ui/types` and
carried by the zod barrel, but the root barrel did not name it, so there was
nothing to import. The preceding commit put the name on that barrel; this one
consumes it at both read sites, `ObjectTreeProps.schema` and `getTreeConfig`.

The type does not move. `ObjectTree.schemaTyped-8655.test.ts` asserts
`ObjectTreeProps['schema']` invariantly equal to the narrowing, independently
of this branch, and it stays green. What goes away is a derived restatement of
a published type - the per-consumer second authority an unimportable type mints,
which is the class objectui#6349 is burning down.

The docblock's justification paragraph goes with it: it gave as its MEASURED
reason for the narrowing that the barrel omits the name so it "cannot be
imported today", and that sentence is false now. The objectui#8651 shadowing
warning beside it is KEPT and re-pointed at the import - a module-local type
wearing a published type's name is the two-layers-one-word trap, and that is
more load-bearing once the published name is importable, not less. The block
now annotates the import rather than a declaration that no longer exists.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UanLVj6xvbS6puBCewLr8L

Copy link
Copy Markdown
Collaborator Author

Patch round — commit 5a82fd9e9 supersedes Acceptance note 2 in the body above

⚠️ The body of this PR is now stale in exactly one place and this comment is the correction (the body is not rewritten: an edit to a created PR body loses its session reference and gets a second attribution footer appended, both measured in AGENTS.md, so the additive channel is the right one).

Acceptance note 2 said the packages/plugin-tree hand-copy was deliberately NOT repaired here, because the file was outside the claim's declared file surface. That is no longer true. The at-tier contract review returned FAIL on exactly that item, the dispatching seat amended the fence to admit packages/plugin-tree/src/ObjectTree.tsx plus a plugin-tree changeset, and the repair is now in this PR. The rest of the fence stands and is still untouched: packages/types/src/objectql.ts and packages/types/src/zod/objectql.zod.ts are absent from all 5 changed files.

What the patch commit does

  • ObjectTreeProps.schema and getTreeConfig's parameter are typed by a type-only named import of ObjectTreeSchema from @object-ui/types; the module-local alias built by narrowing the published union is gone, and ObjectQLComponentSchema drops out of this file's imports with it (occurrences now 0).
  • The docblock's justification paragraph is deleted — it gave as its MEASURED reason for the narrowing that the barrel omits the name so it "cannot be imported today", which the first commit makes false and which nothing re-derived.
  • ⛔ The objectui#8651 shadowing warning beside it is KEPT, not deleted. Its leading clause is re-pointed (it used to read "deliberately NOT spelled ObjectTreeSchema locally", which would itself be false now that the file spells the name as an import); the sentence carrying the ruling — a module-local type under a published type's name is the two-layers-one-word trap recorded when a local CalendarSchema shadowed the published one — is preserved word for word. The block now annotates the import instead of a declaration that no longer exists.
  • .changeset/9550-plugin-tree-import-object-tree-schema.md, @object-ui/plugin-tree patch. The types changeset's first line now names the card, per the review note.

Why there is no ablation here, and what runs in its place

This swap is type-invariant by construction — the imported name and the narrowing are the same declaration — so removing it flips nothing, and claiming a red would be fabricating one. What must not be vacuous is the pin that makes the swap safe: the invariant equality on ObjectTreeProps['schema'] in ObjectTree.schemaTyped-8655.test.ts. A control was run instead: with the prop retyped to a different published type, that assertion reds with TS2344: Type 'false' does not satisfy the constraint 'true', and restoring returned the file to a byte-identical hash. So the green below is a reading.

Gates (exit codes captured to disk before any pipe)

gate exit
pnpm --filter @object-ui/plugin-tree run type-check 0 (both tsc legs)
pnpm --filter @object-ui/plugin-tree run lint 0 (0 errors)
pnpm exec vitest run on ObjectTree.schemaTyped-8655.test.ts 0 — 17 tests, non-zero pass count
pnpm exec vitest run packages/plugin-tree/ packages/types/ 0 — 215 files, 4757 tests
pnpm exec turbo run build --filter=!@object-ui/site 0 — 43/43
check:readme-exports · check:dist-completeness · changeset:check · check-changeset-presence · check-changeset-overwrite · check:changeset-claims · check:pending-changeset-literals · check:spec-symbols · check:component-surface-parity · check:unreferenced-sources · check:self-import · check:entry-guard · check:control-bytes · check:test-path-roots · check:new-line-citations 0

Path filtering only; no -t regex was used anywhere, so the objectui#9660 false-green shape is out of reach.

Two readings for whoever picks this up

  • needs:contract-review is on this PR now (it was absent when the PR was opened and this seat does not hang or clear it). The card carrier should be checked too — objectui's own half-state patrol documents this as a dual-carrier gate.
  • mergeable_state reads behind. Not a conflict, and the merge queue rebuilds on current main anyway; flagged rather than acted on, and if a sync is wanted the compliant route in this repo is a merge, never a rebase plus force-push.

No README change is owed: packages/plugin-tree/README.md teaches an AUTHOR how to write the node through the published union, which is still exactly true, and packages/types/README.md does not enumerate exports.


Generated by Claude Code

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 329 chunks) 3048.9 KB 3104.5 KB
Main entry chunk (gzip) 145.7 KB 350 KB
Entry file index-DbLzpmc-.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.69KB 6.21KB
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) 25.05KB 9.16KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.18KB 10.59KB
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.41KB 1.23KB
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.46KB 3.43KB
auth (index.js) 3.19KB 1.44KB
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) 26.08KB 7.56KB
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) 545.84KB 130.66KB
core (index.js) 8.94KB 3.59KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 215.98KB 59.97KB
fields (index.js) 249.27KB 62.92KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 1.22KB 0.64KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.22KB 2.26KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 32.15KB 10.49KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 38.83KB 10.95KB
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) 2.53KB 0.85KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 4.39KB 1.66KB
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.39KB 3.10KB
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) 14.81KB 3.63KB
plugin-calendar (index.js) 49.92KB 14.22KB
plugin-charts (index.js) 71.49KB 19.99KB
plugin-chatbot (index.js) 195.34KB 46.51KB
plugin-dashboard (index.js) 131.44KB 34.65KB
plugin-designer (index.js) 215.94KB 44.33KB
plugin-detail (index.js) 253.29KB 65.88KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 136.71KB 34.16KB
plugin-gantt (index.js) 167.62KB 41.26KB
plugin-grid (index.js) 212.64KB 57.91KB
plugin-kanban (index.js) 46.41KB 14.49KB
plugin-list (index.js) 112.73KB 27.69KB
plugin-map (index.js) 21.48KB 6.99KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.41KB 11.93KB
plugin-timeline (index.js) 30.07KB 8.74KB
plugin-tree (index.js) 10.58KB 3.72KB
plugin-view (index.js) 85.04KB 21.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) 104.82KB 34.67KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.63KB 2.18KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 6.58KB 2.74KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 5.66KB 2.50KB
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) 14.82KB 4.99KB
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) 4.73KB 2.28KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
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) 14.04KB 5.36KB
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

Copy link
Copy Markdown
Collaborator Author

At-tier contract review record — PR #9685 @ head 5a82fd9e / card objectui#9550 — FAIL (round 2)

Adopted VERBATIM by the domain:spec @ objectui execution seat (session_01UanLVj6xvbS6puBCewLr8L), per 「逐字采纳或整体作废」. ⛔ Nothing softened, dropped or re-ranked.

Tier, from the reviewer's OWN transcript (⛔ not get_session): claude-fable-5-1, 75 of 75. Firing control: the implementer transcripts in this session read claude-opus-5 (137 / 147 / 152 / 152).

Isolation: this reviewer was given the card, the rulings and the PR only — ⛔ never the dispatch order, ⛔ never this seat's conclusions, ⛔ never the implementer's reports, and ⭐ ⛔ never the round-1 review record, so its agreement with round 1 on the shape of this class is independent rather than inherited.

Seat note on one reversal, because it matters: round 1 judged .changeset/8655 narrative-of-the-time and non-blocking; this round judges it blocking. The seat has checked and this round is right: in round 1 ObjectTree.tsx was not being changed, so 8655 accurately described what had shipped. At this head the code IS changed inside the same unreleased window (packages/plugin-tree/CHANGELOG.md mentions 8655 0 times), so it would publish a description of code that never existed. The cited precedent is real and on main: commit c9f9baedf (PR #9495) edits the pre-existing .changeset/6854-…md in place alongside its own entry.


VERDICT: FAIL

Independent contract review of objectstack-ai/objectui PR #9685 at head 5a82fd9e9f282364fe22c4adb9321e0b662ec0a3 (base 72f55c9ec118946d3a7f839013b27d87f78c77d3), against card objectui#9550 as ruled by the triage grading comment. Whole diff judged (5 files, +308/-34). All execution was done in a private clone under my scratchpad directory; the shared checkouts were only read (/home/user/objectui status clean, HEAD unchanged at 72f55c9e after the review).

The implementation is sound and the pins are real. The FAIL is on three prose artefacts this head leaves asserting the opposite of the tree — a pending changeset that publishes verbatim, a test docblock in the touched package, and the PR body that becomes the squash commit message. All three are the exact class the board already ruled on (this PR's own round 1; PR #9495 round 1), and each is a small prose-only repair.

What I measured

# probe reading source / control
1 ObjectTreeSchema in packages/types/src/index.ts base 0, head 1 git show the path piped to grep -c; control ObjectGridSchema reads 2 at base in the same file
2 union arms of ObjectQLComponentSchema in objectql.ts at head 12 arms listed verbatim: Grid, Form, View, Map, Tree, Gantt, Calendar, Kanban, Chart, Gallery, DataTable, ListView
3 each arm's presence in the export type { … } from './objectql.js' clause at base 11 of 12 read 1, ObjectTreeSchema 0, absent-token control ZZZ_ABSENT 0 clause extracted by awk; per-name grep -c
4 export form of the clause at head export type { … } from './objectql.js' — one clause (closing line is the file's only one from that module; the other such line is an import type); no export { / export * from that module type-only, matches all 11 siblings exactly
5 frozen files in the diff git diff --name-only base head over the two frozen paths → empty control: git ls-tree HEAD lists both files, so the empty result is a reading
6 ObjectTreeSchema in zod/index.zod.ts at head 1 (a named export line, between ObjectMapConfigSchema and ObjectGanttSchema) control ObjectGridSchema 1
7 package.json exports keys twelve keys, no ./objectql parsed with node, not grepped
8 ObjectQLComponentSchema / ObjectTreeSchema in ObjectTree.tsx at head 0 / 6 import line has no alias
9 vitest, the two pins at head 2 files, 24 passed (7 + 17) own clone
10 tsc -p tsconfig.test.json in packages/types at head exit 0, 0 lines
11 ablation: delete the one barrel line mutated blob f540b80e = the base blob in the diff header; vitest exit 1, `1 failed 6 passed`, b1 only; tsc exit 2, 8 errors all in the pin: TS2724 on the import, TS2322 on the six a1 members and on a2; no other file reds
12 tsc --noEmit and tsc -p tsconfig.test.json in packages/plugin-tree at head (dependency closure built, 12 turbo tasks) exit 0 / exit 0
13 control on the cross-package pin: retype the prop to a different published type already in scope tsc exit 2, _PropIsThePublishedNode reds with TS2344 at its own row, plus downstream TS2353/TS2559 restore byte-identical
14 whole packages/types/ + packages/plugin-tree/ vitest 215 files / 4757 tests passed, exit 0
15 CI wiring ci.yml type-check job runs pnpm type-check (turbo → each package's type-check, whose third leg in types and second in plugin-tree is tsc -p tsconfig.test.json); test job runs the sharded root vitest whose unit project includes the packages' test globs; the "Decide whether this change needs a full run" step diffs base to head excluding only markdown, content/, docs/, apps/site/ and .changeset/ — this diff has three TypeScript files, so the full run fires read from .github/workflows/ci.yml, vitest.config.mts, both package.json scripts, both tsconfig.test.json
16 check-changeset-claims.mjs base-to-head exit 0, and its own output states it does not cover "a claim about anything it does not spell as a file name in backticks: a symbol"; the only backticked file in the 8655 changeset is ObjectTree.schemaTyped-8655.test.ts, untouched here lit: the gate ran and printed its coverage statement
17 pnpm changeset:check, check-changeset-presence.mjs 0 / 0 ("3 source file(s) of 2 released package(s) changed … declares 2 changeset(s)")
18 line-number citations added by the diff none
19 .changeset/ literals in the new test 0 control: packages/cli/src/__tests__/app-generator.test.ts does name one, so the grep fires
20 BreadcrumbSchema on the root barrel (card option 2, flagged NOT MEASURED) present, one line in the ./navigation.js clause; declared in navigation.ts clean, nothing to repair
21 drift since base origin/main is 5 commits ahead; none touches index.ts, ObjectTree.tsx, objectql.ts or objectql.zod.ts; ObjectTreeSchema in origin/main index.ts still 0 git fetch origin main in my clone
22 PR #9540's changed files 4: a 9309 changeset, object-gallery-filter-9309.test.ts, objectql.ts (hunks at an ObjectChartSchema docblock and ObjectGallerySchema.filter), zod/objectql.zod.ts disjoint from this diff; the b4 regex anchored on the ObjectTreeSchema interface declaration is untouched by those hunks
23 tree-wide search at head for claims that depend on the prior state two hits asserting the prior state — see Blocking 1 and 2; every other hit re-read and still true git grep over 5a82fd9e9

What I checked and what I found

1. Does the diff do what the card asks as ruled — no less, no more? The ruling is the grading comment's 修法边界: put the name on the barrel like its siblings (clause ② surface addition, not accept-set widening), AND retire the objectui#8655 hand-copy in plugin-tree by replacing it with an import, else 「这张卡看起来已经修好了」 while the second authority survives. Both halves are in this head: the barrel line, and ObjectTree.tsx now types the prop and getTreeConfig's parameter with a type-only named import (reading 8). Option 3 (a completeness gate) is correctly not taken and the test docblock says so in as many words. Option 2 is closed by measurement (reading 20). Nothing beyond the ruling is in the diff. Pass on this point.

2. The published surface. Readings 3, 4, 6: all 11 sibling arms are on one explicit type-only re-export clause; the new name is on the same clause in union-arm order; the zod barrel already carried it. This completes an already-published family with measured pull (the #8655 idiom), which is the "completing, not widening" side of 创业阶段不扩散. Pass.

3. Hard constraint. Reading 5: neither frozen file is in the diff; b4 pins that the declaration stays in objectql.ts and that index.ts declares nothing by that name. PR #9540's own hunks (reading 22) do not reach the declaration b4 matches. Pass.

4. Are the pins real? Yes, by my own ablation (reading 11): the vitest half reds on exactly b1, the type half reds on the import and on a1/a2, nothing else in the package moves, and the mutated blob is provably the base blob. The type-level legs are erased at runtime and would be silent under pnpm test alone — but tsc -p tsconfig.test.json is a leg of both packages' type-check scripts, and CI's type-check job runs pnpm type-check for any PR touching non-ignored paths (reading 15). The cross-package pin _PropIsThePublishedNode is live against the head renderer (reading 13), which is what makes the plugin-tree swap type-invariant by measurement, not by argument. Pass.

5. Changesets. @object-ui/types: minor matches both prior root-barrel additions (7697-combobox-option-root-barrel.md, 9406-types-root-barrel-two-names.md, both minor); @object-ui/plugin-tree: patch is right for a type-invariant swap; no major (AGENTS.md rule, gate exit 0). Every factual claim in both bodies checked against the tree: 12 arms / 11 exported / 1 missing (reading 3); zod re-export and objectui#7917 (reading 6, the 7917 changeset exists); no ./objectql subpath and the exports map pinned by package-exports-manifest.test.ts (reading 7; that test's header says so); the #8655 idiom (the removed hunk); a2/b3/b4 pin what the types body says they pin; the 8655 test asserts the equality invariantly and independently through the prop type (its Equal helper is the invariant form, reading 13 proves it can fail); the deleted paragraph did say "cannot be imported today"; the #8651 warning is kept. Pass, with one nuance under Non-blocking.

6. Does anything this merge makes false go unrepaired? Yes — three items, Blocking 1–3. Reading 23 found two in the tree; the PR body is the third.

7. Is the edited docblock itself true? Yes. Each sentence of the relocated block in ObjectTree.tsx was checked: "objectui#9550 is what put the name on that barrel" (this diff); "the interface whose own docblock calls itself the 'Object Tree (tree-grid) Component Schema'" (verbatim in objectql.ts); views.ts names it "the node an author writes" (carried over verbatim from the old block); "the same derivation ResolvedTreeConfig below already uses against TreeViewConfig" (ResolvedTreeConfig is defined below the import from a Pick of TreeViewConfig); "Never re-declared LOCALLY under this name, and not aliased on the way in" (reading 8: no alias, no local declaration); the #8651 sentence is verbatim from the old block and #8651's body does record a local CalendarSchema in ObjectCalendar.tsx beside the published one. The re-pointed leading clause was necessary — the old "Deliberately NOT spelled ObjectTreeSchema locally" would itself have gone false — and the replacement is true. Pass.

Blocking items

Blocking 1 — pending changeset .changeset/8655-object-tree-props-schema-typed.md (present at base, unreleased, @object-ui/plugin-tree: minor) publishes two sentences this head falsifies. It will land in the same plugin-tree CHANGELOG release as this PR's own 9550-plugin-tree-import-object-tree-schema.md, describing shipped code that will not exist:

  • "The type is DERIVED, not written out" — naming the union-narrowing spelling that union's own docblock teaches — at this head the prop is the named import.
  • "…rather than a named import because the TS barrel does not export ObjectTreeSchema — the zod barrel does, its nine siblings are all on the TS one, and repairing that omission is a published-surface addition on another package, so it is reported rather than smuggled in here." — the barrel exports it at this head.

This is the WENT-FALSE shape check-changeset-claims.mjs itself defines (objectui#7721, #8617), and reading 16 shows why the gate stayed silent: the changeset names the state by symbol, not by a backticked file this diff touches. Precedent for the remedy is on main: commit c9f9baedf (PR #9495) corrected three falsified sentences in the pre-existing 6854-layout-renderer-retired-onclick.md in place, prose only, frontmatter byte-identical, after a round-1 contract-review FAIL on exactly this point; and check-changeset-claims.mjs's "The correction path" section says "correcting the body is the answer, and it is precedented rather than forbidden", noting check-changeset-overwrite.mjs will report it as its legitimate case 2. Action: in this PR, rewrite those two sentences to the past tense and point forward — e.g. "…was DERIVED … because, when this landed, the TS barrel did not export ObjectTreeSchema; objectui#9550 put the name on that barrel in this same release and this package now imports it (see that entry)." Frontmatter untouched. The claim comment's file fence needs amending to admit this file, as it was amended in round 1.

Blocking 2 — packages/plugin-tree/src/ObjectTree.schemaTyped-8655.test.ts carries a docblock that now asserts the opposite of the renderer it describes. Directly above its module-local union-narrowing alias the comment reads, verbatim: "The node the checker now sees at every read, spelled the way the renderer spells it." At this head the renderer spells it ObjectTreeSchema (reading 8). The row comment "① — the prop is the published node, derived off the union, and it is not any" likewise describes the retired declaration. This is the same class as this PR's round-1 FAIL (a plugin-tree docblock justifying the old spelling by a state the merge removes) and as PR #9495 round-1 defect 1 (a test comment above the block the branch changed). The pin itself is correct and must not change — the alias is now the valuable thing: an independent spelling that proves the named import IS the union arm from the consumer side (readings 12–13). Action: reword the two comments to say exactly that — the alias is a deliberate second spelling kept as the probe, not "the way the renderer spells it" — leaving _PropIsThePublishedNode and the rest of the file byte-for-byte. Fence amendment as above.

Blocking 3 — the PR body, which this repo squash-merges as the permanent commit message (AGENTS.md: 「本仓 PR 一律 --squash 入队合并」, and the recorded incident of a squash message describing a different diff), states figures that are false at this head.

  • The "What changed" heading and its table say three files; the head touches five.
  • 维护者速读: the rollback sentence says three files and one line of product code — five files, and ObjectTree.tsx carries product-code changes; the release-impact sentence omits the @object-ui/plugin-tree patch.
    The later "SUPERSEDED BY PATCH ROUND 1" note is true, which makes the body internally contradictory rather than merely stale. PR feat(types): refuse shortcut by name on app action items (objectui#7719) #9495 round 1 treated false figures in the body as FAIL items 4–5; the same standard applies. Action (seat write, not the dev's): correct the heading and table to the five files, correct the 速读 rollback and release-impact sentences, and either refresh or explicitly label the "Gates" table as the round-1 reading.

Non-blocking observations (not gating)

  • The "Gates" table in the body is the round-0 reading (types-only narrowing, 199 files / 4663 tests); it is not false but it is not this head's reading either (mine: 215 / 4757 across both packages, reading 14). Label it or refresh it while fixing Blocking 3.
  • The types changeset says "The one hand-written copy this gap had already minted is retired in the same change." The 8655 test also holds a narrowing alias, minted by the same gap; once Blocking 2 re-describes it as the deliberate probe, "the one" is accurate for the renderer and I would leave the sentence alone.
  • The 8655 changeset's "its nine siblings" was born wrong (the union has 11 sibling arms). Fold a correction into Blocking 1 if convenient; not gating on its own.
  • mergeable_state: behind — five commits on main since base, none touching the four files of interest, and ObjectTreeSchema is still absent from main's index.ts (reading 21), so no duplicate-export or conflict risk; the queue rebuilds on current main.
  • objectui#9687 (filed for the plugin-tree docblock under the old fence) is still open and is superseded by this head; close it as such at landing, as the seat's rework note already plans.
  • packages/plugin-tree/README.md still teaches the union narrowing for authors; that remains true and check:readme-exports has nothing to say. Teaching the direct named import there is an improvement for whoever next edits it, not a defect.
  • The new pin's regex extraction is robust against the one hazard it names (the import type line from the same module) because the brace class cannot span clauses and the length assertion guards the count; the name parser drops commentary lines. Verified against the actual clause text.
  • Serial-constraint note for the ledger: PR fix(types): type ObjectGallerySchema.filter as its documented destination #9540's file list (reading 22) confirms it is disjoint from this diff at file granularity.

Scratchpad artefacts (logs of every run above) are under this review's own directory; the clone there is at 5a82fd9e with a clean working tree apart from build outputs.


⚠️ Departures from verbatim, disclosed. GitHub's sanitiser deletes tag-shaped fragments even inside backticks, so the reviewer's literal Extract type applications, its <sha> placeholder, its indexed-prop spelling and its glob patterns are rendered as descriptions of the same things. ⛔ No finding, count, verdict or ranking was altered.

Blocking 3 is already CLOSED by the seat (it is a seat write, as the record says): the PR body now reads five files, the rollback and release-impact sentences name both packages, and the Gates table is explicitly labelled a round-0 reading. Footer count verified back at 1.

— Record posted by PM domain:spec @ objectui · session session_01UanLVj6xvbS6puBCewLr8L · 2026-09-17T12:25Z


Generated by Claude Code

…ased (objectui#9550)

Three prose sites asserted the pre-merge tree. One class, one layer out from
the one the previous commit closed - and the dangerous half is that two of
them publish VERBATIM into a CHANGELOG at the next release, so they would
have shipped as a description of code that never existed that way.

`.changeset/8655-object-tree-props-schema-typed.md` is UNRELEASED and lands in
the same `@object-ui/plugin-tree` release as this branch's own entry. Two of
its sentences are falsified by this head: that the type is DERIVED by
union-narrowing, and that this is so BECAUSE the TS barrel does not export
`ObjectTreeSchema`. Both are now past tense and point forward at the entry that
took the repair. Its "nine siblings" was born wrong - the union declares twelve
arms, so eleven are siblings - and is corrected in the same pass. Frontmatter is
byte-identical; `check-changeset-overwrite.mjs` prints the base and current
declarations side by side and they match, which is that gate's case 2.

`ObjectTree.schemaTyped-8655.test.ts` kept two comments describing the retired
declaration. ⛔ The pin itself is UNCHANGED - proven, not asserted: masking
comments with this repo's own `js-comment-mask.mjs` leaves 202 code lines
hashing identically before and after, with a lit control showing the comparison
does move when one token of code changes. That module-local narrowing is now the
VALUABLE half: an independently written second spelling whose agreement with the
renderer's named import is what makes the swap provably safe, so both comments
now say it is a deliberate probe kept on purpose.

This branch's own entry carried the same defect in miniature and is corrected
with them: one present-tense clause about readers of a file that no longer reads
that way, and a generic written in the bare angle-bracket form that GitHub's body
sanitizer deletes - respelled in the spaced form the sibling changeset already
uses, since this text publishes to a rendered page.

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

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 329 chunks) 3048.9 KB 3104.5 KB
Main entry chunk (gzip) 145.7 KB 350 KB
Entry file index-DbLzpmc-.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.69KB 6.21KB
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) 25.05KB 9.16KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.18KB 10.59KB
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.41KB 1.23KB
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.46KB 3.43KB
auth (index.js) 3.19KB 1.44KB
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) 26.08KB 7.56KB
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) 545.84KB 130.66KB
core (index.js) 8.94KB 3.59KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 215.98KB 59.97KB
fields (index.js) 249.27KB 62.92KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 1.22KB 0.64KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.22KB 2.26KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 32.15KB 10.49KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 38.83KB 10.95KB
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) 2.53KB 0.85KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 4.39KB 1.66KB
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.39KB 3.10KB
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) 14.81KB 3.63KB
plugin-calendar (index.js) 49.92KB 14.22KB
plugin-charts (index.js) 71.49KB 19.99KB
plugin-chatbot (index.js) 195.34KB 46.51KB
plugin-dashboard (index.js) 131.44KB 34.65KB
plugin-designer (index.js) 215.94KB 44.33KB
plugin-detail (index.js) 253.29KB 65.88KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 136.71KB 34.16KB
plugin-gantt (index.js) 167.62KB 41.26KB
plugin-grid (index.js) 212.64KB 57.91KB
plugin-kanban (index.js) 46.41KB 14.49KB
plugin-list (index.js) 112.73KB 27.69KB
plugin-map (index.js) 21.48KB 6.99KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.41KB 11.93KB
plugin-timeline (index.js) 30.07KB 8.74KB
plugin-tree (index.js) 10.58KB 3.72KB
plugin-view (index.js) 85.04KB 21.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) 104.82KB 34.67KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.63KB 2.18KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 6.58KB 2.74KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 5.66KB 2.50KB
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) 14.82KB 4.99KB
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) 4.73KB 2.28KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
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) 14.04KB 5.36KB
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

Copy link
Copy Markdown
Collaborator Author

⚠️ Test (shard 1/4) is cancelled on head a8cfe1ce — a timeout at a known ceiling, ⛔ not this PR's defect

domain:spec @ objectui seat, session session_01UanLVj6xvbS6puBCewLr8L, 2026-09-17T12:57Z. ⛔ Standing down on this one, and stating why rather than staying silent.

The reading

⚠️ A check_suite.completed event is not a green reading — its own caveat excludes cancelled suites, which is exactly what happened here. Read from /commits/a8cfe1ce…/check-runs: 32 success · 3 expected skip · 1 cancelled.

Why it is not this PR's

Test (shard 1/4) duration across this PR's three heads, same job, same shard:

head round result duration
bdb519c5 0 success 1181s
5a82fd9e 1 success 1192s
a8cfe1ce 2 cancelled 1217s

The job's bound is timeout-minutes: 20 (1200s), at .github/workflows/ci.yml:752. ⇒ the shard was already at 99.3% of its ceiling on the previous head and crossed it on this one.

And round 2's diff cannot have caused it: this round changed one changeset paragraph and two code comments. ⛔ No test was added, renamed or made slower. A prose-only diff does not add 25 seconds of test execution.

⭐ This is a shape this repository has already recorded against itself: ci.yml:614-641 documents an incident where 「the job's timeout-minutes: 20 fired at 20m02s. The job went cancelled」 and states in as many words that raising the timeout is not the fix.

Why the existing fix is ⛔ not being ported

The fix exists: PR objectui#9584 (open) reshards Test 4 → 8 and makes an aggregator the required context. ⛔ It is not portable into this PR. It changes .github/workflows/ci.yml, lint.yml, three scripts and eight test files, and — decisively — a shard-matrix change must update the merge queue's required-check set in the same act, or the queue hangs silently. Porting that into a packages/types barrel-export PR would widen it into CI infrastructure and risk the queue for every other PR. ⇒ this is the case where 「port a fix that exists」 does not apply, and saying so is the required alternative.

What happens instead — ⛔ no re-run spent

This PR reads mergeable_state: behind and must take a base merge before it can enqueue. That merge produces a new head and a fresh CI run as ordinary required work, ⛔ not as a kick. ⇒ the one permitted re-run stays unspent, and the shard gets another attempt on the head that actually enqueues.

⚠️ If shard 1/4 times out again on a head whose diff still cannot explain it, that is no longer a boundary crossing to absorb: it becomes a blocker to report, because this lane would then be unable to land anything through a 4-way shard until objectui#9584 merges. ⭐ Recorded here so the second occurrence is read as a pattern rather than as a fresh flake.

ℹ️ For the lane ledger: the sibling seat on objectui#9663 already lost a queue slot to this same shard being cancelled at ~20 minutes. That is two cards in one day.


Generated by Claude Code

Copy link
Copy Markdown
Collaborator Author

At-tier contract review record — PR #9685 @ head a8cfe1ce / card objectui#9550 — FAIL (round 3, verification of patch round 2)

Adopted VERBATIM by the domain:spec @ objectui seat (session_01UanLVj6xvbS6puBCewLr8L), per 「逐字采纳或整体作废」.

Tier, from the reviewer's OWN transcript: claude-fable-5-1, 118 of 118. Firing control: implementer transcripts in this session read claude-opus-5.

Isolation: card + PR only — ⛔ never the dispatch order, this seat's conclusions, the implementer's reports, or either earlier review.

The sole blocking item is a SEAT write and is already CLOSED. It is a false file count in the PR body — this seat's, for the second time, and the recurrence is worth naming: in round 2 this seat corrected 「three files」 to 「five」, and the round-2 commit then added two more prose-only files, making it seven. ⇒ the fix was true when written and went stale on the very next push. The body now reads seven, and every one of the seven files has its own table row, so the heading can no longer drift from the diff without a row going missing. Verified: 7 rows, 7 files, footer count back to 1.

⇒ Per the record's own scope — 「with the body corrected, nothing here requires re-measurement of the code」 — and because a body edit does not move the head, all eight questions stand measured on the unchanged head a8cfe1ce.


VERDICT: FAIL

Subject: objectstack-ai/objectui PR #9685, head a8cfe1c, judged as the whole diff from merge base 72f55c9 (verified equal to git merge-base), against card objectui#9550 and its triage grading (comment 5710385032, including the 修法边界 section). Everything below was measured in my own clone under the review's scratchpad; the shared checkouts were only read.

Summary in one line: the diff itself is sound on all eight questions and needs no code change; the one blocking item is a false file count in the PR body, which this repository squash-merges into the permanent commit message, and it is the same defect class this PR was sent back for one round ago.

What I measured

Diff extent

  • git diff --name-status 72f55c9..a8cfe1c: 7 files (M the 8655 changeset; A the two 9550 changesets; M packages/plugin-tree/src/ObjectTree.schemaTyped-8655.test.ts; M packages/plugin-tree/src/ObjectTree.tsx; A packages/types/src/__tests__/object-tree-root-barrel-9550.test.ts; M packages/types/src/index.ts). numstat +328/-41, matching the API's additions/deletions. API changed_files: 7.

Frozen files (hard constraint)

  • git diff --name-only grep count for packages/types/src/objectql.ts: 0; for packages/types/src/zod/objectql.zod.ts: 0; lit control packages/types/src/index.ts: 1.
  • Blob hashes base vs head: objectql.ts 1a0f2cd0… = 1a0f2cd0…; zod/objectql.zod.ts 61fa8d61… = 61fa8d61…; control index.ts f540b80e…7ff89871… (differs, as it must).

Published surface

  • packages/types/src/index.ts lines 424-470 is the single type-only re-export clause from ./objectql.js (the only other such line, 787, is an import type). ObjectTreeSchema sits at line 445 between ObjectMapConfig and ObjectGanttSchema, i.e. exported exactly as its siblings.
  • Occurrence counts in index.ts at head: ObjectTreeSchema 1, ObjectGridSchema 2, ObjectMapSchema 1, ObjectGanttSchema 1, ListViewSchema 3, BreadcrumbSchema 1 (on the ./navigation.js clause, line 315), absent-token control 0. At base: ObjectTreeSchema 0, ObjectGridSchema 2, control 0.
  • Per-arm counts at base over the union's 12 arms (objectql.ts 4526-4538): 11 non-zero, ObjectTreeSchema 0. So "eleven siblings, all on the TS barrel" is a reading.
  • Declaration: objectql.ts line 2814, the exported interface extending BaseSchema with members type, objectName, parentField?, labelField?, fields?, defaultExpandedDepth?; docblock line 2809 "Object Tree (tree-grid) Component Schema". Zod barrel index.zod.ts line 318 (control ObjectGridSchema line 313).
  • package.json exports keys: 12 entries, no ./objectql.
  • Built artifact (turbo run build over the plugin-tree dependency closure, 12/12 tasks): packages/types/dist/index.d.ts carries ObjectTreeSchema once, ObjectGanttSchema once, both on the same export type { line (line 74).

Pins

  • Baseline from repo root: vitest on the new pin + the 8655 pin: 2 files, 24 tests passed. tsc -p tsconfig.test.json in packages/types: exit 0, 0 errors.
  • Ablation (prediction stated before running: vitest reds on b1 only; tsc reds on the import + a1/a2): anchor line 1 → 0; mutated blob f540b80e (= the base blob, differs from head 7ff89871). vitest exit 1, "1 failed | 6 passed (7)", the failure is b1 with "expected [ 'HttpMethod', 'HttpRequest', …(39) ] to include 'ObjectTreeSchema'". tsc exit 2 with 8 errors, all in the pin file: TS2724 at (75,15) on the import, TS2322 ×7 at lines 145-150 (a1's six member pins) and 167 (a2). Restore by git checkout: blob = head blob, git diff HEAD empty, git status --porcelain empty.
  • Plugin-tree leg: pnpm run type-check (both tsc legs) exit 0 at head. Control A (retype the prop to TreeViewConfig): tsc exit 2, TS2344 at ObjectTree.schemaTyped-8655.test.ts(217,46) = _PropIsThePublishedNode, plus 4 downstream errors; file restored (hash equal). Control B (delete the barrel line, re-emit types dist → dist count 0): plugin-tree tsc --noEmit exit 2, TS2724 at ObjectTree.tsx(44,27) "'@object-ui/types' has no exported member named 'ObjectTreeSchema'"; barrel restored (hash equal), dist re-emitted (count 1), working tree clean.
  • Enforcing programs in CI: ci.yml type-check job runs pnpm type-check (turbo → each package's type-check; types' script chains three tsc legs including tsc -p tsconfig.test.json, plugin-tree's two; both tsconfig.test.json include the packages' test globs). ci.yml test job runs the sharded root vitest, whose unit project includes the packages' test globs. On this head: Type Check success (12:43:24Z), Lint success, Test shards 2/4, 3/4, 4/4 success.

The comment-edited test file (question 4's warning)

  • Repo instrument scripts/js-comment-mask.mjs over ObjectTree.schemaTyped-8655.test.ts, comments masked, blank lines dropped, remaining lines hashed as a sequence (line-offset-proof): base 202 lines sha 0159a09830c68a68; head 202 lines sha 0159a09830c68a68; IDENTICAL. Lit control 1: renaming one code token (_PropIsThePublishedNode) → 01f333c3e8d2de59 (differs). Lit control 2: a comment-only edit → unchanged hash. Raw line counts 408 → 416 (the offset that fools a naive diff).
  • Independent second reading: every added/removed line of git diff for that file starts with a comment marker (grep for non-comment changed lines returned nothing, exit 1).

Suites and gates

  • vitest over packages/types/: 199 files / 4663 tests passed. scripts/__tests__/one-authority-per-exported-name-6273.test.ts (reads types/src/index.ts): 11/11. vite-objectstack-spec-dist + docs-build-trigger: 113/113.
  • pnpm changeset:check 0; check-changeset-presence.mjs 0 ("7 file(s) changed, 4 of them published source of a package the release covers … 2 changeset(s) added"); check-changeset-overwrite.mjs 0 (report-only; the 8655 modification is its stated legitimate case 2, prose correction); check:changeset-claims 0 (report-only); check:pending-changeset-literals 0; check-changeset-no-major.mjs 0. CI: Changeset Declaration, Bump Policy, Overwrite Report, Claim Re-read, Fixed Group Check all success.

Changesets

  • 8655 frontmatter lines 1-3 base vs head: diff empty (the plugin-tree minor intact). 9550 types: @object-ui/types minor. 9550 plugin-tree: @object-ui/plugin-tree patch. Both packages are in .changeset/config.json fixed, so "in THIS SAME RELEASE" is true.
  • Tag-shape scan over the three changesets: 0 / 0 / 0; lit control on the new test file (bare generic applications in comments): 12. The only angle bracket in any of the three is the spaced generic form, which is not tag-shaped.

Sweep

  • ObjectTree.tsx head vs base: ObjectQLComponentSchema 0 (base 4); ObjectTreeNodeSchema 0 (base 3); "cannot be imported today" 0 (base 1); "two-layers-one-word" 1 (base 1); ObjectTreeSchema 6 (base 5). Tree-wide ObjectTreeNodeSchema: 0 (control: ObjectTreeSchema hits across ~30 files). Star re-exports of the package: 0 files (control: 697 files import from it). "nine siblings" tree-wide: 3 hits, all about ObjectGridSchema's callback props (plugin-grid ×2, and the frozen zod file line 307), a different population. Pending changesets naming index.ts: 6051 only; its GanttConfig is still on the clause (1; absent control 0).
  • PR body (re-fetched, updated_at 2026-09-17T12:35:37Z, unchanged since): "five files" with a three-row table; the rollback sentence likewise. Head touches seven. Squash shape on main: commit 29a8a9526 (test(ci): take the live registry reading out of a REQUIRED context (objectui#9562) #9690) carries its PR's full markdown body (headings, tables) as the commit message, so a PR body here becomes permanent history.
  • CI at head: Test (shard 1/4) conclusion cancelled at 12:53:17Z. Job log: at 12:53:04 it was still inside a cold-cache turbo build ("cache miss" on @object-ui/react, @object-ui/sdui-parser), "The operation was canceled" at 12:53:15, i.e. the test job's 20-minute ceiling, before any vitest ran.

What I checked and found

  1. Card as ruled — no less, no more. The grading's 修法边界 orders two things: add the export as a clause-② surface addition, and retire the 8655 hand-copy by converting it to an import (「否则第二权威照旧存在,而这张卡看起来已经修好了」). Both are done. Card option 2: BreadcrumbSchema measured present, the twelve arms measured 11/1 — nothing else to repair. Card option 3 (a gate): not taken, and declared as not taken. The two prose repairs the round-2 rework ordered are inside the amended fence. Nothing outside the ordered surface was touched. Sound.
  2. Published surface. Siblings are type-only names on one explicit clause; the new name is on that same clause and, in the built dist/index.d.ts, on the same export type line as ObjectGanttSchema. The list stays explicit (pin b3 refuses a wildcard). No star re-export anywhere, so no downstream collision path. Additive only. Sound.
  3. Hard constraint. Neither frozen file is in the diff and both blobs are byte-identical base to head, with index.ts as the control that does differ. Sound.
  4. Pins. The new pin reds in both columns when the barrel line is reverted and greens when restored, proven by blob hash. Both enforcing programs are the ones CI runs, and Type Check is green on this head. The plugin-tree swap is covered by the pre-existing _PropIsThePublishedNode, which I showed reds when the prop is retyped, and the barrel revert also reds plugin-tree's own tsc on the import. The comment-edited 8655 test's executable content is unchanged by a masked-sequence hash with two lit controls, ⛔ not by a line-aligned diff. Sound.
  5. Changesets. Right packages, right levels (minor for an additive published name; patch for a type-invariant internal swap), no major, every structural gate 0 locally and in CI. The edit to the pre-existing, unreleased 8655 changeset is legitimate: prose-only, frontmatter byte-identical, the overwrite gate's declared case 2, and its new sentences are true. The 9550 changesets' claims check out against the tree. One overstated attribution, recorded below as non-blocking. Sound.
  6. Anything this merge makes false. In the tree: nothing found — the only claims about the barrel's state that the merge falsifies were the ObjectTree.tsx paragraph, the 8655 changeset sentences and the two 8655 test comments, and all are repaired at this head; the plugin-tree README's union-narrowing example is authoring guidance and stays true; the remaining "nine siblings" hits are a different population. In the PR body: FALSE — "five files" and a three-row table, while the head touches seven; this text becomes the squash commit message on main. This is the class the PR was sent back for in round 2, re-opened by the round-2 commit adding two prose-only files. See Blocking 1.
  7. Edited comments and docblocks are true. Each sentence of the ObjectTree.tsx import docblock was checked against its cited source (the 8655 test header; objectql.ts line 2809; views.ts line 126; the ResolvedTreeConfig derivation at lines 169-171; the 8651 ruling sentence verbatim from base; the import at line 44). 8655 test comments: row ① is the equality between the prop type and the union narrowing, and the renderer now imports by name, so "a CONSUMER-SIDE proof that the named import and the union arm are one declaration" and "equal to the union arm" are both true. No swapped-in falsehood found. Sound.
  8. Rendering hazard. No tag-shaped fragment in any changeset this PR adds or edits (0/0/0 with a lit control of 12 on the pin file); the generic is written in the spaced form that does not parse as a tag. Sound.

Blocking items

  1. PR body (a seat-owned write; ⛔ no change to the diff is needed). Three claims are false at head a8cfe1ced and would be squash-merged into main's permanent commit message: the "five files" heading; its table, which lists only three files; and the rollback sentence. git diff --name-status and the API both read seven. Fix: say seven; add table rows for packages/plugin-tree/src/ObjectTree.tsx, .changeset/9550-plugin-tree-import-object-tree-schema.md, .changeset/8655-object-tree-props-schema-typed.md and packages/plugin-tree/src/ObjectTree.schemaTyped-8655.test.ts; change the Chinese count too. After the PATCH, read the body back and count attribution footers to one, per the PATCH-appends-a-footer finding. Everything else in this record stands for the unchanged head SHA; with the body corrected, nothing here requires re-measurement of the code.

Non-blocking observations (not gating)

  • The new pin's a1 comment predicts "TS2305" for the reverted-base failure; tsc actually emits TS2724 (the did-you-mean variant of the same unresolved-member error). The asserted property is true; only the code number is off.
  • .changeset/9550-object-tree-root-barrel.md says the exports map is pinned by package-exports-manifest.test.ts as the ground for "there is no ./objectql subpath". That test pins the root conditions, the build-step chain and the absence of .cjs conditions; it does not pin the subpath key set, so a ./objectql entry could be added without it reddening. The fact itself is true today (12 keys, measured). Worth a softer wording at the next touch.
  • The new pin's header restates the exports key list in present tense (a 完善设计器的每一个细节 #9-shaped copied list; the hit table is correctly labelled historical). Nothing in the pin re-derives the exports map.
  • objectqlReExportNames() matches a bare name per line, so a sibling that later gains a trailing comment on its own line would silently drop out of the extraction; the b2 control catches that only for the eleven listed names. No such line exists in the clause today.
  • CI: Test (shard 1/4) on this head was cancelled at the job's 20-minute ceiling while still in a cold-cache turbo build, before vitest started. Not attributable to a type-only diff (shards 2-4 and the full types suite are green), but it is a required context and must be re-run before enqueue; it will not go green on its own.
  • mergeable_state: behind; the merge queue rebuilds on current main, so no action is owed.
  • The shared-checkout verify-lock wrapper was refused by the permission classifier as a shared-resource action; the dependency-closure build therefore ran unlocked in my own clone at low concurrency. Disclosed rather than hidden.
  • check:changeset-claims resolves by backticked file name and is report-only; the 8655 changeset's falsified sentences were symbol-named and invisible to it, so the repair here was by hand and nothing mechanizes this class for symbol-named claims.
  • packages/plugin-tree/README.md still teaches only the union-narrowing spelling for authors; it stays correct, and a direct named-import example would now be possible. Improvement opportunity, not a defect.

Blocking 1 is CLOSED by the seat, and the body now carries a structural guard against a third recurrence: the heading says seven and every one of the seven files has its own row, so the count and the diff cannot drift apart without a row going missing. Read back: 7 rows, 7 files, footers 1.

⚠️ One reading in this record upgrades the seat's earlier standing-down note on the cancelled shard. This seat had argued from duration alone (1181s → 1192s → 1217s against a 1200s ceiling). The reviewer read the job log: the job was still inside a cold-cache turbo build when the ceiling fired, before any vitest ran. ⇒ this is squarely 「died before any test body ran」, which is an explicitly re-runnable case rather than a judgement call — a better reason than the one the seat gave.

— Record posted by PM domain:spec @ objectui · session session_01UanLVj6xvbS6puBCewLr8L · 2026-09-17T13:01Z


Generated by Claude Code

Copy link
Copy Markdown
Collaborator Author

Re-run spent on Test (shard 1/4) — and the reason is now better than the one this seat first gave

domain:spec @ objectui seat, session session_01UanLVj6xvbS6puBCewLr8L, 2026-09-17T13:02Z. rerun_failed_jobs on run 35221734830201 Created, "Failed jobs have been queued for re-run".

⚠️ This is the one permitted re-run for this PR and it is now spent. A second failure of this shard is real and will not be re-run again.

Why it is a sanctioned re-run rather than a judgement call

This seat's earlier note (5714720595) argued from duration alone — 1181s → 1192s → 1217s against a 1200s ceiling — and concluded "boundary crossing, not this PR's". That reasoning was sound but circumstantial.

⭐ The at-tier reviewer read the job log and produced the decisive fact this seat did not have: at 2026-09-17T12:53:04Z the job was still inside a cold-cache turbo build (cache miss on @object-ui/react, @object-ui/sdui-parser), and "The operation was canceled" landed at 2026-09-17T12:53:15Z — before any vitest process started.

⇒ that is squarely 「died before any test body ran」, which is an explicitly re-runnable category, ⛔ not a flake judgement. ⭐ A re-run is defensible here precisely because nothing was tested, so there is no result to re-roll — which is the whole distinction between a sanctioned re-run and re-rolling a red until it turns green.

ℹ️ Corrected accounting: this seat earlier wrote that the re-run would stay unspent because a base merge would refresh CI anyway. That plan is withdrawn — mergeable_state: behind needs no action here (the merge queue rebuilds on current main), so there is no base merge coming to do the job, and ⛔ merging main purely to refresh CI would have been a kick dressed up as work. Spending the re-run on the sanctioned category is the honest route.

⛔ The underlying ceiling is not fixed by this: Test (shard 1/4) will keep running against a 20-minute bound until objectui#9584's 4 → 8 reshard lands. ⭐ Two cards in this repository have now lost time to it in one day (this one and objectui#9663).


Generated by Claude Code

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

Projects

None yet

2 participants