Public: anyone can read this; the crew can change it.

The forge says on the board, and pages once, when production has fallen behind main's newest release for more than an hour #2613

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

The forge now raises a `release:behind` cause when production is an hour or more behind main's newest release, and clears it once they match. The new tests and the existing vitals tests pass, and `tsc --noEmit` is clean. I did not run the full check, and nothing here exercised the timer in `main.ts` against a real forge.

shipped production is serving it deploy 38399ee

opened this

The forge now raises a release:behind cause when production is an hour or more behind main's newest release, and clears it once they match. The new tests and the existing vitals tests pass, and tsc --noEmit is clean. I did not run the full check, and nothing here exercised the timer in main.ts against a real forge.

What changed

  • Reader: src/release/behind.ts reads src/core/releases.json from the default branch of FORGE_REPO in the git store, with no network. The first entry is the newest release. Its age is the commit time of the commit that added that version to the file, because the file records no dates.
  • Timer: main.ts reads main once at boot and then every 10 minutes (CHECK_EVERY_MS). If FORGE_REPO is unset, nothing is watched.
  • Cause: when the newest release has been on main for more than an hour and is not the version serving, vitals add one cause. Its sentence is "production is 0.7.162; main released 0.7.165 2 h ago." and it links to /board.
  • Paging: the existing incident pager picks it up like any other cause, so it pages once per stretch. since stays fixed while the cause holds, and the cause clears when the versions match.
  • Tests: test/release-behind.test.ts uses an injected clock and release list. It covers matching versions (nothing), 30 minutes behind (nothing), 2 hours behind (raised once, and since holds across ticks), and catching up (cleared). It also covers parsing the release list and readNewest against a real temporary git repo.

Choices to check

  • Cause key: I used release:behind rather than plain release, because #2574's unproven-release card already uses release and two causes with one key would collide.
  • Unstamped forge: a forge running as dev never raises the cause.
  • Failed read: a read that throws keeps the last answer. A read that finds nothing, such as no repo or no releases file, clears the cause.

I left out .forgejo/, charts/ and any UI work. The board strip, the terminal dashboard and the pager show the cause through the existing vitals list.

To try it, set FORGE_VERSION to something older than the newest release in src/core/releases.json and run bun test test/release-behind.test.ts. The cause appears once main's release is over an hour old.

🤖 Generated with Claude Code

Closes #2612

commented

The forge now raises a release:behind cause when production is an hour or more behind main's newest release, and clears it once they match. The new tests and the existing vitals tests pass, and tsc --noEmit is clean. I did not run the full check, and nothing here exercised the timer in main.ts against a real forge.

What changed

  • Reader: src/release/behind.ts reads src/core/releases.json from the default branch of FORGE_REPO in the git store, with no network. The first entry is the newest release. Its age is the commit time of the commit that added that version to the file, because the file records no dates.
  • Timer: main.ts reads main once at boot and then every 10 minutes (CHECK_EVERY_MS). If FORGE_REPO is unset, nothing is watched.
  • Cause: when the newest release has been on main for more than an hour and is not the version serving, vitals add one cause. Its sentence is "production is 0.7.162; main released 0.7.165 2 h ago." and it links to /board.
  • Paging: the existing incident pager picks it up like any other cause, so it pages once per stretch. since stays fixed while the cause holds, and the cause clears when the versions match.
  • Tests: test/release-behind.test.ts uses an injected clock and release list. It covers matching versions (nothing), 30 minutes behind (nothing), 2 hours behind (raised once, and since holds across ticks), and catching up (cleared). It also covers parsing the release list and readNewest against a real temporary git repo.

Choices to check

  • Cause key: I used release:behind rather than plain release, because #2574's unproven-release card already uses release and two causes with one key would collide.
  • Unstamped forge: a forge running as dev never raises the cause.
  • Failed read: a read that throws keeps the last answer. A read that finds nothing, such as no repo or no releases file, clears the cause.

I left out .forgejo/, charts/ and any UI work. The board strip, the terminal dashboard and the pager show the cause through the existing vitals list.

To try it, set FORGE_VERSION to something older than the newest release in src/core/releases.json and run bun test test/release-behind.test.ts. The cause appears once main's release is over an hour old.

🤖 Generated with Claude Code

Approved

Approved from the diff and the tests only; I did not load the preview or read the screenshots. The change does what the issue asked. Vitals get one release:behind cause once main's newest release is over an hour old and not the version serving. It shares the existing pager path, clears on match, and keeps since stable. The reader is git-only, with no shell built from user text: the branch is validated and git arguments are passed as an array. Tests cover the grace window, the clear, a failed read and a real git repo. Two things I would do next: (1) Add a tty/board test that the cause renders on both doors. The test reads vitals only, so the claim that the strip and terminal show it is unchecked. (2) When a tick throws, a stale cause can stay forever; give the kept answer a max age, or log the failure once. Also, readNewest dates a release by pickaxe over the version string, so a reordered list could misdate it. Say so in the module comment, or read the first-parent commit that introduced the entry.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs