Remove LeadContextGauge.read's 3-arg overload — the last back-compat form that silently restores the fixed 200000 threshold #663
Closed
opened 2026-10-03 19:15:01 +02:00 by ltms
·
2 comments
No Branch/Tag Specified
main
worker/664-c12e95-3
worker/668-08534d-4
worker/672-0f2469-2
worker/670-7d1022-1
worker/661-ac7c28-2
worker/664-37fb9b-3
worker/663-remove-3arg-read-3f6783-1
worker/659-remove-dead-backcompat-ba5e6f-1
worker/637-revision-60a488-23
worker/656-redact-regression-tests-892903-19
worker/637-context-gauge-threshold-466eb5-16
worker/639-redact-line-numbers-de4ac4-17
worker/641-set-reformat-guard-6f96a4-18
worker/642-herdr-guard-scope-5de0e4-15
worker/650-javadoc-scope-95f3b3-14
worker/612-01e9f7-13
worker/612-a-r4-quarantine-outage-7ab0e8-5
worker/612-a-r9-r11-capacity-coverage-peers-cfcc79-7
worker/612-a-r10-loophealth-ccc872-8
worker/612-a-r12-turnregistrar-9e3bb7-9
worker/612-a-r5-leadconfigdir-9e70cf-6
lead/config-edit-redact-anchor-wording
worker/config-edit-seam-ca8dc1-1
worker/612-r67-630-lifecycle-290b8d-3
worker/629-625-ports-seams-da7d5d-4
worker/612-r12-exhaustion-f37cd7-1
worker/612-r38-amqp-24b083-2
worker/fleetd-612-unita-87807e-1
worker/612-b3-mcpwirings-da2b58-3
worker/612-b2-cb185-176d3a-2
worker/612-b1-completion-457459-1
worker/612-agaps-73a926-2
worker/608-sleeps-3a64ff-3
worker/621-b4520b-1
worker/618-b83894-2
worker/fleetd-615-e05481-5
worker/lead-autocompact-5f1ab2-3
worker/fleetd-613-f85deb-3
worker/fleetd-608-flaky-nudge-test-d0c2d1-3
worker/lead-context-gauge-ad404f-1
worker/gauge-wiring-9158c1-4
worker/redeploy-slowstart-ead0e5-5
worker/charter-bytes-13668c-6
worker/rollover-outcome-291483-2
worker/589-f64303-2
worker/593-1a8025-5
worker/589-fcd2aa-1
worker/568-9fdaa2-3
worker/571-attempted-outcome-5739f7-2
worker/581-completionresolver-cas-sites-0542b7-6
worker/562-loop-health-wiring-test-99611c-5
worker/562-surface-loop-health-7df5cc-4
worker/575-waiter-cleanup-sites-62ad80-1
worker/572-answer-lock-release-46a9ae-5
worker/567-probe-channel-leak-a38fc5-6
worker/551-record-before-send-7cbf56-1
worker/561-listener-fanout-survives-a-throw-61d538-2
worker/555-redeploy-main-flow-seam-65c2f5-2
worker/556-injector-owns-registration-e027a5-1
worker/552-post-restart-mktemp-abort-bc2672-4
worker/553-onstatus-completion-leak-0da881-2
worker/550-shasum-linux-196132-1
worker/538-loop-dies-on-error-4a5eeb-6
worker/426-health-coverage-ef1fd4-4
worker/504-failed-reported-clean-3cfd66-3
worker/537-capturedlog-close-e4c437-2
worker/459-broken-link-targets-cadc17-5
worker/535-appender-leak-fe74c1-1
worker/512-part2-shutdown-detection-434701-9
worker/529-logger-level-sweep-2a5533-8
worker/528-drain-gate-call-site-5de83d-7
charter/forge-mcp-vs-token
worker/521-swap-guard-unpinned-28e931-5
worker/519-probe-test-harness-d25ab8-4
worker/525-logger-level-leak-1b4eb0-6
worker/518-fleetmcp-resolver-wiring-8ef96c-1
worker/512-drain-complete-line-7edd71-3
worker/517-abort-branch-and-jar-id-41b641-2
worker/500-9e52c9-3
worker/509-4912f4-2
worker/511-9a4b23-1
worker/493-479f45-2
worker/505-03f8b2-1
worker/492-followup-detect-unclear
worker/501-a31fa0-7
worker/498-451d1c-5
worker/494-1015ce-2
worker/492-209647-1
worker/489-001902-2
worker/480-relative-handover-path-906323-1
worker/480-b-handover-skill-45bf1f-5
worker/474-followup-source-pin-f54a55-17
worker/474-charter-check-on-reload-f54a55-17
worker/466-quarantine-repeatcount-report
worker/393-opencode-skill-seeding-71854b-13
worker/469-canonical-tool-names-2a472a-16
worker/466-quarantine-escalation-5ae9c1-15
worker/446-hot-exhausted-pattern-0af580-6
worker/464-charter-tool-name-guard-a85635-12
worker/463-listfleet-default-fails-open-f1c76c-11
worker/458-invariant-5-by-purpose-862f9a-10
worker/439-coordinator-row-gate-bc032a-8
worker/449-herdr-protocol-576015-4
worker/450-abstract-spawn-599e1c-5
worker/437-ack-refuses-177d91-1
worker/444-placement-window-feb56a-2
worker/440-helddurable-derived-d462d7-13
worker/425-rework-placement-resolve-c58ba1-9
worker/421-lead-peek-held-msgs-cdbad2-10
worker/435-fixed-policy-cap-fe11de-12
worker/422-gate-state-observability-9e79d6-11
worker/431-memberregistry-live-readers-cdbad2-10
worker/424-architect-slot-hot-038b41-7
worker/422-model-gate-spawn-c29f48-6
worker/425-default-profile-live-f55534-8
worker/415-coverage-wording-2cbf9c-5
worker/416-3ad1da-1
worker/418-588283-3
worker/deterministic-stamp-race-409-3cb7b6-10
worker/armed-reads-live-config-404-ed931f-9
worker/reply-peer-refusal-391-5a34bd-7
worker/models-allowlist-aa9e9b-3
worker/ttl-stamp-race-399-f1122f-8
worker/scrub-receipt-400-316b3e-5
worker/exhaustion-detection-395-105105-6
worker/scrub-abort-394-316b3e-5
fix/scrub-uid-abort
worker/task-scrub-517574-2
worker/t386-clock-bd5b78-4
worker/t384-scrub-813790-5
worker/t381-cc-748314-2
worker/t373-336973-2
worker/t365-3920c5-3
worker/t358-6e989b-1
worker/t355-8b321c-1
worker/fleetd-369-hermetic-git-tests-e8b19a-3
worker/fleetd-368-stale-lead-binding-f5682e-2
worker/fleetd-360-deploy-units-0d3793-1
worker/359-dead-lead-tabs-f1253b-4
worker/362-worktree-skills-c03e51-3
worker/361-coord-visibility-655144-1
362-plugin-visibility-and-drift
worker/errscan-bed2ca-2
worker/amqp-log-identity-bed2ca-2
worker/withdefaults-guard-561704
worker/sleepguard-82076d-1
worker/fd334-9ee1b6-5
worker/fd348-f1ab27-4
worker/fd335-a71c35-1
worker/fd342-174a17-2
worker/fd345-490d0f-3
worker/fleetd-337-5ec7d4-21
worker/fleetd-341-af5a6b-24
worker/fleetd-339-5ca0a2-23
worker/fleetd-338-83a4a1-22
worker/fleetd-333-281f46-18
worker/fleetd-329-11bdbb-16
worker/fleetd-330-2770fb-17
worker/fix-326-50506e-15
worker/fix-324-3e9bbf-14
worker/fix-323-b8287d-13
worker/fix-316b-bd0860-11
worker/fix-318-76ca36-9
worker/fix-317-486aec-8
worker/fix-315-ce47c5-6
worker/fix-307-275890-6
worker/fix-308-b4f664-7
worker/fix-309-ec3939-8
worker/fix-310-7a3974-9
worker/fix-302-52ad0e-9
worker/fix-298-ce1acb-8
worker/fix-297-66bd11-7
worker/fix-296-104622-6
worker/fix-293-bare-closetab-eb22b5-3
worker/fix-280-gone-ask-lapse-bca98e-2
worker/fix-290-reapidle-guard-coverage-9b0dd1-1
worker/fix-285-trust-seed-8f3565-10
worker/fix-284-backend-error-seat-85912c-11
worker/fix-282-chained-ask-e6d0bb-8
worker/fix-283-teardown-leaks-f40dfa-9
worker/fix-281-pin-handler-actions-4921ac-7
worker/audit-rendezvous-lifecycle-d072ae-2
worker/audit-health-placement-1a2476-6
worker/audit-teardown-exits-e207a5-3
worker/audit-launcher-asymmetry-27e370-4
worker/audit-rest-authz-6ca53c-5
worker/investigate-275-abandon-asking-fdef52-8
worker/fix-274-worktree-leak-b0095d-7
worker/fix-273-exhausted-pattern-9665b5-6
worker/fleetd-267-model-check-bd8068-1
worker/fleetd-131-archunit-18b834-7
worker/fleetd-266-sshagent-rename-a014ff-6
worker/fleetd-184-uid-claim-8e1f31-4
worker/fleetd-184-warn-b381ee-10
worker/fleetd-184-docs-be1d12-9
worker/fleetd-257-9bf010-7
worker/fleetd-103-23a113-6
worker/fleetd-247-342356-5
worker/fleetd-116-04dea8-4
worker/fleetd-252-a830e0-3
worker/fleetd-111-7e8673-9
worker/fleetd-155c-f8ef4b-8
worker/fleetd-176-b928ca-3
worker/fleetd-249-7a7878-2
worker/cb248-composition-root-b-9acdf7-15
worker/cb148-envrc-default-fa6c82-12
worker/cb201-unit5-wiring-6c12e6-8
worker/cb241-fallback-echo-1175e9-11
worker/cb149-trust-dialog-2392a5-9
worker/cb134-148-overlay-visible-c9b986-10
worker/cb234-session-id-keyed-04e1fc-1
worker/cb201-unit3-nudge-abdf5c-6
worker/cb201-unit2-policy-c1102c-5
worker/cb201-unit4-outcome-a13bfa-7
worker/cb201-unit1-classifier-91b9b1-4
worker/cb201-227-refine-831980-3
worker/cb175-model-readback-0f085f-1
worker/cb222-charter-tmpdir-17f013-1
worker/cb226-architect-slot-race-cd3aa8-3
worker/cb224-worktree-root-group-024523-2
worker/cb-123-role-demotion-c600f7-2
worker/cb-219-opencode-roots-1f677e-1
worker/cb214-claude-session-id-b9eab4-4
worker/cb213-zdotdir-wrong-process-dd6de4-3
worker/cb211-exhaustion-classification-9546e0-2
worker/cb137-ambiguous-task-4df3d8-4
worker/cb209-agentsessionid-4dfdb6-2
worker/cb185-hostenvnames-2692b5-3
worker/cb206-opencode-sqlite-128718-2
worker/cb185-worktree-group-fc0c99-1
worker/cb-137-ask-ticket-e7760c-2
worker/cb-172-broker-uri-d36ae4-4
worker/cb-175-model-readback-76ead6-3
worker/cb-161-pane-ancestry-293510-1
worker/cb-164-rebase-885863-8
worker/cb-164-empty-scrape-false-success-1a80af-3
fix/cb-197-ticket-ttl-from-completion
worker/cb-189-remote-url-coverage-4692f3-1
worker/cb-185-blockers-027756-4
worker/cb-192-gap-log-11b631-2
worker/cb-633-fix-5f4396-3
worker/cb185-router-d6436d-3
worker/cb185-router-routing-gaps-9e9d33-3
worker/cb185-paneids-992586-2
worker/cb-633-allow-list-union-ed374b-1
worker/cb-157-credential-in-remote-url-496e44-2
worker/cb-641-health-herdr-evidence-8f1f54-6
worker/cb-640-health-msg-evidence-99c9cd-1
worker/cb-642-fleets-status-skill-bbbc40-5
cb-634-ide-mcp
worker/lead-comms-wiring-c014b9-7
worker/lead-mailbox-c19577-6
worker/autocompact-window-82bc2f-5
worker/cb-634-probe-18056f-4
worker/cb635-broker-urienv
worker/cb-632-config-retry-8e0efa-7
lead/cb-622e-claude-md
lead/cb-622-followup
worker/cb-622a-165dff-1
lead/cb-622d-opencode-mount
worker/cb-622b-717c67-2
worker/cb-622c-ab7759-3
worker/cb-617b2-20ca4b-3
worker/cb-617a-5c2f4a-1
worker/cb596-4e49ef-3
worker/cb586-10500c-1
worker/cb-606-b9343a-25
worker/cb604-1445f8-24
worker/cb582-477374-21
worker/cb584-8c2281-22
worker/cb600-e6b9a9-20
worker/cb602-ce257f-19
worker/cb601-b42837-18
worker/cb598-6c7ba7-17
worker/cb599-740fe4-16
worker/cb597-282224-15
worker/cb590fix-185e9a-10
worker/cb528-recovery-race
worker/cb594-96bead-8
worker/cb590-916766-2
worker/cb527-997d99-3
worker/cb592-env-leak-3cbf9c-1
worker/cb588-async-ticket-nudge-3218f7-5
worker/cb578b-9dcb13-6
worker/cb581-d24826-5
worker/m2-u5-ef8c42-15
worker/cb578a-516499-2
worker/cb576-01a04b-17
worker/cb579-lead-tab-acba06-20
worker/cb580-terminal-health-ed6058-21
worker/cb577-f36fdc-18
worker/cb573b-3db06f-16
worker/cb568c-f36fdc-18
worker/cb568-drop-cause-c3ac1c
worker/cb575-cancelled-notification-c3ac1c
worker/m4-sol-a2cbec-3
worker/cb574-async-ask-c3ac1c
worker/cb573-health-model-8ca857-14
worker/cb572-unknown-target-7f2e35-13
worker/u4-700706-9
worker/u3-b9fcb6-6
worker/u2-ef5b68-4
worker/u1-469dce-1-clean
worker/u1-469dce-1
worker/cb-564-health-events-70cf7e-2
worker/cb-565-recycle-drops-role-98e58f-3
worker/cb-563-missing-reply-df2866-1
worker/cb-562-readiness-gate-silent-6c23c9-3
worker/cb-560-architect-presence-da8155-1
worker/cb-561-architect-silent-off-a71cab-2
worker/cb-548-bind-architect-slot-fe1b8c-1
worker/parity-overlay-settings-5fb711-1
secrets-central-store
cb-559-hot-key-correction
cb-557-fleet-role-pools
worker/cb-553-maxload-explicit-spawn-305ee3-6
worker/cb-551-idle-lead-heartbeat-f1633c-1
worker/cb-544-drain-preserves-worktree-925fad-3
worker/cb-552-docs-sync-1cb9cf-4
worker/cb-548-rendezvous-guard-rebased
worker/cb-548-rendezvous-guard-116b53-10
worker/cb-548-authz-v2-586df6-8
worker/cb-548-authz-264363-5
salvage/cb-528b-codex-home
salvage/cb-528a-codex-launcher
CB-518-primary-flow
feature/peer-launcher-spi
cb-103-injector
v1.1.0
v1.0.0
Labels
Clear labels
blocked
needs-live-proof
ready-to-delegate
silent-default
Cannot start until something else lands. The body says what.
Merged and green, but never shown working on the running daemon. Not the same as done.
Scope, files and acceptance criteria are written. A worker can be briefed from the body alone.
A feature that compiles, passes tests, and ships turned off. Nine recurrences and counting.
No Label
Milestone
No items
No Milestone
Projects
Clear projects
No project
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: fleet/fleetd#663
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Follow-up to #659, which asked for this decision and did not get one. PR #662 removed the three
forms named in #659's table but left
LeadContextGauge.read's 3-argument overload untouched, andsaid nothing about it either way. This ticket records the measurement and closes the gap.
The measurement
I ran all of this on
mainat9417de1.LeadContextGaugehas tworeadforms:Production callers of the 3-arg form: zero. Both production callers use the 4-arg form:
Test callers of the 3-arg form: 11, split as 10 in
lead/LeadContextGaugeTest.javaand 1 inlead/LeadContextGaugeHighThresholdTest.java. There are 7 further 4-arg test call sites that needno change.
Why it is worth removing
Same reason as #659, and it is the last instance of that shape. The 3-arg form passes
nullforthe window, so the gauge falls back to the fixed
HIGH_THRESHOLD_TOKENS = 200_000. Any futurecaller that reaches for the short form gets #637's defect back, silently and with a green build.
A back-compat form whose fallback is the old bug is a trap, not a convenience.
#659 also noted that this overload is what makes #637's cache-key defect reachable: with only the
4-arg form, every caller for a given lead resolves the same window, and the stale-cache failure
needs two different windows.
The ask
Remove
LeadContextGauge.read(String, String, String)and migrate the 11 test call sites to passthe window explicitly.
The trap — read this before touching the tests
Do not mechanically pass
nulleverywhere. For most of the 10 sites inLeadContextGaugeTestthe window is genuinely irrelevant and an explicit
nullis right. But at least one site isdifferent:
lead/LeadContextGaugeHighThresholdTest.javacallsread(legacyConfigDir, SESSION_ID, "claude")and that test's whole purpose is the fixed-200000 fallback —
noEffectiveWindowFallsBackToTheFixed200000Defaultis the test #637 added, and it is the control for this behaviour. There
nullis themeaningful value under test, not filler. Pass it explicitly and leave the assertion alone.
Read each test's name and assertion before choosing the argument.
Acceptance
grep -n "read(String configDir, String sessionId, String agentType)" fleetd/src/main/java/dev/ltms/fleet/lead/LeadContextGauge.javareturns nothing. Pair that zero with a positive control — a broken pattern returns a clean
0that reads exactly like success, so also grep for the 4-arg form and show it still matches.
cd fleetd && mvn -o clean installpasses, and you report the realTests run:line.LeadContextGaugeHighThresholdTest.noEffectiveWindowFallsBackToTheFixed200000Defaultstillexists and still asserts the 200000 fallback. Prove it still works: mutate
HIGH_THRESHOLD_TOKENSto* 2and show that test goes red, then revert and show an emptydiffstat.
One correction to #659's record, while this is open
#659's body says there were "8 old-form call sites across 4 files", and says a reviewer's count of
7 across 3 files "misses
FleetMcpLeadContextGaugeWiringTest.java". That correction was itselfwrong. The real count was 7 across 3 files, which is what PR #662 changed.
The supposed 8th site is in
FleetdLeadConfigDirSourceWiringTest.java, and it is not a call site.Every
LeadConfigDirSourcemention in that file is either inside a javadoc comment (lines 15-42)or a call to the
Fleetd.leadConfigDirSource(..)factory (lines 69, 85, 94). It never used theremoved 1-argument constructor, which is why PR #662 did not need to touch it and why the build
stayed green without it.
Recording this because #659 tells a future reader to "use the 8/4 figure", and that instruction
would send them hunting for a call site that does not exist.
Lead review of PR #665 — one change needed before merge
I read the diff myself and verified the counts. The migration is correct. One leftover must go.
Verified good
Fleetd.java:1149,mcp/FleetMcp.java:2180).@paramtags and the second javadoc block, so deleting its closing*/, the method, and the opening/**fuses the two blocks into one. The surviving 4-argreadnow documents all four of its params. That is why the production file shows 6 deletions and 0 insertions.LeadContextGaugeTestchanges are all mechanical. Those are generic property tests — token totals, compaction counts, UNKNOWN cases, torn final line, TTL cache — where the window is genuinely irrelevant, sonullis filler there.The finding — a dead assertion with a false message
fleetd/src/test/java/dev/ltms/fleet/lead/LeadContextGaugeHighThresholdTest.java:84-89, the third assertion insidenoEffectiveWindowFallsBackToTheFixed200000Default.Before this change it pinned a real property: the 3-arg
read()behaves exactly like passing a null window. That property needed two ways to callread. Now there is one, and the assertion reads:That is the same call, the same input (200_000) and the same expectation as the
atGaugeassertion four lines above it. Only the temp dir and the gauge instance differ, and the assertion is about neither.Two things are wrong with it:
atGaugealready failed. It adds no coverage.read()" will not find it. Project rule: a comment describes the code as it is now, and a test comment names the behaviour it protects.This is the trap in this issue, in a different shape than expected. The worker did read the assertions and did keep the meaningful ones — the first two still pin the fallback. What it missed is that the third assertion's subject was the thing being deleted.
What to do
Delete those three lines — the
legacyConfigDirsetup, thelegacyGauge, and theirassertEquals. The property they pinned cannot go wrong any more, because there is no second way to callread.Do not weaken the first two assertions.
199_999 → OKand200_000 → HIGHare the test's stated purpose and the behaviour #637 fixed. They stay exactly as they are.Then re-run the mutation:
HIGH_THRESHOLD_TOKENS = 200_000→200_000 * 2must makenoEffectiveWindowFallsBackToTheFixed200000Defaultgo red. The earlier run failing at theatGaugeassertion before reaching the legacy one was fine, and after this deletionatGaugeis the last assertion in the method anyway.Tests run:must stay 1923. Deleting an assertion inside a@Testmethod does not change the test count. If it moves, say so rather than explaining it away.Merged as
7e48d4b, pushed tomainPR #665 was merged locally and pushed. We merge locally, so the forge does not close the PR by itself — I am closing both by hand.
What I verified myself, not taken from the worker
Built the PR head (
60fa86a) in a throwaway git worktree, never the main clone — see #664 for why that matters.mvn clean install, unpiped, exit 0:Tests run: 1923, Failures: 0, Errors: 0, Skipped: 0,BUILD SUCCESS, 170 surefire report files (target/surefire-reportsremoved first, so no deleted class could be re-counted).HIGH_THRESHOLD_TOKENS = 200_000→200_000 * 2turns the test red at the right place:touched the source so maven could not re-run the mutated.class, confirmed the file was byte-identical to the backup and the worktree clean againstHEAD, then re-ran green:Tests run: 4, Failures: 0.9032841433a4d54e61d7a5b1346a1f335ad7b3ccis byte-identical to the PR head tree I had just built, andmainhad not moved (git rev-list --count 9417de1..origin/main= 0).Corrections to this issue's record
\.read\([^()]*\)silently drops any call whose arguments contain nested parens —tmp.toString()— and happens to return a clean "10". My own"claude")check independently landed on 13, missing the two sites that passnulland"opencode"as the agentType. Listing the removed lines settles it at 15, and the diff shows 15 removed and 15 added.tabPlacement()is atFleetConfig.java:845, not 846 as my brief said. Unrelated to this issue, but the same brief carried it.@paramtags and the second javadoc block, so deleting it fuses the two into one block that documents all four params of the surviving method. That is why the production file shows 6 deletions and 0 insertions.The review finding, and what it says about the trap
The first round left a third assertion in
noEffectiveWindowFallsBackToTheFixed200000Defaultwhose subject was the deleted overload: same call, same input and same expectation as theatGaugeassertion above it, under a message naming "the 3-argread()". It could not fail unlessatGaugealready had, and it described a method that no longer existed. Removed in60fa86a; the two meaningful assertions (199_999 → OK,200_000 → HIGH) are untouched.Worth recording for the next person: the trap was predicted as "the worker pattern-matches
nulleverywhere without reading the assertions". It arrived in a different shape. The worker did read them and did keep the meaningful ones. What is easy to miss is that one assertion's subject is the thing being deleted, so it survives as a passing duplicate rather than as a failure.