Skip to content

Revise PR #325: the harness keys on utilization, so it cannot tell a rollover from ordinary usage, and the default invocation never polls - #332

Merged
jaylfc merged 1 commit into
masterfrom
exec/tsk-3te4pi
Aug 18, 2026
Merged

Revise PR #325: the harness keys on utilization, so it cannot tell a rollover from ordinary usage, and the default invocation never polls#332
jaylfc merged 1 commit into
masterfrom
exec/tsk-3te4pi

Conversation

@jaylfc

@jaylfc jaylfc commented Aug 18, 2026

Copy link
Copy Markdown
Owner

CARD TITLE (intent, not commit subject): Revise PR #325: the harness keys on utilization, so it cannot tell a rollover from ordinary usage, and the default invocation never polls

Autonomous build of board card tsk-3te4pi.

Key the flip detection in measure_at_boundary on resets_at (window
identity) instead of utilization, which could not distinguish a rollover
from ordinary account consumption on a shared account. Start the
polling budget (max_wait) after the boundary arrives rather than at
process start, and sample the pre-boundary baseline before the boundary
so a propagation faster than the first poll is measurable. Align the
evidence file's target_location and procedure text with the code, and
split the flip-detection test into ARM A (consumption without rollover)
and ARM B (rollover with flat utilization) as disagreement controls.

Full suite: 1517 passed, 12 skipped.

Files:
benchmarks/measure_upstream_propagation.py | 294 +++++++++++++++++
.../results/tsk-rcnct6_upstream_propagation.json | 11 +
.../tsk-3te4pi-measure-upstream-propagation.md | 16 +
.../tsk-rcnct6-measure-upstream-propagation.md | 8 +
tests/test_measure_upstream_propagation.py | 347 +++++++++++++++++++++
5 files changed, 676 insertions(+)

Key the flip detection in measure_at_boundary on resets_at (window
identity) instead of utilization, which could not distinguish a rollover
from ordinary account consumption on a shared account.  Start the
polling budget (max_wait) after the boundary arrives rather than at
process start, and sample the pre-boundary baseline before the boundary
so a propagation faster than the first poll is measurable.  Align the
evidence file's target_location and procedure text with the code, and
split the flip-detection test into ARM A (consumption without rollover)
and ARM B (rollover with flat utilization) as disagreement controls.

Full suite: 1517 passed, 12 skipped.
@qodo-code-review

Copy link
Copy Markdown

ⓘ Qodo reviews are paused because your trial has ended. Ask your workspace admin to add credits to resume reviews. Manage billing

@coderabbitai

coderabbitai Bot commented Aug 18, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@jaylfc, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 50 minutes

Limit details: You’ve used all 1 included review currently available under your plan.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 40385035-8056-4337-ad78-2351acecaf79

📥 Commits

Reviewing files that changed from the base of the PR and between 631168b and 6abadb6.

📒 Files selected for processing (5)
  • benchmarks/measure_upstream_propagation.py
  • benchmarks/results/tsk-rcnct6_upstream_propagation.json
  • changelog.d/tsk-3te4pi-measure-upstream-propagation.md
  • changelog.d/tsk-rcnct6-measure-upstream-propagation.md
  • tests/test_measure_upstream_propagation.py

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@gitar-bot

gitar-bot Bot commented Aug 18, 2026

Copy link
Copy Markdown

Important

You are using the Gitar free plan. Upgrade to unlock code review, CI analysis, auto-apply, custom automations, and more.

Gitar

raise SystemExit(
"No credentials path: set TAOSMD_ANTHROPIC_CREDS or pass --creds"
)
with open(path, "r") as f:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: resolve_token can raise unhandled exceptions for missing or malformed credentials

The open() call on line 57 can raise FileNotFoundError if the credentials file does not exist, json.load() can raise json.JSONDecodeError for malformed JSON, and creds["claudeAiOauth"]["accessToken"] can raise KeyError if the expected keys are absent. The caller in main() only catches SystemExit, so any of these exceptions produce a raw traceback instead of recording an UNMEASURED evidence file.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

pre_window = pre_usage.get("five_hour", {})
pre_util = pre_window.get("utilization")
pre_resets_at = pre_window.get("resets_at")
except Exception as exc: # noqa: BLE001 - record, proceed without baseline

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Broad except Exception swallows KeyboardInterrupt/SystemExit

Catching Exception in the pre-boundary fetch handler also catches KeyboardInterrupt and SystemExit. For a long-running benchmark that may wait up to 10 minutes for a reset boundary, this makes it impossible for the user to interrupt the process with Ctrl+C. Consider catching BaseException or explicitly excluding KeyboardInterrupt and SystemExit.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

now = datetime.datetime.now(datetime.timezone.utc)
try:
usage = fetch_fn(token)
except Exception as exc: # noqa: BLE001 - record, keep polling

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Broad except Exception swallows KeyboardInterrupt/SystemExit

Catching Exception in the polling loop also catches KeyboardInterrupt and SystemExit. This makes the active polling phase uninterruptible with Ctrl+C, which is problematic for a script that may run for an extended period. Consider narrowing the caught exceptions or explicitly re-raising KeyboardInterrupt and SystemExit.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

@kilo-code-bot

kilo-code-bot Bot commented Aug 18, 2026

Copy link
Copy Markdown

Code Review Summary

Status: 3 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 3
SUGGESTION 0
Issue Details (click to expand)

WARNING

File Line Issue
benchmarks/measure_upstream_propagation.py 57 resolve_token can raise unhandled exceptions for missing or malformed credentials
benchmarks/measure_upstream_propagation.py 128 Broad except Exception swallows KeyboardInterrupt/SystemExit
benchmarks/measure_upstream_propagation.py 150 Broad except Exception swallows KeyboardInterrupt/SystemExit
Files Reviewed (5 files)
  • benchmarks/measure_upstream_propagation.py - 3 issues
  • benchmarks/results/tsk-rcnct6_upstream_propagation.json
  • changelog.d/tsk-3te4pi-measure-upstream-propagation.md
  • changelog.d/tsk-rcnct6-measure-upstream-propagation.md
  • tests/test_measure_upstream_propagation.py

Fix these issues in Kilo Cloud


Reviewed by step-3.7-flash · Input: 56.3K · Output: 15.5K · Cached: 332.8K

@jaylfc

jaylfc commented Aug 18, 2026

Copy link
Copy Markdown
Owner Author

Review: APPROVE and merge

Third pass at this quantity, and the first one that measures what it claims to measure. All four blockers are genuinely fixed, every Credit item survived, and the red-first evidence is the disagreement control the card asked for rather than a test that merely passes.

I re-derived everything below on a trial merge into current master. Nothing here is taken from the PR body.

The disagreement control, run independently: old vs new, same input

Both versions imported by path and called directly, real sleeps, elapsed time asserted non-zero so the durations mean something.

INPUT                                            OLD (#325)          NEW (#332)          HONEST ANSWER
-----------------------------------------------------------------------------------------------------
CONTROL  resets_at 08->13, util 0.80->0.20       MEASURED            MEASURED            MEASURED     (agree)
ARM A    resets_at PINNED 13:00, util 0.20->0.22 MEASURED            NO_FLIP_DETECTED    NO_FLIP      <-- DISAGREE
ARM B    resets_at 08->13, util 0.0 FLAT         NO_FLIP_DETECTED    MEASURED            MEASURED     <-- DISAGREE

The control is what makes this readable: both versions reach the right answer when both signals move together, so the instrument is not simply broken in one direction. The two arms then split, and in both the new version gives the honest answer. BLOCKER 1 fixed. measure_at_boundary now keys on cur_resets_at != pre_resets_at, with utilization kept only as a recorded corroborating signal, and the comment at the guard explains why neither direction of utilization can be the trigger.

BLOCKER 2 fixed, measured on the default-shaped invocation (boundary further out than the whole polling budget: boundary 3s, max_wait 2s):

                              OLD fetches after boundary   NEW fetches after boundary
default-shaped invocation     0   (NO_FLIP_DETECTED)       2   (MEASURED)

t0 now starts after the boundary arrives, and the pre-boundary baseline is sampled before the wait rather than being taken from the first post-boundary response, so a propagation faster than the first poll is measurable by construction. Both halves of that fix are present and both are exercised.

BLOCKER 4: the tests now fail when the behaviour is absent

This is the check that decided it. I swapped #325's harness into the tree and ran this PR's test file unchanged against it:

new tests vs NEW harness (as shipped)   21 passed              <- positive control
new tests vs OLD harness (#325)          5 failed, 16 passed

failing: test_arm_a_consumption_without_rollover_not_measured
         test_arm_b_rollover_with_flat_utilization_is_measured
         test_polling_budget_starts_after_boundary
         test_pre_reset_baseline_in_no_flip_result
         test_evidence_procedure_matches_code

The discrimination is correct in both directions: the five behavioural tests go red on the defective harness, and the sixteen that stay green are the source-text credit-item pins, which should pass on #325's tree because #325 genuinely fixed those. Contrast with what this replaces, where test_measure_at_boundary_detects_flip passed 17/17 with the defect present and blessed it.

BLOCKER 3 fixed

The committed evidence's procedure now reads "...the first response serving the new five_hour window (detected by resets_at changing)", which is what the code does. The record and the code it cites now say the same thing.

Both minors are fixed too: target_location no longer cites the non-existent scripts/resume_arm_time.py and instead says plainly that the constant lives in an out-of-repo helper, and the suite count is reported ("1517 passed, 12 skipped", correct against the base this branch was cut from).

Credit items: all preserved, checked against the shipped file directly

no MockAPI / window_flips / simulate      OK      real endpoint api.anthropic.com/.../usage   OK
uses httpx                                OK      no /tmp path                                OK
no ~/.taos-team or fleet-tools path       OK      no subprocess / sed / shutil                OK
status UNMEASURED, measured_samples []    OK      MIN_LEAD_SECONDS unlabelled, untouched      OK
no scripts at repo root                   OK      evidence committed under benchmarks/results OK

I ran the real CLI entry point rather than only the helper. It writes solely inside the repo, and the shared helper three lead agents depend on is untouched:

before/after   ~/.taos-team/resume_arm_time.py -> ~/.taos-fleet-tools/resume_arm_time.py
               md5 7c54e86e32ba1bd33868b42d69ecfb5d  (identical)

That check matters here specifically because reaching outside the repo is what #288 was blocked for, and because the same shared path actually broke the fleet once last night.

One note, not a blocker

Running the CLI regenerates the evidence file, and the regenerated JSON is not byte-identical to the committed one: indent 2 vs 4, no trailing newline, reason loses the sentence about the bounded wait across a real 5h boundary, and procedure says "in this file" rather than naming the script. So the committed record is a hand-polished version of the script's output, not the output itself.

Nothing here contradicts anything, which is why it is not a blocker: both texts now correctly say the flip is detected by resets_at changing, and the committed copy carries strictly more information. Worth knowing because a future run overwrites the fuller reason with the shorter one. If that record is meant to be reproducible, the generator should emit exactly what is committed.

Also operational, and inherent to the specified fix rather than a defect in it: with the budget now starting at the boundary, the default invocation can block for up to five hours waiting for one, since the pre-boundary wait is deliberately not counted against max_wait. That is what the card asked for and what measuring a boundary requires. --reset-at and --dry-run are the escape hatches.

Gates and suite

conflict markers            none
deleted-symbols-guard       clean
normalise-handle-gate       clean
witness-gate                clean
full suite on trial merge   1522 passed, 12 skipped

1522 is exactly the current master baseline of 1501 plus the 21 tests in the new file, which reconciles with what the diff touched and confirms nothing else moved. The branch's own reported 1517 was honest against the base it was cut from; master has since advanced by #329 and #331.

Merging.

@jaylfc
jaylfc merged commit 688d62c into master Aug 18, 2026
7 checks passed
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.

1 participant