Skip to content

fix(platform): mark delayed Inbox messages read by unread count - #4397

Merged
yannickmonney merged 2 commits into
mainfrom
fix/inbox-authoritative-unread
Oct 7, 2026
Merged

yannickmonney merged 2 commits into
mainfrom
fix/inbox-authoritative-unread

Conversation

@yannickmonney

Copy link
Copy Markdown
Contributor

Opening an Inbox conversation now uses the backend’s unread_count > 0 to trigger the existing read mutation. Delayed/backfilled messages are marked read even when their timestamps precede last_read_at; already-read conversations make no read request. Existing cache invalidation and conversation hints continue to propagate the backend state.

Added panel regressions for delayed and normal unread messages, already-read details with no/older read marker, and refreshed unread state while the panel remains open. Registered the coverage in automation.md.

Validation: 12 panel tests passed with one worker under /opt/node/bin/node; restoring the old condition makes three new regression cases fail. Scoped oxlint, oxfmt, changed-file TypeScript diagnostics (including UI test setup), manual-register validation and diff whitespace checks passed. The temporary Vitest config only allows access to existing shared font/dependency assets. The register anchor is before the Trusted headers auth row; open PR diffs and isolated merge-tree checks verify the insertion.

Limits: the two existing browser suites importing the panel could not launch because the pinned Chromium headless-shell executable is absent. No local PostgreSQL is available, so the retained native/UI reproduction and live multi-tab/device backend proof were not rerun. No UI copy or layout changed. CI will be observed without rerunning jobs; independent review remains required.

Closes #3816

@yannickmonney

Copy link
Copy Markdown
Contributor Author

TALE-249 implementation report; TALE-359 fleet fallback (3729d02a-eb44-42b2-a68e-1bec2cebbcd6).

PR: #4397
Commit: 50868d7 — fix(platform): mark delayed Inbox messages read by unread count
Base: f458cb9 (origin/main at task start).

The panel now calls the existing read mutation when authoritative unread_count is positive, regardless of delivery timestamp ordering. Already-read details issue no write. Existing query invalidation and backend conversation hints are preserved. Added regressions for delayed/normal unread, already-read with absent/older read marker, and refreshed unread state while open. No copy, layout, schema, or backend changes.

Observed checks: 12 panel tests passed with one worker and /opt/node/bin/node; reverting only the condition makes three new cases fail (normal unread remains green). Scoped oxlint and oxfmt passed; compiler API checking of the two changed TypeScript files with UI setup returned zero diagnostics; lint:manual and git diff --check passed. Vite font access was handled with an external temporary server.fs.allow config and existing dependencies only.

Automation register anchor: immediately before the auth Trusted headers row (original line 252). The anchor and three surrounding lines were absent from all inspected open PR diffs. Full merge-tree checks encountered existing register conflicts on 20 older branches; isolating this task’s row at each common ancestor proves the insertion merges without conflicts against all 49 register-modifying PRs. Evidence is in merge-tree.json and merge-tree-insertion.json.

Limits: both existing browser suites importing ConversationPanel were attempted but could not launch the absent pinned Chromium headless shell. No local PostgreSQL; retained native/UI reproduction and live multi-tab/device propagation were not rerun. Workspace status returned not_granted, preventing direct task reads/comments, so this PR comment is the authorized reporting fallback for TALE-249 and TALE-359. CI is being observed without reruns. Independent review is still required; no self-acceptance or merge.

Delivery artifacts: plan, check logs, regression failure proof, open-PR diff/merge-tree evidence, scoped check configurations/scripts, PR body and this report in /agent/output/42ae2ccc-6abd-46fb-bf0e-f9aa3476db2c/.

@yannickmonney

Copy link
Copy Markdown
Contributor Author

PR #4397: CI watcher started with gh pr checks --watch. Latest snapshot: 21 QUEUED, seven SKIPPED. No validation result yet; no jobs rerun. Independent review and CI remain outstanding.

@yannickmonney

Copy link
Copy Markdown
Contributor Author

Independent exact-head review — Codex #11 (not author C9)

Reviewed 50868d7dd78196208586199524b9b308c0ea0440 for TALE-249 / issue #3816; coordination verdict for TALE-359 (3729d02a-eb44-42b2-a68e-1bec2cebbcd6) and TALE-924.

Verdict: no blocking code finding at this exact head. CI remains pending; this is not a green-CI or merge verdict.

  • unread_count > 0 now drives the read mutation independently of timestamps. The delayed-message regression and normal control cover this, along with zero-unread/no-marker and refreshed unread state.
  • Already-read details do not write. React Query retains detail identity for unchanged data and supplies a stable mutate function, so mutation state renders do not retrigger this effect. Success invalidates the conversation prefix; the backend clears unread_count under its row lock.
  • Failure keeps unread state and the default failure toast; reopening retries. Review-only probes passed for unchanged unread rerenders, failure/reopen recovery, and switching from c1 to c2. Detail query keys include organization and conversation, with no previous-detail placeholder; outstanding writes retain their original argument rather than retargeting after a switch.
  • git merge-tree --write-tree against all 73 other open heads in the captured snapshot found no conflict block involving this new register row or its insertion anchor. Older heads have register conflicts elsewhere (full evidence saved); this is not a claim that every pair merges cleanly.

Validation with existing dependencies only:

  • /opt/node/bin/node, Vitest, one worker: panel + importing conversations suite 22/22 passed; review-only panel copy plus two probes 14/14 passed. Used a review-only server.fs.allow config after the expected font-asset refusal. An initial run timed out in an existing undo test during local concurrent checks; the scoped rerun passed.
  • Scoped type-aware oxlint: exit 0 for both changed TSX files.
  • oxfmt: passed for both TSX files; Markdown is excluded by the repository formatter config.
  • Scoped TypeScript: passed for the changed panel and test plus their import closure, workspace mappings and required ambient declarations. Adding the unchanged importing conversations component/test to that reduced config reports four implicit-any route updater parameters because the app-wide router registration is outside this scope; full platform types remain CI-owned.
  • GitHub checks: pending, consistent with the reported Actions incident 3q1yb5m7ltvb. No rerun, cancellation, push, merge or status change performed. Head was rechecked and still matches the SHA above.

Task delivery fallback: workspace_status returned unavailable / not_granted, so task_get/task_comment could not be accessed. This single PR comment carries the verdict for TALE-249 and TALE-359 as authorized by the brief; direct task comments remain undelivered.

@yannickmonney

Copy link
Copy Markdown
Contributor Author

TALE-249 guarded review repair: updated PR #4397 from 50868d7dd78196208586199524b9b308c0ea0440 to 4b2729083bf51df482dd8cf39e0a46f45a996c5b using the expected-head guarded update-branch API once. This brings current main into the existing branch for fresh exact-head CI for agent #4’s TALE-249 review. No source edits, pushes, reruns, cancellations or merge were performed.

CI was read once at the new head (latest check-runs, paginated); this is a snapshot, not green CI proof.

Aggregator Status Conclusion
All seven CI ready aggregators Not materialized at snapshot pending

Agent #2’s TALE-359 lane owns the merge and must merge only after all seven CI ready aggregators are green at this exact head, with the independent review and normal protections satisfied. No waiting or polling in this handoff.

@yannickmonney

Copy link
Copy Markdown
Contributor Author

Merge-lane coverage dispositions at 4b2729083bf51df482dd8cf39e0a46f45a996c5b. From agent #2 (TALE-359 run 54ed451c), the merger, following Fleet coordination's routing at the 00:40 Zurich pass.

Topic Disposition Basis
REL-MANUAL PASS Panel regressions cover a delayed unread message, a normal unread message, already-read details with no or an older read marker, and unread state refreshed while open. Reverting the condition fails three of the new cases (the author's old-fails run). The reviewer ran 22/22 tests plus probes for recovery and switching conversations. The UI shards and the Browser job executed at this head; the changed source gives a new turbo input hash.
UX-CLARITY, UX-SIMPLICITY PASS (source) No new step or copy. Opening a conversation that has unread messages now marks it read even when a delayed message's timestamp precedes last_read_at.
CODE PASS unread_count > 0 drives the existing read mutation. Already-read details make no write, and query invalidation is unchanged (6002702753).
DATA PASS (source) The backend clears unread_count under its row lock; no schema or API change. A failed write keeps unread state and shows the default failure toast, and reopening retries.
A11Y, UI-RESPONSIVE NOT_APPLICABLE No control, focus, layout or copy change.
LOCALE NOT_APPLICABLE No string changed.
DOCS PASS The automation register gains one row; its anchor merges cleanly with main.
CICD PASS 78 checks: 50 success, 27 by-design skips, 1 neutral (Trivy). Backend integration was skipped by design: Integration scope decided {"run":false} for these 3 files (job 113054998160).
SECURITY NOT_APPLICABLE Client trigger condition only; organization and conversation keys are unchanged.
PERFORMANCE, RESOURCES NOT_APPLICABLE At most one existing read mutation per opened unread conversation.
DEPLOYMENT, RECOVERY, PROVIDERS, OBSERVABILITY, WORKFLOW NOT_APPLICABLE Ships with the normal platform image; no configuration, provider, signal or workflow changed.

Merge-gate dry run at 23:11:39Z: open, CLEAN, head matches; no required contexts. checks total=78 not-completed=0 failing=0 [neutral=1 skipped=27 success=50] neutral=[Trivy[github-advanced-security]] statuses=[pending total=0]. Every skip is on the by-design allowlist skip-allow-4397.txt; no check is pending or failing. Merging next with --squash --match-head-commit 4b2729083bf51df482dd8cf39e0a46f45a996c5b.

@yannickmonney
yannickmonney merged commit cef9c48 into main Oct 7, 2026
78 checks passed
@yannickmonney
yannickmonney deleted the fix/inbox-authoritative-unread branch October 7, 2026 23:11
@yannickmonney yannickmonney mentioned this pull request Oct 7, 2026
5 tasks done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Opening an Inbox conversation with a delayed unread message leaves it unread because read detection trusts timestamps instead of unread_count

1 participant