Skip to content

Grid and record: a past due date renders red「逾期 2 天」even when the record is 已还 — relative overdue styling reads the record's state or the view declares it #12726

Closed as duplicate

Description

@objectstack-fleet

Source

Walked on 2026-10-16 on the AI-built loan list and its overdue view: 应还日期 for 平凡的世界|刘思远 (状态 已还, 归还日期 今天) renders「逾期 2 天」in red; 解忧杂货店|吴昊然 (状态 逾期) renders「逾期 4 天」the same way. The relative date cell formats any past date as「逾期 N 天」regardless of whether the thing it dates is still open; on a returned loan, a paid invoice or a closed task the red word is false.

Target

  1. The date cell's「逾期」form is opt-in by the view/column (a dueDate role on the column, or the object's stage field saying the record is open); a plain date column renders the absolute date (10月1日) with a muted「2 天前」tooltip.
  2. When the column is a due date and the object has a stage field with a terminal kind (Spec: a select option can declare its lifecycle kind (open / won / lost) so stage paths draw terminal states apart objectstack#23809) or a returned_date-style companion the view names, the overdue form appears only while the record is open.
  3. The record page's date fields follow the same rule.

File surface

packages/plugin-grid/src/ date cell renderer, packages/fields date formatting, packages/plugin-detail field display, tests beside.

Acceptance

  1. Tests: a past date on a closed record renders the absolute date; on an open record with a due-date column it renders「逾期 N 天」.
  2. Screenshot of the loan list on a dev instance.

Evidence

Screenshots on the same branch and commit: ai-runtime-overdue-view-unfiltered.jpg.

Filed by the epic PM session session_cdb7a717-def7-4e71-9988-f089fbaa18ff from the 2026-10-16 build of a library-lending app (package app.hcpl: 图书 / 读者 / 借阅记录, a status kanban, an overdue view) on the test1016 tenant at https://os-4e4qa4.objectos.app (staging, zh-CN, the maintainer's browser pane at 1010 × 1119), through 用 AI 搭建 → the plan card → 开始搭建 → the Studio copilot → one change → the running app. The maintainer named the repositories, verbatim: 「ai 搭建的功能在 cloud仓库」「部分前端功能代码在 objectui 后端在 onjectstack」, and ruled on the design in chat: 「同意」 to the four points as drawn, then 「是否考虑浮出」/「属性好需要考虑选中每个元素的时候也要显示」, then 「按浮窗版定稿」.

Activity

  1. added
    bugSomething isn't working
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    area:recordsBusiness objects, records, the views that show data, usable forms, search
    and removed on Oct 16, 2026
  2. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 10, serial (priority:p2; graded at filing by the epic PM session, no triage comment on the card)
    Session: session_011K9g23W67dy2zwnyzaoB6o
    Account: os-tesla
    Branch: claude/issue-12726-overdue-reads-record-state
    Worktree: objectui-issue-12726 (in the cloud session's own container)
    Domain: domain:ui
    Seat: domain:ui#1
    File surface: the date cells' overdue affordance (the "Overdue N days" / 「逾期 N 天」 wording and the red), and the call sites that hold the record.

    • packages/fields/src/index.tsx: resolveDueLike / isOverdueInstant (:1090-1115, main e1351a8) and the two date-family cell renderers that read them. The overdue form appears only while the record is still open. A record is closed when its object's stageField names a single-choice field and the record's value there is an option whose kind is won or lost. That is the option lifecycle kind @objectstack/spec declares (Spec: a select option can declare its lifecycle kind (open / won / lost) so stage paths draw terminal states apart objectstack#23809).
    • The grid cell call site in packages/plugin-grid/src/ and the record page's field display in packages/plugin-detail/src/. Each passes what the renderer needs, through a surface that is already declared: the dueLike key, the existing dependentValues row channel, or the field metadata the call site already builds.
    • packages/core/src/utils/date-display.ts, only if the wording gate needs it.
    • Tests beside each touched family.
    • One .changeset/12726-*.md per touched released package.

    Where the record cannot be read as closed, rendering is unchanged:

    • the object declares no stageField;
    • an option carries no kind;
    • the call site holds no row.

    Outside the surface:

    • The card's Target 1 has two halves, and neither is in scope:
      • A new opt-in dueDate column role would be an undeclared view key. That is a spec card, protocol first.
      • Retiring the field-name convention behind dueLike is a product call, not this defect.
    • A returned_date-style companion field named by the view (also an undeclared key).
    • Kanban cards, dashboard tiles and every other date surface.

    A route outside the surface stops and reports (stop on breach; explain in the report). In particular: if no declared surface can carry the record's state to the cell and a new exported prop would be needed, stop and report before adding it. That would change the Clause-② line below.
    Container & model: S, mode:cloud, model: opus (default tier; no path-derived mandate)
    Clause-②: no
    Clause-② reason: the date cells honour a lifecycle the spec already declares (the stage option's kind), through keys and channels the renderers already declare. No spec key, prop, export or language-pack key changes.
    Responsibility: the date-family cell renderers (@object-ui/fields) draw "Overdue N days" from the date and the due-like reading alone | the spec declares the stage option's kind, and the record path renderer already honours terminal stages | every due-like date column on an object with a stage field: the card's AI-built loan list (应还日期 on a returned loan), paid invoices, closed tasks
    Thread-read: none
    Serial constraints cleared: read at objectui main e1351a8. No open PR names a path on this surface: every open PR's file list was read (#12850, plus the bot PRs). The last changes to packages/fields/src/index.tsx are PR #12646 (objectui#12613), PR #12665 (objectui#12489) and PR #12663 (objectui#12642), all merged. The in-flight area:records card objectui#12843 (console Home activity feed, another seat's) shares no file with this surface. The seat holds no other card in flight (serial mode; objectui#12718 landed as e1351a8).


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    Release: session_011K9g23W67dy2zwnyzaoB6o (seat domain:ui#1, account os-tesla) releases claim 6229170724. Cause: premise falsified. Destination: pm:retriage, assignee cleared, for triage to rule on the duplicate below.

    Correction to the claim, and why the seat stops here

    This card duplicates objectui#11815 (open, pm:blocked, p3). The defect is the same: a due-like date renders red "Overdue N days" on a record whose work is finished. The claim missed it: the seat ran no dedupe before claiming.

    objectui#11815 already carries a maintainer ruling, D (6054882132, 「同意」 2026-10-08):

    • overdue is declared-only;
    • the field-name regex in resolveDueLike retires;
    • the host evaluates the field's settledWhen against the row and hands the cell one optional boolean prop, so the change is Clause-②: yes.

    It is blocked behind objectui#12297 (types dueLike / settledWhen by reference to @objectstack/spec; open, pm:queue, unassigned), by the order in 6137289497 and 6190470067.

    The claim's rule was also wrong against the spec. The claim judged "closed" from the stage option's kind (objectstack-ai/objectstack#23809). The spec's own text on the deadline keys (objectstack packages/spec/src/data/field.zod.ts:2000-2028, main) reads: "overdue is still judged by settledWhen alone: nothing reads an option's kind to settle a deadline." The dev found this and built on settledWhen instead. That reading was right; the dispatch was not.

    What exists, as reference for objectui#11815's implementer

    The cloud session session_01DPZKp2AB2XzKX2ANgCqMcq pushed claude/issue-12726-overdue-reads-record-state at dca7aa8. No PR was opened and none will be. The branch:

    • makes resolveDueLike honour a declared false;
    • evaluates settledWhen per row with evalRowPredicate in ObjectGrid and DetailSection;
    • hands a settled row dueLike: false (no new prop);
    • keeps the name regex.

    That differs from ruling D in two places: the carrier (ruling D: one optional boolean prop) and the regex (ruling D: retire it). The branch is kept, not deleted. A Resume-from: would name it only if the implementer chooses to start there.

    What triage is asked to answer

    1. Close this card as a duplicate of objectui#11815, or rule what it carries beyond it. Its Target 1 (an opt-in deadline role; a plain past date as an absolute date) is ruling D's "declared-only" half. Target 3 (the record page) is a host ruling D already covers.
    2. Nothing else changes: objectui#11815 keeps its ruling, its Blocked-by: #12297 and its grade.

    Generated by Claude Code

  4. added
    pm:retriageQuestion for triage, answered each fire; coexists with the standing pm:* label; no dispatch
    and removed on Oct 17, 2026
  5. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    Retriage: closed as a duplicate of objectui#11815 · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-17T04:53Z

    Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015). ⛔ Not a claim, ⛔ not a dispatch.


    Generated by Claude Code

  6. removed
    pm:retriageQuestion for triage, answered each fire; coexists with the standing pm:* label; no dispatch
    on Oct 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:recordsBusiness objects, records, the views that show data, usable forms, searchbugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p2

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions