Skip to content

Usage reports: retry on the heartbeat, time real first runs, honest respawn hooks, Windows shell and CLI versions - #1928

Merged
BarganConstantin merged 5 commits into
developmentfrom
fix/reports-checkin
Oct 4, 2026
Merged

BarganConstantin merged 5 commits into
developmentfrom
fix/reports-checkin

Conversation

@BarganConstantin

Copy link
Copy Markdown
Owner

What changes

  • A check-in that still owes something goes out on the next heartbeat. A boot check-in that could not get through (a login item started before the network was up), or a UTC day with no "active" yet, used to wait for the six-hour timer, which does not run while the machine sleeps. Each beat now checks in first when something is due (the same conditions the check-in acts on, read off the prefs and the clock), and never beside a check-in that is still running.
  • Only a real first run is timed. An install upgraded from a version without reports had no install id, so its first check-in made one dated "now" and its next session went out as a new install that activated within minutes. The install time is now kept only when the boot read found no settings file at all; any other install is never timed, the same way an id from before the install time existed never was.
  • A respawned deck reports the Claude hooks as it saw them. A respawn used to say "ok" before it had done anything, so the "update" a self-update sends said the hooks went in even after the re-install refused settings.json. A respawn that re-installed now says how that went; one on the same version says what the session's first boot said, which the supervisor now hands down in AGENTS_DECK_BOOT_HOOKS (the worker tells it over the existing IPC channel); and one under a supervisor that handed nothing down leaves the field out.
  • Windows shells are told apart, or the shell is left out. PSModulePath and ComSpec are set machine-wide, so every Windows deck said "pwsh". The shell is now read off what each one leaves for what it starts: PowerShell's user module folder under the user's profile ("pwsh" for PowerShell 7, "powershell" for Windows PowerShell) or cmd's PROMPT ("cmd"). With none of them, as for the desktop app started from the Start menu, no shell is sent. Nothing about the profile path leaves: the field is still one of those fixed words.
  • The Claude Code and Codex versions are learned before the first report, and again each day. The probe used to start on the first report's facts, so install, update and every "active" sent at a boot carried no CLI version, and a deck left running kept the versions it booted with. The reporter now starts the probe once the prefs say reports are on (still never under the machine's veto), waits up to eight seconds for it before an install, update or "active", and asks again on each new UTC day.

What leaves is unchanged in kind: the same fields, each still a count, a bucket or a short fixed token, and a field that cannot be told is left out.

Verification

  • npm run typecheck: clean.
  • Full suite (npx vitest run --maxWorkers=3 --minWorkers=1): 845 files, 11388 tests passed.
  • New regression tests, each run against the code before its fix and seen to fail for the reason described:
    • reports-checkin-retry.test.ts: a boot check-in that failed offline was followed by pings only (expected [] to deeply equal ['install', 'active']), and a day woken into got no "active" on the next beat. Two guards also cover a beat with nothing due and a beat during a check-in that is still running.
    • reports-upgrade-first-run.test.ts: an upgrader's id got installedAt = now (expected '2026-10-04T10:00:00.000Z' to be ''). It also checks the boot read itself: no file means a first run, while a settings file or a corrupt one does not.
    • shell-token-windows.test.ts: machine-wide variables alone read as "pwsh" (expected 'pwsh' to be undefined), and so did cmd and Windows PowerShell.
    • reports-cli-version-probe.test.ts: install, update and the first "active" had no claudeVersion, and a new day's "active" kept the boot-time version. Guards also cover a hanging probe (bounded wait) and no probe while reports are off or vetoed.
    • respawn-hooks-report.test.ts: spawns the real bin/deck.js as a respawn, with fetch replaced before it loads. The "update" carried claudeHooks: "ok" after "Claude hooks not updated … could not be read as JSON", and also with a handed-down "failed" or with nothing handed down. A second case runs the shipped bin/agent-dag.js over a stub worker, which got nothing handed down before the change.
  • Existing source pins repointed, none removed: activation.test.ts (the respawn's noteSetup line), second-deck-attaches.test.ts (the boot read's prefsRead line) and reports-1853.test.ts (the two Windows shell cases, plus the harness now says it is a first run instead of reading this machine's settings).
  • No UI change, so no browser check.

A boot check-in that failed (a login item started before the network was
up) or a UTC day with no "active" yet waited for the six-hour timer, which
does not run while the machine sleeps. The beat now checks in first when
something is due, and never beside a check-in that is still running.
An install upgraded from a version without reports had no id, so its
first check-in made one dated now, and its next session went out as a
new install that activated within minutes. The id now carries an
install time only when the boot read found no settings file at all.
PSModulePath and ComSpec are set machine-wide, so every Windows deck said
pwsh. The shell is now read off what each one leaves for what it starts:
PowerShell's user module folder (pwsh or powershell) or cmd's PROMPT.
With neither, as for the desktop app from the Start menu, none is sent.
The probe started on the first report's facts, which went out without
them, so install, update and every active sent at a boot carried no
Claude Code or Codex version, and a deck left running kept the ones it
booted with. The reporter now starts the probe once reports are known to
be on, waits up to eight seconds for it before an install, update or
active, and asks again on each new UTC day.
A respawned deck said the Claude hooks were ok before it had done
anything, so the update a self-update sends said so even when the
re-install had just refused settings.json. A respawn that re-installed
now says how that went; one that installed nothing says what the first
boot said, which the supervisor hands down in AGENTS_DECK_BOOT_HOOKS,
and nothing at all when none was handed down.
@BarganConstantin
BarganConstantin merged commit bb67a1c into development Oct 4, 2026
10 checks passed
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.

1 participant