Skip to content

Tool deferral follow-ups from the #861 review (N1–N10, N12) #866

Open

Description

@amiddavid

Summary

These are the follow-ups from Osher's review of #861 (tool deferral in ultrahigh). #861 fixes the blocking and high items (B1–B4, H1–H4), plus N11 and the signal.sh match from N12. The items below are not blocking. Each has a fix.

What we found

# Problem Fix
N1 The history flush clears dirty before the write. On any SQLite error it returns, so those sessions are not written until they change again. Set dirty back on a failed write.
N2 Every request moves a session's last time and marks it dirty. Each 5 s flush then rewrites every tool row of every active session. Mark a session dirty only when its tool sets change. Write last_ts on a set change or at close.
N3 The project veto reads at most 10 project sessions out of the newest 64 per account. A user in 4 or more projects, or with scripted claude -p runs, pushes a project's older sessions out. Also keep the newest 10 sessions per account and project.
N4 Rebuild can drift. Observe adds a session at its first request, so a session that only started in between changes UserSessions. After #861 this runs only when a record was evicted at the pin cap. When Rebuild gives a set other than what the transcript proves, send the original and do not save. Or keep it, and say so in the code.
N5 sniffer.bytes() is head plus tail. For a response of 64–128 KiB the two windows overlap, so SearchesInSSE can count one search twice. Scan the tail only past the head.
N6 The 200-token minimum counts o200k tokens, about 337 Claude tokens. The ledger scales by BilledDeltaFactor; the rule does not. Scale the rule the same way, or write "200 o200k tokens" in the docs.
N7 The net saving leaves out the cache write of a loaded definition on the next request. Add the loaded tokens at the write price, once per load.
N8 The metrics that #485 lists are missing: per-account counters, the wrong-guess count (a deferred tool that was then used), dropped parallel searches, and the keep-alive ledger credit. Add wrong_guesses and dropped_searches to the tool_defer block, per account.
N9 The seeded history misses the tools this feature targets. tool_declarations lacks the built-ins Claude Code defers, and tool_uses lacks search loads. Fix it with the dashboard follow-up from #485.
N10 Running sessions count as history. On the hosted database, 94% of decisions had a running session among the last 3. A replay gave 24 wrong guesses with running sessions counted and 22 with ended sessions only, at the same deferred volume. So the current rule is fine. Write this in a code comment, so nobody "fixes" it.
N12a The probe sends no OAuth beta header. Direct Anthropic with a subscription token may answer 401. #861 now makes a 401 "no verdict", so deferral stays off and the probe retries. Inferred, not tested. Send the header the client sent, or probe with the client's own headers.
N12b false, 0, no and off all turn deferral off. The design says only a literal false. The owner decides.

Also found while fixing B3: an account purge removes tool deferral's rows from session_state, but not the tenant's other session-state keys (cg:sum:, cg:bin: and so on). That is older than #861, and it is not part of it.

Open questions

  • N12b: keep false/0/no/off, or go back to a literal false?

Refs #861, #485.

🤖 Generated with Claude Code

Activity

  1. amiddavid commented on Nov 2, 2026

    @amiddavid
    CollaboratorAuthor

    Answer to the open question (N12b): keep false, 0, no and off as off values. The owner decided this on 2026-11-02. Only these four count as a deliberate opt-out; auto, true and an unset value do not. No change needed.

    🤖 Generated with Claude Code

  2. amiddavid commented on Nov 2, 2026

    @amiddavid
    CollaboratorAuthor

    One more from the #861 round-4 review: the 400 turn-off map (Gate.broken, tooldefer/gate.go) is one global map capped at 20,000 across tenants. One tenant's 400s can push out another tenant's turn-offs. Each entry expires in 24 h. Fix: key and cap it per tenant, like the pending opt-outs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions