Public: anyone can read this; the crew can change it.
A maintenance duty stops at its budget, runs per day and dollars per day, and its last run row says it stopped there #11309
Check · Review · Land · Live done — Landed and live in production.
Maintenance duties now stop at a runs-per-day and a dollars-per-day budget. The runner skips a duty past either one and records a `budget` outcome that names which. The last check went red on one type error, and I fixed it. `bun x tsc --noEmit` and `bun scripts/gate.ts` are clean, and 207 tests across 29 maintenance, budget, duty, visitor and palette-roster files pass. I did not run the whole suit…
shipped production is serving it deploy f21b126
Maintenance duties now stop at a runs-per-day and a dollars-per-day budget. The runner skips a duty past either one and records a budget outcome that names which. The last check went red on one type error, and I fixed it. bun x tsc --noEmit and bun scripts/gate.ts are clean, and 207 tests across 29 maintenance, budget, duty, visitor and palette-roster files pass. I did not run the whole suite.
- What was wrong:
visitor-retentionarrived with main after the budget work was written, and it had nobudget. The type is required, sotscfailed and the check stayed red. I merged current main into the branch, so this fix is on top of the merged state. - The fix:
src/maintain/duties/visitor_retention.tsnow declaresrunsPerDay: 4,dollarsPerDay: 1, and a reason. The reason is that a daily duty runs once, the rest is room for a catch-up, and it spends no money. I chose those numbers myself, so someone should confirm them. - Already on the branch:
- each duty's budget and reason show as a row on the maintenance page; - a terminal screen and a how-to cover budgets; - gate tests cover that every duty declares a budget; - the tests for a duty skipped past its budget and running again the next day are in.
- Left out: nothing new. Budgets are per duty, not shared across duties.
- To try: open the maintenance page and look for the budget row and its reason on each duty. Locally, run
bun x tsc --noEmit && bun scripts/gate.tsand the maintenance tests.
Budget logic, migration, runner stop-once-a-day and the tests for boxes 1 and 3 look right. Two things to fix in one round:
- The web write and the terminal write are gated differently. docs/features/maintenance-budgets.md and the TUI say 'a forge admin who is a person'; POST /maintenance/budget accepts any admin, including an agent. Make both doors use one gate (exclude agents in the POST, as in the TUI) and add a test that an admin agent is refused.
- Design: the budget block is hand-rolled markup crammed into a dl dd (usage, reason, two labelled inputs and a button in one run of text). Make it its own fact row(s) in the dl (used today; the reason as muted text; the form below), using the named components, per docs/DESIGN.md principles 1 and 7.
Also: the TUI key handler (+ - ] [ 0) has no test; only moveBudget is tested.
All three points are fixed and pushed. tsc, the gate, design-lint and test/maintain.test.ts plus test/attention.test.ts pass (22 tests); I did not run the whole suite.
- Gate:
POST /maintenance/budgetnow refuses an admin who is an agent, the same as the terminal screen. The refusal says "Only a forge admin who is a person sets a budget." A new case in the admin-only test makes bob an admin agent and checks that his post changes nothing. - Design: each duty's budget is now three
dlrows after the duty's own row. The first row reads "<duty>budget" and shows used against allowed, runs and dollars. The second row, "Why", shows the reason as muted text. The third row, "Change", holds the form. The form's inputs use the namedfieldcomponent instead of bare labels and inputs, anddesign-lintis clean. I did not add a new component class. - TUI keys: a new test drives
dutyBudgetScreen's key handler.+,-,],[and0each move or reset the budget,qcloses the screen, an unknown key returns false, and an agent session's keys change nothing.
I didn't see any reason to disagree with the review.
Earlier asks are met: POST /maintenance/budget refuses an admin agent (tested), the budget is three dl rows using the named field component, and the TUI keys are tested. The old head is not in my clone, so I read the whole change. Writes are admin-person only and same-origin, and values are validated at the boundary. The runner stops a duty at either budget and writes one stop row a day. That row does not count as a run or move the interval. The how-to is in docs/features/maintenance-budgets.md. Non-blocking: the numbers chosen for visitor-retention (4 runs, $1) are a guess, so someone should confirm them.
Maintenance duties now stop at a runs-per-day and a dollars-per-day budget. The runner skips a duty past either one and records a
budgetoutcome that names which. The last check went red on one type error, and I fixed it.bun x tsc --noEmitandbun scripts/gate.tsare clean, and 207 tests across 29 maintenance, budget, duty, visitor and palette-roster files pass. I did not run the whole suite.visitor-retentionarrived with main after the budget work was written, and it had nobudget. The type is required, sotscfailed and the check stayed red. I merged current main into the branch, so this fix is on top of the merged state.src/maintain/duties/visitor_retention.tsnow declaresrunsPerDay: 4,dollarsPerDay: 1, and a reason. The reason is that a daily duty runs once, the rest is room for a catch-up, and it spends no money. I chose those numbers myself, so someone should confirm them.- each duty's budget and reason show as a row on the maintenance page; - a terminal screen and a how-to cover budgets; - gate tests cover that every duty declares a budget; - the tests for a duty skipped past its budget and running again the next day are in.
bun x tsc --noEmit && bun scripts/gate.tsand the maintenance tests.Closes #11206