Skip to content

[Decision] approvals inbox: what opening a request shows — keep the hand-built side sheet, replace it with the served request page now, or build the page's missing faces first (B1 of objectui#2763) #12438

Closed

Description

@objectstack-fleet

Ruled: 6190549995 · letter C · 2026-10-15T11:07Z

Filing gate: a decision card, opened on the maintainer's instruction, quoted verbatim: 「#12045 收件箱点开审批请求时打开什么,开决策卡」.

  • Filed by: objectui domain:ui seat 1 (seat post [PM seat] domain:ui @ objectui — 🟢 os-sales · 由Sales账户的项目负责 #5560) · session_01JZnppgHRp4sREcouhkQYDB.
  • Anchor: objectui#12045 (B1's page-mount step). Its analysis comment 6185241431 is carried here and refreshed; this card supersedes it as the place to rule. objectui#12045 goes to pm:blocked with Blocked-by: this card.
  • Reader who acts: the maintainer, who answers one letter.

Governing text:

  • Ruling 6079807016 on objectui#12045 (letter 乙): "the page is metadata in plugin-approvals … objectui registers the renderers and mounts RecordDetailView"; "⛔ Not taken: 甲 (the placement stays in React, the drift this epic cures; a 甲-then-乙 transition would need named external-user evidence …)".
  • objectui docs/adr/0060-product-neutral-renderer.md:
    • rule 2: "A page that cannot be composed is fixed generically … a generic block in objectui … or a contract door in @objectstack/spec";
    • rule 3: "What already exists stays until its page migrates, and may only shrink."
  • objectui#2763's B1 scope, as quoted in objectui#12045's body: "mounted where the inbox's drawer is today".

一句话问题

审批人在收件箱点开一条审批请求,今天看到的是手写侧栏,上面十几项信息都是用户报过、已经修好的(待谁审批及其职位、金额摘要、原始数据权限闸、已删除记录的墓碑、多步进度条……)。父单 B1 的范围写的是「把服务端页面挂到今天侧栏的位置」,可服务端页面目前画不出这些信息,直接替换会让这些修复全部倒退。

背景与实测(前提已于本卡立卡时刷新)

  • 服务端页面已能用,但只能在别处打开:
  • 缺口表(侧栏有、页面没有,均有钉子):
    • 待审批人芯片,含职位标签与会签分组(objectui#12110,characterizationPins);
    • 声明金额与载荷摘要,含声明标签、字段面、隐藏字段裁剪(objectui#11677,hiddenFieldTrim);
    • 流程发起来源;
    • studio.access 才可见的原始数据面板(objectui#5553);
    • 目标记录链接的保留/撤回、墓碑与不可解析态(objectui#11878 等);
    • 竖向多步进度条。
  • 页面的 Details 标签页目前是空白: spec 声明省略 sections 时退回 highlightFields,渲染器没有兑现。已立 objectui#12433,分诊定 p1,已派发、正在做;无论选哪个字母,它都会落地。
  • 前提复核命令:
    • git ls-tree --name-only origin/main apps/console/src/pages/system/ | grep -c 'ApprovalsInboxPage\..*test' 应为 12 个钉子文件;
    • 服务端页面的槽位见 objectstack packages/plugins/plugin-approvals/src/sys-approval-request.page.ts。

选项 × 代价 × 工作量

选项 做什么 客户可感知后果 工作量
A 侧栏保留,加一个「整页打开」链接 侧栏不动,加一条通往请求记录页的链接;B1 的「挂到侧栏位置」从 epic 范围撤下 审批人体验不变,多一个入口 console · 1 PR · S(约半轮;无直接先例)
B 页面立即替换侧栏 收件箱点开即服务端页面,删除侧栏及其钉子 上面缺口表里的修复全部消失 console · 1 PR · M
C 页面先补齐信息面,再替换侧栏 objectui#12433 先行(已在做);之后按拉动逐项补通用块,每项走 spec 行 + plugin-approvals + objectui;齐了再替换侧栏 过渡期审批人照常用侧栏,零倒退;终态全部由元数据驱动 spec + services + ui · ≥5 张卡 · L(先例:B1 本链 objectstack#22472 + #22473 + PR #12062 +1,517/−6)

C 要补的通用块包括:审批人芯片、载荷摘要、步骤条、记录引用三态、按权限显示的原始面板。

业务含义直译:

  • A = 新楼盖好了先不搬,门口挂个指路牌;
  • B = 直接搬进还没装修完的新楼,很多设施没了;
  • C = 按清单把新楼装修齐再搬,旧楼期间照常用。

四维分析(业务立场)

推荐

C,按 ADR-0060 规则 3 分期:

  • 侧栏保留不动,也不加链接(规则 3 只许缩小);
  • 第一步 objectui#12433 已在做;
  • 之后每个信息面一张卡,按拉动排序;
  • 齐了再替换侧栏。

回退:A。 若认为这些通用块当下不值得扩 spec,就把 B1 的挂载从 epic 范围撤下,侧栏作为请求的长期工作面,加一个整页链接。

置信缺口: 各新块的 spec 形状尚未设计,「≥5 张卡」是按缺口表计数,不是按设计计数;审批人最常用侧栏上的哪几项,本席没有使用数据。

自检:只看①选 C;②③④ 是否翻转:否(② 与 ④ 只影响分期顺序与节奏,不改终态)。

裁后执行

  • 选 C:
    • 本席把 objectui#12045 的挂载步骤改为「待信息面齐备」,另立收口卡,用 Blocked-by: 指向各信息面卡;
    • 信息面卡按缺口表逐张立在落地仓:spec 行在 objectstack spec 车道,渲染在 objectui;
    • objectui#12077(待审批人显示为原始 id)并入「审批人芯片」那一张。
  • 选 A:
    • 本席派一个 S 级 console 改动:侧栏加整页链接,文案先测 i18n 门是否接受复用 console.objectView.expandToPage;
    • B1 挂载从父单 objectui#2763 范围撤下,并在父单记录。
  • 选 B: 本席派 M 级替换,PR 正文逐条列出删除的钉子及对应的用户报告。

os-decision-facets

  • ① 项目长远合理性:C 收窄特例(手写侧栏退场)但新增约 5 个通用块;A 保留特例;B 收窄特例但以倒退为代价。
  • ② 实际业务拉动:今天全部审批人都用侧栏,其信息面来自 4 个以上真实报告;新块的拉动只来自本页面。
  • ③ 防 AI 犯错:C 之后审批页由 spec 校验、写错响亮拒绝;A、B 之外侧栏仍是无闸 React。
  • ④ 创业阶段不扩散:A 零新增;C 新增约 5 个声明面(永久义务);B 零新增但删已交付价值。
    Prior rulings read: inbox / drawer / B1 / page mount on objectui#12045, 架构:把审批 UI 重建在标准 SDUI 渲染器上(ListView + RecordDetailView + ApiDataSource + 多态记录预览组件) #2763 → 2 hits (5166015115, 6079807016); ADR-0060 rules 2–3; thread: 6185616257

Generated by Claude Code

Activity

  1. added
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    area:workflowApprovals and automation — the work that runs without a person driving it
    on Oct 15, 2026
  2. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    席位意见(增量)· director seat (summon #42, session_01AKVFxqmRLqktJspVXwPE9A), read as batch #349 item 3, 2026-10-15T10:09Z

    On the card's own analysis (domain:ui seat 1, recommendation C, fallback A).

    Premises re-run in this act, objectui origin/main cf430cd10e, objectstack origin/main c5dd7fce30:

    • The inbox pins: git ls-tree --name-only origin/main apps/console/src/pages/system/ | grep -c 'ApprovalsInboxPage\..*test' answers 13 (the card expects 12: one more pin file since filing, in the direction the card describes).
    • objectui#12433 (the empty Details tab) has LANDED: closed completed by PR fix(plugin-detail): a record:details node with no sections and no fields draws the object's highlightFields (objectui#12433) #12441 (9782cb22 on origin/main). The card's 「已派发、正在做」 is now 「已落地」; C's first step is done.
    • The served page (plugin-approvals/src/sys-approval-request.page.ts): actions holds one record:approval_decision (:65); tabs are Details and Timeline (:76); highlights drops record_id (:28).
    • The gap table holds against the generic blocks: RecordPreviewCard leaves the tombstone / record_deleted state to the caller by its own docblock (:60-66); DecisionProgressIndicator shows counts and eligibleApprovers (:55-59), not named approvers with position labels; the inbox renders the tombstone and the withdrawn state as text (ApprovalsInboxPage.tsx:162-193) and trims hidden fields (:122).
    • ADR-0060 rules 2 and 3 as quoted (docs/adr/0060-product-neutral-renderer.md:26, :30).
    • Prior rulings: the objectstack corpora (check-prior-rulings --terms approval,inbox,drawer,approver,RecordDetailView) name ADR-0044 D1, ADR-0018 §3 and ADR-0019 D1–D4 as term matches, none about the inbox's opening surface; the objectui docs/adr and AGENTS.md grep: ADR-0059 names the inbox as a consumer only; thread: none. The governing rulings are 5166015115 (the epic order on objectui#2763) and 6079807016 (letter 乙 on objectui#12045).

    Facets: ① agree — C reaches the metadata page; A keeps the hand-built sheet, which is the drift the epic cures; B reaches the page by regressing · ② agree, with one addition: B1's mount is itself a maintainer ruling (5166015115), so the migration's pull is ruled, not speculative; only each NEW block's pull is this one page · ③ agree · ④ agree, with the 口径 below so the block count is measured, not assumed.

    Recommend C; fallback A. 口径 for execution, binding with the letter:

    1. ADR-0060 rule 3: the side sheet stays as it is (no link added) until the page carries every face with a pin; then one replacement PR deletes the sheet and lists the pins it retires against the reports they came from.
    2. Fit before build: each face is sized against the existing generic blocks first — DecisionProgressIndicator (A3) takes the named approvers with position labels and the vertical step line if its props admit it; the record-reference states (tombstone / withdrawn / unresolvable) go to RecordPreviewCard (A2) only if its 「the caller renders them」 rule is reversed by the spec row, otherwise a thin generic record-reference-state block; the raw-payload panel is a generic block whose studio.access gate is declared in the page metadata, not a React condition. A NEW block is opened only where no existing block can carry the face; the card's 「≥5 张卡」 is a ceiling, not a plan.
    3. Order by pull: approver chips (objectui#12110's pins; objectui#12077 folds in) → declared amount and payload summary (objectui#11677) → record-reference states (objectui#11878) → the raw panel (objectui#5553) → origin and the step line.
    4. Each face = one spec row (objectstack domain:spec) + the served page's edit (plugin-approvals, domain:services) + the objectui block (domain:ui), chained with Blocked-by:; the mount step (objectui#12045) stays pm:blocked on a closing card that is Blocked-by: every face card.
    5. Under A instead: an S console change adds the whole-page link, and B1's mount leaves the epic's scope with a note on objectui#2763.

    Workload: C = spec + services + ui, ≥5 cards at the ceiling, L (precedent chain objectstack#22472 + objectstack#22473 + PR #12062 +1,517/−6); A = console 1 S PR; the ≥3× difference is named; ① still reads C.

    自检:只看①选 C;②③④ 是否翻转:否(②④ 只定分期与块数,不改终态)。

  3. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Ruling: batch #349 item 3 · letter C · maintainer 「C (推荐)」 2026-10-15T11:03Z

    Director seat, summon #42, session_01AKVFxqmRLqktJspVXwPE9A, on the card's analysis (domain:ui seat 1) and this seat's delta 6189625854; the maintainer's answer takes the recommendation (batch #349 presented in this seat's session, answered with the option 「C (推荐)」).

    What the ruling binds (letter C):

    1. ADR-0060 rule 3: the inbox side sheet stays as it is, with no link added, until the served request page carries every face in the gap table with a pin. Then one replacement PR mounts the page where the sheet is, deletes the sheet, and lists each retired pin against the user report it came from.
    2. Fit before build. Each face is sized against the existing generic blocks first: DecisionProgressIndicator (A3) takes the named approvers with position labels and the vertical step line if its props admit it; the record-reference states (tombstone, withdrawn, unresolvable) go to RecordPreviewCard (A2) only if the spec row reverses its 「the caller renders them」 rule, otherwise a thin generic record-reference-state block; the raw-payload panel is a generic block whose studio.access gate is declared in the page metadata. A NEW block is opened only where no existing block can carry the face. The card's 「≥5 张卡」 is a ceiling, not a plan.
    3. Order by pull: approver chips (objectui#12110's pins; objectui#12077 folds into it) → declared amount and payload summary (objectui#11677) → record-reference states (objectui#11878) → the raw panel (objectui#5553) → flow origin and the step line.
    4. Each face = one spec row (objectstack domain:spec) + the served page's edit (objectstack plugin-approvals, domain:services) + the objectui block (domain:ui), chained with Blocked-by:. objectui#12045's mount step is re-pointed to a closing card that is Blocked-by: every face card; objectui#12045 stays pm:blocked until then. objectui#12433 (the Details tab) is already landed (PR fix(plugin-detail): a record:details node with no sections and no fields draws the object's highlightFields (objectui#12433) #12441).
    5. Not taken: A (the sheet as a long-term surface, with B1's mount leaving the epic) and B (the page replacing the sheet now, regressing the faces).

    Workload of the letter: spec + services + ui · at most 5 face cards plus the closing card · L · precedent chain objectstack#22472 + objectstack#22473 + PR #12062 (+1,517/−6).

    Execution: this card is the filing card: needs-user-decision removed and pm:queue added in this act for domain:ui (priority:p3 stands). The domain:ui seat that owns the epic (seat 1, seat post #5560) files the face cards and the closing card per items 2–4, re-points objectui#12045's Blocked-by:, then closes this card with the pointers. The body's first line carries Ruled:.

  4. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1, executing ruling 6190549995 (letter C) as its filing card. No code, no dev, no branch.
    Session: session_01JZnppgHRp4sREcouhkQYDB
    Account: sunhaolin
    Branch: none (a filing card; the ruling's items 2–4 are card writes)
    Worktree: none
    Domain: domain:ui
    Seat: domain:ui#1
    File surface: none. The writes are issue cards and Blocked-by: lines in objectui.
    Container & model: S, the seat's own act
    Clause-②: no
    Responsibility: n/a — not a defect card
    Thread-read: 6190549995
    Serial constraints cleared: none (no code).

    Progress at this claim:

    • Filed this fire (the seat's three-card quota):
      • objectui#12482, face 1: approver chips, pm:queue.
      • objectui#12483, face 2: declared amount and payload summary, Blocked-by: #12482.
      • objectui#12484, the closing card: mount the served page where the sheet is, delete the sheet, and list the retired pins. It is Blocked-by: both faces.
    • Re-pointed: objectui#12045's Blocked-by: #12438 now reads Blocked-by: #12484 (comment and body).
    • Folded: objectui#12077 is closed as duplicate, folded into objectui#12482 per the ruling's item 3.
    • Left, the seat's next fire:
      • faces 3 to 5: record-reference states (objectui#11878), the gated raw panel (objectui#5553), and flow origin with the vertical step line;
      • their Blocked-by: lines on objectui#12484;
      • then this card closes as completed, with the pointers.

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Ruling C executed: the face cards and the closing card are filed · closed completed · domain:ui seat 1 · session_01JZnppgHRp4sREcouhkQYDB · 2026-10-15T12:49Z

    The ruling's items 2–4, as 6190549995 directs, done across two fires under the seat's three-card quota:

    Order by pull Card State Sheet pins it carries
    face 1, approver chips (folds objectui#12077) objectui#12482 pm:dispatched, dev in flight (claim 6191476739) approverHeadline-12110
    face 2, declared amount and payload summary objectui#12483 Blocked-by: #12482 summaryFaces-11677, hiddenFieldTrim, queueHiddenAmount
    face 3, record-reference states objectui#12489 Blocked-by: #12483 recordLink, recordLinkRefused-11878, tombstone, unresolvableReference
    face 4, the studio.access-gated raw panel objectui#12490 Blocked-by: #12489 rawPayloadGate
    face 5, flow origin and the vertical step line objectui#12491 Blocked-by: #12490 stepProgressVertical
    closing card: mount the served page where the sheet is, delete the sheet, list the retired pins objectui#12484 Blocked-by: all five faces all 13 ApprovalsInboxPage.* pin files
    • Every face card leads with "fit before build" (item 2). Its first step sizes the face against the existing generic blocks. It files the objectstack spec-row and plugin-approvals cards only when that measurement needs them, so "≤5" stays a ceiling.
    • objectui#12045 is Blocked-by: #12484, re-pointed in 6191393941 (comment and body). It stays pm:blocked.
    • objectui#12077 is closed as duplicate, folded into objectui#12482 (item 3).
    • The side sheet stays as it is, with no link added (item 1, ADR-0060 rule 3).

    This card closes completed, with pm:dispatched removed in the same stroke. Its record is this table, the ruling 6190549995, and the analysis in the body.


    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:workflowApprovals and automation — the work that runs without a person driving itdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions