Skip to content

fix(plugin): accept verbose side-call event arrays, skip failed proposer calls (#131) - #134

Closed
Dhruv Arora (dhruv1220) wants to merge 2 commits into
microsoft:mainfrom
dhruv1220:fix/verbose-sidecall-array
Closed

Dhruv Arora (dhruv1220) wants to merge 2 commits into
microsoft:mainfrom
dhruv1220:fix/verbose-sidecall-array

Conversation

@dhruv1220

Copy link
Copy Markdown

Fixes #131: with "verbose": true in the user's Claude Code settings, every side call failed and a failed proposer call aborted the whole fold.

What changed

  • tokeneconomizer/plugin/sidecall.py: claude_call now accepts the verbose form of the output. With verbose on, Claude Code streams a JSON array of events instead of one result object, and data.get("result") raised AttributeError on the list. The call now takes the last event whose type is "result", which carries the same result/usage fields as the single-object form; an array with no result event behaves like an empty reply. The --settings verbose=false alternative from the issue was deliberately not taken: accepting the array works whatever the CLI version supports.
  • tokeneconomizer/microskills/distiller.py: _maybe_propose now catches a runner exception and skips the proposal instead of letting it escape and abort the fold, as the judge path already does for its runner errors. A failed tick admits nothing and does not claim a proposal happened.
  • tests/test_verbose_sidecall.py: regression tests for both halves, plus the no-result-event case. The claude_call tests fake the subprocess and carry the repo's real_sidecalls marker so the suite's side-call stub does not mask them.

How it was tested

  • All three new tests fail on pristine code (AttributeError on the list; RuntimeError escaping the fold) and pass with the fix.
  • python -m pytest tests experiments/tests: everything passes except experiments/tests/test_fleet_budget.py::test_an_unwritable_cgroup_warns_and_never_fails_the_launch, which fails identically on pristine code (cgroup environment, unrelated to this change).

A side call that raises now skips the proposal without aborting the fold.
Two follow-ups on that:
- the failed tick sets last_propose, so a CLI that keeps failing is called
  every PROPOSE_EVERY sessions, not at every fold;
- the fold's runner writes the traceback to errors.log before the distiller
  swallows it; until now the hook's fail-open path was what recorded it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@SakshamUboweja

Copy link
Copy Markdown
Collaborator

Hi Dhruv Arora (@dhruv1220), please reply to the agreement accordingly, so we can proceed.
#134 (comment)

Saksham Uboweja (SakshamUboweja) added a commit to SakshamUboweja/TokenEconomizer that referenced this pull request Nov 8, 2026
…ips its tick

With "verbose": true in the person's Claude Code settings, `claude -p
--output-format json` prints the whole event list instead of one result
object, so every Claude Code side call failed, and the micro-skills
proposer's unguarded call aborted the fold (microsoft#131).

- sidecall.claude_json: the result object from either shape, {} for
  none; claude_call and the toolprune measure probe both read it.
- claude_call: an is_error result is no reply, not the proposer's text,
  and a signed-out one pauses the host's side calls as intended.
- Distiller._maybe_propose: a runner that raises skips the tick instead
  of the fold, and counts as the tick, so a failing CLI is not retried
  at every fold.
- runner_for: a side call that raises leaves one line in errors.log
  before it propagates, for the judge and the proposer alike. Never the
  command: most hosts take the prompt on argv, and `te doctor` prints
  the log's tail.

Fixes microsoft#131. Builds on the approach in microsoft#134 by @dhruv1220 and the
follow-up commit there.
@SakshamUboweja

Copy link
Copy Markdown
Collaborator

Thanks a lot for this, Dhruv Arora (@dhruv1220), and for the clear write-up. Since the CLA couldn't be signed, we couldn't merge this PR as it stands, so we wrote an independent fix for #131 in #164 that follows the same approach: it reads the result event out of the verbose list, and a failed proposer call skips its tick instead of the fold. It also covers the te toolprune measure probe, treats an is_error result as no reply, and notes a failed side call in errors.log without the command line. Your PR is credited in its description. I'm closing this one in favour of it. Thanks again for the contribution.

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.

Claude Code side calls fail when the user settings have verbose: true, and a failed proposer call aborts the fold

3 participants