fix(library): dose the broken circuit at climbing pace, and guard the rate - #128
Merged
Merged
Conversation
… rate `broken_circuit_redpoint`'s `work_seconds` was 25 in STRENGTH and POWER against instructions saying "around twenty-five moves" — the move count leaked into a seconds field, at 1.00 s/move. Ruling 50: 90 s in all three phases, which deletes the 3.6x phase step rather than rescaling it. PERFORMANCE already carried 90; `sets` 4/4/3 and the rests are untouched, because a set of a work_seconds-carrying circuit is one attempt at the whole circuit by the library's own filing convention. No source states a move->seconds rate for An Pow, so the conversion is declared at the row as the app's own rather than dressed as sourced. The guard is the load-bearing half: that cell's `work_seconds` was read by NO guard in the repo, so it could have been 90, 120 or 180 with a green suite. - a move-rate band over every row stating a move count AND carrying `work_seconds` (1.50-4.17 s/move), reading BOTH ends so editing the prose to close a breach fails just as loudly - the progression arm's sampling unit widened from a week PAIR to a DRAWN CELL: `shorter_rest` 15 -> 189 cells, and this row 0 -> 99. Pair arm kept beside it - per-(rule, phase) coverage floors, so a phase falling silent turns red instead of going quiet Displacement, 72-plan sweep sabotage-checked at 9999 s first: only `power` moves, +256.3 min there, ruling 27's fill absorbs it; pooled -87.1 min / -9 blocks. `library_digest` ad0cbbc9 -> cca51ea1, which is the intended provenance signal. `GENERATOR_VERSION` unmoved: the library is a third input covered by the digest, and every past bump also changed the planner package. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This was referenced Sep 6, 2026
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes F26 (ruling 50). v8.14.0.
The defect
broken_circuit_redpointdoseswork_seconds=25in STRENGTH and POWER while its owninstructionssay "a hard circuit of around twenty-five moves". That is the move count leakedinto a seconds field — 1.00 s/move, the only value below 2.00 anywhere in the library or the
sources. PERFORMANCE's 90 s for the same 25 moves is 3.6 s/move and correct, so the 3.6× "phase
progression" was an artifact of the error rather than a rule.
The 25 s reached a climber in exactly one place: the library-browse line "4 sets · 25s work",
sitting beside instructions saying "around twenty-five moves".
protocol.ts::setPhasesmapscircuitto an open phase, so it was never a countdown — the fix carries no player risk.The fix — ruling 50
work_secondsis 90 in all three phases. This deletes the phase step rather than rescalingit, because §5.4 progresses An Pow by cutting rest, never by lengthening work. PERFORMANCE is
untouched, so only the two wrong cells move.
sets4/4/3 andrest_between_sets_secondsare unchanged: all four circuit rows carryingwork_secondsdose the whole circuit and usesetsfor rounds, while the three counting pieces userepsand carry nowork_seconds. No row mixes the idioms, so a set here already means one attemptat the whole circuit.
only. So the conversion is declared at the row as the app's own, not dressed as sourced. The
PERFORMANCEcomment said "fewer, longer pieces", which one number for the row makes false; itis reworded.
The guard is the load-bearing half
work_secondswas read by NO guard in the repository. §7's rest:work band guardexcludes
power×circuitby scope (ruling 43, correctly — the sources are silent). The progressionarm read 0 pairs from the row's 136 drawn blocks. The player never renders it. Measured: the value
could be 90, 120 or 180 with the whole suite green.
(a) A move-rate band. For every row whose
instructionsstate a move count and whoseprescriptions carry
work_seconds, the implied s/move must sit in 1.50–4.17. It reads bothends, so "fixing" a breach by editing the prose fails just as loudly. Move counts are held as data
restated from the prose, with an arm proving the restatement still matches — no runtime numeral
parsing. Floor pinned at 4 rows / 16 (row, phase) prescriptions.
long_boulder_link_ups(ruling 45) and
explosive_move_intervalsare named exclusions carrying their reasons as data.(b) The progression arm's sampling unit, week PAIR → DRAWN CELL. The pair arm inspected 15
week-pairs against 429 drawn loading-week cells (3.5%) and was silent in
strengthandperformanceentirely — pooled green, false per phase. Cause:_pool_indexrotates the pool byweek, so a row lands in one loading week per block and a pair needs two. Now: every loading week
after the first must have left the authored dose behind, in the direction its rule names, read as
authored-vs-emitted without asking
progression.pywhat the rule is.shorter_rest15 → 189cells (12.6×); this row 0 → 99. All three rules green today — a sweep widening, not a re-dose.
The pair arm is kept beside it.
(c) Per-(rule, phase) coverage floors, so a phase falling silent turns red instead of going
quiet.
(shorter_rest, strength)is a declared zero:boulders_on_the_two_minuteis drawn 104times there and every draw is week 1, so there is no later-week dose to read. That is a
selection fact — pinned, not papered over with a synthetic plan.
Captured red — all four shown to fail at the final code state
(a) at 25 s:
(a) the other end — dose left at 90, prose reworded to "ninety moves":
(b) with this row's progression frozen:
entire rest of the suite is green (1151 passed) — including the pair arm. That is the measured
proof the cell arm reads a row nothing else in the repo read.
(c) both directions — a floor raised 16 → 99 goes red, and moving the declared zero to the
wrong phase goes red on both halves at once.
Displacement — 72-plan sweep, sabotage-checked at 9999 s before any figure was believed
Only the
powerphase moves. The row gains +256.3 min there and ruling 27's session fillabsorbs it (filler −266.7, phase
estimated_minutes−79). Pooled −87.1 min / −9 blocks over72 plans. 25 of 72 profiles move at all; worst case +18.4 min over a 20-week plan ≈ +0.9 min a
week. Zero guard failures at 90 (240 breaks two, so "a bit more" is not free).
library_digestad0cbbc9…→cca51ea1…— intended: the library is a third reproducibilityinput. Persisted plans keep their stored digest and their stored 25 s, which is correct provenance.
python -m server.contentseedre-run;prescription_templateverified at 90 in all three phases.GENERATOR_VERSIONstays 8.0.0.fingerprint.pyandPlanOutboth scope the library tolibrary_digest();contract.py's own comment scopes the version to the planner package, whichthis PR does not touch. Checked with
--numstat: every bump #120–#126 also changedgenerate/climbing/selection/periodisation/progression, and #125 re-authored doses inexercises.py— including anaspect_keyre-file that moves selection — without bumping.Corrections to the research report, recorded rather than smoothed
_SWEEPbuilds 20-week plans, so its +1.5 min/week wasoverstated 1.67×; the real figure is +0.9
powerdraws fall64 → 63 (a longer block stops fitting one session's ceiling)
explosive_move_intervalsEverything load-bearing reproduced exactly: pooled minutes, blocks, the
powergain, and everycoverage figure.
Found, not fixed
Two side findings, neither F26's: the library holds two incompatible circuit time models
(
work_secondsat ~3 s/move vsSECONDS_PER_REP = 4pricing a whole 5–7 move boulder at 4 s, sothe counted-pieces rows systematically under-contribute to every minute figure in the repo), and
short_rest_boulder_setsstates its work period only in prose — guard (a)'s completeness arm nowturns red if anyone authors
work_secondsonto it.npm run checkgreen: web 1282, server 1322 passed.🤖 Generated with Claude Code