Skip to content

console record drawer v2: the bar is ↑ ↓ · ⤢ · ✕ (no object name, no counter); a related row or a lookup opens its record in place with a trail, ← / Esc go back one level; ⤢ carries the trail into the page; on the record page a related row opens a drawer over the page #26679

Closed

Description

@objectstack-fleet

Part of the record-page-v2 epic #26676 (child 3 of 4). Runs after #26677 (shared files).

Source (origin/main 416a76030e)

  • The drawer's bar: ui/packages/components/src/custom/navigation-overlay.tsx:601-603 draws the object label as the SheetTitle, :614-622 the Maximize2 expand icon (already icon-only, gated on onExpand, aria-label and title from expandLabel), :625-633 close inside SheetClose; there is no previous / next and no counter anywhere in the file.
  • A related row inside the drawer leaves it: ui/packages/app-shell/src/views/RelatedRecordActionsBridge.tsx:553 onView: (id) => openRecord(objectName, id) and :390-395 openRecord = navigate(path); the file has no embedded branch at all (docblock :18 「查看详情 → navigate to the child record's detail route」). Whether a lookup value on the detail navigates the same way is not measured here — measure it first.
  • ui/packages/app-shell/src/views/objectViewRecordNavigation.ts holds one open record (RECORD_DRAWER_PARAM at :87), no stack or trail; objectViewRecordLinks.ts beside it builds the record URLs. ObjectView.tsx is being carved into sibling hooks (slices 5+6 on 2026-10-26, 11a/11b on 2026-10-27): work on the merged code, not on the card's line numbers.

Target

  1. Bar: left side empty at the root level; right side ↑ ↓ (previous / next through the host list's current rows; disabled at the ends; keyboard ↑ / ↓ and j / k when no input has focus), ⤢ (icon only, tooltip 「展开为整页」), ✕. No object name, no "n / N" (rulings 2 and 3).
  2. In-place descent: a related row, a lookup value, or any record link inside the drawer opens that record in the same drawer and pushes the previous one on a stack; the bar's left side shows ← and the trail 「线索 Mira Costa › 任务」 (each ancestor a link that pops to it); ← or Esc pops one level; Esc at the root closes; ✕ closes the whole stack. ↑ ↓ at a deeper level move through that level's sibling set (the parent's related rows of that object), never across levels. Never a second drawer (ruling 5).
  3. ⤢ at any level navigates to that record's page with the trail carried in router state, so the page breadcrumb reads 「线索 / 全部线索 / Mira Costa / 任务 / 跟进报价」 and 「收为抽屉」 restores the stack.
  4. On the record page (not embedded): a related row or lookup opens its record in a drawer over the page under the same rules; an object declaring page navigates instead (spec(+ui): navigation.mode keeps page | drawer | new_window | none — modal, split and popover are retired; the default becomes drawer in the schema and in the console (no field-count guess); list-page recordAction drops modal; the console's split pane becomes a per-user preference read #26677's resolution).
  5. URL: the root record stays ?recordId=; the stack is in-memory (router state), so a reload shows the root record — document this in the component docblock.

File surface

ui/packages/components/src/custom/navigation-overlay.tsx (bar slots: leading trail, prev / next), ui/packages/app-shell/src/views/objectViewRecordNavigation.ts (stack, sibling sets, expand-with-trail), objectViewRecordLinks.ts, objectViewRecordOverlay.tsx, RelatedRecordActionsBridge.tsx (查看详情 when embedded → push), RecordDetailView.tsx (lookup links when embedded, the page-over-drawer host), ui/packages/plugin-detail/src/RelatedList.tsx only if its row click needs a new callback; tests beside; changesets for @object-ui/components and @object-ui/app-shell.

Acceptance

  1. Tests: open a lead from the list → bar has no title text and no counter; ↓ opens the next row's record; click a related task → trail shows the lead, ← returns to the lead with its tab state; Esc at root closes; ⤢ from the task level lands on the task page with the lead in the breadcrumb.
  2. Screenshot of the drawer at the root level and one level down (HotCRM lead → task), and of the page opened by ⤢ from the task level.
  3. Keyboard: ↑ / ↓ / Esc behave as above and never fire while an input has focus.

Rulings (maintainer, 2026-10-27, chat in the filing session — verbatim, not re-decidable here)

  1. The model, quoted back by the maintainer and ordered built: 「1. 一个对象一个默认打开方式:默认抽屉(带展开整页),page 只给显式声明的对象,modal 退役,split / popover 变成用户个人偏好;抽屉和整页是同一张页在两个宽度。」
  2. On the drawer's top bar: 「左上角的 任务 · 2 / 2 · 分屏 几个字有必要嘛」 — no object name, no mode label on the bar.
  3. On the position counter: 「我觉得记录详情页显示第几条记录 好像也没必要」 — no "n / N" anywhere on a record; the ↑ ↓ previous / next controls stay.
  4. On the right pane: 「右侧应该可以拖动吗?展开为整页那个是不是用图标就可以」 — the pane is drag-resizable and "open as full page" is an icon-only control with a tooltip.
  5. On related records, the maintainer confirmed the in-place model: 「所以关联记录是一层一层的往下点,然后可以一层一层的反悔吗」 — one level down per click, one level back per ← / Esc, never a second drawer.

Filed by the epic PM session session_cdb7a717-def7-4e71-9988-f089fbaa18ff on 2026-10-27, from the record-page / list-page assessment and the clickable prototype the maintainer walked and ruled on in that session (objectstack main 416a76030e, HotCRM 1f3f8880 on platform 18.2.0). The maintainer's instruction to build it, verbatim: 「你直接立卡派发处理这个开发,然后审核。」 Design evidence (never merged): branch claude/record-page-v2-evidence-20261027b at commit 345ec777220843ce1fd7f95b6cc0b2b6dcc81bf8, folder docs/design/record-page-v2-2026-10-27/ (prototype.html, artboards/, assessment.md).

Activity

  1. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Premise reading before dispatch · epic PM session_cdb7a717-def7-4e71-9988-f089fbaa18ff · origin/main 7bb8084590 · 2026-10-27T23:57Z

    Target unchanged; the Source section's line numbers predate #26804 (merged 23:43Z) and #26758. Readings on the new main (read-only pass, this seat verified the shape):

    • ui/packages/components/src/custom/navigation-overlay.tsx (587 lines): modes are page | drawer | split | new_window | none; faces drawn are the drawer (Sheet, :431) and the split pane (:530); the drawer header is SheetHeader :484, title :486-488 (resolvedTitle = title || t('detail.recordDetail')), expand Maximize2 icon-only :498-507, close :509-518; no previous / next, no counter. The split face draws its own h3 title and close and no expand button.
    • ui/packages/app-shell/src/views/objectViewRecordNavigation.ts (215 lines): returns { listRecordActions, navOverlay, handleDrawerClose, handleRowClick, handleExpandDrawer }; RECORD_DRAWER_PARAM (app-shell/src/urlParams.ts:86, 'recordId') read at :107; one open record, no stack; handleExpandDrawer closes the drawer and navigates to record/:id with router state { from: { pathname, label } }.
    • objectViewRecordOverlay.tsx passes title={objectLabel(objectDef)} — that is the object name the bar shows today (ruling 2 removes it).
    • RelatedRecordActionsBridge.tsx:553 onView: (id) => openRecord(objectName, id); :390-394 openRecord = recordPath + navigate(path); no embedded branch; mounted at RecordDetailView.tsx:3980 for both embedded and page use. A lookup value measured now: ReferencedRecordLink (fields/src/index.tsx ~2520-2565) → host.openRecord → the same navigate — identical to the related-row path, so one handler covers both.
    • An existing URL trail already exists for page navigation: recordPath appends ?from= (RECORD_TRAIL_PARAM, appendRecordTrail) when a parent is known. The in-drawer trail of this card composes with it rather than adding a second trail carrier.
    • RecordDetailView.tsx has no NavigationOverlay / RECORD_DRAWER_PARAM today: the page-over-drawer host (Target 4) is new wiring.
    • Churn: ObjectView.tsx is carved into sibling hooks almost hourly and RecordDetailView.tsx took four commits on 2026-10-27; feat(spec)!: the action blocks spell the destructive variant danger, the word ActionSchema.variant uses #26966 (draft) edits RecordDetailView's action-variant region.

    Generated by Claude Code

  2. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 2 (epic #26676, child 3 of 4)
    Session: session_cdb7a717-def7-4e71-9988-f089fbaa18ff
    Account: zhuangjianguo
    Branch: claude/issue-26679-drawer-in-place-navigation
    Worktree: objectstack-issue-26679
    Domain: domain:ui
    Seat: epic #26676 (the epic PM session, not a domain seat)
    File surface: ui/packages/components/src/custom/navigation-overlay.tsx (bar slots: leading trail / back, previous / next), ui/packages/app-shell/src/views/objectViewRecordNavigation.ts (stack, sibling sets, expand-with-trail), objectViewRecordLinks.ts, objectViewRecordOverlay.tsx, RelatedRecordActionsBridge.tsx (查看详情 when embedded → push in place), RecordDetailView.tsx only the embedded lookup-link handler and the page-over-drawer host region, ui/packages/plugin-detail/src/RelatedList.tsx only if its row click needs a new callback, i18n keys, tests beside, changesets for @object-ui/components and @object-ui/app-shell; ⛔ packages/spec/**, ⛔ the Display menu (#26681) (stop on breach; explain in the report)
    Container & model: M, mode:subagent (desktop session on the maintainer's macOS; verify lock in declared-unlocked mode; one of two parallel subagents, the other on plugin-list / plugin-grid), model: TIER_DEFAULT (dispatch-gates --tier 2026-10-27T23:59Z: no path-derived mandate), effort: high
    Clause-②: no
    Metadata-protocol: none
    Responsibility: n/a — not a defect card
    Thread-read: none
    Premise: corrected 6456653001 (line numbers and landing path re-read on origin/main 7bb8084; target unchanged)
    Serial constraints cleared: #26804 (this epic) MERGED at 23:43Z — the surface is rebuilt on main 7bb8084590, line numbers in the card are from the old main and are re-read in the dispatch order; #26966 (draft, action variant danger) edits RecordDetailView.tsx in the action-rendering region, disjoint from the lookup-link / host region this card touches — merge main before opening the PR; #26841 edits a RecordDetailView test only; #26681 (this epic, in parallel) edits plugin-list ViewSettingsPopover.tsx, plugin-grid ObjectGrid.tsx and the preference write side in app-shell utils/, disjoint (scan 2026-10-27T23:59Z)

    Dispatched at 2026-10-27T23:59Z as an os-dev subagent of this session; the dispatch order lives in the subagent's opening prompt.


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 26679,
    "status": "rework",
    "branch": "claude/issue-26679-drawer-in-place-navigation",
    "pr": "#27038",
    "session": "session_cdb7a717-def7-4e71-9988-f089fbaa18ff — the parent PM session's id (mode:subagent)",
    "premise_still_valid": true,
    "summary": "Drawer bar: left side empty at the root (title sr-only on every NavigationOverlay host), right side ↑ ↓ / ⤢ / ✕ through three new optional props (onBack, trail, stepper); Esc pops when onBack is set; ↑/↓/k/j skip text fields, composite widgets and modifiers. New app-shell recordDrawerStack.tsx: an in-memory stack over a host-controlled root, ← plus a clickable path, per-level ?tab= save and restore, ↑ ↓ through the level's sibling set (the related list's rows on show, threaded RelatedList onRowClick third arg → onView third arg). RelatedRecordActionsBridge.openRecord (related rows and lookups both use it) opens in the nearest drawer host when the target object opens in the drawer; objects declaring page/new_window/none still navigate. ObjectView's overlay and the RecordDetailView page (new RecordPageDrawerHost) are hosts. ⤢ at any level opens the record page with the levels below as its ?from= trail, and the page's Collapse to drawer link restores the stack, consumed once from history state. Status is rework because one target half is missing: ↑ ↓ at the root of an object list's drawer needs ListView (plugin-list, fenced by this dispatch) to publish its rows, so the PR says Part of #26679. Two premise corrections: (1) the top bar draws no record crumb on main (AppHeader, object routes draw no crumb after the pill), so the path goes through the existing ?from= trail and the page back link, not a breadcrumb; (2) the zh ⤢ tooltip reads 以完整页面打开, not 展开为整页, and I left it unchanged because the dispatch marked the tooltip as done.",
    "tests": "Head ec88340 (merged with origin/main 5e99bd9). app-shell^... build plus app-shell type-check (tsc --noEmit and tsconfig.test.json): VERDICT command-exit 0. vitest packages/app-shell/: 1801 files passed, 1 skipped, 16511 tests passed, VERDICT command-exit 0. vitest components+plugin-detail+i18n+react (before the merge): 977 files passed, 1 failed (navigationOverlayConsumers.onRowClickArity-9357 pinned RelatedList onRowClick at exactly 2 params). The pin now takes a per-site arity of 3, with every param after the first required to be optional; rerun 26/26 passed. New tests: navigation-overlay-bar-26679 (9), recordDrawerStack-26679 (12), RelatedList.rowClickSiblings-26679 (2), and a sibling-ids case in RecordRelatedListRenderer.hostactions; all pass. No ablation: the behaviour is new, and each case has a control leg (no onBack → Esc closes; no stepper → no pair; page-mode object → navigates; no rows → two-arg onView). Screenshots NOT MEASURED: no HotCRM or console stack was booted. Every run used os-verify-lock DECLARED UNLOCKED MODE (no flock on macOS), disclosed in the PR body.",
    "gates": "dispatch-gates --commands --repo objectstack-ai/objectstack on ec88340: 34 families, each exit captured to file before any pipe. --ran: 34 derived, 34 run, 0 UNRUN (exit codes are in the runner file, not passed to --ran). 33 exit 0. pnpm --dir ui exec vitest run scripts/ exited 1 under load average about 26. The 11 failing files rerun alone left 2. select-affected-tests-wiring exits 127 because macOS bash 3.2 has no mapfile (a host fact). One check-i18n-dead-keys case timed out at 15s. Both are NOT MEASURED, family ui-scripts, reason: host shell and load; CI Test UI and Lint & Repo Gates read them. pnpm check:new-line-citations: 0 new. PR check-runs: in_progress (just opened, not awaited per os-dev.md).",
    "mcp_calls": "0",
    "api_writes": "3 — POST /repos/objectstack-ai/objectstack/pulls (draft, via with-fleet.sh direct: dispatch named the relay's session-id refusal), POST /repos//issues/27038/assignees, POST /repos//issues/26679/comments (this report, post-stamped); plus git push (not REST). Labels: zero writes; the dispatch named none, and skip-changeset does not apply because the diff publishes",
    "open_questions": [
    {
    "question": "Root ↑ ↓ on the object list's drawer needs the list's displayed rows, and ListView (plugin-list) publishes none (only onTotalChange). How should it land?",
    "options": [
    "A: follow-up card in objectstack, Blocked-by #26681: ListView gains an onRowsChange host prop (sibling of onTotalChange), and ObjectView passes root.siblings and onRootStep to useRecordDrawerStack (the page host already does both). About 40 lines plus tests.",
    "B: ObjectView re-queries the list itself to build the set. A second query with the list's filter/sort/search re-derived, which drifts from what is shown; not recommended.",
    "C: no root ↑ ↓; ruling 3 kept the controls, so this would need a maintainer re-ruling."
    ],
    "recommendation": "A, because the producer (ListView) owns the rows it shows, the drawer side is already built and tested, and it only waits for #26681's plugin-list fence to lift."
    }
    ],
    "out_of_scope_findings": [
    "carrier: 承接者:无 · noted, not filed — InterfaceListPage, ObjectDataPage and ObjectView's split pane embed RecordDetailView but are not drawer hosts, so a related row inside them still navigates; adoption is the same RecordStackDrawer swap (in Acceptance notes)",
    "carrier: 承接者:无 · noted, not filed — ui/content/docs/guide/user-state-persistence.md 'Authoring note' still lists modal/split/popover as navigation.mode values retired by #26804 (doc drift, Acceptance notes only)"
    ],
    "line_budget": "n/a — no skills/** or governed ledger touched",
    "deviations": "(1) Files outside the dispatch's surface list: ObjectView.tsx (3 lines passing two new overlay props), plugin-detail renderers/record-related-list.tsx and react RelatedRecordActionsContext.tsx (optional sibling-ids arg on the onView seam), and react navigationOverlayConsumers.onRowClickArity-9357 pin (per-site arity 3 for RelatedList). (2) RecordDetailView touched in a third region beyond the two named: the origin back link is now hidden when embedded and sits next to the Collapse to drawer link. (3) The drawer decision reads a context (RecordDrawerContext) instead of the embedded flag, so the record page can be a host too. (4) No PM progress reply mid-run: the probe arrived during verification, and this report is that reply. (5) Worktree cleanup (node_modules, worktree remove) is done after this report.",
    "files_changed": [
    "/.changeset/26679-drawer-in-place-navigation.md",
    "ui/content/docs/guide/user-state-persistence.md",
    "ui/packages/app-shell/src/views/{ObjectView.tsx,RecordDetailView.tsx,RelatedRecordActionsBridge.tsx,objectViewRecordNavigation.ts,objectViewRecordOverlay.tsx,recordDrawerContext.ts (new),recordDrawerStack.tsx (new),tests/recordDrawerStack-26679.test.tsx (new)}",
    "ui/packages/components/src/custom/navigation-overlay.tsx",
    "ui/packages/components/src/tests/navigation-overlay-bar-26679.test.tsx (new)",
    "ui/packages/i18n/src/locales/{ar,de,en,es,fr,ja,ko,pt,ru,zh}.ts (detail.collapseToDrawer)",
    "ui/packages/plugin-detail/src/{RelatedList.tsx,renderers/record-related-list.tsx,tests/RelatedList.rowClickSiblings-26679.test.tsx (new),tests/RecordRelatedListRenderer.hostactions.test.tsx}",
    "ui/packages/react/src/context/RelatedRecordActionsContext.tsx",
    "ui/packages/react/src/hooks/tests/navigationOverlayConsumers.onRowClickArity-9357.test.ts"
    ],
    "dedupe_words": [
    "drawer in-place stack",
    "ListView onRowsChange",
    "record drawer previous next root",
    "collapse to drawer"
    ]
    }

  4. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "round": "patch round 1",
    "issue": 26679,
    "status": "rework",
    "branch": "claude/issue-26679-drawer-in-place-navigation",
    "pr": "#27038",
    "head": "2baea3a5c7",
    "gates": "Head 211c988 (code-final; 2baea3a adds only changeset prose). dispatch-gates --commands --repo objectstack-ai/objectstack derived 34 families, each exit captured to file before any pipe. 33 exit 0. pnpm --dir ui exec vitest run scripts/ exit 1: 3 files. select-affected-tests-wiring exits 127, mapfile: command not found (macOS bash 3.2, a host fact). check-i18n-dead-keys and check-hand-rolled-comment-mask each hit a 15s timeout under load; the latter passed in an isolated rerun earlier this session. Those 3 are NOT MEASURED locally (host shell and load); CI Test UI reads them. On final head 2baea3a the changeset families were rerun: adr-0087-registration, changeset-no-major, empty-changeset, changeset-gate-self-tests, pm-changeset-deadline-census and nul-bytes all exit 0. Tests: console approvalRequestsDataSource.servedPageLookupEnter-12569 plus servedPageRecordLink-12557, packages/components/src/renderers/complex/ (whole dir), recordDrawerStack-26679: 36 files and 254 tests passed, VERDICT command-exit 0. zh-touching tests (navigation-overlay-chrome-i18n, objectView-value-language-3582, viewReadonlyTooltip-semantics-3625, console-namespace-3546): 6 files and 112 tests passed. Reverse verification of the new data-table-rowClickInDialog-26679 test: with the fix committed, restoring the old closest dialog line (injected=1, removed_left=0 by grep -c) makes 'a table inside a dialog opens the clicked row' fail (1 failed, 2 passed), and the two control cases stay green. Restored by git checkout HEAD; git diff HEAD is 0 lines. All runs used os-verify-lock in DECLARED UNLOCKED MODE (no flock on macOS).",
    "line_budget": "n/a — no skills/** or governed ledger touched",
    "deviations": "(1) New on-the-spot fix outside the named surface: ui/packages/components/src/renderers/complex/data-table.tsx. Its row-click heuristic dropped every click whose target had any dialog ancestor. Because the record drawer is a dialog, the HotCRM screenshot run found that related-list rows inside the drawer were pointer rows that opened nothing, so this card's in-place descent never fired in the real app; the jsdom tests do not render data-table and did not catch it. Now only a dialog that does not contain the row (a portalled overlay) stops the click. Pinned by new data-table-rowClickInDialog-26679.test.tsx, reverse-verified, and named in the changeset. (2) zh: the dispatch asked to change only console.objectView.expandToPage. objectView-value-language-3582 pins it byte-identical to detail.openAsFullPage in every pack, so both zh keys now read 整页打开, and navigation-overlay-chrome-i18n's zh expectation moves with them. console.ai.dock.maximize (a different control) stays 以完整页面打开. (3) The two console pins were flipped, not deleted. Each now asserts that the router stays on the request page, a dialog opens containing the target (ACCOUNT_TITLE / TARGET_TITLE), host.findOne was called for the target, the href still resolves to the record path, and Enter copies nothing. A new case pins that a meta-click is not intercepted (no preventDefault, no dialog). The illegal-shape controls (refused / unresolvable / absent) are unchanged. The approval request page stays a drawer host: its target objects declare no navigation.mode, so ruling 5 applies. (4) Screenshots: measured on HotCRM 1f3f8880 (platform 18.2.0 backend, objectstack dev --fresh) with this branch's console from vite source on port 5197. Three local test tasks were added to lead Mira Costa (fresh temp DB, deleted on exit). HotCRM's served crm_lead.all_leads view declares navigation.mode page, so the drawer was opened from the leads kanban view (crm_lead.kanban_by_status, mode drawer). Evidence branch claude/issue-26679-evidence-20261028 at 8ef7f64, never to merge; committed with --no-verify (screenshots only). Servers stopped by recorded PID; the throwaway evidence worktree was removed. (5) The PR body is not PATCHed (os-dev.md); seat edits are below in pr_body_edits.",
    "pr_body_edits": [
    "Replace the 'Screenshots ... NOT MEASURED' bullet with: Screenshots (HotCRM lead Mira Costa → task, this branch's console): drawer root https://github.com/objectstack-ai/objectstack/blob/8ef7f64917413235c23cf1030260423f76b2d382/docs/evidence/issue-26679/1-drawer-root-lead.png · one level down https://github.com/objectstack-ai/objectstack/blob/8ef7f64917413235c23cf1030260423f76b2d382/docs/evidence/issue-26679/2-drawer-one-level-down-task.png · after ⤢ https://github.com/objectstack-ai/objectstack/blob/8ef7f64917413235c23cf1030260423f76b2d382/docs/evidence/issue-26679/3-expanded-task-page.png (evidence branch, never merged).",
    "Add under What changes: data-table inside a dialog. A table drawn inside a dialog opens its rows. The click heuristic stopped every click with a dialog ancestor, so related-list rows in the record drawer opened nothing. Now only a dialog portalled out of the row stops the click (data-table-rowClickInDialog-26679.test.tsx).",
    "Add under What changes: the served approval-request page is a drawer host like any record page. Its two pins (servedPageLookupEnter-12569, servedPageRecordLink-12557) now assert that the drawer opens over the page with the target record in it, the router does not move, the href stays the record path, and a modified click is the browser's.",
    "Replace the zh Acceptance-notes bullet with: zh ⤢ label reads 整页打开 (detail.openAsFullPage and console.objectView.expandToPage, kept byte-identical by objectView-value-language-3582).",
    "Tests section: append the patch-round runs (see gates)."
    ],
    "files_changed": [
    ".changeset/26679-drawer-in-place-navigation.md",
    "ui/apps/console/src/services/approvalRequestsDataSource.servedPageLookupEnter-12569.test.tsx",
    "ui/apps/console/src/services/approvalRequestsDataSource.servedPageRecordLink-12557.test.tsx",
    "ui/packages/components/src/renderers/complex/data-table.tsx",
    "ui/packages/components/src/renderers/complex/tests/data-table-rowClickInDialog-26679.test.tsx (new)",
    "ui/packages/components/src/tests/navigation-overlay-chrome-i18n.test.tsx",
    "ui/packages/i18n/src/locales/zh.ts"
    ],
    "api_writes": "1 — POST /repos//issues/26679/comments (this report, post-stamped); git push x5 (branch) + 1 (evidence branch), not REST",
    "mcp_calls": "0",
    "not_done_this_round": "Root ↑ ↓ (waits for #27031, per the dispatch)"
    }

  5. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "round": "patch round 2",
    "issue": 26679,
    "status": "done",
    "branch": "claude/issue-26679-drawer-in-place-navigation",
    "pr": "#27038",
    "head": "811a10fa14",
    "gates": "Final head 811a10f, after merging origin/main da8e6e7 (which includes #27031, 7414fc8). Libraries built first: pnpm --filter '@object-ui/console^...' build, VERDICT command-exit 0. Type-check (tsc --noEmit plus tsconfig.test.json): plugin-list then app-shell, VERDICT command-exit 0. dispatch-gates --commands --repo objectstack-ai/objectstack on 811a10f derived 34 families, each exit captured to file first. --ran reconciliation: 34 derived, 34 run, 0 UNRUN. 33 exit 0. pnpm --dir ui exec vitest run scripts/ exit 1 with 6 files: 5 'Test timed out in 15000ms' plus select-affected-tests-wiring 'mapfile: command not found' (macOS bash 3.2, a host fact). Of the timeouts, vite-dts-fail-on-type-errors, js-comment-mask-returns-interpolation-9424, check-hand-rolled-comment-mask and check-ui-root-lookups rerun alone pass: 4 files, 44 tests. select-affected-tests-wiring and the check-i18n-dead-keys real-tree timeout stay NOT MEASURED locally (host shell, load); CI Test UI reads them. check:new-line-citations: 0 new. Suites on 811a10f: components + plugin-detail + i18n + react + plugin-list + the two console approval pins: 1148 files passed, 2 skipped, 11809 tests, VERDICT command-exit 0. app-shell full (ObjectView tests included): 1817 passed, 1 failed (ListView.gridRowColorSelect-12393, a loading-state assertion under load); that file rerun alone passes 2/2. New pins: ListView.onRowsChange-26679 (2) and recordDrawerStack.rootStepper-26679 (4), plus recordDrawerStack-26679 (12): 3 files, 18 tests pass. Reverse verification, each with its fix committed and a grep -c count proving the mutation landed. (a) ListView: the emit line is replaced (injected=1, removed_left=0) and both onRowsChange cases go red. (b) Stack: root stepping disabled (if (depth === 0) return undefined, injected=1), and the two presence/end cases go red while the two absence controls stay green. Both restored by git checkout HEAD: git diff HEAD is 0 lines and the ablation marker count is 0. All runs used os-verify-lock in DECLARED UNLOCKED MODE.",
    "line_budget": "n/a — no skills/** or governed ledger touched",
    "deviations": "(1) Two merge conflicts, both resolved toward the dispatch's intent and leaving #27031 as it landed. ObjectView.tsx takes #27031's useRecordOpenPreference() live hook and comment as landed, plus this branch's drawerRoot / drawerRestore / handleListRowsChange / handleRootStep returns. zh.ts keeps both keys: #27031's console.objectView.openAsPage: 整页打开 and round 1's expandToPage: 整页打开. (2) onRowsChange semantics: it answers where onTotalChange does (a paged grid drawing the rows it fetched). Any other kind (board, calendar, grouped grid) reports [], so a host never steps through a stale set. The report is keyed on the ids in order, never on identity (ui/AGENTS.md #10). Root stepping writes ?recordId= with replace, so stepping stacks no history entries. (3) ObjectView's split face (the reader preference) still draws no ↑ ↓: it is not a stack host. (4) The changeset drops the 'Not yet' root line, gains '@object-ui/plugin-list': patch and describes onRowsChange. The PR body is not edited; the seat sets Fixes #26679 at close-out. (5) No ObjectView-level integration pin wires ListView into a mounted ObjectView; the producer (ListView) and consumer (stack root) are pinned separately, and the hook glue is about 25 lines.",
    "files_changed": [
    ".changeset/26679-drawer-in-place-navigation.md",
    "ui/packages/plugin-list/src/ListView.tsx (onRowsChange)",
    "ui/packages/plugin-list/src/tests/ListView.onRowsChange-26679.test.tsx (new)",
    "ui/packages/app-shell/src/views/objectViewRecordNavigation.ts (listRowIds, handleListRowsChange, handleRootStep, drawerRoot.siblings)",
    "ui/packages/app-shell/src/views/objectViewListRenderer.tsx (onRowsChange threaded)",
    "ui/packages/app-shell/src/views/objectViewRecordOverlay.tsx (onRootStep)",
    "ui/packages/app-shell/src/views/ObjectView.tsx (wiring, merge resolution)",
    "ui/packages/app-shell/src/views/tests/recordDrawerStack.rootStepper-26679.test.tsx (new)",
    "ui/packages/i18n/src/locales/zh.ts (merge resolution only)"
    ],
    "api_writes": "1 — POST /repos//issues/26679/comments (this report, post-stamped); git push x3, not REST",
    "mcp_calls": "0"
    }

  6. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Review recorded on the PR: #27038 ## 席位核对 — ACCEPT at head 811a10fa14 after two patch rounds on the same claim (drawer stack + bar; list-root ↑ ↓ once #27031 was on main); body set to Fixes #26679; ready + auto-merge handed to the queue on the maintainer's standing authorization for this epic. pm:dispatched stays until MERGED; the card closes by the PR's Fixes line. — epic PM session_cdb7a717-def7-4e71-9988-f089fbaa18ff, 2026-10-28T06:34Z


    Generated by Claude Code

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

Metadata

Metadata

Assignees

Labels

area:recordsBusiness objects, records, the views that show data, usable forms, searchdomain:uienhancementNew feature or requestpm:epicpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions