Skip to content

fix(plugin-detail,app-shell,components): record page round 2 — related OFF draws no column or rail, one segmented panel control in the header row, three columns in a 1440 window with the sidebar - #27473

Merged
objectstack-fleet[bot] merged 5 commits into
mainfrom
claude/issue-27055-v3-patch-27241
Oct 29, 2026

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #27055
Fixes #27241

Clause-②: no
Metadata-protocol: none

Round 2 of the record page v3 (epic #26676), on main after #27310: the three rulings of #27241, the #27069 fence half of #27055, and a standing 「恢复默认顺序」 entry. Maintainer, 2026-10-28, verbatim: 「是:三栏阈值改成 1440 窗口(含侧栏)即三栏;开关改进头部动作行,关联 OFF 就没有栏」.

What changes

A1 — the related switch decides whether the column exists. recordPageArrangementFor sets relatedRail to switches.related && !columns.includes('related'), and RecordPageColumns draws the related column only when the arrangement places it. Related OFF: no related column and no rail toggle, in both column tiers. Related ON with no room (two-column tier): the rail toggle, which opens the column. With both switches off the page is the details column alone.

A2 — one segmented control at the end of the header's action row. PanelToggles (@object-ui/components) is now one segmented control, an icon and a label per segment (Timeline with the activity glyph, Related column with the right-panel glyph). The console's record view hands it to page:header through a new host slot, PageHeaderTrailingContext. PageHeaderActions draws it as the last segment of its role=toolbar row, after ⋯, behind a vertical hairline. It is drawn in both column tiers, and not in the tabbed tier or in the drawer. The toolbar gained max-w-full, so on a narrow header the segment wraps onto its own line, right-aligned, instead of running past the page (measured at a 1024 px window; see screenshot 08). The crumb row keeps only the ways back (origin link, 「Collapse to drawer」) and has no child without one, so empty:hidden removes it. Tooltip keycaps and aria-keyshortcuts are unchanged. The chord matcher accepts code Period / Comma, or key . / > and , / <.

A3 — thresholds. Measured on the console from this branch (HotCRM contact, sidebar expanded): the sidebar is 255 px plus its 1 px border, and [data-record-page-root] is 1184 px in a 1440 window, 1024 px in 1280 and 768 px in 1024. The constants are 1440 − 256 − 64 = 1120 and 1024 − 256 − 8 = 760, with the derivation in their docblock. The #26758 tier pins move to 1120 / 760, plus a pin on the three windows the thresholds serve. e2e/live/record-history-display.spec.ts opens the tab strip, so its viewport moves from 1200 to 1000, which keeps the record view under the new two-column floor.

B — the #27069 fence half.

C — standing 「恢复默认顺序」. resolveRelatedArrangement now reports rearranged: the shown order differs from the default, or a card is hidden. The column foot, which is the same line as 「已隐藏 N 张 · 显示」 and appears in both the related column and the tabbed tier's Related tab, then offers 「Restore default order」 (new key detail.relatedRestoreDefaultOrder, ten packs). It writes the new edit restore-default-arrangement: order: [], hidden: [], basedOn set to the current default's hash, seen: {}. Collapsed state is kept. The stored shape {v,order,collapsed,hidden,basedOn,seen} is unchanged. RelatedDefaultChangedHint is unchanged.

Not touched: packages/spec/**, navigation-overlay.tsx, recordDrawerStack.tsx.

Screenshots

HotCRM contact record page. The console runs on vite from this branch; the backend is objectstack dev --fresh --seed-admin from hotcrm 1f3f8880; headless Chromium. The images are on the never-merged branch claude/issue-27055-evidence-20261029.

  1. 1440 window, sidebar expanded: three columns, the segmented control in the header row · header row close up
  2. Related OFF: details and timeline, no rail toggle
  3. Timeline OFF: details and related, the timeline folded at the related column's foot
  4. A card moved: Restore default order at the column foot · foot line close up. Clicking it put the default order back; stored value {"order":[],"collapsed":[],"hidden":[],"basedOn":"e40133ac","v":1}.
  5. 1024 window, sidebar expanded: two columns, related ON, the rail toggle · related OFF: no rail toggle; the segmented control wraps
  6. Dark theme header row, timeline off and related on

Tests

Head `9c82d929a8`. The build and type-check closure was rebuilt first (`pnpm --workspace-concurrency=2 --filter '@object-ui/console^...' build`, VERDICT command-exit 0, 72 of 127 projects, then `@object-ui/i18n`, `components` and `plugin-detail` again after the edits). Every run went through `scripts/pm/os-verify-lock.sh`, UNLOCKED (declared below).

  • `@object-ui/plugin-detail` whole package: `Test Files 334 passed | 1 skipped (335)`, `Tests 3058 passed | 18 skipped`.
  • `@object-ui/components` whole package, on the final head: `Test Files 449 passed | 1 skipped (450)`, `Tests 4338 passed | 24 skipped`.
  • `@object-ui/i18n` whole package: `Test Files 89 passed (89)`, `Tests 1373 passed | 13 skipped`.
  • `@object-ui/app-shell` `src/views/`: `Test Files 1262 passed (1262)`, `Tests 11874 passed | 1 skipped`. This includes `panelToggles-27052`, `recordPageTiers-26678` and the new `relatedListsOrder-27241`.
  • The changed and new files were re-run on the final head after the last edits: 7 files / 65 tests in app-shell, and 3 files / 11 tests in the components header suite.
  • Type-check, each script echoed (`tsc --noEmit && tsc -p tsconfig.test.json`), exit 0 with 0 `error TS`: components, plugin-detail, app-shell, i18n.
  • eslint on the changed files of the four packages: 0 errors.
  • ui `check:new-line-citations` reported 0 new citations, and ui `check:spec-symbols` exited 0.
  • `ui/e2e/record-header-title-width.spec.ts` ran locally under a throwaway config with no webServer (the spec uses `page.setContent`), with the installed `chromium_headless_shell-1234` given as `executablePath`: `14 passed (1.8s)`. The config was deleted after the run.

Reverse verification

Each new pin was run against its mutation through `node scripts/ablation-replace.mjs`. The tool's own verdict was `ok mutation landed` (anchor 1 → 0, blob moved), and it restored with `git diff HEAD empty` and the HEAD blob matching. All runs were vitest on the aliased `src`, so no dist step applies.

  1. Related OFF keeps the rail (`relatedRail: !columns.includes('related')`): 7 failed (arrangement, `RecordPageColumns` and app-shell pins).
  2. The header row drops the trailing segment: 10 failed (the components slot pin and the app-shell toggles file). The first attempt was refused by the tool as a no-op, because the replacement text already existed in the file. It was re-run with a distinct replacement.
  3. The chord matcher reads `code` only: 1 failed (the code-less event pin).
  4. Three-column floor back to 1280: 2 failed. The first run failed at import, with `@objectstack/spec/data` not found while the gate battery was running beside it. That run is not counted as a measurement, and the re-run is the reading.
  5. Two-column floor back to 1024: 3 failed.
  6. `deriveRelatedLists` drops `relatedLists`: 1 failed (the mounted order pin).
  7. `bodyTablePlacement` places nothing: 5 failed.
  8. The foot line never offers the restore: 2 failed.
  9. `restore-default-arrangement` keeps `hidden`: 2 failed.
  10. The pressed tint back to `bg-muted`: 1 failed.

`git diff HEAD` was empty after the ten runs.

Gates

Derived with `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` at `9c82d929a8`. The change set is 38 paths against merge base `3bfb357aa3`, which derives 34 commands. Each command's exit code was written before any pipe. `--ran` reports `Run reconciliation — 34 derived, 34 run, 0 NOT-MEASURED, 0 UNRUN`.

33 commands exited 0. `pnpm --dir ui exec vitest run scripts/` exited 1, with `Test Files 2 failed | 167 passed | 2 skipped (171)` and `Tests 3 failed | 4898 passed`. All three failures are known host gaps on this macOS box, the same three as in rounds 0 and 1 of #27310. Two are the bash 3.2 `mapfile: command not found` in `select-affected-tests-wiring.test.ts`. The third is the `check-i18n-dead-keys` 「on the real tree」 case, which times out. These three are NOT MEASURED locally, and CI reads them.

Declared narrowing — verification ran UNLOCKED. scripts/pm/os-verify-lock.sh
could not take the shared verify lock on this host: no usable flock. The shared
verify lock is declared Linux-only (flock is util-linux, and a stock macOS does
not ship it), so every build and test command in this PR was run directly, without the lock —
a declared narrowing, not a silent one. No serialization guarantee held for these
runs, nor for any sibling agent in this container while they ran.

Acceptance notes

  • text-accent vs text-accent-foreground. The ruling names bg-accent + text-accent and describes the result as 「accent 浅底深字」. In both console themes, text-accent is the same pale HSL as bg-accent (light: --accent 240 18% 94%, measured on the page). The literal pair would draw invisible text. The on segment is therefore bg-accent + text-accent-foreground, which is the light-tint, dark-text pair the ruling describes. An off segment is text-muted-foreground. This is flagged for the seat in the report.
  • Wrapping on a narrow header. At a 1024 px window (768 px record page) the header's actions plus the segmented control are wider than the header. The toolbar now wraps inside the header (max-w-full), and the segment ends its own line. Before this, the toolbar overflowed and a click scrolled the page sideways. e2e/record-header-title-width.spec.ts ran locally: 14 passed.
  • A group naming a side card. Per the ruling, bodyTablePlacement places body tables only. A field group whose relatedList names a relationship that is not a body table (not 'primary', not an inline-edited master_detail) places nothing, and the card stays in the related column. Before this, such a group drew nothing either.
  • main gained 7 commits since the base 3bfb357aa3, none touching a changed path. GitHub reports no conflict, and no merge was made.

Generated by Claude Code

hotlong and others added 5 commits October 29, 2026 14:51
…related OFF has no rail, one segmented panel control in the header row, 1120/760 container thresholds, relatedLists order and field-group placement, a standing restore-default-order entry

Claude-Session: https://claude.ai/code/session_cdb7a717def74e719988f089fbaa18ff
Co-authored-by: Claude <noreply@anthropic.com>
…e trailing panel switches never overflow a narrow record page

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

Copy link
Copy Markdown
Contributor Author

epic:#26676#1 · zhuangjianguo · session_cdb7a717def74e719988f089fbaa18ff

席位核对 · PR #27473 ← #27055 round 2 + #27241 · epic PM session_cdb7a717-def7-4e71-9988-f089fbaa18ff · 2026-10-29T08:34Z

Verdict: ACCEPT — ordinary queue landing (governed register: 0 of 38 paths; packages/spec untouched; +958 / −159, under the 3000-line threshold). The round-2 report on #27055 (comment 6491778760) is read and accepted as filed; the round-2 Claim: naming this branch is 6491819758 (posted after the PR opened, which is why the closing-target claim guard was red on its first run and re-run).

Checklist, judged on GitHub, on the branch and on the seat's console preview:

Landing: ready + auto-merge in this stroke on the maintainer's standing authorization for this epic (verbatim, 2026-10-28: 「授权你用车队身份给 #26758 翻 ready 并挂 auto-merge(squash),后续本 epic 的 PR 复核 ACCEPT 后同样处理」); the queue decides the rest. After MERGED both cards close by the Fixes lines and the seat clears pm:dispatched on each.


Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 29, 2026 08:36
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 29, 2026 08:36
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 29, 2026
Merged via the queue into main with commit 273137d Oct 29, 2026
56 of 57 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-27055-v3-patch-27241 branch October 29, 2026 08:53
This was referenced Oct 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/xl tests tooling Fix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface

Projects

None yet

2 participants