Skip to content

fix(status): reopen a status whose preset deadlines coincide as Today - #3449

Merged
matt2e merged 2 commits into
mainfrom
mtoohey/flake-status-today-tie
Nov 14, 2026
Merged

matt2e merged 2 commits into
mainfrom
mtoohey/flake-status-today-tie

Conversation

@matt2e

@matt2e matt2e commented Nov 13, 2026

Copy link
Copy Markdown
Contributor

Why

user-status.spec.mjs, "statuses edit, synchronize, clear, reject stale traffic and retain failed drafts", failed once in CI with Expected "Duration: Today", Received "Duration: 8 hours": 9 Nov, Flake check, WebKit 2/9, passed on re-run.

The failure is a real product bug that the journey only meets in one second of the day. A status saved as "Today" at exactly 16:00 local time reopens in the editor as "8 hours".

Root cause

statusDuration infers the duration preset from a saved expiry. It takes the preset whose deadline is closest to the expiry, iterating 1 hour, 8 hours, Today and This week with a strict <. At exactly 16:00 the 8 hours and Today deadlines are the same midnight, and the earlier-listed 8 hours won the tie.

The failed attempt's trace (artifact 13688728980) puts the first "Save status" click at 16:00:00.559 UTC, so the status was created at 16:00:00 and its expiry was midnight. The same tie occurs for 1 hour at 23:00, and on a Sunday This week ends at the same midnight as Today.

Fix

Let Today win a tie between presets.

  • The stored expiry is the same either way. The label the editor shows now matches the deadline it describes, and a re-save without changing the duration keeps that expiry.
  • Today already won the Sunday tie with This week by list order and still does, so a This week status saved on a Sunday reopens as it did before.
  • An hour preset can only tie with the midnight that is also Today's, so preferring Today covers every tie.
  • The tie applies only between presets. The second commit, a review follow-up, restricts it so an expiry exactly at the edge of the 121 s tolerance still reopens as custom, as it did before this change. The tolerance and the custom fallback are unchanged.

Tests

status-duration.test.ts gains the 16:00 and 23:00 ties, the Sunday three-way tie, the Sunday Today and This week tie, and the tolerance-edge case.

  • On the unfixed code the first tie assertion fails with '28800'.
  • With only the first commit, the tolerance-edge expectation fails with 'today'.

Evidence

Scope Result
This branch's head, macOS: bin/pnpm exec vitest run src/features/user-status 3 files, 29 passed
Linux, WebKit: user-status.spec.mjs, --workers=1 --repeat-each=8 8/8 passed, 12.5 to 12.8 s each
Scratch copy of the journey with the page clock fixed at 16:00:00 UTC before the first save unfixed code fails with the CI error, the fix passes
Biome on the touched files, tsc --noEmit clean

The scratch copy is not kept. The unit cases are the gate, and a fixed clock would change the rest of the journey's timing.

Not run

  • Not tried in the desktop app.
  • No human has tested this yet, so buzz-review-completed is not set.

Overlap with open PRs

🤖 Generated with Claude Code

matt2e and others added 2 commits November 13, 2026 13:42
statusDuration infers the duration preset from a saved expiry by taking
the preset whose deadline is closest to it, iterating 1 hour, 8 hours,
Today and This week with a strict `<`. At exactly 16:00 local time the
8 hours and Today deadlines are the same midnight, and the earlier-listed
8 hours won the tie, so a Today status saved in that second reopened as
"Duration: 8 hours". Flake check (webkit, 2/9) job 129271665827
(2026-11-09) failed user-status.spec.mjs:116 this way. The triage read
the re-run's artifact; the failed attempt's own artifact (13688728980)
has the trace, and it puts the first Save status click at 16:00:00.559
UTC, so created_at was 16:00:00 and the expiry midnight. The same tie
occurs for 1 hour at 23:00, and on a Sunday This week ends at the same
midnight as Today.

Let Today win a tie. The stored expiry is the same either way; the label
the editor shows now matches the deadline it describes, and a re-save
without changing the duration keeps that expiry. Today already won the
Sunday tie with This week by list order and still does, so a This week
status saved on a Sunday reopens as it did before. An hour preset can
only tie with the midnight that is also Today's, so preferring Today
covers every tie; the 121 s tolerance and the custom fallback are
unchanged.

Unit coverage: status-duration.test.ts gains the 16:00 and 23:00 ties,
the Sunday three-way tie, and the Sunday Today/This week tie. On the
unfixed code the first assertion fails with '28800'; with the fix the
file's 3 tests and all 29 tests under src/features/user-status pass.

Verified with `bin/pnpm test:browser:ci --project webkit --no-deps
--workers=1 --repeat-each=8 --reporter=list
tests/browser/user-status.spec.mjs`: 8/8 passed (12.5-12.8 s each,
1.8 m). The spec only meets the tie in the 16:00:00 UTC second, so a
scratch copy truncated after the reopen check, with
`page.clock.setFixedTime("2026-11-12T16:00:00Z")` before the first save,
served as evidence: HEAD's status-duration.ts fails it with the CI error
(Expected "Duration: Today", Received "Duration: 8 hours"), the fix
passes it. The scratch is not kept: the unit case is the gate, and a
fixed clock would change the rest of the spec's timing. Biome and
tsc --noEmit are clean.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Signed-off-by: mtoohey <[email protected]>
Signed-off-by: Matt Toohey <[email protected]>
The Today tie-break fired whenever a preset's distance equalled
bestDistance, which starts at the 121 s tolerance, so a saved expiry
exactly 121 s from midnight reopened as Today where it was custom before
the tie-break was added, although that change's message said the
tolerance was unchanged. Restrict the tie to presets (best !== "custom"),
so a tie can only occur at a distance already under the tolerance.

The new unit expectation (midnight + 121 saved at 18:00 is "custom")
fails on the unfixed code with 'today' and passes with the fix.

Verified as part of the combined review follow-up, before it was split
by path:
- bin/pnpm exec vitest run src/features/user-status: 29 passed.
- biome check --error-on-warnings on the touched files and tsc --noEmit
  are clean.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Signed-off-by: mtoohey <[email protected]>
Signed-off-by: Matt Toohey <[email protected]>
@matt2e
matt2e requested a review from a team as a code owner November 13, 2026 02:53

@kazemek21 kazemek21 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reviewed the PR and went through the Nexus review-tracker notes. I didn't see any P2-or-higher issues in this change.

Posted by Codex (gpt-6.1-sol) on behalf of kylez

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Star Lord’s automated source review via Wes’s account.

No actionable findings at 93752d7445098db018eca95c7357604eb3f9715f against base/merge-base 7f03764beb8eb0ddcb4ff9ec0b8bda3e07699716.

The tie-break gives Today preference only after a preset has qualified, preserving the strict <121s tolerance and Custom fallback. Unequal distances still choose the closest preset. The added cases cover the eight-hour, one-hour and Sunday ties plus the tolerance edge; the editor preserves an unchanged future expiry when re-saving. Undefined expiry still selects Don’t clear.

Reviewed helper/test changes and the editor/persistence callers, including refresh, failure/retry and expiry renewal. This is source-only review: no local tests, builds or app execution. The hosted check snapshot reports CI required successful, but the author’s fixed-clock reproduction and human/desktop acceptance were not independently verified. No approval or merge recommendation is implied.

@matt2e
matt2e merged commit f2c3053 into main Nov 14, 2026
64 checks passed
@matt2e
matt2e deleted the mtoohey/flake-status-today-tie branch November 14, 2026 00:46
wpfleger96 added a commit that referenced this pull request Nov 14, 2026
…y-unreads

* origin/main: (24 commits)
  [1/2] feat(agents): add a recommended agent setup (core) (#3344)
  test(browser): survive the live-stream restart a page-clock jump causes (#3442)
  chore(renovate): hold rusqlite below 0.41 for mesh-llm (#3438)
  test(browser): serve the diffs and CLI reload fixtures outside the navigation budget (#3445)
  test(browser): play the draft clip at rate 0 instead of looping it before the Play click (#3446)
  fix(status): reopen a status whose preset deadlines coincide as Today (#3449)
  fix(messages): tolerate a cancelled reaction-name chunk load (#3450)
  fix(pairing): tolerate /proc/net/tcp rows printed twice or missed (#3451)
  test(browser): wait on the signal each test asserts in local-agent-activity and message-navigation (#3444)
  Expose native channel headings to Solo sources (#3523)
  test(browser-host): run the 100,000-channel broker scale check alone in the measurements lane (#3447)
  fix(solo): keep every contributed destination action (#3516)
  fix(identity): report an issuer that keeps rate-limiting an agent as a limit (#2365)
  fix(identity): let a stuck at-launch sign-in copy its link (#2453)
  fix(profiles): open avatar previews on hover in compact density (#3510)
  feat(solo): smooth chat recency reordering (#3502)
  Reject self-mentions that cannot wake another session (#3513)
  feat(status): offer don't clear for every status (#3515)
  Let plugin panels name their tab with panels.useTabTitle (#3251)
  fix(agents): report a conversation wake that fails before its turn starts (#2192)
  ...

# Conflicts:
#	tests/browser/message-management.spec.mjs
wpfleger96 added a commit that referenced this pull request Nov 14, 2026
* origin/main: (27 commits)
  [2/2] feat(agents): offer Automatic (Recommended) in Create agent and Identity (#3345)
  fix(solo): preserve and resume unsent chat drafts (#3525)
  fix(builderlab): give refused app sign-ins and Identity links a route to Organization sign-in (#3078)
  fix(agents): say why Import an agent can't import here, and link Manage plugins (#3073)
  [1/2] feat(agents): add a recommended agent setup (core) (#3344)
  test(browser): survive the live-stream restart a page-clock jump causes (#3442)
  chore(renovate): hold rusqlite below 0.41 for mesh-llm (#3438)
  test(browser): serve the diffs and CLI reload fixtures outside the navigation budget (#3445)
  test(browser): play the draft clip at rate 0 instead of looping it before the Play click (#3446)
  fix(status): reopen a status whose preset deadlines coincide as Today (#3449)
  fix(messages): tolerate a cancelled reaction-name chunk load (#3450)
  fix(pairing): tolerate /proc/net/tcp rows printed twice or missed (#3451)
  test(browser): wait on the signal each test asserts in local-agent-activity and message-navigation (#3444)
  Expose native channel headings to Solo sources (#3523)
  test(browser-host): run the 100,000-channel broker scale check alone in the measurements lane (#3447)
  fix(solo): keep every contributed destination action (#3516)
  fix(identity): report an issuer that keeps rate-limiting an agent as a limit (#2365)
  fix(identity): let a stuck at-launch sign-in copy its link (#2453)
  fix(profiles): open avatar previews on hover in compact density (#3510)
  feat(solo): smooth chat recency reordering (#3502)
  ...

# Conflicts:
#	src-tauri/src/federated_identity/agent/tests.rs
#	src-tauri/src/federated_identity/mod.rs
#	src-tauri/src/federated_identity/protocol.rs
joahg added a commit to joahg/buzz-app that referenced this pull request Nov 14, 2026
* origin/main: (133 commits)
  Expose ordinary chats without workspace headings (block#3530)
  [2/2] feat(agents): offer Automatic (Recommended) in Create agent and Identity (block#3345)
  fix(solo): preserve and resume unsent chat drafts (block#3525)
  fix(builderlab): give refused app sign-ins and Identity links a route to Organization sign-in (block#3078)
  fix(agents): say why Import an agent can't import here, and link Manage plugins (block#3073)
  [1/2] feat(agents): add a recommended agent setup (core) (block#3344)
  test(browser): survive the live-stream restart a page-clock jump causes (block#3442)
  chore(renovate): hold rusqlite below 0.41 for mesh-llm (block#3438)
  test(browser): serve the diffs and CLI reload fixtures outside the navigation budget (block#3445)
  test(browser): play the draft clip at rate 0 instead of looping it before the Play click (block#3446)
  fix(status): reopen a status whose preset deadlines coincide as Today (block#3449)
  fix(messages): tolerate a cancelled reaction-name chunk load (block#3450)
  fix(pairing): tolerate /proc/net/tcp rows printed twice or missed (block#3451)
  test(browser): wait on the signal each test asserts in local-agent-activity and message-navigation (block#3444)
  Expose native channel headings to Solo sources (block#3523)
  test(browser-host): run the 100,000-channel broker scale check alone in the measurements lane (block#3447)
  fix(solo): keep every contributed destination action (block#3516)
  fix(identity): report an issuer that keeps rate-limiting an agent as a limit (block#2365)
  fix(identity): let a stuck at-launch sign-in copy its link (block#2453)
  fix(profiles): open avatar previews on hover in compact density (block#3510)
  ...

Signed-off-by: Joah Gerstenberg <[email protected]>

# Conflicts:
#	src/bundled/codex/prompt.test.ts
#	src/bundled/goose/runtime.ts
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.

3 participants