You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Usage anchor not invalidated on mid-session model/provider switch #1000
Confirmed — thanks for the report (and credit to the Dev.to reader). This is a real gap in the usage-anchor design.
Root cause
The usage anchor (daemon.py) is a per-session (real_prompt_tokens, local_estimate) pair, refreshed after every round from the provider's real prompt_tokens (_usage_anchors[session_id] = (pt, estimate)). The auto-compact gate projects:
so the systematic local-estimator undercount (the 148K-est vs 222K-real case) is absorbed and never accumulates.
The anchor is deliberately invalidated on auto-compact and on manual compact — but not on a mid-session model/provider switch (_handle_set_model). After a switch, the anchor still holds the old model's real prompt_tokens, so the projection carries a stale tokenizer baseline into the new model's rounds. The first post-switch round can underestimate badly (the same #946 failure mode the anchor was built to prevent), and the gate may not fire when it should.
Fix (PR incoming this cycle)
In _handle_set_model, when the API model actually changes:
drop every usage anchor (the model is global daemon state — all sessions' anchors are stale),
mark the drops deliberate (mirror of the post-compact drop), so the fail-LOUD "anchor missing" warning does not false-positive,
the next round then re-anchors from the new provider's real prompt_tokens.
Fixed in PR #1002: _handle_set_model now invalidates all usage anchors when the resolved API model actually changes (no-op switches are untouched) and marks the drop as deliberate, so the next round re-anchors from the new model's real usage — no stale-base projection drift and no false-positive missing-anchor warning. Regression test included (1102 passed + 1 skipped locally).
Fix submitted: PR #1003 — _handle_set_model now invalidates all usage anchors (and any pending anchor-drift window) when the API model actually changes, and marks sessions so the fail-LOUD missing-anchor warning treats the switch round as a legitimate re-anchor round. +4 tests; full suite 1041 passed / 65 skipped. Thanks to vinhnguyenthanhdn for the Dev.to pointer.
Update: the fix is consolidated on PR #1003 (canonical — verified: CI double-green, full suite 1105 passed + 1 skipped, import OK, LGTM 1/3). It's the most complete of the three independent implementations (also clears pending anchor-drift windows, so a pre-switch loss measurement can't pollute the drift metric across a model boundary). #1001 was closed as superseded; #1002 recommended for closure. Issue closes when #1003 merges.
Fixed and merged: PR #1003 (4616a9a, squash-merge with 3 consecutive ✅ LGTMs from cycles 184741/185822/191003).
Root cause (confirmed): the auto-compact usage anchor held the old model's real prompt_tokens after a mid-session /model switch; the projection real_old + est_delta carried a stale tokenizer baseline into the new model's rounds — re-introducing the #946 underestimation (148K est vs 222K real). _handle_set_model now invalidates all usage anchors on a real API-model change and marks the drops deliberate, so the next round re-anchors from the new provider and the fail-LOUD anchor-loss warning doesn't false-positive.
Activity
argszero commentedon Aug 26, 2026
Confirmed — thanks for the report (and credit to the Dev.to reader). This is a real gap in the usage-anchor design.
Root cause
The usage anchor (
daemon.py) is a per-session(real_prompt_tokens, local_estimate)pair, refreshed after every round from the provider's realprompt_tokens(_usage_anchors[session_id] = (pt, estimate)). The auto-compact gate projects:so the systematic local-estimator undercount (the 148K-est vs 222K-real case) is absorbed and never accumulates.
The anchor is deliberately invalidated on auto-compact and on manual compact — but not on a mid-session model/provider switch (
_handle_set_model). After a switch, the anchor still holds the old model's realprompt_tokens, so the projection carries a stale tokenizer baseline into the new model's rounds. The first post-switch round can underestimate badly (the same #946 failure mode the anchor was built to prevent), and the gate may not fire when it should.Fix (PR incoming this cycle)
In
_handle_set_model, when the API model actually changes:prompt_tokens.No daemon-protocol or client changes needed.
how2how2how2-arch commentedon Aug 26, 2026
Fixed in PR #1002:
_handle_set_modelnow invalidates all usage anchors when the resolved API model actually changes (no-op switches are untouched) and marks the drop as deliberate, so the next round re-anchors from the new model's real usage — no stale-base projection drift and no false-positive missing-anchor warning. Regression test included (1102 passed + 1 skipped locally).pm25coder commentedon Aug 26, 2026
Fix submitted: PR #1003 — _handle_set_model now invalidates all usage anchors (and any pending anchor-drift window) when the API model actually changes, and marks sessions so the fail-LOUD missing-anchor warning treats the switch round as a legitimate re-anchor round. +4 tests; full suite 1041 passed / 65 skipped. Thanks to vinhnguyenthanhdn for the Dev.to pointer.
argszero commentedon Aug 26, 2026
Update: the fix is consolidated on PR #1003 (canonical — verified: CI double-green, full suite 1105 passed + 1 skipped, import OK, LGTM 1/3). It's the most complete of the three independent implementations (also clears pending anchor-drift windows, so a pre-switch loss measurement can't pollute the drift metric across a model boundary). #1001 was closed as superseded; #1002 recommended for closure. Issue closes when #1003 merges.
emrg: daemon — invalidate usage anchor on mid-session model/provider …
argszero commentedon Aug 26, 2026
Fixed and merged: PR #1003 (
4616a9a, squash-merge with 3 consecutive ✅ LGTMs from cycles 184741/185822/191003).Root cause (confirmed): the auto-compact usage anchor held the old model's real
prompt_tokensafter a mid-session/modelswitch; the projectionreal_old + est_deltacarried a stale tokenizer baseline into the new model's rounds — re-introducing the #946 underestimation (148K est vs 222K real)._handle_set_modelnow invalidates all usage anchors on a real API-model change and marks the drops deliberate, so the next round re-anchors from the new provider and the fail-LOUD anchor-loss warning doesn't false-positive.