feat(metrics): a forced run can override more than one stop - #171
Conversation
issue-pr-cron#245 was re-ruled: `--force` now overrides POLICY stops — the usage-gate PAUSE and the DISABLED kill switch — while correctness stops (the flock, a gate config refusal) still never yield. One forced run can therefore walk past two stops, so `forced`/`forceReason` became parallel LISTS: index i is a stop's kind and that stop's own line, verbatim. The tooltip names every stop it overrode, each with its line, instead of one. The caption and the aria description stop naming the usage gate, because the gate is no longer the only stop a force can walk past and naming one would mislabel a run that overrode the other. `"forced": []` is the ordinary case and is rendered as its own words: a human started the run and nothing was in the way. That row still rings and still counts — "the schedule did not start this" is the fact the marker carries, and the stops are detail on top of it. `forcedKinds`/`forcedReasons` coerce the shape once, so a bare string (the row shape #169 shipped against), a non-list, a null element or a non-string kind all render as something a reader can act on rather than as `undefined`. Rows without the fields render exactly as before: byte-identical PNGs against the live file, which still carries no forced row at all. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Warning Review limit reached
Next review available in: 2 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Screenshots
Live data: still no visible changeNo forced run has ever been recorded, so the live Fixture: the two cases the new shape exists forThe live file plus two rows, and nothing else changed:
What the shot shows:
|
|
Reviewed ef3a813: pass Verified on the head blob. Backward compatibility is by construction, not by branch.
Every field stays untrusted: kinds and reasons are filtered, Rulings-conformance: checked against the rulings governing this work.
The prose correctly moves off "forced past the usage gate" to "started by hand", which is now the accurate claim since a marker can name a kill switch, a gate, both, or neither. CI: all checks pass. Merging with |



Refs rainlanguage/issue-pr-cron#245
Follows #169 (merged), and pairs with rainlanguage/issue-pr-cron#248, which changes the field this page reads.
Why the shape changed
issue-pr-cron#245 was re-ruled by the user after the first observation run printed
SKIP: DISABLED flag presentand did nothing:--forcenow overrides policy stops — the usage-gate PAUSE and theDISABLEDkill switch — while correctness stops (the flock, a gate config refusal) still never yield. So a single forced run can walk past two stops, andforced: "usage-gate"cannot say that. Both fields are now parallel lists: index i offorcedis a stop's kind and index i offorceReasonis that stop's own line, verbatim.What changed here
"forced": []gets its own words. That is the ordinary case — a human started a run to watch it and nothing was in the way — and the row still rings and still counts. "The schedule did not start this" is the fact the marker carries; the stops are detail on top of it. Rendering that run as an ordinary tick is the corruption the whole field exists to prevent.forcedKinds/forcedReasonscoerce the shape once, so a bare string (the row shape feat(metrics): draw a forced run apart from a paced tick #169 shipped against), a non-list, a null element, or a non-string kind all render as something a reader can act on rather than asundefined. The emitter can also grow a third stop kind without this page learning its name.The reasons are deliberately not zipped into the kind line by index. The emitter refuses a mismatched pair, so zipping here would be a second place believing the two lists are the same length — and the failure of that belief would silently drop a reason rather than showing it.
Screenshots
nix run .#screenshot(pinned chromium),metrics.html, 1300×1500, each read before posting.nix run .#roh-scanwas NOT run — pure rendering change. Posted as a comment below.The live file still carries zero forced rows — no forced run has ever been recorded — so the live state is again no visible change, demonstrated rather than asserted: master and this branch render byte-identical against it (
cmp, 111381 bytes each). The fixture is the live file plus two rows, chosen as the two cases the new shape exists for: one mid-series run forced past both stops (and errored, so the ring is seen composing with the red dot), and one appended run with"forced": []— forced, nothing overridden.QA
metrics forced: the tooltip names EVERY stop, each with its own line(renamed from…carries the gate's line verbatim, now looping both lists),metrics forced: a run that overrode NOTHING still says a human started it(new —"forced": []is forced, is ringed, is counted, and says so without claiming it walked past anything),metrics forced: a legacy single-value row still renders(new — the row shape feat(metrics): draw a forced run apart from a paced tick #169 shipped against, coerced rather than refused),metrics forced: a stop kind that is not a string still names itself(widened to[true, null]),metrics forced caption: counts them, and says they still count(now also asserts the caption does not claim one particular stop), plus the unchangedthe gate field marks a forced run and nothing else,a forced run is a run — it charts, and it counts,the chart rings the forced run, and only it,the ring is ADDED to an errored run,a forced run with no plotted value gets no ring,the end label clears the ring on a forced last run,a file with no forced runs renders exactly as before, and bothhostile inputtests. Fails on base: with master'ssite/metrics.htmlrestored under this branch's tests, the suite reports0 passed | 1 failed— it cannot even load, becausebind("metrics.html", "forcedKinds", …)is a top-level binding and master's page has no such function. That is the structural form of "fails on base": every assertion below it is unreachable against the old renderer. 261 pass on this branch.forcedKindswraps the list instead of spreading it →metrics forced: a run that overrode NOTHING still says a human started itforcedKinds/forcedReasonsdrop the non-list arm →metrics forced: a legacy single-value row still renders, bothhostile inputforced testsa run that overrode NOTHING…a run that overrode NOTHING…metrics forced: a stop kind that is not a string still names itselfmetrics forced: the tooltip names EVERY stop, each with its own linemetrics forced caption: counts them, and says they still countinnerHTMLinstead of a text node →dashboard pages contain no markup sink at all, bothhostile inputforced tests,a legacy single-value row still renders,the tooltip names EVERY stopfinal_recordandForceStamp— parallel arrays, absent (not null) on scheduled rows, empty as a real state, never besideskipped. The legacy-string case is read off what feat(metrics): draw a forced run apart from a paced tick #169 actually shipped, not guessed. Visual claims are checked against actual screenshots, read, not assumed.Refsrather thanCloses: the issue is in another repo and fix(runners): --force overrides policy stops, not correctness stops issue-pr-cron#248 is the PR that carries it.