Skip to content

claude: a computer with no engine declares a window it can reach (#1246) - #1257

Merged
gen16k merged 1 commit into
mainfrom
fix/1246-picker-rows-residuals
Sep 6, 2026
Merged

gen16k merged 1 commit into
mainfrom
fix/1246-picker-rows-residuals

Conversation

@gen16k

@gen16k gen16k commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Three residuals of the /model restructure (#1185, #1177, #1186, #1187), all
found reading the surrounding code during L97 and filed rather than fixed in
passing. Each is answered here, so the issue closes whole.

1. A computer with no engine declares a window it can reach

This is the part #1246 calls "a real gap rather than a trade-off, and the one
part of this worth fixing regardless of which direction the rest goes".

CLAUDE_CODE_MAX_CONTEXT_TOKENS was written only when this host resolved a
local window. On a computer with no engine of its own that number is 0, so
nothing was written at all — and Claude Code then did two things:

  • assumed its own 200k default for every Waired row, and
  • showed "waired/peer" isn't described by this version's model catalog on
    each of them.

That second one is exactly what the variable exists to suppress (measured on
2.1.261 during L97: with the variable present the notice is gone, and the
Prompt is too long classification still works).

Every row such a host offers is a peer row, so a peer's window is not an
approximation of something better — it is the only honest number available.
WriteOptions and RemoveOptions gain PeerContextWindow, used only when
the local window is 0, and both go through DeclaredContextWindow() so a
scrub recognises exactly what a write would have put there. Without that
second half, a value written from a peer's window would survive
waired claude disable and go on steering every session that starts on that
computer — the shape #1174 warns about.

Smallest reachable window, not largest: the number sizes one session and
the rows it covers are several computers, so over-declaring means a turn is
compacted only after the gateway has already refused it, which is the one
outcome the variable is there to avoid. Nothing reachable still writes
nothing, the same rule claudeLocalWindowFromModels follows — this decides
what an elevated process tells Claude Code about a window, so declining beats
guessing.

2. One number for rows that hold different windows — settled as leave it

Recorded rather than changed
(docs/decisions/20260906/0415-the-declared-window-falls-back-to-a-peers.md).
The variable is a compaction hint; what actually refuses an over-long prompt
is this gateway's own 400, unified on capability_rejected: prompt_too_long in
#1187. Claude Code offers no documented way to declare a window per picker row
behavesAs maps a row onto a known model's client-side handling, which is a
different and coarser thing, and appears in no public settings reference. So
the current number stays right for the row most people use, and the rest is
the limit of what the client accepts.

3. Two event kinds with no producer

KindClaudeNodeChange and KindClaudeNodeFallback have had no writer since
#1198 removed the anthropic-route degrade and, with it, the per-class routes.
KindClaudeNodeFallback's own doc comment named the producer that is gone.

#1246 deliberately left them alone because the ring is a shared surface, so
both repositories were checked before removing them: no readers in code,
and two mentions in the private dev-docs (the observability kind table and one
current-behaviour paragraph), which follow in a separate small PR there. The
dated records — the rc7 review-machine observation and
docs/decisions/20260802/0631 — stay frozen; they are what was actually seen
at the time.

KindPinnedPeerUnreachable is untouched: since #325 it is the only record of a
pin going down, and it is a different event.

Tests

  • internal/integration/claudemanaged/reachable_context_window_test.go (new):
    DeclaredContextWindow() as a table, including that a bigger peer window
    never overrides a serving host's own; the engine-less write; the scrub
    recognising a peer-derived value; and an operator's own value surviving it.
  • cmd/waired/claude_reachable_window_test.go (new): driven through the real
    fetch against an httptest listener rather than a swapped seam, so the route
    and the parsing are exercised too. Covers the smallest of several, peers that
    are not serving, a peer that declares no window, an empty mesh, and an
    unreachable daemon.

Docs

guides/claude-code.mdx (+ja) said the limit Claude Code works to "is the one
this computer's engine holds". That is now incomplete, and one sentence says
what an engine-less computer passes on instead.

Checks

go build ./..., go test ./..., gofmt -l,
golangci-lint run --max-same-issues=0, the decision-log guard, and
i18n-pair-guard.sh.

Fixes #1246
Refs waired-ai/waired#1313

🤖 Generated with Claude Code

https://claude.ai/code/session_01HJUUSmAfbRdjER1seDdjXm

Three residuals of the /model restructure, all found reading the
surrounding code during L97.

CLAUDE_CODE_MAX_CONTEXT_TOKENS was written only when this host resolved a
local window, so a computer with no engine wrote nothing at all — and
Claude Code then assumed its own 200k default AND showed "isn't described
by this version's model catalog" on every Waired row, which is the notice
the variable exists to suppress. Every row such a host offers is a peer
row, so a peer's window is not an approximation of something better; it is
the only honest number available. WriteOptions and RemoveOptions gain a
PeerContextWindow used only when the local one is 0, and both go through
DeclaredContextWindow() so a scrub recognises exactly what a write would
have put there.

Smallest reachable window, not largest: the number sizes one session and
the rows it covers are several computers, so over-declaring means a turn
is compacted only after the gateway has already refused it. Nothing
reachable still writes nothing — declining beats guessing about what an
elevated process tells Claude Code.

The general "one number for rows that hold different windows" question is
settled as leave it, recorded rather than changed: the variable is a
compaction hint, and what actually refuses an over-long prompt is this
gateway's own 400.

KindClaudeNodeChange and KindClaudeNodeFallback have had no producer since
#1198 removed the anthropic-route degrade and the per-class routes. Both
repositories were checked for readers: none in code, two mentions in the
private dev-docs, which follow separately.

Fixes #1246

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HJUUSmAfbRdjER1seDdjXm
Signed-off-by: gen16k <gen16k@users.noreply.github.com>
@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown

📘 Docs preview — the preview channel for this PR has been deleted now that it is closed.

@gen16k
gen16k merged commit b6c00ed into main Sep 6, 2026
33 checks passed
@gen16k
gen16k deleted the fix/1246-picker-rows-residuals branch September 6, 2026 09:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

observability/claude: two producerless event kinds, and one context-window number for rows that hold different windows

1 participant