Skip to content

fix(types): declare hideEmpty on the record:details section mirror and hold the member set to the spec (objectui#12348) - #12388

Merged
objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-12348-details-sections-mirror
Oct 14, 2026
Merged

objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-12348-details-sections-mirror

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #12348
Clause-②: yes — this widens the accept set of the published @object-ui/types type RecordDetailsComponentProps.sections[] by one member, hideEmpty, to follow the spec row. The seat's claim takes the stricter reading over triage's no, so a contract review is owed before the queue.

Contract review: what the section type accepts, against the installed spec

The spec was measured at the PR head (80506a725, after merging main with objectui#12370): @objectstack/spec 18.0.0-next.1. It was measured first at base d75f21285 on 18.0.0-next.0, and both versions declare the same thirteen section members. The member list was read off RecordDetailsProps.shape.sections element shape in node_modules, not copied from the card.

spec RecordDetailsProps.sections[] member spec type @object-ui/types before after
name string, optional declared unchanged
label I18nLabel, optional declared unchanged
columns int 1-4, optional declared unchanged
group string, optional declared unchanged
fields string array, optional declared unchanged
hideEmpty boolean, optional missing (TS2353) added, boolean
collapsible boolean, optional declared unchanged
showBorder boolean, optional declared unchanged
defaultCollapsed boolean, optional declared unchanged
icon string, optional declared unchanged
description string, optional declared unchanged
headerColor six-token enum, optional declared unchanged
count object with field, optional declared unchanged

hideEmpty is the only member added, and nothing is removed. The type now declares exactly the spec's member set.

Still refused on a typed section literal: any key the spec does not declare on the section. That includes the retired collapsed (objectui#8583 item 2) and any misspelling. The type has no index signature, so excess-property checking still applies. The pin's refusedByTsc and retiredSpellingRefusedByTsc literals still compile only through their @ts-expect-error directives. Cross-key rules (fields versus group, count needing a label hole) stay the spec parser's job, the same as before. The type does not encode them.

The ruling this follows: objectui#7129 Q1-A rested on "the spec refuses hideEmpty". The director's dated note on #7129 records that premise as superseded by the objectui#8603 ruling (batch #137 item 3): spec 17.3.0+ declares the key, and objectui follows the protocol. RecordDetailsRenderer already reads it as s.hideEmpty ?? true, so nothing changes at runtime.

What changed

  • packages/types/src/record-components.ts: the section entry declares hideEmpty?: boolean, with a doc comment covering the renderer default, false semantics, and that it is permitted beside group.
  • packages/types/src/__tests__/record-details-section-members-8583.test.ts (the types: RecordDetailsComponentProps.sections[] omits six member keys @objectstack/spec 17.3.0 declares, and declares one (collapsed) the spec refuses — a spec-valid section does not type-check #8583 pin), extended so the mirror cannot drift in either direction:
    • _HideEmpty: an invariant Equal of the member's type against the spec's z.input type.
    • _KeySetMirrorsSpec: Equal of keyof Section and keyof SpecSection. It goes red under type-check on a missing member or an extra one.
    • _EveryMemberTypeMirrorsSpec: a mapped Equal over every spec member, so a member added later on both sides is held to the spec's type without anyone writing a new line.
    • MIRRORED_SECTION_KEYS is tied to the type by _ListIsTheTypesKeySet. A vitest case then asserts that list equals the installed spec's section keys, sorted, so drift in either direction is also red under vitest, which strips types.
    • A runtime case: hideEmpty: false parses clean and survives the parse, both on an enumerated section and beside group. A control on the same position refuses a non-boolean value with invalid_type at sections.0.hideEmpty.
  • packages/types/src/zod/objectql.zod.ts: the object-grid emptyState describe now reads { title, message, icon, link }. This is a text-only change: the schema is the spec EmptyStateSchema by reference, and that schema's shape has four keys on both next.0 and next.1.
  • apps/console/src/__tests__/registry-inputs-spec-parity.test.ts: the MEMBER_PINS row object-grid.emptyState now says three of the four members are pinned there and names link's pin, ObjectGrid.emptyStateLink-12270.test.tsx. This too is a text-only change inside a string literal.
  • .changeset/12348-details-sections-mirror.md: @object-ui/types minor.

Verification (head 80506a725)

  • packages/types pnpm type-check (all three legs: tsc --noEmit, examples, tsconfig.test.json): exit 0.
  • pnpm exec vitest run packages/types/ apps/console/src/__tests__/registry-inputs-spec-parity.test.ts: Test Files 381 passed (381), Tests 10577 passed (10577). The console file alone, run at the first commit: 255 passed (255).
  • Pre-tsc battery, each pnpm check:NAME exit 0: phantom-deps, self-import, unreferenced-sources, doc-example-readers, handler-key-reads, side-effects-array, element-data-source-declaration, spec-symbols, action-forward-parity, designer-field-key-parity, icon-record-names, i18n-keys, i18n-drift, i18n-designer-parity, new-line-citations. Also exit 0: node scripts/check-changeset-fixed.mjs and node scripts/check-changeset-presence.mjs.
  • check:spec-floors: exit 1, "The scan collapsed: 0 package(s) declare @objectstack/spec in a consumer-facing field". This failure is already on main (objectui#12334). It is recorded here and left as it is.
  • Lint, narrowed to the four changed .ts files: eslint --no-inline-config --format json returns 4 files in its JSON (none ignored by the config), with 0 errors and 1 warning. The warning is the existing no-explicit-any on the base file's Equal of any direction proof. eslint.config.js sets no parserOptions.project / projectService, so linting is not type-aware and this diff cannot move the verdict on any untouched file. The repo-wide pnpm lint is left to CI.
  • NOT MEASURED: console type-check. The reason is PREREQUISITE NOT MET: the workspace dist/ for the console's dependency closure is not built in this container, so all 726 errors are module-resolution errors (Cannot find module '@object-ui/...') and their cascades. The run never reached the console's own types. The console edit is a text change inside a string literal. Declared to CI.

Ablations (one-off, each mutation verified on disk by ablation-replace.mjs and restored to the HEAD blob with git diff HEAD empty)

  1. The base type with the new pin. Deleting hideEmpty?: boolean; from the type made tsc -p tsconfig.test.json exit 2 with errors on _HideEmpty (TS2339), _KeySetMirrorsSpec, _EveryMemberTypeMirrorsSpec and _ListIsTheTypesKeySet (TS2344), and TS2353 on both new hideEmpty literals. This is the card's own TS2353.
  2. The other direction. Adding a member the spec lacks (extraKeyTheSpecLacks?: boolean) made it exit 2 with errors on _KeySetMirrorsSpec and _ListIsTheTypesKeySet. The first two attempts at this leg were no-ops: in each, the replacement text still contained the anchor, so the tool refused with "a drop of 0" and nothing was measured. The third attempt changed the anchor text itself.
  3. The runtime half. Dropping 'hideEmpty' from MIRRORED_SECTION_KEYS made vitest fail 1 test of 9, the new set-equality case, with the diff naming "hideEmpty".

Acceptance notes (observations, not filed)

  • The spec's sections[].count describe still reads "[EXPERIMENTAL — not enforced] … until the record detail renderer reads it", while this type's count doc says RecordDetailsRenderer fills the hole (objectui#12192). This is spec-side describe text and outside this card's file surface. Carrier: none.
  • The section entry's collapsible member has no doc comment, unlike its neighbours. This is polish only, and it is not changed here.

Overlap

PR #12380 (another .describe() in objectql.zod.ts) landed before this branch merged main, and the auto-merge was clean.


Generated by Claude Code

…and hold the member set to the spec

`RecordDetailsComponentProps.sections[]` omitted `hideEmpty`, which
`@objectstack/spec` declares on the section and `RecordDetailsRenderer`
reads, so a spec-valid section failed to type-check with TS2353. The
section-member pin now holds the whole member set (keys and each member's
type) to the installed spec in both directions.

Also: the `object-grid` `emptyState` describe and its MEMBER_PINS row now
account for the spec EmptyStateSchema's fourth member, `link`.

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

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 69 chunks) 3073.9 KB 3119.4 KB
Main entry chunk (gzip) 73.8 KB 350 KB
Entry file index-BRLuHJV6.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) 20.90KB 7.67KB
app-shell (runtime-config.js) 22.59KB 7.89KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.11KB 3.87KB
auth (ActiveOrganizationStorage.js) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.22KB 10.61KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.40KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.72KB 2.24KB
auth (SocialSignInButtons.js) 9.70KB 3.93KB
auth (UserMenu.js) 3.39KB 1.21KB
auth (auth-gate-events.js) 1.62KB 0.83KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 41.19KB 11.12KB
auth (createAuthenticatedFetch.js) 8.54KB 3.46KB
auth (index.js) 3.63KB 1.64KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 27.26KB 8.03KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.28KB 2.60KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (commentAuthorship.js) 1.39KB 0.78KB
collaboration (index.js) 1.93KB 0.85KB
collaboration (useCollaborationTranslation.js) 6.50KB 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) 591.65KB 142.68KB
core (index.js) 10.18KB 4.04KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 248.41KB 69.48KB
fields (index.js) 282.89KB 72.11KB
i18n (LocalizationContext.js) 2.92KB 1.42KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 2.59KB 1.22KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.52KB 2.39KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.35KB 12.88KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 36.87KB 9.88KB
i18n (useSafeTranslation.js) 7.14KB 2.92KB
layout (index.js) 40.26KB 11.71KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 6.62KB 2.45KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 5.52KB 2.10KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 15.35KB 5.51KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.82KB 2.38KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.33KB 3.07KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 16.04KB 3.92KB
plugin-calendar (index.js) 54.94KB 16.05KB
plugin-charts (index.js) 84.72KB 23.27KB
plugin-chatbot (index.js) 201.72KB 48.07KB
plugin-dashboard (index.js) 143.63KB 38.79KB
plugin-designer (index.js) 233.77KB 50.02KB
plugin-detail (index.js) 259.78KB 68.65KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 179.38KB 46.59KB
plugin-gantt (index.js) 178.36KB 45.08KB
plugin-grid (index.js) 259.02KB 72.24KB
plugin-kanban (index.js) 53.23KB 16.71KB
plugin-list (index.js) 123.35KB 31.60KB
plugin-map (index.js) 27.07KB 8.96KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 46.66KB 13.13KB
plugin-timeline (index.js) 39.21KB 11.85KB
plugin-tree (index.js) 15.07KB 5.33KB
plugin-view (index.js) 91.99KB 23.23KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 12.07KB 3.68KB
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) 120.63KB 39.56KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.50KB 2.06KB
react (schema-input.js) 4.31KB 2.07KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.50KB 1.99KB
sdui-parser (codegen.js) 9.45KB 3.76KB
sdui-parser (dashboard-widget-options.js) 3.07KB 1.30KB
sdui-parser (index.js) 7.30KB 3.12KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 25.28KB 7.81KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.29KB 0.24KB
sdui-parser (validate.js) 23.87KB 7.83KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 4.12KB 1.61KB
types (authoring-nodes.js) 0.20KB 0.19KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (cloud.js) 0.20KB 0.18KB
types (complex.js) 4.44KB 2.07KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (dashboard-widget-layout.js) 2.06KB 0.96KB
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) 1.13KB 0.65KB
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) 5.78KB 2.70KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 5.00KB 2.39KB
types (navigation.js) 0.20KB 0.18KB
types (node-slots.js) 7.18KB 2.34KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 2.52KB 1.31KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-approval-decision.js) 0.20KB 0.20KB
types (record-components.js) 0.20KB 0.19KB
types (record-panels.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) 4.99KB 1.96KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 19.93KB 7.26KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.48KB 3.50KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

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

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 80506a725c213adc1ae1f3c841c5c3a507a45dd7
Local-runs: probe — one node -e against node_modules/@objectstack/spec in the read-only checkout to read the section key set; the checkout has no node_modules, so nothing loaded and nothing was measured. The verdict rests on the diff, the card and the head's check-runs alone.

Inputs read: card #12348 (body and all four comments: 6161115787, 6161914173, 6176655336, 6177528145), PR #12388 (body, five-file list, per-file patches against main), and the 33 check-runs on 80506a725: every run that executed is success (Type Check, Lint, Test and all twelve shards, Test (dist pins), Build & E2E, Build Docs, Spec Main Shape Gate, Repo Gates, Line Citation Gate, Governed Surface Queue Guard, Changeset Declaration, Changeset Claim Re-read, Changeset Bump Policy, Changeset Fixed Group Check, Changeset Overwrite Report, Bundle Analysis, label, Live E2E (informational)); the four skipped are the coverage legs and dependabot, skipped by design. No check is red.

① Derived judgments

# What the diff implies Judgment
1 packages/types/src/record-components.ts: RecordDetailsComponentProps.sections[] gains hideEmpty?: boolean. This widens the accept set of a published @object-ui/types face by exactly one optional member. Right. The spec row declares hideEmpty as z.boolean().optional() (triage 6161914173 read it at packages/spec/src/shared/section-group-reference.ts:28), the renderer reads it (packages/plugin-detail/src/DetailSection.tsx:291, s.hideEmpty ?? true), and the ruling of record is objectui#8603 batch #137 item 3 (objectui follows the protocol), which the director's note on #7129 records as superseding Q1-A. The type is boolean, not unknown or string, and _HideEmpty holds it Equal to the spec's z.input member; Type Check is green on the head, so the equality holds against the installed 18.0.0-next.1.
2 Nothing else is added to, and nothing is removed from, the section entry: the type has no index signature, so every key the spec does not declare on the section (the retired collapsed, misspellings) is still TS2353 on a typed literal. Right. The existing refusedByTsc / retiredSpellingRefusedByTsc literals keep their @ts-expect-error directives, and tsc reports an unused directive as an error, so a green Type Check is evidence the refusals still fire. The diff touches no other member.
3 The #8583 pin is extended to hold the whole member set to the spec in both directions: _KeySetMirrorsSpec (keyof Section equals keyof SpecSection), _EveryMemberTypeMirrorsSpec (a mapped Equal whose value union must collapse to true; a single false makes it boolean and the line red; a key absent from Section indexes as never and also reds), _ListIsTheTypesKeySet (the runtime list equals the type's key set), and a vitest set-equality case against specSectionKeys(). Right. The construction is sound in both directions and is the extension the card asked for. The runtime case passed on the head (all Test shards green), which is the measurement that the thirteen-name list equals the installed spec's listed section keys. The dev's three ablations (base type under the new pin, extra member, dropped runtime name) match what the construction predicts; they were run at 0d1fc4a5f, before the main merge, and the diff between that commit and the head is the merge itself, which the green head covers.
4 New runtime case: hideEmpty: false parses clean on an enumerated section and beside group, with an invalid_type control at sections.0.hideEmpty. Right. It measures the card's exact shape ({ fields, hideEmpty: false } and the group form) against the installed spec, with a control that proves the acceptance is about the declared boolean and not a permissive schema.
5 packages/types/src/zod/objectql.zod.ts:783: the object-grid emptyState describe now reads { title, message, icon, link }. Right, and not an accept-set change. The schema is stripImportedDefaults(SpecEmptyStateSchema) by reference; only the .describe() string moved. This closes the first of the two sentences 6161115787 attached to this card.
6 apps/console/src/__tests__/registry-inputs-spec-parity.test.ts: the MEMBER_PINS row object-grid.emptyState now says three of four members are pinned there and names ObjectGrid.emptyStateLink-12270.test.tsx for link. Right, text inside a string literal; no public surface moves. Closes the second 6161115787 sentence. The console Type Check and the console spec-parity file both ran green on the head, which answers the dev's NOT MEASURED console leg. Polish only, not a finding: the row still ends with "New file.", which described the 11227 file when the row was written.
7 Public surface outside @object-ui/types: none. The Bundle Analysis report shows types (record-components.js) unchanged at 0.20KB, consistent with a type-only diff. No governed path is touched (Governed Surface Queue Guard green). Right.

File surface honoured: the five files are exactly the claim's four named surfaces plus the changeset. No breach.

② Semver level

  • Changeset .changeset/12348-details-sections-mirror.md: @object-ui/types: minor. Right. The diff widens a published type's accept set, so Clause-②: yes is owed and yes takes at least minor; the objectui fixed group never declares major (objectui AGENTS.md, version alignment). patch would have understated a widening; skip-changeset would have been wrong because @object-ui/types is a released package.
  • Clause-②: line: present as the PR body's second line, yes, with the widening named in prose (one member, hideEmpty, on RecordDetailsComponentProps.sections[]) and nothing narrowed. Changeset Declaration, Changeset Claim Re-read and Changeset Bump Policy are green on the head. The seat's yes over triage's no is the right call: triage's no reasoned from the spec lane, but the type that widens here is objectui's own published face.
  • The changeset body states what now compiles, the member set, what is still refused, and that nothing changes at runtime; nothing is removed or renamed, so no migration text or ADR-0087 marker is owed.

③ Boundary flags

  • Dev deviation 1, commit trailers use objectui AGENTS.md's model-free pair rather than the harness reminder's model-named trailer: answered, accepted. The harness reminder itself yields to a CLAUDE.md or AGENTS.md rule, and this record names no model either.
  • Dev deviation 2, console type-check NOT MEASURED locally (PREREQUISITE NOT MET, unbuilt dist/): answered by the head's check-runs. Type Check and Build & E2E are green on 80506a725.
  • Dev-reported check:spec-floors exit 1 (scan collapsed): answered. It is the known main failure objectui#12334, and the head's Spec Main Shape Gate and Repo Gates are green; it is not this PR's to fix.
  • open_questions: [] in the os-dev-report. Nothing to answer or escalate.
  • out_of_scope_findings (carrier: none): the spec's sections[].count describe still reads "[EXPERIMENTAL — not enforced]" while this type's count doc says the renderer fills the hole (objectui#12192). Escalated as an observation, not a ground. It is spec-side describe text in the objectstack repo, outside this card's file surface; it is left for the domain:ui seat to file on objectstack if it wants the text tracked. It does not affect what this PR publishes.
  • The ablation leg "the other direction" had two no-op attempts before the third measured: noted, no action. The dev recorded the no-ops as no-ops and the third attempt's exit 2 on _KeySetMirrorsSpec and _ListIsTheTypesKeySet is what the construction predicts.

Implemented-by: claude/issue-12348-details-sections-mirror
Reviewed-by: session_01XVp19E1MYUTFM3dnkwz8gB

VERDICT: PASS


Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 14, 2026 20:39
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 14, 2026 20:39
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 14, 2026
Merged via the queue into main with commit 1c72d77 Oct 14, 2026
34 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-12348-details-sections-mirror branch October 14, 2026 21:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

2 participants