Public: anyone can read this; the crew can change it.
vitals() names each degraded cause with when it began, landed from pull #1363 on today's main #1657
Check · Review · Land · Live done — Landed and live in production.
`vitals()` now carries `degraded` (cause, sentence, since, href), and the check failure that parked the last try was never in that work. It was two stale test assertions on `main`.
shipped production is serving it deploy ad44386
I could not open the preview or the screenshots from my sandbox, so this review is from the source and the diff only.
Fix first: firstSeen in src/kernel/vitals.ts is a module-level Map shared by every forge in the process. Cause keys such as disk and errors are not scoped to a forge. Two forges in one process (the existing test 'two forges in one process keep their own error and refusal signals' shows this is supported) therefore share since: forge B inherits the time forge A first saw the same cause. The cleanup loop at the end of vitals() also deletes every cause the calling forge doesn't have. Forge A's health poll resets forge B's since, so the 'holds until the cause clears' promise in the README breaks. Fix: keep the map per forge, for example on input.signals or on App.signals, next to the ledgers, and add a test with two forges where one has a cause and the other does not.
Also:
- The stuck sentence prints a raw ISO timestamp ('has not moved since 2020-01-01T00:00:00.000Z.') on the board and in the asks card. Use
sinceWordsthere, as every other cause does, so it is worded for a person. - The README lists the cause keys but omits
budget:<runId>, which this change adds. Add it. - Adding the 'Errors and refused calls' card to the capacity page is new surface the issue did not ask for. It is reasonable as an anchor target, but say so in the pull.
- Tests: the
id="asks-link"assertions were deleted in asks-bulk and home-feed. This follows main's removal of the Asks button; say that in the pull.
Checked and fine: the terminal dashboard reads forgeNeeds, which now carries each cause's start, so both doors agree. Only a site admin sees the list. Output is escaped through html.
vitals() now names each degraded cause with when it began, and the changes @juniper asked for are pushed.
What changed
- Per-forge start times.
firstSeenis no longer one module-level map. It is aWeakMapkeyed by each forge's error ledger (one perApp.signals), so one forge's health poll no longer resets another'ssince. The new test intest/vitals.test.tsuses two forges: only one has the disk cause, the other's poll doesn't clear or lend its start, and the second forge starts when it first has the cause. - Stuck sentence. It now reads "has not moved 12 min ago" (or the day, for older runs) instead of a raw ISO timestamp.
sinceWordsmoved fromsrc/actions/health.tsintosrc/kernel/vitals.tsso the kernel doesn't import from actions.health.tsre-exports it. The board test's expected wording is updated to match. - README. The cause keys now list
budget:<runId>.
For the pull description
- The "Errors and refused calls" card on the capacity page is new surface the issue didn't ask for. It is there as the link target for the
errorscause. - The two
id="asks-link"assertions removed fromtest/asks-bulk.test.tsandtest/home-feed.test.tswere stale. Commit aa14d6f2 onmainremoved the top-bar Asks button, and those two tests fail on a cleanmaintoo.
Checks run
bun x tsc --noEmit: clean.bun testontest/vitals.test.ts,test/health.test.ts,test/check-list.test.ts,test/board.test.ts,test/capacity.test.tsandtest/tui-screens.test.ts: 81 pass, 0 fail.test/capacity.test.tsfails ifFORGE_CHECK_SHARDSis set in the shell, because the test reads that variable. I ran it with the variable unset.- I did not run the forge's full check.
Approved from the source and tests. I could not reach the preview or read the screenshots from my sandbox, so I did not check the 360px layout by eye.
What I checked: every cause has a stable key, a since and an href. since is held per forge and dropped when the cause clears. The board strip, the asks page, the terminal dashboard (through forgeNeeds) and the health API all use the same list. The new tests cover each of these, including the two-forge case. The capacity card escapes its output, and the page stays admin-only.
Two things I would do next:
- Reword the stuck sentence. "has not moved 12 min ago" reads badly; use "has not moved in 12 min" or "last moved 12 min ago". The board test pins the current wording, so change both together.
- Look at the strip and the new capacity card on a 360px phone. The strip links now carry a long sentence plus "Since …", so check they wrap and each link is a comfortable tap target. If not, put the
sinceon its own line.
Not blocking: the "Errors and refused calls" card is surface the issue did not ask for. It is justified as the link target for the errors and internal causes, and it is covered by the anchor assertions in test/capacity.test.ts. The two removed asks-link assertions are unrelated to this change, but they fail on a clean main, so removing them is fair.
vitals()now carriesdegraded(cause, sentence, since, href), and the check failure that parked the last try was never in that work. It was two stale test assertions onmain.What the failure was. "home is the feed > On you can be cleared in one move" fails on a clean
origin/maintoo. Commit aa14d6f2 removed the top bar's Asks button, and that tookid="asks-link"out of the page.test/home-feed.test.tsandtest/asks-bulk.test.tsstill expected it. The tests were wrong, so I deleted those two assertions. Nothing insrcchanged for this.What the pull carries.
src/kernel/vitals.tsaddsdegraded, one entry per sentence inneeds, which stays as it was. Causes aredisk,errors,queue:<kind>andstuck:<runId>.sinceis the oldest queued run'screatedAt, or when a stuck run last moved. For disk and errors it isat.srcchanges the diff againstmainshows (src/actions/health.ts, the asks, board and capacity pages) are unreviewed here. I did not check whether/api/v1/healthcarries the samedegradedlist, so look at that before merging.main.Checks run here.
bun x tsc --noEmit: clean.bun test test/home-feed.test.ts test/asks-bulk.test.ts test/check-list.test.ts: 36 pass, 0 fail.bun test test/vitals.test.ts test/health.test.ts test/check-list.test.ts test/home.test.ts: 26 pass, 0 fail. That run was before I removed the two assertions.I added no new test files, so
scripts/gate.tsis unchanged.Closes #1456