Skip to content

record page under approval: the admin override bar ("管理员代为通过 / 代为拒绝 / 代为转签 / 撤回 / 回复") sits above the record title as five primary-looking buttons, and 撤回 is drawn twice on the page #25877

Closed

Description

@os-steve

Filing gate ① a user-visible defect with a named landing site (placement only; no change to who may override). Batch-of: 2026-10-25 browser pass on @objectstack/* 18.1.0 (second batch, 8 cards). Filed by the maintainer's account (os-steve) from the HotCRM pass driven in session session_01AwpXhq2nFKU6J7GmbCEmZu; ⛔ not a claim. Grade and routing are objectui triage's.

What is seen (HotCRM on @objectstack/console 18.1.0, dev admin)

Opening an opportunity whose large-deal approval is pending, the first row of the page, above the record title, is a bar of five buttons: three amber-outlined 「管理员代为通过」「管理员代为拒绝」「管理员代为转签」, then 「撤回」「回复」. Below it the title, the real actions (生成报价单 / 克隆商机 / 记录通话 / 编辑), and, in the 明细 tab, a second strip 「审批中已锁定 · 撤回审批」. 51-opportunity-tall.png. For the actual approver the same slot shows 「通过 / 拒绝 / 转签 / 退回修改 / 退回补充 / 回复」, which is the right content for that person: g3-mgr-request-detail.png.

For an administrator who is not the approver, "act in the approver's place" is the exception path; drawn as the most prominent row on the page it invites the click, and the bar pushes the record title below the fold on a phone (m5-opp-detail.png: the title starts at 200 px). 撤回 appears both in the bar and in the 明细 strip.

reach: the public UI, measured once as the dev admin and once as the approver.

Expected

  • For the approver: keep the bar (it is their task).
  • For an administrator who is not the approver: a status strip 「审批中 · 等待 sales.manager」 with one 「…」 menu holding the three override actions and 撤回; 回复 stays visible.
  • 撤回 in one place; the 明细 strip keeps the lock badge only.
  • Behaviour (who may override, what is recorded) unchanged; this is layout.

Dedupe

MCP search_issues objectui "approval banner admin override approve reject reassign buttons shown above record title too prominent" → 23 hits, none about placement (#12816 inbox columns, objectstack-ai/objectui#13225 Recall wording, objectstack-ai/objectui#12489 reference states, objectstack-ai/objectui#12751 print …). Report: REPORT.md §3.5.

Activity

  1. added
    area:workflowApprovals and automation — the work that runs without a person driving it
    bugSomething isn't working
    and removed on Oct 25, 2026
  2. objectstack-fleet commented on Oct 25, 2026

    @objectstack-fleet
    Contributor

    Triage: first grade — bug · priority:p2 · domain:ui · area:workflow · pm:queue · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-25T14:56Z

    ⛔ Not a claim, ⛔ not a dispatch.

    • p2: an admin override is a privileged act drawn as five primary buttons above the title, and 撤回 appears twice. Group the override actions behind one clearly marked control, and draw 撤回 once.

    Generated by Claude Code

  3. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    Contributor

    Transferred 2026-10-26T02:02Z from objectstack-ai/objectui#13535, with its comments and timeline; the old URL redirects here. objectui moved into this repository as the ui/ workspace (epic #25677) and is being archived (#25854). The body is left exactly as filed.

    Paths. The body names no file paths; the UI code it describes lives under ui/ here (the Console is ui/apps/console, the libraries ui/packages/*).

    References. The bare issue numbers in the body were written in objectui and now resolve against this repository by mistake; read them as objectstack-ai/objectui#12489, objectstack-ai/objectui#12751, objectstack-ai/objectui#12816, objectstack-ai/objectui#13225.

    No stale pm:dispatched or assignee to strip.


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    Contributor

    Claim: PM loop round 1
    Session: session_017iXjUm1rujwDk7f3KT1Pkk (seat); implementing card thread session_014N3u93mMkVGhq6DBKXqx4J
    Account: os-steve
    Branch: claude/project-thread-udq66w (platform-assigned card-thread branch; a card thread can push only its assigned branch, and the name carries no issue number, so this claim is the identity record)
    Worktree: the card thread's own container
    Domain: domain:ui
    Seat: domain:ui#1
    File surface: ui/packages/app-shell/src/views/RecordDetailView.tsx and DeclaredActionsBar.tsx (the approval bar collapses to one line 「审批中 · 等待 X」 + one 「…」 menu holding the override actions and 撤回 for a non-approver admin; 回复 stays visible; the approver's own bar unchanged), ui/packages/app-shell/src/utils/approvalOverride* if a predicate is needed; route A as ruled: one optional host signal on ui/packages/react/src/context/InlineEditContext.tsx ("the host already draws the declared recall"), read by the approval band in ui/packages/plugin-detail/src/DetailView.tsx so that band keeps the lock badge only (plugin-detail is seat 2's package; this card holds it with seat 2's knowledge); tests beside each. ⛔ Routes B and C rejected (B keeps 撤回 in the 明细 strip; C borrows approvalIsSubmitter for a meaning it does not have) (stop on breach; explain in the report). ⛔ ui/.github/** and the root .github/workflows/ci.yml are out of bounds (maintainer's word, ui-merge epic in flight). Changeset in the root .changeset/.
    Container & model: M, mode:thread, model: TIER_DEFAULT (dispatch-gates --tier: no path-derived mandate), effort: high
    Clause-②: yes (an optional member on the exported InlineEditContext value of @object-ui/react widens its public type surface, additive; the seat owes a TIER_DEFAULT review record before the queue)
    Metadata-protocol: none
    Responsibility: n/a: renderer defect in ui/, the producing code is the cited ui file; no platform path covers it; reached through the public Console
    Thread-read: 6406577326
    Premise: holds (card thread read-only check at origin/main a4eae06, both hypotheses confirmed; the second 撤回 is the submitter arm of the plugin-detail approval band, so ordinary submitters see it twice too; spot-checked by the seat 2026-10-26T08:45Z)
    Serial constraints cleared: none: no open PR touches RecordDetailView.tsx, DeclaredActionsBar.tsx, InlineEditContext.tsx or plugin-detail DetailView.tsx (open-PR file scan 2026-10-26T08:45Z); #25998 is in plugin-detail DetailSection.tsx / HeaderHighlight.tsx only

    Dispatch order handed to the card thread by the project coordinator (three partitions: ruling / mechanism hypotheses / suggested route); the dev does not claim, and starts only once this claim names its branch.

  5. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    Contributor

    os-dev-report

    {
      "issue": 25877,
      "status": "done",
      "branch": "claude/project-thread-udq66w",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/26053",
      "session": "session_014N3u93mMkVGhq6DBKXqx4J",
      "premise_still_valid": true,
      "summary": "For a viewer with can_act false and can_override true, the record page's DeclaredActionsBar (new optional foldOverrides) draws one line: a Pending badge with Waiting on plus the pending approvers' names, the levers with no override arm as buttons (Reply), and one amber Admin override menu holding every lever whose visible gate admits can_override (Override Approve/Reject/Reassign and Recall); the approver's bar is unchanged. The bar reports the actions it actually draws (onDrawnActionsChange); while it draws approval_recall the page sets the new optional @object-ui/react InlineEditContext member approvalRecallDrawnByHost (absent = false = band draws Recall as before) and the plugin-detail DetailView band keeps only its lock badge and tally. Route A per the seat ruling, placement in place above the title (not page:header); status line reuses existing i18n keys (statusPending/waitingOn/viaOverrideChip), so zh-CN reads 待审批 + 等待以下审批人 rather than a new 审批中 · 等待 X key, which would need ui/packages/i18n outside the claim. Behaviour (who may override, what is recorded, override notices, requests sent) unchanged.",
      "tests": "head df86fb71 (origin/main 39a78b15 merged): cd ui && pnpm exec vitest run --maxWorkers=2 over 101 files (all RecordDetailView.*, RecordApprovalsPanel.*, DeclaredActionsBar.* in app-shell, all DetailView.* in plugin-detail, InlineEditContext + resolveApprovalLock in react) under os-verify-lock: Test Files 101 passed (101), Tests 728 passed (728). Type-check react + plugin-detail + app-shell after pnpm --filter '@object-ui/app-shell^...' build: os-verify-lock VERDICT command-exit 0 (first merged-tree run failed only in metadata-admin/useMonacoFallback.ts on a pre-#25993 plugin-editor dist, not in this diff). New: DeclaredActionsBar.foldOverrides-25877 (8), DetailView.approvalRecallHostDrawn-25877 (3), RecordDetailView.approvalRecallGate +3 seam cases; approvalDeclaredActions override case updated to open the menu. Ablations via scripts/ablation-replace.mjs (on-disk proof, restore to HEAD; tests alias @object-ui/* to src so no rebuild): band gate dropped -> 2/3 red; fold disabled -> 3/8 red; menu trigger forced -> empty-menu test red; page signal forced false -> seam test red; signal on mount instead of drawn (&& to ||) -> bar-up-draws-none test red. Narrowed: full app-shell package (about 1700 files) left to CI Test Core.",
      "gates": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 46 commands (10 paths vs merge base 39a78b15), list identical at df86fb71; each run with exit captured before any pipe: 46/46 exit 0, incl. check-sdui-manifest.mjs after node scripts/gen-sdui-manifest-node.mjs re-record. --ran: '46 derived famil(ies) accounted for — 46 run, 0 NOT-MEASURED'. Last commit is changeset wording only; changeset gates re-run, exit 0. PR check-runs not yet concluded at report time.",
      "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
      "mcp_calls": "4 — mcp__github__issue_read get x2, get_comments x2; 0 write tools",
      "api_writes": "3 classes — git push to claude/project-thread-udq66w (one per commit round, head df86fb71); 1 relay pr_create via scripts/pm/with-fleet.sh --via dispatch (run 40305766361, PR #26053, draft, assignee os-steve, body read back identical); 1 issue comment os-dev-report via scripts/pm/post-stamped.mjs",
      "open_questions": [],
      "out_of_scope_findings": [
        "deviations noted, not filed: Clause-② written in the closed spelling 'yes (widening)' for the claim's 'yes (additive optional member)'; PR assignee set by the relay, no MCP assignee/reviewer request (coordinator forbids MCP writes); commit trailers use AGENTS.md's model-free Claude-Session + Co-authored-by pair and the PR ends with AGENTS.md's session-URL footer instead of the harness footer · carrier: this report"
      ]
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:workflowApprovals and automation — the work that runs without a person driving itbugSomething isn't workingdomain:uipriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions