fix(types)!: retire DetailViewSchema.related — author record:related_list (objectui#7997, Route C) - #8984
Conversation
… name (objectui#7997)
The member was declared `TableColumn[]`. `RelatedList.normalizeColumn` has a
dedicated bare-string branch — it resolves the name against the related
object's schema, derives the header from the field's `label` and attaches a
type-aware cell renderer — and `RelatedList.columnIdentityAccessor.test.tsx`
has pinned that branch for cards. So the renderer accepted two arms and this
declaration named one, and only on the typed authoring path: `DetailView`
reaches the renderer through `columns={related.columns as any}`, so the cast —
not the type — was carrying the string arm at runtime.
The member becomes `Array<TableColumn | string>`. Additive: the object arm is
untouched and the README's own related block is type-checked unchanged.
Two pins, in different programs and for different reasons:
`packages/types` — the DECLARATION. Mutual-assignability `Eq` on the member
(fails on the revert, on the `any[]` caricature and on over-rotating to
`string[]` alike), three `@ts-expect-error` refusals that hold the union
against `any[]`, a cross-face row asserting one `string[]` value assigns to
BOTH this member and `RecordRelatedListComponentProps['columns']`, and the zod
mirror's current reading with two live controls.
`packages/plugin-detail` — the BEHAVIOUR, authored through the real view type,
so a revert stops the file compiling rather than merely changing its meaning.
Its firing control was measured by ablating the string branch on disk, not
asserted.
Scope note: `@objectstack/spec` declares no `DetailView` schema — this is
objectui's own host-facing view schema. The spec-bound twin
(`record:related_list`, spec `z.array(z.string())`, objectui `string[]`) was
already aligned and is unchanged.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jmxdo7bmeqCQHLSfmLVX9w
…t it was expected to (objectui#7997) The firing control was run: the string branch of `RelatedList.normalizeColumn` was ablated on disk (guard widened so bare strings fall into the object branch), proved present by blob hash, and the pin was run against it — 2 failed | 2 passed, restored from the HEAD blob with `git diff HEAD` empty. Two of the three behaviour rows fired, and NOT the pair the header first claimed. The header derivation rows failed (`Unable to find an element with the text: SchemaLabel` / `…RenamedInSchema`); the type-aware CELL row stayed green, because the object branch attaches `makeCell` on the same terms and `columnIdentity` resolves a bare string. The header now names the measured split and the cell row is labelled for what it is — a non-regression control that the header assertions are read off a list that really rendered, not a firing row. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Jmxdo7bmeqCQHLSfmLVX9w
✅ Console Performance Budget
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
Size Limits
|
…ed_list` (objectui#7997)
Maintainer ruling 2026-09-10, quoted verbatim and untranslated:
关掉详情页那个入口(推荐)
This SUPERSEDES the widening this branch carried as Route A. `related` on a
`detail-view` node was objectui's own second entry to a capability the
protocol already governs, and `@objectstack/spec` declares no `DetailView`
schema at all — every `DetailView` occurrence in `packages/spec/src` is prose
about this repo's own `RecordDetailView.tsx`. So the array mirrored nothing
and drifted: it typed `columns` as `TableColumn[]` while the renderer it fed
also accepted bare field names and the `{ field, label }` / `{ name, label }`
spellings.
The axis that carried the ruling was measured ZERO PULL, not the alias
argument the dispatch offered — that argument was refuted on this branch and
is recorded as refuted in the pins so it is not repeated.
A NAMED REFUSAL, not a bare delete. `BaseSchemaCore` ends `.passthrough()`
and the TS `BaseSchema` closes with an any-valued index signature, so a
dropped member key is KEPT, not refused — deleting the declaration would have
left the silent accept exactly as it was (the mechanism objectui#7963
measured). `?: never` on the TypeScript face, `retirementTombstone()` on the
mirror, one guidance string feeding both the parse-time message and
`.describe()`. A pin authors an UNDECLARED sibling key through the same parse
and watches it survive, so that reasoning is a reading rather than a claim.
The entry closes at the renderer too, which is what the ruling asked for:
`DetailView` no longer reads `schema.related`, and the flat Related section,
the `autoTabs` Related tab, its trigger and its count badge are gone, as is
`related` from the `detail-view` registry `inputs` / `defaultProps`.
`RelatedList` itself, the `related-list` / `related_list` registrations and
`record:related_list` are untouched — both entries always rendered through
the same component, so nothing about the rendered result is lost.
Two shipped documents stop teaching the retired array and gain a migration
block each. The docs page had been teaching `{ name, label }` columns, a shape
the retired declaration itself never admitted.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jmxdo7bmeqCQHLSfmLVX9w
✅ Console Performance Budget
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
Size Limits
|
Contract reviewPR: #8984 · head reviewed: Everything below was measured in my own fresh clone ( Tier fuseHarness-stamped ① derived judgments1. The narrowing is exactly the second door, not the capability — CORRECT. The diff vs merge-base is 10 files. 2. Blast-radius method and count — CORRECT, reproduced. The method is sound for a narrowing: the repo-wide 3. Absence pin and its control legs — CORRECT, reproduced. 4. Restoration criterion — CORRECT. At ablation time HEAD was 5. Documentation. 6. Conversion rather than reopen — consistent. Title, body, changeset and the head commit all say Route C and why A and B lost; the two Route A commits are kept as the measurement trail, and 7. ⛔ The finding that decides this review: CI is red at this head, on this PR's own diff, and the dev's suite selection could not see it. ② semver
③ boundary flags
IndependenceSELF-REVIEW. The implementer and this reviewer are subagents of the same dispatch session. Under the regimen this is not an independent review and must not be recorded as one; it is a same-session, transcript-verified tier reading in which every dev claim above was re-measured rather than accepted. The verdict is not softened for it. Required before re-reviewAll on the docs / prose surface — no code-path change is asked for:
VERDICT: REWORK What I did not measure:
Generated by Claude Code |
…claims the review caught (objectui#7997) Contract review VERDICT: REWORK on PR #8984. Route C, the blast radius, the ablation, the grading and the scope split were all reproduced and upheld; this commit is the docs/prose surface it asked for. R1, the decisive one — CI was RED at the previous head on this PR's own diff and my suite selection could not see it. `scripts/__tests__/check-doc-links.test.ts` failed two rows because the two call-outs I wrote were `> #### …` headings INSIDE blockquotes. fumadocs' TOC counts a blockquoted heading; the gate's ATX scan (`/^#{1,6}\s+\S/`) cannot, so the two files read "39 headings, 38 ATX" and "22 headings, 21 ATX". They were the only `> #` headings in the whole md/mdx surface. Both now use this tree's idiom for exactly this call-out, `> **Retired: KEY** (objectui#NNNN, ADR-0049 …)`, which has 39 instances under `content/docs`. ⛔ The gate was not touched. Local: 121/121, rc 0 — the same count the reviewer measured at the merge base. R2, five precision fixes: 1. The changeset said `{ name, label }` was "a shape the retired declaration itself never admitted". True of the TypeScript face only. The retired ZOD face spelled the member `z.array(z.any())`, so the JSON document the docs page taught parsed green and rendered. The page was wrong for a TYPED author and right for a JSON author — a sharper defect than one bad example, and the changeset becomes CHANGELOG, so it now says so. 2. "the only entry" ignored `related-list`, still registered at `plugin-detail/src/index.tsx` against the same component with untyped `columns`. Every site now says "the only DECLARED / protocol-governed entry" — changeset, zod tombstone, TS tombstone, the types pin's describe, and the docs page. 3. `detail.related` is newly `[needs-review]` in the i18n report. The pack key is genuinely live through `containers.tsx`, so it stays; what was left dangling is `useDetailTranslation.ts`'s fallback row. Kept DELIBERATELY, with the reason in place: that map mirrors the `en` PACK, not this package's call sites, and dropping the row would leave the built-in Related page tab untranslated in exactly the no-I18nProvider case the map exists for. 4. `DetailView.tsx` no longer declares `isMobile` (its only consumer was the removed `defaultCollapsed`), and the now-unused `useIsMobile` import goes with it. 5. `deriveRelatedLists.ts`'s comment no longer calls `DetailView.related` "legacy" as though it were live. Both migration blocks also gain the sentence that makes them runnable rather than merely compilable: `record:related_list` reads the parent record from the record page's `RecordContext`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Jmxdo7bmeqCQHLSfmLVX9w
✅ Console Performance Budget
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
Size Limits
|
Contract reviewRound 2 (incremental) — PR: #8984 · head reviewed: Scope of this round is the delta Tier fuseOwn transcript ( CI at this head, read by this seat34 check runs, 34 completed: 31 ① derived judgments — the deltaR1 — the two blockquoted headings: FIXED, correctly. Both call-outs now use the tree's own idiom ( R2.a — the R2.b — "only DECLARED / protocol-governed entry": ACCURATE, and applied at every site (changeset, R2.c — ⛔ the retained
R2.d / R2.e — routine: Migration blocks — the runnable sentence: TRUE. ② semverUnchanged from the previous verdict: ③ boundary flags — the three self-reported items
IndependenceSELF-REVIEW. Implementer and reviewer are subagents of the same dispatch session; this is not an independent review and must not be recorded as one. Every delta claim above was re-measured, not accepted, and the verdict is not softened for it. Required before re-reviewExactly one item, docs-surface, one comment: R2.c — either drop the VERDICT: REWORK What I did not measure this round:
Generated by Claude Code |
… reason I wrote for keeping it was false (objectui#7997)
Incremental contract review returned REWORK on one item, and it overturned me
correctly. Keeping the row was a defensible CALL; the justification I committed
next to it was not TRUE, and this whole family of cards is about source that states
something false about itself.
What I had written: that `@object-ui/components` `containers.tsx` resolves the
built-in Related page tab through this map, so dropping the row would leave it
untranslated with no I18nProvider mounted. Re-measured on my own clone, all
three legs, and every one refutes it:
- `DETAIL_DEFAULT_TRANSLATIONS` has exactly ONE runtime consumer, the
`createSafeTranslation(...)` call in this same file. Every other tree-wide
occurrence is a test, a comment, or the barrel re-export.
- `@object-ui/components` declares NO dependency on `@object-ui/plugin-detail`
— not in `dependencies`, `peerDependencies` or `devDependencies` — so it
could not reach this map even if it wanted to.
- `containers.tsx:491` resolves that label with `useSafeTranslate()` from
`@object-ui/i18n`, whose contract (`useSafeTranslation.ts`) is: try each
key, and with no provider return the POSITIONAL English fallback. The token
`Related` is itself that fallback, stated in the call site's own comment.
And the decisive one: after this card removed the render branch, NOTHING in
`plugin-detail` resolves `detail.related` any more — the only textual
occurrences left were the row and my own comment about it.
So the row is genuinely unreachable from its only consumer, and it goes. The
PACK key stays live through `containers.tsx`, which is a different surface; the
i18n report confirms the split — `detail.related` still lists
`components/renderers/layout/containers.tsx` and no longer lists
`useDetailTranslation.ts`, while its neighbour `detail.relatedRecordOne` still
does.
Deletion was checked against the contract that actually governs this map before
committing: `app-shell/src/__tests__/defaults-maps-mirror-en-pack.test.tsx` is
15/15 green with the row gone — its byte-identity case judges rows the map HAS,
so removing one is permitted, and its sentinel rows are the
`detail.showEmptyRelated*` trio, not this key.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jmxdo7bmeqCQHLSfmLVX9w
✅ Console Performance Budget
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
Size Limits
|
Contract reviewRound 3 (incremental, R2.c only) — PR: #8984 · head reviewed: Scope: the delta Tier fuseOwn transcript ( CI at this head, read by this seat34 check runs, 34 completed: 31 ① derived judgments — the delta1. The deletion is correct and complete. In 2. The i18n-report contrast IS a real control. Re-run at this head ( 3. "Check the governing contract before deleting" — the reasoning is right, and it is the test's own shape. ② semverUnchanged: ③ boundary flags
IndependenceSELF-REVIEW. Implementer and reviewer are subagents of the same dispatch session; this is not an independent review and must not be recorded as one. The delta was re-measured, not accepted, and the verdict is not softened for it. VERDICT: PASS What I did not measure this round:
Generated by Claude Code |
Part of objectui#7997.
Session provenance, in prose and as a code span because a footer link does not reliably survive an edit:
session_01Jmxdo7bmeqCQHLSfmLVX9w.Rework round — contract review returned REWORK, and this is what moved
Review:
5621736903. Route C, the blast radius, the ablation, theminorgrading and the scope split were all re-measured in the reviewer's own clone and upheld — the rework is entirely on the docs / prose surface, plus two dead residues. No code path changed.R1, the decisive one, and my mistake: CI was RED at the previous head, on this PR's own diff, and my suite selection could not see it.
scripts/__tests__/check-doc-links.test.tsfailed two rows because the two call-outs I wrote were> ####headings inside blockquotes. fumadocs' TOC counts a blockquoted heading; the gate's ATX scan cannot, so the two files read "39 headings, 38 ATX" and "22 headings, 21 ATX". They were the only such headings in the entire md/mdx surface. Both now use this tree's idiom for exactly this call-out —> **Retired: KEY** (objectui#NNNN, ADR-0049 ...), 39 instances undercontent/docs. ⛔ The gate was not touched. Local re-run: 121 of 121 passed, rc 0 — the same count the reviewer measured with the two files at their merge-base blobs.Two process lessons, recorded because they are the reusable part:
scripts/__tests__/too. That directory is the docs gates' own self-test surface, and it was in none of the suites I picked. I pickedpackages/andapps/; CI runs everything.Test (shard 2/4)was still running — it finished red at 15:49:27. "My suites are green" is not "this head is green": my suites are the ones I chose. This round waited for all 34 checks to reach a terminal state before the report was written, and the counts are in it.Second rework round — one item, one comment, and I was overturned
Review:
5622684649. Everything else passed: the R1 heading fix,scripts/untouched, 121/121, zero> #residue tree-wide, pins 49/49, the two-faces statement about{ name, label }, every "only declared / protocol-governed entry", the migration sentence, and both of my self-reported readings (the timeout disposition and the lint separation) were reproduced and upheld.The one item: I kept
useDetailTranslation.ts'sdetail.relatedfallback row and wrote a reason next to it that is FALSE. Keeping it was a defensible call; the justification was not true, and this whole family of cards is about source that states something false about itself — so leaving a false comment in the source of the PR that repairs a false docs page is self-contradictory. Re-measured on my own clone, all three legs, and every one refutes what I wrote:DETAIL_DEFAULT_TRANSLATIONShas exactly one runtime consumer — thecreateSafeTranslation(...)call in that same file. Every other tree-wide occurrence is a test, a comment, or the barrel re-export.@object-ui/componentsdeclares no dependency on@object-ui/plugin-detail— not independencies,peerDependenciesordevDependencies— so it cannot reach that map at all.containers.tsxresolves the built-in Related tab throughuseSafeTranslate()from@object-ui/i18n, whose contract is: try each key, and with no provider return the positional English fallback. The tokenRelatedis that fallback, as the call site's own comment says.And the decisive one: after this card removed the render branch, nothing in
plugin-detailresolvesdetail.relatedany more — the only textual occurrences left were the row and my own comment about it.⇒ The row is deleted. The pack key stays live through
containers.tsx, which is a different surface, and the i18n report confirms the split:detail.relatedstill listscomponents/renderers/layout/containers.tsxand no longer listsuseDetailTranslation.ts, while its neighbourdetail.relatedRecordOnestill does. Deletion was checked against the contract that actually governs that map before committing —app-shell/src/__tests__/defaults-maps-mirror-en-pack.test.tsxis 15/15 green with the row gone, because its byte-identity case judges rows the map has, and its sentinel rows are thedetail.showEmptyRelated*trio, not this key.The reviewer's own self-reported gap, now closed with a reading rather than an inference. It noted that the timed-out case had not been named, so "contention" was inferred. The case is
scripts/__tests__/check-readme-exports.test.ts > the PARTIAL_EXCERPTS ledger, as it stands in this repository > hides ONLY omissions, at every declaration the tree can judge — in ANY build state, and it is now measured on both sides of the same budget:A 2.8x slowdown on one case under a saturated box. That is contention as a reading, ⛔ not as a story — and it reproduced twice, at 15944ms and 15786ms, in two independently scheduled long runs. CI's
Test (shard 1/4), which owns that file, issuccessat this head.R2, five precision fixes:
{ name, label }claim was half wrong. It was never admitted by the retired TypeScript face (TableColumnrequiresheaderandaccessorKey) — but the retired zod face spelled the memberz.array(z.any()), so the JSON document the docs page taught parsed green and rendered. The page was wrong for a typed author and right for a JSON author. That is a sharper defect than one bad example — the two authoring faces of one member disagreed about what a column is — and since a changeset becomes CHANGELOG, it now says exactly that.related-list, still registered inplugin-detail/src/index.tsxagainst the same component with untypedcolumns. Every site now reads "the only declared / protocol-governed entry": changeset, both tombstones, the types pin, and the docs page.detail.related— I first keptuseDetailTranslation.ts's fallback row. ⛔ That was corrected in a later round: the row is deleted. See the section below; the keeping was defensible, the reason I wrote beside it was not true.DetailView.tsxno longer declaresisMobile— its only consumer was the removeddefaultCollapsed— and the now-unuseduseIsMobileimport goes with it.deriveRelatedLists.ts's comment no longer callsDetailView.related"legacy" as though it were live.Both migration blocks also gained the sentence that makes them runnable rather than merely compilable:
record:related_listreads the parent record from the record page'sRecordContext, so a block authored off a record page scopes to nothing and renders empty.The first revision of this branch widened
DetailViewSchema.related[].columnstoArray of (TableColumn OR string)— Route A. That is superseded. The maintainer ruled Route C: retire the surface, recorded at objectui#79975620774833, verbatim and untranslated because a paraphrase is a different ruling:The Route A commits are kept in history on purpose rather than rebased away: they are the measurement that produced the analysis the ruling was taken on, and the review trail that goes with it. The branch was converted rather than closed-and-reopened for the same reason — the ruling comment names conversion, and a new PR would strand that trail.
Why A lost, in one line: no axis supported it. The full four-axis analysis is at
5620459298; "it is already implemented and green" was explicitly not allowed to act as a fifth axis. Why B lost: it is Route A's problem one step further — strictly mirroring the protocol asstring[]would still have left two shipped documents teaching object columns, and it would still have been a second door.relatedaway totabs— was refuted on this branch: the alias lives inRecordPageSchema.slots, a slot-name map (header | actions | alerts | highlights | details | tabs | discussion), and says "if you name a SLOTrelated, we mean thetabsslot". It matched the word. The refutation is recorded in the pins so the argument is not repeated by the next reader.What changed
Two declaration faces,
@object-ui/types:DetailViewSchema.related(views.ts)?: never— a tombstoneviews.zod.ts)z.array(z.object(...))retirementTombstone(guidance)The renderer entry,
@object-ui/plugin-detail— this is the half the ruling actually names.DetailViewno longer readsschema.related: the flat Related section, theautoTabsRelated tab, its trigger and its count badge are gone, andrelatedis off thedetail-viewregistry'sinputsanddefaultProps.Untouched, and pinned as untouched:
RelatedListitself, therelated-listandrelated_listregistrations,record:related_list, andRecordRelatedListComponentProps(columns: string[], already mirroring the protocol). Both entries always rendered through the sameRelatedListcomponent, so nothing about the rendered result is lost — only the second door.⛔ A named refusal, not a bare delete — and that is measured, not asserted
BaseSchemaCoreends.passthrough()and the TypeScriptBaseSchemacloses with an any-valued index signature. A dropped member key is therefore KEPT, not refused: deleting the declaration would have left the silent accept exactly as it was and thrown the diagnostic away with it. That is the mechanism objectui#7963 measured, and this PR does not take it on faith — a pin authors an undeclared sibling key through the very same parse and watches it come back out intact:One guidance string feeds both the parse-time issue message and
.describe(), so what an author reads and what generated docs publish cannot drift apart. The message namesrecord:related_listand objectui#7997, and a pin asserts both — a refusal an author cannot act on is half a refusal.The consumer sweep — a NARROWING, so the blast radius is named, not assumed
turbo run type-check --concurrency=2repo-wide: 81 successful, 81 total. But that is green after the in-repo consumers were converted, so on its own it names nothing. The blast radius was measured separately by restoring the pre-conversion consumer against the retired declaration:⇒ Exactly two call sites break, both in one test file, and zero production call sites in 81 type-check programs. Both were converted:
should render related lists when providedbecame an absence row, andshould use i18n fallback for related section headingwas absorbed into it, since its whole subject was a heading that no longer exists.relatedis a worthless probe here and fails towards "live". These are all live and all untouched:buildDefaultPageSchema's ownrelatedoption inplugin-detail/src/synth/(which emitsrecord:related_listnodes),RecordDetailView'ssynthParts.relatedin@object-ui/app-shellwhich feeds it,relatedListColumns,autoDiscoverRelated,RelatedRecordActionsContext, and thedetail.relatedi18n key, still read bycontainers.tsx. A grep reports many "consumers"; none of them is this member.The firing control, MEASURED
An absence pin that cannot fail is decoration. The retirement was ablated on disk by restoring
DetailView.tsxfrom the pre-retirement commit — entry open again, everything else unchanged — proved present by blob hash and by an on-disk marker count, then the pin was run against it.Every absence row fired, and only those:
renders no related section, no heading and no rows—expected document not to contain element, found SPANgrows no Related TAB either, under autoTabs—expected document not to contain element, found BUTTON(the tab trigger)with ONLY the retired key authored, autoTabs renders no tab strip at all—expected [ BUTTON, ...(1) ] to have a length of +0 but got 2The two rows that stayed green are the controls, correctly: "the rest of the node renders" and "the SAME RelatedList still renders a related list" are true on both sides of the ablation. That is what separates the door closed from the component broke and from the room is gone.
git diff HEAD— which is non-empty here by construction, because the retirement is the diff. That distinction is the whole reason the saved-blob comparison exists.Documentation — in scope, and it had a pre-existing defect
Two shipped documents taught the retired array; both are rewritten with a migration block:
packages/plugin-detail/README.md— the tutorial example dropsrelated, the schema tour dropsrelated: [], and the RelatedList section gains a migration block showing therecord:related_listreplacement.content/docs/api/schema-reference.md— the authored JSON block drops"related", the property-table row is marked RETIRED with the remedy, and a migration block follows the table.content/docs/guide/building-crud-app.mdauthors adetail-viewnode but never authoredrelated, so it needed no change — stated rather than silently skipped.{ "name": ..., "label": ... }columns, and the two faces disagreed about that shape. The retired TypeScript declaration never admitted it; the retired zod mirror (z.array(z.any())) did, so that JSON document parsed green and rendered — the page was wrong for a typed author and right for a JSON author. The runtime accepted it either way (columnIdentityfoldsname,columnHeaderfoldslabel). Repairing it was in scope under C and is done here.tsxfence.check-doc-snippet-typesfailed with 15 TS1xxx parse errors and, correctly, refused to report a semantic pass over a block it never reached. Fixed, re-run, 639 of 639 blocks judged, 0 failed.Verification
CI, at terminal state. Head
8348568f9: 34 of 34 checkscompleted— 31success, 3skipped, 0 non-passing.Test (shard 2/4), the check that was red two heads ago, issuccessat 18:17:42Z, andTest (shard 1/4)— which owns the locally-timing-out file — issuccessat 18:20:23Z. (Previous head9835365e1read the same: 34/34, 31 success, 3 skipped, 0 non-passing.)Lint,Type Check,Build Docs,Doc Snippet Type Check,Internal Docs Link Checkand shards 1/3/4 allsuccess. The threeskippedare the coverage-shard matrix placeholder and two conditional jobs, skipped at 16:53:05Z before any of this PR's work ran.Local readings from head
8348568f9unless a row says otherwise.vitest run scripts/__tests__/ packages/types/ packages/plugin-detail/ packages/app-shell/scripts/__tests__/check-readme-exports.test.ts87 of 87 passedvitest run scripts/__tests__/check-doc-links.test.tsvitest run packages/types/ packages/plugin-detail/ apps/console/(previous head)turbo run type-check --concurrency=2(repo-wide)turbo run lint(types + plugin-detail + app-shell + root)isMobileremoval)check-changeset-presencecheck-doc-snippet-typescheck-sdui-registration-pinscheck-readme-exports·check-doc-component-types·check-doc-fence-languagescheck-doc-links·check-i18n-dead-keys·check-control-bytes·check-new-cross-file-line-citations·check-shell-escape-residueEvery exit code was captured to a file before any pipe.
check-readme-exports.test.tsfailed one row withError: Test timed out in 15000ms— the row took 15944ms against a 15000ms budget inside a run that held the shared verify lock for 26m06s. Re-run alone it is 87 of 87 passed in 28s of lock time, and CI'sTest (shard 1/4)— which owns that file — issuccess. So: a contention timeout on a saturated shared box, ⛔ not a flake to be papered over and ⛔ not a reason to raise a timeout. Recorded rather than dropped, because "one red row" and "one red row I decided to ignore" must not look the same.error— five of them, all inapp-shell, and every one is printed source context inside a warning (console.error(...),error: null,error: initialError ?? ...), not a diagnostic. The authoritative read is eslint's own summary line per task, and all four say0 errors. Separated deliberately: grepping the word alone would have reported this clean run as dirty.Changeset
@object-ui/types: minor.@object-ui/plugin-detail: minor. Breaking, gradedminorby this repo's convention — amajorwould drag the whole 39-package fixed group off@objectstack's cadence. A document that authoredrelatedused to parse green and render a section; it now reds at that key and renders nothing.验收备注 — noted, not filed
1.
record:related_listhas the mirror-image mismatch, and it is explicitly NOT in this PR. It declarescolumns: string[](correctly mirroring the protocol) whilerenderers/record-related-list.tsxfolds{ field }/{ name }/{ key }objects throughcolName— runtime wider than declaration. The ruling names it as carried forward and needing its own answer. Withrelated[]retired it becomes the only declared entry, so it stops being second-order. ⛔ Untouched here.2.
record:related_list.actions— asked explicitly, answered: no. This change givesactionsno read site.apps/console/src/__tests__/registry-inputs-spec-parity.test.tswas not touched, and it contains nodetail-viewreference at all.3. The
detail.relatedi18n key is still live and deliberately not removed:packages/components/src/renderers/layout/containers.tsxstill reads it for the page-tabs built-in label.check-i18n-dead-keysis green.🤖 Generated with Claude Code
https://claude.ai/code/session_01Jmxdo7bmeqCQHLSfmLVX9w
Generated by Claude Code