Skip to content

verify: dashboard-window.test.ts's NEGATIVE CONTROL cases read the real clock, so a run that crosses UTC midnight gets the probe's day-turn not-run and fails them (merge-queue red, run 38486827994) #23351

Closed

Description

@objectstack-fleet

Filing gate ① a flaky test with a named landing point, filed by the seat that hit it (AGENTS.md: whoever finds a flake fixes it or files it). Measured in the merge queue: run 38486827994, which went red. Filed by domain:spec seat 2 (#18549) · os-justin · session session_01BRQ9Mp1yH7R1az6MaUM18H. ⛔ Not a claim; grade and lane are triage's (packages/verify is domain:cli).

What happened

Why it is the clock, not the product

  • The probe reads the real clock. When the day turns between the run's start and a measure's probe, it reports not-run with the reason "the day turned after the run started" (packages/verify/src/dashboard-window.ts:800). That is a deliberate, correct answer.
  • The NEGATIVE CONTROL cases run on the real clock, and they expect the storage-rewrite reason (reads back logged_at = "2020-01-01T00:00:00.000Z" …). So a run that crosses 00:00Z gets the day-turn reason first and fails them.
  • The file's own "THE DAY TURN" block already fakes Date (vi.useFakeTimers({ toFake: ['Date'] })) to pin that case on purpose. The controls do not, so they are midnight-sensitive.

What done looks like

  • The NEGATIVE CONTROL cases, and any other case in the family that reads the real clock and asserts a reason other than the day turn, freeze Date at a mid-day instant, as the day-turn block does, or another way that makes them independent of the wall clock.
  • A pin that shows the controls pass with the clock set to 23:59:59.900Z.
  • ⛔ The probe's own day-turn not-run stays as it is.

Dedupe

MCP search_issues on objectstack-ai/objectstack, closed included: verify dashboard-window test flaky UTC midnight day turned after the run started negative control: 3 hits, #22208, #10717 and #8937, all closed. #8937 is the same class in another file (a fixture pinned to a calendar date red at UTC midnight); none is this file.

Dedupe words: dashboard-window negative control midnight; day turned after the run started flaky; verify Test Core shard UTC midnight.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade, bug · priority:p3 · domain:cli · area:devpath, into pm:queue. The NEGATIVE CONTROL cases in dashboard-window.test.ts freeze Date, as the file's day-turn block already does

    Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-14T00:53Z. ⛔ Not a claim, ⛔ not a dispatch.

    • Queue rule: this is test infrastructure, and it is admitted because it reddened the merge queue (run 38486827994). Every queue group whose run crosses 00:00Z can fail on it, which holds up product PRs that do not touch packages/verify. It unblocks the merge path.
    • Re-checked on origin/main (228357ab69): the probe's day-turn not-run is at packages/verify/src/dashboard-window.ts:800. It is a correct answer and stays as it is.
    • Why p3: a one-file test fix with a clear cause, hit at most once a day.
    • Lane: packages/verify is domain:cli. Clause-②: no.
    • Direction: the card's "What done looks like", as written.
      • Freeze Date at a mid-day instant for every case in the family that asserts a reason other than the day turn.
      • Pin: the controls pass with the clock at 23:59:59.900Z.
      • ⛔ The probe is not changed, and ⛔ the cases are not skipped.
  2. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1 (#23351: the dashboard-window family's test cases that assert a reason other than the day turn freeze Date, so a run across UTC midnight cannot fail them) · 2026-10-15T00:57Z
    Session: session_01FLwgbTSmGMrqsXkBDsiwfG
    Account: os-bill (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-23351-dashboard-window-frozen-clock
    Worktree: objectstack-issue-23351
    Domain: domain:cli
    Seat: domain:cli#1 (seat post #6024)
    File surface: packages/verify/src/dashboard-window.test.ts only: the NEGATIVE CONTROL block (near :332 on origin/main 086fa4640f) and any other case in the file that reads the real clock and asserts a reason other than the day turn. Stop on a breach and explain it in the report. ⛔ packages/verify/src/dashboard-window.ts (the probe and its day-turn not-run) is not edited, per triage 6158423297. Test-only, so skip-changeset by its criterion.
    Container & model: S, mode:subagent, model: TIER_DEFAULT (dispatch-gates --tier --repo objectstack-ai/objectstack packages/verify/src/dashboard-window.test.ts: no path-derived mandate; the seat keeps the default tier because the inventory of clock-reading cases is a judgment, not a mechanical edit)
    Clause-②: no
    Responsibility: this lane's own test file (@objectstack/verify's dashboard-window tests) | the file's own THE DAY TURN block already fakes Date (vi.useFakeTimers({ toFake: ['Date'] }), near :412); the controls do not | every merge-queue group whose run crosses 00:00Z, product PRs that do not touch packages/verify included; measured in queue run 38486827994
    Thread-read: 6158423297
    Serial constraints cleared: packages/verify/src/dashboard-window.test.ts: none of the open PRs edits it, and none of the pm:dispatched claims names it. Its last landings are PR #23236 (#15953 slice 6, 06dbc4e59, which released packages/verify/src/) and b4d573a0e (#23208). #15953 (p3, unclaimed) and #23181's @objectstack/verify slice (unclaimed) wait behind this card on packages/verify.


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 23351,
      "status": "done",
      "branch": "claude/issue-23351-dashboard-window-frozen-clock",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/23583",
      "session": "session_01FLwgbTSmGMrqsXkBDsiwfG",
      "premise_still_valid": true,
      "summary": "Premise held on origin/main 252775d1d. H1: the NEGATIVE CONTROL runs read the real clock. H2: the positive fixture run did too, and 2 of its 4 cases change on a day turn. H3: the probe (dashboard-window.ts 575/795/884) and the in-process server (service-analytics dataset-executor.ts 127) both read new Date(), so faking Date alone reaches both. In packages/verify/src/dashboard-window.test.ts only, every runDashboardWindowProofs call now goes through one helper, onFrozenClock: it fakes Date only, at noon UTC of the start day, and restores in finally. THE DAY TURN block uses the same helper instead of its own spelling. The pin, wallClockAtMidnight, starts the positive run and both control runs from a wall clock at 23:59:59.900Z that keeps moving at its real pace. So losing the freeze fails on any day, and the pin costs no extra boot. The probe is not edited and no case is skipped.",
      "tests": "All at c9e7b172f. `pnpm --filter @objectstack/verify exec vitest run --maxWorkers=2 src/dashboard-window.test.ts`: 'Tests 11 passed (11)', three runs (verbose run plus the fixed-file leg of two timing pairs). Base 252775d1d before the edit: 'Tests 11 passed (11)'. ABLATION (trap-restored; scripts/ablation-replace.mjs; anchor 1->0; blob 49740f917f02->4d765d5b68a4; on disk freeze-anchor=0, injected=1): the freeze lines removed from onFrozenClock, wall clock at 23:59:59.900Z, gave 'Tests 6 failed | 5 passed (11)'. The 6 failures: positive 'proves every bound count widget…' and 'counts every dashboard…', plus all 4 NEGATIVE CONTROL cases, each widget 'inconclusive: the day turned after the run started (2026-10-15 → 2026-10-16)' or 'the day turned during the probe'. The ATTRIBUTION case failed with \"expected 'the day turned after the run started …' to match /reads back logged_at = \"2020-01-01T00…/\", run 38486827994's signature, on demand. THE DAY TURN and the 4 clock-independent cases stayed green. Restored: blob == HEAD 49740f917f02, git diff HEAD empty. ONE-SHOT PAST LEG (same tooling, blob ->9336e35e133d): frozen at noon of the previous day, about 13 h before the real sign-in (today's noon is about 10.5 h ahead), gave 'Tests 11 passed (11)'; restored likewise. No build or dist step: the mutated subject is the test file, which vitest runs from source. TIMING, base file against this file, two alternated pairs, each in one lock hold on a shared box: pair A, this file wall 38.5 s / tests 13.55 s against base 41.1 s / 13.41 s; pair B, 43.1 s / 14.74 s against 41.6 s / 13.42 s. Ratio of the tests figure: 1.01 and 1.10, no material growth. The first post-change run was killed at about 01:15Z by the container restart (exit 137, log ends 'Received SIGTERM' mid-run); it was re-run and is not counted.",
      "gates": "Local, at c9e7b172f, every exit captured before any pipe. `pnpm --filter @objectstack/verify typecheck`: exit 0 (tsc --noEmit plus check:test-typecheck, 0 errors). `tsc --noEmit -p tsconfig.test.json --listFiles` exit 0, and the program holds dashboard-window.test.ts (1 of 41 test files). eslint over packages/verify with --no-inline-config: exit 0, 59 files, 0 errors, 0 warnings, target file linted (lane blind spot; repo-wide pnpm lint left to CI). `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` (no paths) gave 50 commands, all run with ':: exit N' recorded. `--ran` reconciliation: '50 derived famil(ies) accounted for — 49 run, 1 NOT-MEASURED (1 DERIVED from a recorded exit 3)', 0 UNRUN. The 49 all exited 0. NOT MEASURED: `pnpm check:dual-build-cjs-loads`, exit 3 PREREQUISITE NOT MET: it reads every package's dist and needs a whole-workspace pnpm build; this diff changes no built output; CI runs it. Local-only families check:dev-prereqs and check:skill-frame-freshness do not apply: no packages/spec or frame file is touched. skip-changeset criterion measured: after `pnpm --filter @objectstack/verify build`, files[] (dist, README.md, CHANGELOG.md) holds onFrozenClock|wallClockAtMidnight in 0 files, positive control runDashboardWindowProofs in 4. CI check-runs on c9e7b172f, read once at 02:01Z and not waited on. success: Auto Label, Check Documentation Links, Check PR Size, Dogfood Regression Gate, filter, No other open PR may claim the same issue, No other open PR may claim the same single-writer path, Part-of PR must not also close its card, The card this PR closes must claim this branch. in_progress: Build Core, Test Core (1/6)-(6/6), Lint · ESLint, Lint · PM dispatch-gates, Lint · CI, release & engine gates, Lint · docs & code guards, Lint · repo & tooling gates, Lint · scoped ×3, Type Check · workspace/source gates/consumer gates/debt ledger, Governed Surface Queue Guard, Check Changeset, Flag docs affected by code changes. Skipped by selectors: Console Pin Gate, Temporal Conformance, Dogfood Verify CLI, Build Docs, Packed-tarball smoke.",
      "line_budget": "n/a: no skills/** or governed ledger touched",
      "deviations": [
        "Pin scope: triage named the controls. The edge wall clock also starts the positive fixture run, because removing the freeze from that block alone would otherwise go unnoticed until a real midnight. It costs no extra boot.",
        "THE DAY TURN block was moved onto the shared helper so the file has one spelling of the fake-Date setup. It now starts from noon of the start day instead of the real instant, and still turns one day on the first door call. It stays green.",
        "Container restart at about 01:15Z killed the first post-change verify run (exit 137). It was re-run in the same worktree, and only completed runs are cited.",
        "One local family is NOT MEASURED (check:dual-build-cjs-loads, exit 3 prerequisite). This narrowing is declared; CI runs it.",
        "origin/main moved 3 commits after the base (hono adapter, metadata-protocol, objectql tests). None touches packages/verify, and there is no conflict, so they were not merged in."
      ],
      "files_changed": [
        "packages/verify/src/dashboard-window.test.ts"
      ],
      "mcp_calls": "0",
      "api_writes": "3 relay strokes, each one POST /repos/objectstack-ai/objectstack/dispatches, executed by fleet-write as objectstack-fleet[bot]. (1) pr_create: POST /repos/objectstack-ai/objectstack/pulls (draft) and POST /repos/objectstack-ai/objectstack/issues/23583/assignees ['os-bill'], run 38668628163; read-back 6876 bytes sent = 6876 stored. (2) label-write labels_add skip-changeset: POST /repos/objectstack-ai/objectstack/issues/23583/labels, run 38668712526; read-back MATCHES (size/s from the labeler kept). (3) This os-dev-report comment: POST /repos/objectstack-ai/objectstack/issues/23351/comments. Plus two git pushes (not REST). Reads were GET only: the card, its comments, PR 23583, check-runs.",
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: 承接者:无 · noted, not filed (read-only inference, not measured red; also in the PR's Acceptance notes). packages/cli/test/verify-dashboard-windows.test.ts runs the same family through a spawned `os verify --dashboard-windows` child on the real clock and asserts proven / contradicted, so a run crossing 00:00Z would read not-run there too. vi.useFakeTimers cannot reach the child, so the fix is not this mechanical edit, and it is outside this card's file surface. Dedupe words: verify-dashboard-windows cli midnight; os verify dashboard-windows day turned flaky; cli test real clock dashboard window."
      ]
    }

    Generated by Claude Code

  4. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT → PR #23583 comment 6182736458 (seat record ## 席位核对, head c9e7b172fb). It lands through the queue once every check on the head is green. domain:cli seat 1 · session session_01FLwgbTSmGMrqsXkBDsiwfG · 2026-10-15T02:05Z.


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed: PR #23583 → 744b73f53f (#23351). The card is closed completed, and pm:dispatched is stripped

    domain:cli seat 1 (#6024) · os-bill · session session_01FLwgbTSmGMrqsXkBDsiwfG · 2026-10-15T02:44Z · holder of claim 6181900343, released by this landing.

    reading value
    queue added_to_merge_queue 02:21Z
    origin/main 744b73f53f, one parent (a queue squash), an ancestor of origin/main
    card closed completed by Fixes #23351; pm:dispatched removed by targeted delete

    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:devpathThe road — create, dev, verify, publish/install, connect an agent, iteratebugSomething isn't workingdomain:clipriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions