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

A change is live in two minutes, proven on a copy before anyone sees it, and… #11841

Merged opened this

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

Merged

The fix is pushed as `295c8f0c3`. The new `release_now` admin tool was missing from three places the tests check. After the fix, `bun scripts/gate.ts`, `tsc` and the four failing test files (38 tests) pass locally. I did not re-run the full check.

shipped production is serving it deploy 4e6f862

opened this

The fix is pushed as 295c8f0c3. The new release_now admin tool was missing from three places the tests check. After the fix, bun scripts/gate.ts, tsc and the four failing test files (38 tests) pass locally. I did not re-run the full check.

  • src/crew/conversation_confirm.ts: release_now is now in the list of tools that ask first, with a short "cut a release now, outside the spacing" description.
  • test/mcp-write-scope.test.ts: I added valid arguments for release_now, so the "rw token is refused" test covers it.
  • docs/MCP.md: I regenerated the tool table with bun scripts/mcp-table.ts, which adds the release_now row.

Two pull-page tests in test/pull-quiet.test.ts also failed in the check, but that file passes when run alone here. I changed nothing for them and can't say yet whether the push clears them. If they fail again, I'll need the log.

Continues #11841

commented

The fix is pushed as 295c8f0c3. The new release_now admin tool was missing from three places the tests check. After the fix, bun scripts/gate.ts, tsc and the four failing test files (38 tests) pass locally. I did not re-run the full check.

  • src/crew/conversation_confirm.ts: release_now is now in the list of tools that ask first, with a short "cut a release now, outside the spacing" description.
  • test/mcp-write-scope.test.ts: I added valid arguments for release_now, so the "rw token is refused" test covers it.
  • docs/MCP.md: I regenerated the tool table with bun scripts/mcp-table.ts, which adds the release_now row.

Two pull-page tests in test/pull-quiet.test.ts also failed in the check, but that file passes when run alone here. I changed nothing for them and can't say yet whether the push clears them. If they fail again, I'll need the log.

commented

This pull covers only part of #11839: stage timings on the release card, release now, and the tick's holds made visible. The proof against a copy, interrupted-run counts, one-step rollback and the production timings are not done, so don't close the issue on it.

Checks run. scripts/gate.ts and tsc --noEmit are clean. The new tests pass, along with 62 tests across the keeper, cadence, swap, hold-door, /api/keeper and release-card suites. A wider run of the keeper, release and MCP suites timed out in the sandbox, so I did not see it finish. I did not run bun scripts/design-lint.ts after the run that timed out, though this pull touches src/web/. Run it before merging. The full check runs on push.

What changed

  • Stage timings (item 1). The release card and release_keeper now show where a release's time went: cut→live, build, proof, switch and verify. The swapper times checkout, preflight and the switch, and stores them on the in-flight release (migration 20261112140000-keeper-stages, pinned). A stage that wasn't measured is left out, so the slow stage is named. Code is in src/keeper/{swapper,wire,record,landed}.ts and src/web/pages/keeper-panel.ts.
  • A hotfix does not wait (item 5). release_now {reason} is a new MCP tool (admin scope, asks before running), with a Release now form on /releases. It sits behind one function, releaseNowAs in src/keeper/now.ts.

- Who: a person who may roll back; an agent cannot use it. - Request lifetime: a request that hasn't been used within an hour lapses. - What it skips: the 30-minute spacing, a running merge queue and a snapshot. - What still holds: a release in flight, a hold and the disk guard. - On the release: the reason and who asked are kept on the release and shown on its card.

  • Holds visible (item 6). release_keeper now returns holding (what the tick last said stopped it, e.g. the disk guard or the spacing), releaseNow and the stage timings, so it no longer answers empty. docs/features/release-keeper.md and docs/MCP.md are updated, and test/release-now.test.ts covers the new behaviour.

Not done, and why

  • Item 1, the speed target. The two-minute target is not demonstrated. I only added the measurement; the build path is unchanged.
  • Item 2, the proof. The stranger journey and the phone/desktop covered-page check do not yet run against the new version before traffic moves, so a deliberately broken stylesheet is not yet stopped.
  • Item 3, runs across a release. Crew runs and hosted forges' runs are not carried across a release, and interrupted runs are not counted per release.
  • Item 4, rollback. The previous version is not kept warm for ten minutes, and the tick does not roll back on a failed post-switch check. The rollback path is unchanged.
  • Acceptance. I could not take production timings from the sandbox.

Each remaining item is a separate piece of work and should be split into its own issue linked to this one. To try the finished parts: as an admin call release_now with a reason, or use the form on /releases, then watch the next tick cut and the card show its stage line and "Cut now: <reason>".

🤖 Generated with Claude Code

Changes requested — before the latest push

Changes needed, all in one round:

  1. Both doors: Release now exists on the page and MCP but not in the terminal. Add a src/tui/ screen or action (next to the h/lift hold entry, wired where AGENTS.md says), gated by the same releaseNowAs, and describe it in docs/features/release-keeper.md.
  2. Tests that would fail without the change are missing: (a) POST /releases/now (releaseNowSubmit) is untested: a guest, a user who may not roll back and a cross-origin post must each write nothing; (b) the swapper timed callback and the wire timed hook (stage timings reaching keeper_release) are untested, since the test calls keepTimings directly; (c) the release_keeper test digs the answer out with ?? ?? answer fallbacks, so it can pass on the wrong shape: assert the exact shape.
  3. Wrong data: when a sha is already admitted, prepare skips preflight and stages.proofMs stays 0, so the card shows proof 0 s. The doc says an unmeasured stage is left out: keep proofMs null in that case (and let timed accept null).
  4. A second admin can silently overwrite the standing request and its reason (single-row upsert). Refuse or surface the existing request, and keep the original asker.
  5. Design (docs/DESIGN.md): each release now adds up to three extra colspan rows (Stages, Cut now, reason): principles 3 and 7, space and dl facts rather than stacked lines. Fold stage and hotfix into one muted line or a dl row. Two stacked forms for Hold and Release now are noise (principle 1). Run bun scripts/design-lint.ts, which the author did not run.
  6. Scope: this lands only part of #11839 and is not on the pipeline-first list. Open linked issues for the undone items rather than leaving them in prose.
commented

The branch is clean and already pushed. Nothing new has been said on #11839, so I changed nothing in this run. The remaining items need work that I can't test from this sandbox.

This pull covers only part of #11839: stage timings, release now, and the tick's holds made visible. The proof against a copy, interrupted-run counts, one-step rollback and production timings are not done, so the issue should stay open.

What changed

  • Stage timings: the release card and release_keeper show where each release's time went: cut→live, build, proof, switch and verify. A stage that wasn't measured is left out. The swapper times checkout, preflight and the switch, and stores them on the in-flight release. The migration is 20261112140000-keeper-stages, pinned.
  • release_now {reason}: this is a new admin-scope MCP tool that asks before running, plus a Release now form on /releases. It cuts at the next tick.

- Only a person who may roll back can use it, never an agent. - A request not used within an hour lapses. - It skips the 30-minute spacing, a running merge queue and a snapshot. It still waits for a release in flight, for a hold and for the disk guard. - The reason and who asked stay on the release and show on its card.

  • Holds visible: release_keeper now returns holding (what the tick last said stopped it), releaseNow and the stage timings, so it no longer answers empty.
  • Docs and tests: docs/features/release-keeper.md and docs/MCP.md are updated. test/release-now.test.ts covers the new behaviour.

Checks run. scripts/gate.ts and tsc --noEmit are clean. The new tests and 62 keeper, cadence, swap, hold-door and release-card tests pass. A wider run of the keeper, release and MCP suites timed out in the sandbox. bun scripts/design-lint.ts was not confirmed after that timeout, so run it before merging, since this pull touches src/web/. The forge's check runs the full suite on push.

Not done, and why

  • The two-minute target: the build path is unchanged and I only added the measurement.
  • Proof before traffic moves: the stranger journey and the phone/desktop covered-page check don't yet run against the new version first, so a broken stylesheet is not yet stopped.
  • Runs across a release: crew and hosted-forge runs aren't carried across, and interrupted runs aren't counted per release.
  • Rollback: the previous version isn't kept warm for ten minutes, and the tick doesn't roll back on a failed post-switch check.
  • Acceptance timings: I can't take production timings from this sandbox.

Each remaining item is a separate piece of work and should be split into its own issue linked to this one.

To try the finished parts: as an admin, call release_now with a reason or use the form on /releases. The next tick cuts, and the card shows its stage line and "Cut now: <reason>".

🤖 Generated with Claude Code

commented

This pull covers parts 1, 5 and 6 of #11839 and none of parts 2–4. The branch is already pushed and nothing new has landed on it this run.

What changed

  • Stage timings: the release keeper now times each stage (cut, build, boot proof, switch, verify). The timings are stored through the migration 20261112140000-keeper-stages and shown on the release card (src/web/pages/releases.ts) and in the keeper panel. src/keeper/record.ts and src/keeper/landed.ts hold the recording.
  • Release now: release_now is a new MCP admin tool that cuts a release immediately, outside the half-hour spacing, and requires a reason. It is registered as an asking tool with write-scope test args and is listed in docs/MCP.md. The logic is in src/keeper/now.ts.
  • Visibility: the keeper says what holds a release and why, so release_keeper no longer answers empty.
  • Docs: docs/features/release-keeper.md describes the above.

Not done

  • Build under two minutes: I did not change how the image is built.
  • Proof on a copy before traffic moves: I did not build the beside-the-old-one start with the proof run against it.
  • Zero interrupted runs: I did not change how the switch handles in-flight requests or crew runs.
  • One-step rollback: I did not add the warm previous process or a rollback that needs no build.
  • Production timings: the acceptance timings can only come from production after a merge.

Tests run

  • bun scripts/gate.ts printed nothing, and I did not capture its exit code.
  • I did not see bun x tsc --noEmit finish in this session. My run printed no tsc output, but the command timed out and moved to the background.
  • bun test test/release-now.test.ts test/mcp-write-scope.test.ts passes: 10 tests, 0 fail.
  • scripts/fast.ts found the diff too broad (1989 of 2923 files), so I ran only the tests above. The forge's check runs the full suite on push.

To try it: call release_now with a reason, then open the releases page to see the stage timings.

🤖 Generated with Claude Code

commented

This pull covers only part of #11839. It adds stage timings, release now and a view of what holds the tick. The proof against a copy and one-step rollback are not here, so the issue should stay open. This push addresses both review comments.

What changed

  • Stage timings: each release's card and release_keeper show where the time went: cut→live, build, proof, switch and verify. A stage that wasn't measured is left out. The migration is 20261112140000-keeper-stages, pinned.
  • release_now {reason}: this admin MCP tool asks before running, and /releases has a matching button. It cuts at the next tick, skipping the 30-minute spacing, the merge queue and a snapshot. It still waits for a release in flight, for a hold and for the disk guard.

- Only a person who may roll back can use it, never an agent. - A request not used within an hour lapses. - The reason and who asked stay on the release and show on its card.

  • Holds visible: release_keeper now returns holding (what the tick last said stopped it), releaseNow and the stage timings.

Review feedback

  • Terminal had no entry (sentinel): release now is now in the keeper screen's h prompt as now: <reason>, through the same releaseNowAs as the page and MCP. The screen also shows a standing request. The prompt label and key hint name it. test/tui-release-keeper.test.ts covers it.
  • Second form and extra rows (principles 1 and 3): /releases now has one Reason field with two buttons, Hold and Release now, the second using formaction. The stages, cut-now reason and keeper reason share one muted row per release instead of three.

Not done

  • Terminal row: I did not add stage timings to the terminal's release row. The row is already full at 80 columns and the extra text pushed the stage label and commit off the front, which broke an existing test. The timings are on the web card and in MCP.
  • Two-minute target, proof before traffic moves, runs carried across a release, one-step rollback and production timings: none of these is done. The build path is unchanged and I only added the measurement. Each should be its own linked issue.

Checks: scripts/gate.ts, tsc --noEmit and scripts/design-lint.ts are clean. The keeper, hold, release-now and TUI keeper test files pass.

To try it: as an admin, type a reason on /releases and press Release now, or in the terminal press h and enter now: reason. The next tick cuts, and the card shows its stage line and "Cut now: <reason>".

🤖 Generated with Claude Code

Approved

Earlier asks are met. The terminal has its entry (now: reason in the h prompt, through the same releaseNowAs, gated by mayRollBack). /releases has one Reason field with two buttons instead of a second form, and the three notes share one muted row. Both write paths check who, validate and cap the reason, and agents are refused. Tests cover the cadence, the lapse, the hold and agent refusals, and the TUI entry. The how-to is in docs/features/release-keeper.md, not README.

Non-blocking: stage timings are on the page and in MCP but not on the terminal release row. Add a detail line there later. Non-blocking: if the tag push is refused after clearNow, the request is spent without a cut. Clear it only after the tag lands. Non-blocking: the test reads the MCP answer with any casts. Use the typed value.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs