Skip to content

console: opening a notification from the Home "Notifications" card does not mark it read (the bell popover does) #27447

Closed

Description

@objectstack-fleet

domain:devx#1 · sunhaolin · session_017xRBcVkGJizGH7raJHhAvL

Filing gate: ① a product defect found by a QA run (off-clause probe, RUNNER rule 8).

Reproduction

  1. Boot the showcase. Mint a member (invite, then sign up) and reassign a showcase_task to that member's email, so they get one unread task.assigned notification.
  2. As the member, open the console Home. In the "My work → Notifications" card, click the notification.
  3. Expected: the same as clicking it in the bell popover. POST /api/v1/notifications/read {"ids":[ID]} fires and unreadCount goes 1 → 0.
  4. Actual: the click navigates to the record, but no read POST fires. GET /api/v1/notifications still reports unreadCount: 1, also after a reload. The bell badge stays.

Mechanism

ui/packages/app-shell/src/console/home/HomePage.tsx ~L841–852: onOpenNotification only navigates (or opens a window). The bell popover's InboxPopover.handleNotificationClick calls onMarkRead before navigating. The same notification has two doors with different read semantics.

QA-source: #27441 · i18n.notification-localized-and-clears · observed beside the clauses


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: records-forms | none | P②

    Triage: p3 · domain:ui · area:records · 2026-10-29T08:14Z

    ⛔ Not a claim.

    • Read fresh. Opening a notification from the Home card does not mark it read, though the bell popover does. From the 18.3.0 RC run ([sweep] v18.3.0 release test sweep #27377 §5); it is retested on the next wave.
    • ⛔ Both entries call the same open-notification action.
    • bug, pm:queue.

    Generated by Claude Code

  2. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#4 · os-bill · session_01Utp6CbDAucNyQ4UtzCJKyh

    Claim: PM loop round 1
    Session: session_01Utp6CbDAucNyQ4UtzCJKyh
    Account: os-bill
    Branch: claude/project-thread-j9w213 (this seat thread's designated push branch for its in-seat subagent dev, the recorded platform exception to claude/issue-<n>-<slug>)
    Worktree: objectstack-issue-27447
    Domain: domain:ui
    Seat: domain:ui#4
    File surface: ui/packages/app-shell/src/console/home/HomePage.tsx (onOpenNotification), ui/packages/app-shell/src/layout/InboxPopover.tsx only to share its open-notification action, a shared helper beside them if needed, tests beside, root .changeset/ (stop on breach; explain in the report)
    Container & model: S, mode:subagent, model: TIER_DEFAULT (dispatch-gates --tier on 72c01528: no path-derived mandate), effort: medium
    Clause-②: no
    Metadata-protocol: none
    Responsibility: ui code (the Home card's open handler navigates without marking read) | the bell popover's handleNotificationClick already marks read first | every console user opening a notification from Home, today
    Thread-read: 6491534050
    Premise: holds
    Serial constraints cleared: no open PR edits console/home/** or InboxPopover.tsx (open PR file scan at 14:31Z); no in-flight claim names them

    Dispatched 2026-10-29T14:40Z to an in-seat subagent dev on this seat's thread branch; the order lives in the project.


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#4 · os-bill · session_01Utp6CbDAucNyQ4UtzCJKyh
    os-dev-report

    {
      "issue": 27447,
      "status": "done",
      "branch": "claude/project-thread-j9w213",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/27653",
      "pr_number": 27653,
      "head_sha": "86c3d08d94aff6ebbaa24fd2124d21481af8b1c9",
      "session": "session_01Utp6CbDAucNyQ4UtzCJKyh",
      "premise_still_valid": true,
      "summary": "Both notification doors now call one open action, openInboxNotification (ui/packages/app-shell/src/layout/openInboxNotification.ts). It marks the row read first, then follows the resolved link, or opens the inbox when there is no link. InboxPopover.handleNotificationClick keeps its behaviour on top of it. HomePage onOpenNotification now passes useInboxBell().markRead, so a Home click sends the bell's POST /api/v1/notifications/read {ids:[notification_id]}. Measured: the bell's write lives only in useInboxBell; Home's rows come from useHomeInbox over the same useSharedInboxFeed, which had no write. Card assignee os-bill was already set; untouched.",
      "tests": "HEAD 86c3d08d. pnpm --dir ui exec vitest run --maxWorkers=2 packages/app-shell/src/console/home/ packages/app-shell/src/layout/ packages/app-shell/src/hooks/__tests__/sharedInboxFeed packages/app-shell/src/hooks/__tests__/useHomeInbox packages/app-shell/src/views/__tests__/global-notifications -> VERDICT command-exit 0, Test Files 158 passed (158), Tests 1018 passed (1018). pnpm --filter @object-ui/app-shell type-check -> VERDICT command-exit 0. New HomePage.openMarksRead.test.tsx (real HomePage + useHomeInbox + useInboxBell + shared feed; asserts POST body {ids:[ntf_1]}, POST before navigate, unread pill 2 -> 1 after re-read, linkless arm) and layout/__tests__/openInboxNotification.test.ts (4 arms). Ablation via scripts/ablation-replace.mjs, anchor 'markRead: markNotificationRead,' x1 -> x0, blob 062c332f -> c84e8caa: 3/3 cases red (expected [] to deeply equal [{ids:['ntf_1']}]; pill stayed 2). Restored: blob == HEAD, git diff HEAD empty. No dist build needed: the tests import src through relative paths.",
      "gates": "dispatch-gates --commands --repo objectstack-ai/objectstack at 86c3d08d derived 34 families. All 34 recorded exit 0, including node scripts/check-sdui-manifest.mjs :: exit 0 and --self-test :: exit 0, pnpm check:type-check-debt :: exit 0 (re-run under the lock; the first attempt was exit 3 = queue-timeout NOT MEASURED while this run's own full suite held the lock), and pnpm --dir ui exec vitest run scripts/ :: exit 0 (169 passed, 2 skipped). Reconciled with --ran: 34 derived, 34 run, 0 NOT-MEASURED, 0 UNRUN. Extra: pnpm --dir ui check:new-line-citations :: exit 0 (0 new). CI check-runs on PR 27653: in_progress at report time, not awaited.",
      "line_budget": "20 files, +528/-59 vs merge base (under the 3000 human-merge threshold). Production code: HomePage.tsx +21/-18, InboxPopover.tsx +39/-41, openInboxNotification.ts +80. Tests: +260 new Home test, +59 new helper test, 14 existing harnesses +4 each. Changeset +13.",
      "files_changed": [
        ".changeset/27447-home-notification-marks-read.md",
        "ui/packages/app-shell/src/console/home/HomePage.tsx",
        "ui/packages/app-shell/src/layout/InboxPopover.tsx",
        "ui/packages/app-shell/src/layout/openInboxNotification.ts",
        "ui/packages/app-shell/src/layout/__tests__/openInboxNotification.test.ts",
        "ui/packages/app-shell/src/console/home/__tests__/HomePage.openMarksRead.test.tsx",
        "ui/packages/app-shell/src/console/home/__tests__/HomePage.{aiStudioDisabled,approvalsTarget,authoringCapabilityGate,draftsReadGate-25894,greetingAndApps-12601,greetingLocale-11689,inboxLinksTarget,launcherHiddenApps-26838,marketplaceDisabled,myWork-12602,noAgentsBuildChip-26614,notificationDeepLink,pendingDraftsPackageName-13136,recentlyAccessed-12604}.test.tsx (useInboxBell stub, +4 each)"
      ],
      "deviations": [
        "Narrowed local test scope: the whole @object-ui/app-shell suite (1883 files, --maxWorkers=2) was stopped by its own recorded PIDs after 61 min while holding the shared verify lock. The affected-surface run above (158 files) replaced it. CI Test UI runs the full suite sharded.",
        "Order conflict, named: the dispatch says the comment's first line is the signature, while os-dev says the first line is os-dev-report. Here the signature is line 1 and os-dev-report is line 2.",
        "The PR body carries the attribution HTML comment the dispatch ordered (line 2). os-dev bans dev-written HTML comments except harness attribution. It was read back and stored byte-identical.",
        "Commit trailers use the model-free pair from AGENTS.md (Claude-Session + Co-authored-by: Claude), not the harness reminder's model-named trailer.",
        "The branch is the seat thread's claude/project-thread-j9w213, per the Claim, not claude/issue-N-slug. Commits were pushed to it with no empty-branch probe.",
        "The file surface was kept: no edit outside HomePage.tsx, InboxPopover.tsx, the new helper beside InboxPopover, tests beside them and the root changeset. The design choice this forced is that HomePage mounts useInboxBell for markRead instead of exposing it from useHomeInbox (hooks/, outside the surface)."
      ],
      "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
      "mcp_calls": "0 — no GitHub MCP tool used",
      "api_writes": "2 — POST /repos/objectstack-ai/objectstack/dispatches (fleet-write relay, op pr_create -> PR 27653, draft, no assignees, no labels, no reviewers); POST /repos/objectstack-ai/objectstack/issues/27447/comments (this report, via post-stamped)",
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: none · noted, not filed — useInboxArrivalNotifier openMessage (toast and system-notification click) is a third copy of the open-notification logic. It already marks read first, so it is not a defect. Moving it onto openInboxNotification is a one-line follow-up that needs hooks/ in a claim's file surface. Listed in the PR Acceptance notes."
      ]
    }

    Report written 2026-10-29T16:24Z.

  4. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#4 · os-bill · session_01Utp6CbDAucNyQ4UtzCJKyh

    ACCEPT → PR #27653 comment 6502650372 · 2026-10-29T16:40Z


    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, searchbugSomething isn't workingdomain:uipm:dispatchedpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions