Skip to content

feat: output-token reduction — verbosity shaper, per-user learning, counterfactual savings - #965

Merged
chopratejas merged 3 commits into
mainfrom
feat/verbosity-learning-and-counterfactual
Jun 17, 2026
Merged

feat: output-token reduction — verbosity shaper, per-user learning, counterfactual savings#965
chopratejas merged 3 commits into
mainfrom
feat/verbosity-learning-and-counterfactual

Conversation

@chopratejas

@chopratejas chopratejas commented Jun 14, 2026

Copy link
Copy Markdown
Collaborator

Description

Adds the first levers that reduce the tokens the model writes back (output), complementing Headroom's existing input compression. Output costs 5× input on Opus-class models and is full of waste (ceremony, restated code, deep "thinking" on routine steps). Two phases in one self-contained PR off main: the request-side output shaper, then per-user verbosity learning plus an honest counterfactual savings estimator and dashboard surfacing.

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Performance improvement
  • Code refactoring (no functional changes)

Changes Made

  • Output shaper (output_shaper.py, opt-in HEADROOM_OUTPUT_SHAPER=1): cache-safe verbosity steering appended to the system-prompt tail (5 levels); effort routing that lowers output_config.effort on mechanical tool-result continuations; legacy thinking.budget_tokens clamp. Never injects effort where absent, never toggles thinking.type.
  • headroom learn --verbosity: mines Claude Code transcripts for behavioral signals (interrupts, length-adaptive fast-skips, echo ratio), recommends a verbosity level (heuristic + optional --llm-judge), and seeds the savings baseline.
  • Counterfactual estimator (output_savings.py): per-stratum synthetic-control (estimated) + A/B holdout (measured) with a propagated 95% CI; conversation-stable arm assignment for A/B validity and prefix-cache safety.
  • AIMD verbosity controller (verbosity_controller.py): additive-increase / fast-back-off state machine; live signal emission gated off by default.
  • Wiring + surfaces: shaper resolves the learned level; recording rides the existing transforms_applied channel through the outcome funnel (no RequestOutcome changes); headroom output-savings CLI; dashboard "Output Tokens Saved" card.
  • Docs: simple-words user guide + design doc with the counterfactual methodology.

Testing

  • Unit tests pass (pytest)
  • Linting passes (ruff check .)
  • Type checking passes (mypy headroom)
  • New tests added for new functionality
  • Manual testing performed

Test Output

$ pytest tests/test_output_savings.py tests/test_output_savings_cli.py \
        tests/test_verbosity_learn.py tests/test_verbosity_controller.py \
        tests/test_output_shaper.py -q
94 passed in 0.54s

$ pytest tests/test_request_outcome.py tests/test_handler_outcome_tag_invariant.py \
        tests/test_proxy_dashboard_stats_cache.py -q
44 passed

$ ruff format --check .
831 files already formatted

$ mypy headroom --ignore-missing-imports
Success: no issues found in 361 source files

Real Behavior Proof

  • Environment: macOS, Python 3.12 (.venv), anthropic 0.76, live API model claude-opus-4-8.
  • Exact command / steps: HEADROOM_OUTPUT_SHAPER=1; headroom learn --verbosity --apply (seeds level + baseline); python scripts/eval_output_shaper.py A (live before/after); simulate holdout traffic then headroom output-savings.
  • Observed result: code-review ask — baseline 1,750 output tokens → L2 1,354 (−22.7%) → L3 599 (−65.8%), same bugs found. learn --verbosity on 24 real sessions → 11% interrupt / 26% fast-skip → L3 (high confidence). Measured A/B path → 31.7% reduction (95% CI 27.7%–35.7%). 94 new tests + 44 existing outcome/dashboard tests green; ruff + mypy clean.
  • Not tested: live streaming-path recording exercised only via unit tests (the transforms_applied funnel is shared across paths); runtime AIMD signal emission is gated off by default and not exercised live.

Review Readiness

  • I have performed a self-review
  • This PR is ready for human review

Checklist

  • My code follows the project's style guidelines
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • I have updated the CHANGELOG.md if applicable

Additional Notes

Output savings are counterfactual (we never observe what the model would have written), so the estimator separates estimated (vs a learned baseline) from measured (A/B holdout via HEADROOM_OUTPUT_HOLDOUT) and always reports a confidence band — never a single made-up number. CHANGELOG left unchecked (release-please manages it). Runtime AIMD self-tuning is intentionally a TODO (controller built/tested; live signal emission gated behind HEADROOM_VERBOSITY_AUTOTUNE).

@github-actions

github-actions Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

PR governance

This PR follows the template and is marked ready for human review.

@github-actions github-actions Bot added status: needs author action Pull request body or readiness checklist still needs author updates status: ci failing Required or reported CI checks are failing status: ready for review Pull request body is complete and the author marked it ready for human review and removed status: needs author action Pull request body or readiness checklist still needs author updates status: ready for review Pull request body is complete and the author marked it ready for human review labels Jun 14, 2026
chopratejas added a commit that referenced this pull request Jun 14, 2026
)

## Description

Every `test (N)` shard has been failing on all PRs and on pushes to
`main`, even though all tests pass. Root cause: **Codecov retired
tokenless uploads.** Without a token, the upload is rejected with `Token
required because branch is protected`, and `ci.yml` had
`fail_ci_if_error: true` with no token — so the rejected upload failed
the whole shard.

This passes `CODECOV_TOKEN` to the coverage-upload steps so uploads
authenticate again.

Closes #

## Type of Change

- [x] Bug fix (non-breaking change that fixes an issue)
- [ ] New feature (non-breaking change that adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] Documentation update
- [ ] Performance improvement
- [ ] Code refactoring (no functional changes)

## Changes Made

- `ci.yml`: add `token: ${{ secrets.CODECOV_TOKEN }}` to the shard
upload step; guard `fail_ci_if_error` so it stays enforced on same-repo
PRs and pushes but relaxes on fork PRs (which cannot read repo secrets).
- `wrap-native-e2e.yml`, `install-native-e2e.yml`: add the same token so
their coverage uploads authenticate too (these were silently dropping
coverage; already non-fatal).

## Testing

- [x] Unit tests pass (`pytest`)
- [x] Linting passes (`ruff check .`)
- [ ] Type checking passes (`mypy headroom`)
- [x] New tests added for new functionality
- [x] Manual testing performed

### Test Output

```text
$ python -c "import yaml; [yaml.safe_load(open(f)) for f in [
    '.github/workflows/ci.yml',
    '.github/workflows/wrap-native-e2e.yml',
    '.github/workflows/install-native-e2e.yml']]"
OK ci.yml
OK wrap-native-e2e.yml
OK install-native-e2e.yml

This PR's own `test (N)` shards are the real test: with CODECOV_TOKEN set,
they should upload successfully and go green.
```

## Real Behavior Proof

- Environment: GitHub Actions, `codecov/codecov-action@v5` (ci.yml) /
`@v4` (e2e); repo is public; `CODECOV_TOKEN` repo secret set by the
maintainer.
- Exact command / steps: open this PR → observe the `test (1..4)` shards
upload coverage with the token instead of being rejected.
- Observed result: prior runs showed `1592 passed` then `Token required
because branch is protected` → shard failed; main's own push CI was red
for the same reason. With the token referenced, the upload
authenticates.
- Not tested: fork-PR path (no secret) — by design it now relaxes
`fail_ci_if_error` so the tokenless rejection is non-fatal there.

## Review Readiness

- [x] I have performed a self-review
- [x] This PR is ready for human review

## Checklist

- [x] My code follows the project's style guidelines
- [x] I have performed a self-review of my code
- [x] I have commented my code, particularly in hard-to-understand areas
- [x] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [ ] I have updated the CHANGELOG.md if applicable

## Additional Notes

Requires the `CODECOV_TOKEN` repository secret (GitHub → Settings →
Secrets and variables → Actions). No code/CHANGELOG change. Separate
from the output-token-reduction feature PR #965.
@github-actions github-actions Bot added status: ready for review Pull request body is complete and the author marked it ready for human review and removed status: ci failing Required or reported CI checks are failing labels Jun 14, 2026
@JerrettDavis
JerrettDavis requested a review from Copilot June 15, 2026 20:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds output-side token reduction to Headroom’s proxy (verbosity steering + effort routing), plus a per-user verbosity learning flow and a counterfactual/measured savings estimator surfaced via CLI and dashboard.

Changes:

  • Introduces an opt-in request rewriter (output_shaper) that appends cache-safe verbosity steering to the system-prompt tail and routes effort down on mechanical tool-result continuations.
  • Adds verbosity learning (headroom learn --verbosity) that mines Claude Code transcripts for behavioral signals and seeds a per-stratum output-token baseline.
  • Adds an output-savings ledger/estimator with holdout arm assignment, CLI reporting, and dashboard stats surfacing.

Reviewed changes

Copilot reviewed 20 out of 21 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
tests/test_verbosity_learn.py Unit tests for transcript signal extraction + heuristic recommendation.
tests/test_verbosity_controller.py Unit tests for AIMD verbosity controller state machine + persistence.
tests/test_output_shaper.py Unit tests for turn classification, steering idempotency, and effort routing.
tests/test_output_savings.py Unit tests for stratification, arm assignment, baseline/holdout estimation, and echo ratio.
tests/test_output_savings_cli.py Smoke tests for CLI output + outcome→ledger wiring via labels.
scripts/eval_output_shaper.py Live eval script comparing baseline vs shaped request output tokens.
README.md Documents the new “Output token reduction” feature and basic usage.
headroom/proxy/verbosity_controller.py Adds AIMD controller + state load/save helpers.
headroom/proxy/server.py Surfaces output reduction stats in /stats payload for dashboard consumption.
headroom/proxy/output_shaper.py Implements request-side verbosity steering and effort routing.
headroom/proxy/output_savings.py Implements ledger, stratification, deterministic holdout assignment, and estimators.
headroom/proxy/outcome.py Records output-token observations into the savings ledger (best-effort).
headroom/proxy/handlers/anthropic.py Wires shaper + holdout assignment + stratum labels into Anthropic request path.
headroom/learn/verbosity.py Implements transcript parsing, signal extraction, baseline building, and recommendation logic.
headroom/dashboard/templates/dashboard.html Adds “Output Tokens Saved” hero card.
headroom/cli/output_savings.py Adds headroom output-savings command.
headroom/cli/main.py Registers the new CLI command module.
headroom/cli/learn.py Adds --verbosity / --llm-judge mode and persistence/baseline seeding.
docs/proposals/output-token-reduction.md Design doc including methodology/constraints and measurement approach.
docs/output-token-reduction-guide.md End-user guide for enabling, learning, and measuring output reduction.
.gitignore Ensures the new eval script is not ignored under scripts/*.

Comment thread headroom/proxy/output_savings.py
Comment thread headroom/proxy/output_savings.py
Comment on lines +193 to +210
def lookup(self, key: str) -> tuple[float, float, int]:
"""Return ``(mean, var, n)`` for *key* with hierarchical back-off.

Falls back by trimming trailing (least-specific) stratum fields, then
to the global mean. Back-off keeps the estimate defined for strata the
baseline never saw, at the cost of specificity.
"""
acc = self.strata.get(key)
if acc is not None and acc.n > 0:
return acc.mean, acc.var, acc.n
parts = key.split("|")
while len(parts) > 1:
parts = parts[:-1]
prefix = "|".join(parts)
for k, a in self.strata.items():
if k.startswith(prefix + "|") and a.n > 0:
return a.mean, a.var, a.n
return self.glob.mean, self.glob.var, self.glob.n
Comment on lines +306 to +315
output_config = body.get("output_config")
if isinstance(output_config, dict):
effort = output_config.get("effort")
if (
isinstance(effort, str)
and effort in _EFFORT_RANK
and _EFFORT_RANK[effort] > _EFFORT_RANK[settings.mechanical_effort]
):
output_config["effort"] = settings.mechanical_effort
labels.append(f"output_shaper:effort:{effort}->{settings.mechanical_effort}")
Comment on lines +1734 to +1742
# Stratum from request features observable now (mirrors the
# offline baseline so live and learned strata line up).
_turn_kind = classify_turn(body.get("messages", [])).value
_stratum = stratum_key(
turn_kind=_turn_kind,
input_tokens=original_tokens,
model=model,
has_tools=bool(body.get("tools")),
)
Comment on lines +96 to +101
try:
d = json.loads(Path(path).read_text())
state = ControllerState.from_dict(d)
except (OSError, json.JSONDecodeError, ValueError):
state = ControllerState(level=default_level)
state.level = max(floor, min(ceil, state.level))
@github-actions github-actions Bot added status: ci failing Required or reported CI checks are failing and removed status: ready for review Pull request body is complete and the author marked it ready for human review labels Jun 16, 2026
…c requests

Verbosity steering (5 levels, cache-safe system-tail injection) + effort
routing that lowers output_config.effort on mechanical tool_result
continuations and clamps legacy thinking budgets. Opt-in via
HEADROOM_OUTPUT_SHAPER; never injects effort where absent, never toggles
thinking.type. Live eval: -22% (L2) / -63% (L3) output tokens on a code
review ask; -29% on an agentic continuation turn (opus-4-8).
…s + dashboard

Phase 2 of output-token reduction, built on the Phase 1 shaper:

- learn --verbosity: mine Claude Code transcripts for behavioral signals
  (interrupts, length-adaptive fast-skips, echo ratio), recommend a verbosity
  level (heuristic prior + optional --llm-judge), and seed the savings baseline.
  Real data: 11% interrupt / 26% fast-skip -> L3, high confidence.
- Counterfactual savings estimator (output_savings.py): per-stratum synthetic
  control (estimated) + A/B holdout (measured), signed-delta aggregate with a
  propagated 95% CI. Conversation-stable arm assignment (clean A/B + cache-safe).
- AIMD verbosity controller: additive-increase / fast-back-off state machine
  with hysteresis; live signal emission gated off by default.
- Shaper resolves the learned level (env > controller > learned > default);
  recording rides the existing transforms_applied label channel through the
  outcome funnel, so all response paths feed the ledger with no RequestOutcome
  changes.
- CLI: headroom output-savings (reduction % + CI, measured vs estimated).
- Dashboard: 'Output Tokens Saved' hero card (count, %, CI, measured/estimated).
- Docs: simple-words user guide + design doc with the counterfactual methodology.
- Tests: 94 new (estimator stats, signal extraction, controller, CLI), all green;
  44 existing outcome/dashboard tests still pass.

Opt-in: HEADROOM_OUTPUT_SHAPER=1; HEADROOM_OUTPUT_HOLDOUT=0.1 for a measured number.
@chopratejas
chopratejas force-pushed the feat/verbosity-learning-and-counterfactual branch from 23a6828 to 803dbdf Compare June 17, 2026 03:46
@github-actions github-actions Bot added status: ready for review Pull request body is complete and the author marked it ready for human review and removed status: ci failing Required or reported CI checks are failing labels Jun 17, 2026
@chopratejas
chopratejas merged commit a99dc61 into main Jun 17, 2026
32 checks passed
@github-actions github-actions Bot mentioned this pull request Jun 22, 2026
chopratejas pushed a commit that referenced this pull request Jun 22, 2026
🤖 I have created a release *beep* *boop*
---


<details><summary>0.27.0</summary>

##
[0.27.0](v0.26.0...v0.27.0)
(2026-06-22)


### Features

* **cli:** add headroom doctor setup diagnostics
([#926](#926))
([e45cf4e](e45cf4e))
* **cli:** add headroom update command and release banner
([#1088](#1088))
([26be2c3](26be2c3))
* compression extraction — Rust knob exposure, CCR hardening, traffic
audits ([#818](#818))
([b7be381](b7be381))
* measure and surface token throughput (tokens/sec) through the proxy
([#983](#983))
([0d89c67](0d89c67))
* output-token reduction — verbosity shaper, per-user learning,
counterfactual savings
([#965](#965))
([a99dc61](a99dc61))
* **policy:** decay P_alive from idle time near cache TTL
([#856](#856) P3b)
([#1028](#1028))
([fe4f9ee](fe4f9ee))
* **providers:** add Cortex Code (Snowflake CoCo) as a supported agent
([#1190](#1190))
([d9d0bf4](d9d0bf4))
* **proxy:** cc-switch reconciler — keep Headroom in the request path
alongside cc-switch
([#1030](#1030))
([e8fc8a0](e8fc8a0))
* **proxy:** hot-reload live env knobs so a reused proxy picks them up
without a restart
([#1090](#1090))
([6904d47](6904d47))
* **proxy:** make COMPRESSION_TIMEOUT_SECONDS configurable via env
([#946](#946))
([#991](#991))
([addebdb](addebdb))
* **transforms:** tabular + spreadsheet (.xlsx/.xls) compression
([#1128](#1128))
([d789a7c](d789a7c))
* **vertex:** turnkey Claude Code + Vertex compression (+ fixes from the
Vertex review)
([#1113](#1113))
([0e05915](0e05915))


### Bug Fixes

* **ccr:** accept 12-char SmartCrusher hashes in tool injection
([#1095](#1095))
([#1141](#1141))
([9f7f3ad](9f7f3ad))
* **ccr:** return stored content when headroom_retrieve query matches
nothing ([#1213](#1213))
([#1236](#1236))
([08fb845](08fb845))
* **content-router:** honor target_ratio in compression cache + add
proxy --target-ratio flag
([#1108](#1108))
([8894ee0](8894ee0))
* **dashboard:** light-mode backgrounds + aligned savings tables
([#1064](#1064))
([5eae32b](5eae32b))
* **deps:** make litellm optional on Python 3.14
([#956](#956))
([#993](#993))
([b2f04e4](b2f04e4))
* **e2e:** align Codex wrap e2e with global-only RTK guidance
([#1240](#1240))
([#1254](#1254))
([bc12ace](bc12ace))
* **init:** set ENABLE_TOOL_SEARCH=true so Claude Code keeps deferring
tools ([#746](#746))
([#995](#995))
([500ec2b](500ec2b))
* **kompress:** never block the request path on the cold-cache model
download ([#1161](#1161))
([3fc2a78](3fc2a78))
* **memory:** use ONNX embedder for `wrap --memory` sync
([#1092](#1092))
([#1262](#1262))
([4f9feda](4f9feda))
* **openclaw:** wrap plugin export as {register} object for OpenClaw
2026.x compatibility
([#1218](#1218))
([2e6c442](2e6c442))
* **providers:** update DeepSeek V3 context limit from 128K to 1M
([#1038](#1038))
([#1137](#1137))
([bcabc5c](bcabc5c))
* **proxy:** allow disabling periodic TOIN stats logging
([#1265](#1265))
([b5f63d8](b5f63d8))
* **proxy:** honor HEADROOM_EXCLUDE_TOOLS for Codex /v1/responses tool
outputs ([#940](#940))
([#1053](#1053))
([f03e77b](f03e77b))
* **proxy:** preserve byte-faithful Anthropic tool forwarding
([#1222](#1222))
([1f18d59](1f18d59))
* **proxy:** route Codex OAuth image requests
([#1215](#1215))
([381d771](381d771))
* **proxy:** scope CORS to loopback + gate operator/content endpoints
([#1226](#1226))
([bd55a42](bd55a42))
* **proxy:** stamp X-Client: codex on Responses endpoint for
unidentified callers
([#1036](#1036))
([b0cd032](b0cd032))
* **proxy:** treat NODE_EXTRA_CA_CERTS as additive, not replacement
([#998](#998))
([#1031](#1031))
([c987283](c987283))
* **telemetry:** switch anonymous telemetry to opt-in (off by default)
([#1223](#1223))
([b998697](b998697))
* **tokenizers:** bound tiktoken vocab load so a stalled download cannot
hang requests
([#956](#956))
([#994](#994))
([7e86baf](7e86baf))
* **unwrap:** remove ANTHROPIC_BASE_URL + ENABLE_TOOL_SEARCH and init
hooks on unwrap
([#992](#992))
([5b84691](5b84691))
* **wrap:** keep Codex RTK guidance global
([#1240](#1240))
([7c26a54](7c26a54))
* **wrap:** percent-encode non-ASCII cwd names in X-Headroom-Project
header ([#1071](#1071))
([9f712cc](9f712cc))
* **wrap:** write env.ANTHROPIC_BASE_URL to settings.json so
daemon-spawned conversations inherit proxy
([#951](#951))
([#1078](#1078))
([a554c3a](a554c3a))
</details>

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
studyzy pushed a commit to studyzy/headroom that referenced this pull request Jun 24, 2026
…ounterfactual savings (headroomlabs-ai#965)

## Description

Adds the first levers that reduce the tokens the model **writes back**
(output), complementing Headroom's existing input compression. Output
costs 5× input on Opus-class models and is full of waste (ceremony,
restated code, deep "thinking" on routine steps). Two phases in one
self-contained PR off `main`: the request-side output shaper, then
per-user verbosity learning plus an honest counterfactual savings
estimator and dashboard surfacing.

## Type of Change

- [ ] Bug fix (non-breaking change that fixes an issue)
- [x] New feature (non-breaking change that adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [x] Documentation update
- [ ] Performance improvement
- [ ] Code refactoring (no functional changes)

## Changes Made

- **Output shaper** (`output_shaper.py`, opt-in
`HEADROOM_OUTPUT_SHAPER=1`): cache-safe verbosity steering appended to
the system-prompt tail (5 levels); effort routing that lowers
`output_config.effort` on mechanical tool-result continuations; legacy
`thinking.budget_tokens` clamp. Never injects effort where absent, never
toggles `thinking.type`.
- **`headroom learn --verbosity`**: mines Claude Code transcripts for
behavioral signals (interrupts, length-adaptive fast-skips, echo ratio),
recommends a verbosity level (heuristic + optional `--llm-judge`), and
seeds the savings baseline.
- **Counterfactual estimator** (`output_savings.py`): per-stratum
synthetic-control (estimated) + A/B holdout (measured) with a propagated
95% CI; conversation-stable arm assignment for A/B validity and
prefix-cache safety.
- **AIMD verbosity controller** (`verbosity_controller.py`):
additive-increase / fast-back-off state machine; live signal emission
gated off by default.
- **Wiring + surfaces**: shaper resolves the learned level; recording
rides the existing `transforms_applied` channel through the outcome
funnel (no `RequestOutcome` changes); `headroom output-savings` CLI;
dashboard "Output Tokens Saved" card.
- **Docs**: simple-words user guide + design doc with the counterfactual
methodology.

## Testing

- [x] Unit tests pass (`pytest`)
- [x] Linting passes (`ruff check .`)
- [x] Type checking passes (`mypy headroom`)
- [x] New tests added for new functionality
- [x] Manual testing performed

### Test Output

```text
$ pytest tests/test_output_savings.py tests/test_output_savings_cli.py \
        tests/test_verbosity_learn.py tests/test_verbosity_controller.py \
        tests/test_output_shaper.py -q
94 passed in 0.54s

$ pytest tests/test_request_outcome.py tests/test_handler_outcome_tag_invariant.py \
        tests/test_proxy_dashboard_stats_cache.py -q
44 passed

$ ruff format --check .
831 files already formatted

$ mypy headroom --ignore-missing-imports
Success: no issues found in 361 source files
```

## Real Behavior Proof

- Environment: macOS, Python 3.12 (`.venv`), `anthropic` 0.76, live API
model `claude-opus-4-8`.
- Exact command / steps: `HEADROOM_OUTPUT_SHAPER=1`; `headroom learn
--verbosity --apply` (seeds level + baseline); `python
scripts/eval_output_shaper.py A` (live before/after); simulate holdout
traffic then `headroom output-savings`.
- Observed result: code-review ask — baseline 1,750 output tokens → L2
1,354 (−22.7%) → L3 599 (−65.8%), same bugs found. `learn --verbosity`
on 24 real sessions → 11% interrupt / 26% fast-skip → L3 (high
confidence). Measured A/B path → 31.7% reduction (95% CI 27.7%–35.7%).
94 new tests + 44 existing outcome/dashboard tests green; ruff + mypy
clean.
- Not tested: live streaming-path recording exercised only via unit
tests (the `transforms_applied` funnel is shared across paths); runtime
AIMD signal emission is gated off by default and not exercised live.

## Review Readiness

- [x] I have performed a self-review
- [x] This PR is ready for human review

## Checklist

- [x] My code follows the project's style guidelines
- [x] I have performed a self-review of my code
- [x] I have commented my code, particularly in hard-to-understand areas
- [x] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [ ] I have updated the CHANGELOG.md if applicable

## Additional Notes

Output savings are counterfactual (we never observe what the model
*would* have written), so the estimator separates **estimated** (vs a
learned baseline) from **measured** (A/B holdout via
`HEADROOM_OUTPUT_HOLDOUT`) and always reports a confidence band — never
a single made-up number. CHANGELOG left unchecked (release-please
manages it). Runtime AIMD self-tuning is intentionally a TODO
(controller built/tested; live signal emission gated behind
`HEADROOM_VERBOSITY_AUTOTUNE`).
studyzy pushed a commit to studyzy/headroom that referenced this pull request Jun 24, 2026
🤖 I have created a release *beep* *boop*
---


<details><summary>0.27.0</summary>

##
[0.27.0](headroomlabs-ai/headroom@v0.26.0...v0.27.0)
(2026-06-22)


### Features

* **cli:** add headroom doctor setup diagnostics
([headroomlabs-ai#926](headroomlabs-ai#926))
([e45cf4e](headroomlabs-ai@e45cf4e))
* **cli:** add headroom update command and release banner
([headroomlabs-ai#1088](headroomlabs-ai#1088))
([26be2c3](headroomlabs-ai@26be2c3))
* compression extraction — Rust knob exposure, CCR hardening, traffic
audits ([headroomlabs-ai#818](headroomlabs-ai#818))
([b7be381](headroomlabs-ai@b7be381))
* measure and surface token throughput (tokens/sec) through the proxy
([headroomlabs-ai#983](headroomlabs-ai#983))
([0d89c67](headroomlabs-ai@0d89c67))
* output-token reduction — verbosity shaper, per-user learning,
counterfactual savings
([headroomlabs-ai#965](headroomlabs-ai#965))
([a99dc61](headroomlabs-ai@a99dc61))
* **policy:** decay P_alive from idle time near cache TTL
([headroomlabs-ai#856](headroomlabs-ai#856) P3b)
([headroomlabs-ai#1028](headroomlabs-ai#1028))
([fe4f9ee](headroomlabs-ai@fe4f9ee))
* **providers:** add Cortex Code (Snowflake CoCo) as a supported agent
([headroomlabs-ai#1190](headroomlabs-ai#1190))
([d9d0bf4](headroomlabs-ai@d9d0bf4))
* **proxy:** cc-switch reconciler — keep Headroom in the request path
alongside cc-switch
([headroomlabs-ai#1030](headroomlabs-ai#1030))
([e8fc8a0](headroomlabs-ai@e8fc8a0))
* **proxy:** hot-reload live env knobs so a reused proxy picks them up
without a restart
([headroomlabs-ai#1090](headroomlabs-ai#1090))
([6904d47](headroomlabs-ai@6904d47))
* **proxy:** make COMPRESSION_TIMEOUT_SECONDS configurable via env
([headroomlabs-ai#946](headroomlabs-ai#946))
([headroomlabs-ai#991](headroomlabs-ai#991))
([addebdb](headroomlabs-ai@addebdb))
* **transforms:** tabular + spreadsheet (.xlsx/.xls) compression
([headroomlabs-ai#1128](headroomlabs-ai#1128))
([d789a7c](headroomlabs-ai@d789a7c))
* **vertex:** turnkey Claude Code + Vertex compression (+ fixes from the
Vertex review)
([headroomlabs-ai#1113](headroomlabs-ai#1113))
([0e05915](headroomlabs-ai@0e05915))


### Bug Fixes

* **ccr:** accept 12-char SmartCrusher hashes in tool injection
([headroomlabs-ai#1095](headroomlabs-ai#1095))
([headroomlabs-ai#1141](headroomlabs-ai#1141))
([9f7f3ad](headroomlabs-ai@9f7f3ad))
* **ccr:** return stored content when headroom_retrieve query matches
nothing ([headroomlabs-ai#1213](headroomlabs-ai#1213))
([headroomlabs-ai#1236](headroomlabs-ai#1236))
([08fb845](headroomlabs-ai@08fb845))
* **content-router:** honor target_ratio in compression cache + add
proxy --target-ratio flag
([headroomlabs-ai#1108](headroomlabs-ai#1108))
([8894ee0](headroomlabs-ai@8894ee0))
* **dashboard:** light-mode backgrounds + aligned savings tables
([headroomlabs-ai#1064](headroomlabs-ai#1064))
([5eae32b](headroomlabs-ai@5eae32b))
* **deps:** make litellm optional on Python 3.14
([headroomlabs-ai#956](headroomlabs-ai#956))
([headroomlabs-ai#993](headroomlabs-ai#993))
([b2f04e4](headroomlabs-ai@b2f04e4))
* **e2e:** align Codex wrap e2e with global-only RTK guidance
([headroomlabs-ai#1240](headroomlabs-ai#1240))
([headroomlabs-ai#1254](headroomlabs-ai#1254))
([bc12ace](headroomlabs-ai@bc12ace))
* **init:** set ENABLE_TOOL_SEARCH=true so Claude Code keeps deferring
tools ([headroomlabs-ai#746](headroomlabs-ai#746))
([headroomlabs-ai#995](headroomlabs-ai#995))
([500ec2b](headroomlabs-ai@500ec2b))
* **kompress:** never block the request path on the cold-cache model
download ([headroomlabs-ai#1161](headroomlabs-ai#1161))
([3fc2a78](headroomlabs-ai@3fc2a78))
* **memory:** use ONNX embedder for `wrap --memory` sync
([headroomlabs-ai#1092](headroomlabs-ai#1092))
([headroomlabs-ai#1262](headroomlabs-ai#1262))
([4f9feda](headroomlabs-ai@4f9feda))
* **openclaw:** wrap plugin export as {register} object for OpenClaw
2026.x compatibility
([headroomlabs-ai#1218](headroomlabs-ai#1218))
([2e6c442](headroomlabs-ai@2e6c442))
* **providers:** update DeepSeek V3 context limit from 128K to 1M
([headroomlabs-ai#1038](headroomlabs-ai#1038))
([headroomlabs-ai#1137](headroomlabs-ai#1137))
([bcabc5c](headroomlabs-ai@bcabc5c))
* **proxy:** allow disabling periodic TOIN stats logging
([headroomlabs-ai#1265](headroomlabs-ai#1265))
([b5f63d8](headroomlabs-ai@b5f63d8))
* **proxy:** honor HEADROOM_EXCLUDE_TOOLS for Codex /v1/responses tool
outputs ([headroomlabs-ai#940](headroomlabs-ai#940))
([headroomlabs-ai#1053](headroomlabs-ai#1053))
([f03e77b](headroomlabs-ai@f03e77b))
* **proxy:** preserve byte-faithful Anthropic tool forwarding
([headroomlabs-ai#1222](headroomlabs-ai#1222))
([1f18d59](headroomlabs-ai@1f18d59))
* **proxy:** route Codex OAuth image requests
([headroomlabs-ai#1215](headroomlabs-ai#1215))
([381d771](headroomlabs-ai@381d771))
* **proxy:** scope CORS to loopback + gate operator/content endpoints
([headroomlabs-ai#1226](headroomlabs-ai#1226))
([bd55a42](headroomlabs-ai@bd55a42))
* **proxy:** stamp X-Client: codex on Responses endpoint for
unidentified callers
([headroomlabs-ai#1036](headroomlabs-ai#1036))
([b0cd032](headroomlabs-ai@b0cd032))
* **proxy:** treat NODE_EXTRA_CA_CERTS as additive, not replacement
([headroomlabs-ai#998](headroomlabs-ai#998))
([headroomlabs-ai#1031](headroomlabs-ai#1031))
([c987283](headroomlabs-ai@c987283))
* **telemetry:** switch anonymous telemetry to opt-in (off by default)
([headroomlabs-ai#1223](headroomlabs-ai#1223))
([b998697](headroomlabs-ai@b998697))
* **tokenizers:** bound tiktoken vocab load so a stalled download cannot
hang requests
([headroomlabs-ai#956](headroomlabs-ai#956))
([headroomlabs-ai#994](headroomlabs-ai#994))
([7e86baf](headroomlabs-ai@7e86baf))
* **unwrap:** remove ANTHROPIC_BASE_URL + ENABLE_TOOL_SEARCH and init
hooks on unwrap
([headroomlabs-ai#992](headroomlabs-ai#992))
([5b84691](headroomlabs-ai@5b84691))
* **wrap:** keep Codex RTK guidance global
([headroomlabs-ai#1240](headroomlabs-ai#1240))
([7c26a54](headroomlabs-ai@7c26a54))
* **wrap:** percent-encode non-ASCII cwd names in X-Headroom-Project
header ([headroomlabs-ai#1071](headroomlabs-ai#1071))
([9f712cc](headroomlabs-ai@9f712cc))
* **wrap:** write env.ANTHROPIC_BASE_URL to settings.json so
daemon-spawned conversations inherit proxy
([headroomlabs-ai#951](headroomlabs-ai#951))
([headroomlabs-ai#1078](headroomlabs-ai#1078))
([a554c3a](headroomlabs-ai@a554c3a))
</details>

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
DevZonayed pushed a commit to DevZonayed/headroom that referenced this pull request Aug 17, 2026
…eadroomlabs-ai#968)

## Description

Every `test (N)` shard has been failing on all PRs and on pushes to
`main`, even though all tests pass. Root cause: **Codecov retired
tokenless uploads.** Without a token, the upload is rejected with `Token
required because branch is protected`, and `ci.yml` had
`fail_ci_if_error: true` with no token — so the rejected upload failed
the whole shard.

This passes `CODECOV_TOKEN` to the coverage-upload steps so uploads
authenticate again.

Closes #

## Type of Change

- [x] Bug fix (non-breaking change that fixes an issue)
- [ ] New feature (non-breaking change that adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] Documentation update
- [ ] Performance improvement
- [ ] Code refactoring (no functional changes)

## Changes Made

- `ci.yml`: add `token: ${{ secrets.CODECOV_TOKEN }}` to the shard
upload step; guard `fail_ci_if_error` so it stays enforced on same-repo
PRs and pushes but relaxes on fork PRs (which cannot read repo secrets).
- `wrap-native-e2e.yml`, `install-native-e2e.yml`: add the same token so
their coverage uploads authenticate too (these were silently dropping
coverage; already non-fatal).

## Testing

- [x] Unit tests pass (`pytest`)
- [x] Linting passes (`ruff check .`)
- [ ] Type checking passes (`mypy headroom`)
- [x] New tests added for new functionality
- [x] Manual testing performed

### Test Output

```text
$ python -c "import yaml; [yaml.safe_load(open(f)) for f in [
    '.github/workflows/ci.yml',
    '.github/workflows/wrap-native-e2e.yml',
    '.github/workflows/install-native-e2e.yml']]"
OK ci.yml
OK wrap-native-e2e.yml
OK install-native-e2e.yml

This PR's own `test (N)` shards are the real test: with CODECOV_TOKEN set,
they should upload successfully and go green.
```

## Real Behavior Proof

- Environment: GitHub Actions, `codecov/codecov-action@v5` (ci.yml) /
`@v4` (e2e); repo is public; `CODECOV_TOKEN` repo secret set by the
maintainer.
- Exact command / steps: open this PR → observe the `test (1..4)` shards
upload coverage with the token instead of being rejected.
- Observed result: prior runs showed `1592 passed` then `Token required
because branch is protected` → shard failed; main's own push CI was red
for the same reason. With the token referenced, the upload
authenticates.
- Not tested: fork-PR path (no secret) — by design it now relaxes
`fail_ci_if_error` so the tokenless rejection is non-fatal there.

## Review Readiness

- [x] I have performed a self-review
- [x] This PR is ready for human review

## Checklist

- [x] My code follows the project's style guidelines
- [x] I have performed a self-review of my code
- [x] I have commented my code, particularly in hard-to-understand areas
- [x] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [ ] I have updated the CHANGELOG.md if applicable

## Additional Notes

Requires the `CODECOV_TOKEN` repository secret (GitHub → Settings →
Secrets and variables → Actions). No code/CHANGELOG change. Separate
from the output-token-reduction feature PR headroomlabs-ai#965.
DevZonayed pushed a commit to DevZonayed/headroom that referenced this pull request Aug 17, 2026
…ounterfactual savings (headroomlabs-ai#965)

## Description

Adds the first levers that reduce the tokens the model **writes back**
(output), complementing Headroom's existing input compression. Output
costs 5× input on Opus-class models and is full of waste (ceremony,
restated code, deep "thinking" on routine steps). Two phases in one
self-contained PR off `main`: the request-side output shaper, then
per-user verbosity learning plus an honest counterfactual savings
estimator and dashboard surfacing.

## Type of Change

- [ ] Bug fix (non-breaking change that fixes an issue)
- [x] New feature (non-breaking change that adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [x] Documentation update
- [ ] Performance improvement
- [ ] Code refactoring (no functional changes)

## Changes Made

- **Output shaper** (`output_shaper.py`, opt-in
`HEADROOM_OUTPUT_SHAPER=1`): cache-safe verbosity steering appended to
the system-prompt tail (5 levels); effort routing that lowers
`output_config.effort` on mechanical tool-result continuations; legacy
`thinking.budget_tokens` clamp. Never injects effort where absent, never
toggles `thinking.type`.
- **`headroom learn --verbosity`**: mines Claude Code transcripts for
behavioral signals (interrupts, length-adaptive fast-skips, echo ratio),
recommends a verbosity level (heuristic + optional `--llm-judge`), and
seeds the savings baseline.
- **Counterfactual estimator** (`output_savings.py`): per-stratum
synthetic-control (estimated) + A/B holdout (measured) with a propagated
95% CI; conversation-stable arm assignment for A/B validity and
prefix-cache safety.
- **AIMD verbosity controller** (`verbosity_controller.py`):
additive-increase / fast-back-off state machine; live signal emission
gated off by default.
- **Wiring + surfaces**: shaper resolves the learned level; recording
rides the existing `transforms_applied` channel through the outcome
funnel (no `RequestOutcome` changes); `headroom output-savings` CLI;
dashboard "Output Tokens Saved" card.
- **Docs**: simple-words user guide + design doc with the counterfactual
methodology.

## Testing

- [x] Unit tests pass (`pytest`)
- [x] Linting passes (`ruff check .`)
- [x] Type checking passes (`mypy headroom`)
- [x] New tests added for new functionality
- [x] Manual testing performed

### Test Output

```text
$ pytest tests/test_output_savings.py tests/test_output_savings_cli.py \
        tests/test_verbosity_learn.py tests/test_verbosity_controller.py \
        tests/test_output_shaper.py -q
94 passed in 0.54s

$ pytest tests/test_request_outcome.py tests/test_handler_outcome_tag_invariant.py \
        tests/test_proxy_dashboard_stats_cache.py -q
44 passed

$ ruff format --check .
831 files already formatted

$ mypy headroom --ignore-missing-imports
Success: no issues found in 361 source files
```

## Real Behavior Proof

- Environment: macOS, Python 3.12 (`.venv`), `anthropic` 0.76, live API
model `claude-opus-4-8`.
- Exact command / steps: `HEADROOM_OUTPUT_SHAPER=1`; `headroom learn
--verbosity --apply` (seeds level + baseline); `python
scripts/eval_output_shaper.py A` (live before/after); simulate holdout
traffic then `headroom output-savings`.
- Observed result: code-review ask — baseline 1,750 output tokens → L2
1,354 (−22.7%) → L3 599 (−65.8%), same bugs found. `learn --verbosity`
on 24 real sessions → 11% interrupt / 26% fast-skip → L3 (high
confidence). Measured A/B path → 31.7% reduction (95% CI 27.7%–35.7%).
94 new tests + 44 existing outcome/dashboard tests green; ruff + mypy
clean.
- Not tested: live streaming-path recording exercised only via unit
tests (the `transforms_applied` funnel is shared across paths); runtime
AIMD signal emission is gated off by default and not exercised live.

## Review Readiness

- [x] I have performed a self-review
- [x] This PR is ready for human review

## Checklist

- [x] My code follows the project's style guidelines
- [x] I have performed a self-review of my code
- [x] I have commented my code, particularly in hard-to-understand areas
- [x] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [ ] I have updated the CHANGELOG.md if applicable

## Additional Notes

Output savings are counterfactual (we never observe what the model
*would* have written), so the estimator separates **estimated** (vs a
learned baseline) from **measured** (A/B holdout via
`HEADROOM_OUTPUT_HOLDOUT`) and always reports a confidence band — never
a single made-up number. CHANGELOG left unchecked (release-please
manages it). Runtime AIMD self-tuning is intentionally a TODO
(controller built/tested; live signal emission gated behind
`HEADROOM_VERBOSITY_AUTOTUNE`).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status: ready for review Pull request body is complete and the author marked it ready for human review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants