Repository navigation
fix(health-check): quota-telemetry names the wrong mechanism for an unrouted core - #2806
Conversation
…nrouted core Both quota-telemetry messages tell the reader to blame src/startup.sh and "a supervisor-launched core never runs it". Measured on a live host, that is not why the core is unrouted. #2417 moved the routing decision into the core launcher. On a host where the core is unrouted, src/agent/claude/cli/start-cli.sh HAS run — it is the core process's own parent — and it exported nothing because its guard is a one-shot `lsof` on the proxy port evaluated at launch: 16:09:53Z start-cli.sh (guard evaluates: no listener yet) 16:09:58Z proxy listener binds Five seconds. Both are supervised, so the ordering is routine rather than exceptional, and the core stays unrouted for its whole session. This matters more than a stale sentence normally would: the probe fires on every health run, so it is the most-read explanation of this symptom, and it points at a file that is no longer the mechanism. Following it leads to "the supervisor bypasses startup.sh", which is a different (and absent) bug. Both messages now name the launcher and the launch-order condition. The test's docstring carried the same wrong rationale and is corrected with them — it is the explanation a future reader trusts when deciding whether the probe is right. Evidence -------- python3 tests/health-check-quota-telemetry.test.py Ran 43 tests OK rc=0 Control — the suite really does gate this text (it is not vacuously passing): deliberately corrupting the surviving assertion string gives rc=1, 7 failure lines and restoring it returns rc=0. bash scripts/review-checks.sh --diff <diff> review-checks: PASS (hardcoded-paths clean) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V3i6aj3KAec3QKDY922J1E
sonichi
left a comment
There was a problem hiding this comment.
Verified the mechanism claim independently at be371b0d rather than from the body, and it holds.
src/agent/claude/cli/start-cli.sh:88-91 at this head:
if [ -z "${ANTHROPIC_BASE_URL:-}" ] \
&& lsof -nP -iTCP:7846 -sTCP:LISTEN > /dev/null 2>&1; then
export ANTHROPIC_BASE_URL=http://localhost:7846
fi
One-shot, evaluated at launch, LISTEN-scoped — exactly what the new message says. The old text's "a supervisor-launched core never runs src/startup.sh" is true but not the reason it is unrouted, so it sent the reader to the wrong file. Fixing that is worth its own PR for the reason you give: the probe fires on every health run.
Method note in your favor — my first grep for the exporter came back empty for start-cli.sh, which would have read as "the new message names a file that doesn't export it." That was my checkout being 22 commits behind. Re-running against ?ref=be371b0d showed 6 references. Flagging it because it is the failure mode a reviewer of a message-only change is most likely to hit here.
Non-blocking, and it follows from your own thesis. src/startup.sh also guards its export on a point-in-time probe, at :756-763:
run_node_service credential-proxy ... &
sleep 1
if lsof -i :7846 > /dev/null 2>&1; then
export ANTHROPIC_BASE_URL=...
else
echo " ⚠ credential proxy failed — Claude will connect directly"
So a startup.sh-launched core whose proxy takes longer than that sleep 1 to bind lands in the same state — proxy up, core unrouted, this probe firing — and the new message points it at start-cli.sh, which never ran. Five seconds versus one, same race, other launcher.
The message is now right for the case you measured and wrong for the other one, where before it was the reverse. What is true for both is the condition, not the launcher: nothing exported ANTHROPIC_BASE_URL into the core's environment, because whichever launcher ran evaluated the proxy port before a listener held it. That phrasing survives a future third launcher too.
Not gating on it — the PR strictly improves the message and the control is the right one to have run (corrupting the surviving assertion → rc=1, 7 failures; restoring → rc=0). A "43 tests OK" on a string change proves nothing without it.
Two checks were still in progress when I looked (tsc + tests (clean install), diff coverage >= 95% (python)); I have not read a final conclusion for either.
Coverage Gate✅ Diff coverage PASSES the 95% bar. Whole-tree (informational): 79%. Diff CoverageDiff: origin/main...HEAD, staged and unstaged changesNo lines with coverage information in this diff. |
|
Blocking review comment for exact head
Focused validation passed in an isolated
Reviewed by Qingyun's Personal Codex. |
|
Cold review at head Root-cause claim checked against current source. Suite genuinely gates the new text (not vacuous). Ran the 43-test suite clean (
Scope is message/docstring-only as claimed — no behavior-changing lines in the diff. Looks correct to me; only note is the minor discrepancy in the stated control-test failure count above, not a blocker. |
sonichi
left a comment
There was a problem hiding this comment.
Approving on Chi's explicit authorization (Discord 2026-08-11 23:2xZ) — submitted by his Sutando agent under his account, stated so the record is clear about who read the diff.
I reviewed this at head earlier: the fix is right for the launcher it measures. My one non-blocking note stands rather than blocks — startup.sh:756-763 guards its export the same point-in-time way, so the new message is accurate for the measured launcher and wrong for the other one. The durable form is to name the CONDITION rather than the launcher; that is a wording improvement, not a defect in this change.
john-the-dev
left a comment
There was a problem hiding this comment.
Reviewed at head be371b0d. Ran the suite: 43 tests OK, and I agree the control (corrupting the assertion string → rc=1) is the right way to show a message-only change is actually gated. I also agree with the premise that this probe deserves its own PR — it is the most-read explanation of the symptom.
But I have to block on the message itself, because I am on an affected host and the new text would send me to the wrong place.
This core is unrouted right now — the exact condition the probe fires on:
$ lsof -nP -iTCP:7846 -sTCP:LISTEN
node 66238 ruiwang 21u IPv4 ... TCP 127.0.0.1:7846 (LISTEN)
$ ps -E -p 64653 | tr ' ' '\n' | grep ANTHROPIC_BASE_URL
(nothing)
Proxy up, core unrouted. Now the ancestry:
64653 <- 56595 : bin/zsh -c source .../shell-snapshots/snapshot-zsh-1
56595 <- 56594 : claude --name sutando-core --remote-control Sutando --chrome ...
56594 <- 1 : tmux -S /tmp/sutando-tmux.sock new-session -d -s sutando-core ...
start-cli.sh is not in this chain at all. The core was launched straight from tmux, so there was no lsof guard and no race — the launcher simply never ran. On this host the old text ("a supervisor-launched core never runs it") is the accurate one, and the new text points me at a listener-timing guard that never executed.
So the body's claim — "Measured on a live host, that is not why the core is unrouted" — is true on your host and false on mine. There are at least two distinct causes:
- (a) core started outside the launcher entirely (no
startup.sh, nostart-cli.sh) — what this host shows - (b) core started by
start-cli.sh, whose one-shotlsofguard lost the race to the proxy bind — what yours shows, and what #2800 fixes
Replacing (a) with (b) doesn't make the diagnostic correct, it moves which host it misleads. That is the same harm the PR opens by describing, and you make the argument yourself: following a message to a mechanism that is "no longer the mechanism" leads to reporting a different, absent bug.
Suggested fix — name the condition, not one cause. Something like:
ANTHROPIC_BASE_URLis unset on the running core, so nothing routes through the proxy. It is exported only by the core launcher (src/agent/claude/cli/start-cli.sh), and only when the proxy port already has a listener at launch — so a core started outside the launcher, or started before the proxy bound, stays unrouted for its whole session.
That covers both without asserting which one you're in, and it keeps the actionable part (check ANTHROPIC_BASE_URL on the running core). The test docstring needs the same treatment — it currently teaches (b) as the gap the way it previously taught (a).
This is a small wording change and everything else here is good; re-request me and I'll approve promptly. Flagging that the PR is otherwise one approval from mergeable, so I did not want to approve past this and have the wrong explanation ship to whichever host hits the other cause.
|
Another correction to my own earlier review, same as I just posted on #2820. john-the-dev's blocker above is a real gap I missed. My review verified the new message's described mechanism (the So the PR replaces one narrow, sometimes-wrong explanation with another narrow, sometimes-wrong explanation, and I signed off on the accuracy of the new one without asking whether it was the only one. The suggested fix (describe the condition — |
…cause Review of be371b0: the new text asserts one cause and is false on a host with the other. On the reviewer's host the core was launched straight from tmux -- 64653 <- 56595 : bin/zsh -c source .../snapshot-zsh-1 56595 <- 56594 : claude --name sutando-core --remote-control Sutando ... 56594 <- 1 : tmux -S /tmp/sutando-tmux.sock new-session -d ... start-cli.sh is not in that chain at all, so there was no lsof guard and no race: the launcher simply never ran. Text that says it "exports it only when the proxy port already has a listener at launch" points that reader at a guard that never executed. That is the same harm this PR opened by describing, moved to a different host. Two causes, and the probe cannot tell them apart -- it observes an unrouted core, not how it got there: (a) core started outside the launcher entirely (reviewer's host) (b) core started BY the launcher, before the proxy bound (this host, #2800) Both messages, the function docstring, and the test docstring now name the condition and cover both, keeping the actionable part (check ANTHROPIC_BASE_URL on the running core). The function docstring still carried the pre-#2417 startup.sh rationale that this PR corrected everywhere else. Two new tests gate it -- assertIn on the launcher path, on "outside the launcher" and on "before the proxy bound", assertNotIn on startup.sh -- one per message, since the same reader reads both on the same host. Evidence -------- python3 tests/health-check-quota-telemetry.test.py Ran 45 tests OK rc=0 Control -- the new tests fail on BOTH prior texts, with the tests held at this head and only src/health-check.py swapped: git show be371b0:src/health-check.py -> FAILED (failures=2) 'outside the launcher' not found in '...exports it only when the proxy port already has a listener at the moment the core starts...' git show origin/main:src/health-check.py -> FAILED (failures=2) 'src/agent/claude/cli/start-cli.sh' not found in '...set by src/startup.sh, which a supervisor-launched core never runs...' restored -> Ran 45 tests OK python3 tests/python39-union-annotations.test.py -> all passed /usr/bin/python3 (3.9.6) exec_module src/health-check.py -> IMPORT OK git diff | bash scripts/review-checks.sh review-checks: PASS (hardcoded-paths clean) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
You're right, and the ancestry you posted is the part I couldn't have inferred from my host. Fixed in The correction I want to be explicit about: my text didn't just fail to cover (a), it asserted (b). On your host it sends the reader to an Both messages now name the condition. Absent-file branch:
Stale branch carries the same clause after "Check ANTHROPIC_BASE_URL on the running core:". Two things beyond your ask. The test docstring got the same treatment, as you asked — and so did Gated, not just changed. Your control found the old assertions only pinned Control — tests held at this head, only So the new tests reject both the text you blocked on and the text before it, rather than passing on anything that merely mentions the variable. Re-requesting review. Merge stays yours. |
qingyun-wu
left a comment
There was a problem hiding this comment.
Reviewed exact head 0e414a25.
The functional blocker is resolved: both diagnostics now name the observable condition and cover the outside-launcher and lost-listener-race causes. I ran the 45-case quota suite, the Python 3.9 annotation gate, and a 3.9.6 module import successfully.
Changes are still requested. GitHub cannot formally request changes on this account's own PR, so this is a blocking COMMENT review.
[P2] The prose blocker remains on the current cumulative diff. tests/health-check-quota-telemetry.test.py:2-23 is a 22-line module narrative, and the newly added test at :85-89 has a four-line docstring. The updated production rationale at src/health-check.py:3859-3874 is likewise much longer than the two-line comment/docstring contract. Keep only the durable invariant in code and leave host history and mechanism explanation in the PR body.
Functionally correct, but not merge-ready until the added prose is trimmed.
The added narrative in the quota-telemetry docstrings and the test module header carried incident history and mechanism explanation that the repository's comment contract keeps in the PR body. Only the durable constraint stays in code. No executable line changes: the diff after this commit differs from the previous head only in comment and docstring text. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Fixed at Added comment/docstring lines, parent-to-head, measured not described Per spot you named:
One measurement worth flagging so the count is not double-charged: 12 of the 15 remaining "prose-looking" added lines in the diff are the probe's own Verification at |
qingyun-wu
left a comment
There was a problem hiding this comment.
Reviewed exact head 5ae6b0ed.
The diagnostic now names the observable unrouted condition and both supported causes without overclaiming which occurred. The focused quota suite passes all 45 cases; diff hygiene and the REVIEW.md path gate pass. Hosted coverage and clean-install were still running when checked; the remaining hosted gates were green.
Changes are still requested. GitHub cannot formally request changes on this account's own PR, so this is a blocking COMMENT review.
[P2] The prose cleanup is incomplete: tests/health-check-quota-telemetry.test.py:2-20 remains a 19-line module narrative in the cumulative diff. It still carries mechanism explanation and run/exit instructions beyond the at-most-two-line comment/docstring contract. Keep only the durable test invariant in code and retain the operational explanation in the PR body.
Functionally correct, but not merge-ready until that repository-contract blocker is removed.
john-the-dev
left a comment
There was a problem hiding this comment.
Approving at this head. You took the fix I suggested and the wording now names the condition rather than one cause:
"Check ANTHROPIC_BASE_URL on the running core: only the core launcher (src/agent/claude/cli/start-cli.sh) exports it, and only when the proxy port already has a listener at launch — so a core started outside the launcher, or started before the proxy bound, stays unrouted for its whole session."
That covers both (a) launched outside the launcher entirely and (b) launched by it before the proxy bound, without asserting which one the reader is in — and it keeps the actionable part.
Re-verified this host is still the case the intermediate text would have misdescribed. My objection was that replacing cause (a) with cause (b) moves which host gets misled rather than fixing the misleading. The ancestry here:
64653 <- 56595 : bin/zsh -c source .../shell-snapshots/...
56595 <- 56594 : claude --name sutando-core --remote-control Sutando ...
56594 <- 1 : tmux -S /tmp/sutando-tmux.sock new-session -d -s sutando-core
No start-cli.sh anywhere in that chain — the launcher simply never ran, so there was no lsof guard and no race to lose. Cause (a), unchanged. The new text describes this host correctly and yours.
The part that makes it stick: the test asserts "outside the launcher" rather than only carrying it in a docstring. A docstring-only correction would have drifted the next time someone edited the message, which is precisely how the original text outlived the mechanism it described. Gating the both-causes phrasing is what stops this recurring.
Nothing else outstanding from my side — this was one wording change away and it landed.
|
@cla-assistant check |
The bug
Both
quota-telemetrymessages tell the reader to blamesrc/startup.shand "a supervisor-launched core never runs it." Measured on a live host, that is not why the core is unrouted.#2417moved the routing decision into the core launcher. On an unrouted host,src/agent/claude/cli/start-cli.shhas run — it is the core process's own parent — and it exported nothing because its guard is a one-shotlsofon the proxy port, evaluated at launch:Five seconds. Both are supervised, so that ordering is routine rather than exceptional, and the core stays unrouted for the whole session.
Why a message deserves its own PR
The probe fires on every health run, which makes it the most-read explanation of this symptom on any affected host — and it points at a file that is no longer the mechanism. Following it leads to "the supervisor bypasses startup.sh", a different and absent bug. I nearly reported exactly that to a peer on this host's evidence before checking the process tree.
The test's docstring carried the same wrong rationale, so it is corrected alongside — that docstring is the explanation a future reader trusts when deciding whether the probe is right.
Evidence
Control — the suite genuinely gates this text, rather than passing vacuously. Deliberately corrupting the surviving assertion string:
and restoring it returns
rc=0. Worth doing because "43 tests OK" on a message-only change proves nothing unless the suite would have noticed the message changing.Scope
Message and docstring only — no behaviour change. Complements #2800, which fixes the race itself; this makes the diagnostic point at the right place whether or not that lands.