Skip to content

fix(transforms): bound native content detection with a Windows watchdog (#575)#1563

Merged
JerrettDavis merged 2 commits into
headroomlabs-ai:mainfrom
Parideboy:fix/575-native-detect-watchdog
Jul 2, 2026
Merged

fix(transforms): bound native content detection with a Windows watchdog (#575)#1563
JerrettDavis merged 2 commits into
headroomlabs-ai:mainfrom
Parideboy:fix/575-native-detect-watchdog

Conversation

@Parideboy

@Parideboy Parideboy commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Description

On Windows, the first call into the native headroom._core.detect_content_type can park forever in an ort/Once initialization (WaitOnAddress) at 0% CPU. A wedged native call cannot be cancelled from Python, so it deadlocks the caller. In the proxy it is worse: each affected request permanently consumes a compression-executor worker, eventually saturating the pool (running == max_workers, leaked_threads_total == 0 because the worker never finishes) and stalling every subsequent request for the full COMPRESSION_TIMEOUT_SECONDS before passthrough.

The Rust backend is already off by default on Windows — _resolve_detect_backend() returns "python" there — but an explicit HEADROOM_DETECT_BACKEND=rust, or any future regression of that default, re-exposes the hang with no escape hatch. This implements the issue's third ask: a timeout/watchdog so a hung native init degrades gracefully instead of deadlocking the agent / MCP server / proxy.

Closes #575

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

  • Added a Windows-only watchdog around the native detect call in transforms/content_router.py. _rust_detect_watchdogged() runs detect_content_type on a daemon thread and bounds the caller's wait; on timeout it raises TimeoutError, which the existing except BaseException handler degrades to the pure-Python regex detector. Detection therefore always returns instead of deadlocking (and, in the proxy, instead of permanently consuming a compression-executor worker).
  • Added _detect_timeout_secs() reading HEADROOM_DETECT_TIMEOUT_SECS (default 5s; blank / non-numeric / non-positive values fall back to the default).
  • Gated the watchdog to sys.platform == "win32" — the only platform where the hang is observed. Other platforms keep the direct native call with no per-call thread overhead (the trusted hot path is unchanged).
  • Added regression tests for the watchdog, env parsing, error relay, the Windows degrade-on-hang path, and the Windows happy path.

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

$ ruff check headroom/transforms/content_router.py tests/test_transforms_content_router.py
All checks passed!

$ ruff format --check headroom/transforms/content_router.py tests/test_transforms_content_router.py
2 files already formatted

$ mypy headroom --ignore-missing-imports
(exit 0)

$ pytest tests/test_transforms_content_router.py -q
33 passed

Real Behavior Proof

  • Environment: Windows 11, Python 3.13, ruff 0.15.17 / mypy 1.20.2 / pytest 9.1.0, headroom._core built locally, branch fix/575-native-detect-watchdog.
  • Exact command / steps: ran the four checks above. test_detect_content_watchdog_degrades_on_windows_hang forces HEADROOM_DETECT_BACKEND=rust, patches sys.platform to "win32", sets HEADROOM_DETECT_TIMEOUT_SECS=0.1, and injects a native detect_content_type that blocks on an Event (simulating the WaitOnAddress park, GIL released) — then asserts detection still returns. The companion tests cover env parsing, error relay through the watchdog, and the fast-native Windows path.
  • Observed result: with a hung native detector, _detect_content('[{"id": 1}]') returns ContentType.JSON_ARRAY (the pure-Python degrade path) within the 0.1s budget instead of hanging; with a fast native detector on Windows it returns the native result unchanged; non-Windows behavior (direct call) is untouched and the existing rust-delegation test still passes. All 33 tests in the file pass; ruff / format / mypy clean.
  • Not tested: the live from headroom._core import detect_content_type; detect_content_type("hello world") deadlock on an affected Windows 11 24H2 machine was not reproduced end to end (it requires the specific System32 ONNX Runtime build). The fix is instead covered by the deterministic hung-detector injection test, which exercises the exact degrade path the watchdog adds. This PR does not attempt the Rust-side fix for the underlying first-call init deadlock (asks Add Claude Opus 4.5 and Claude 4 model family to context limits #1) — it is the Python-side watchdog (ask Fix ZlibError by removing compression headers after httpx decompression #3); the existing HEADROOM_DETECT_BACKEND flag already covers ask [BUG] Decompression error: ZlibError #2.

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

  • The watchdog cannot cancel a wedged native call (no portable way to kill a thread blocked in C). It frees the caller and leaves the stuck daemon thread to die with the process; this is marked with a ponytail: comment naming the upgrade path (the Rust-side non-blocking first-call init). For the saturation scenario this is still a strict improvement: callers no longer block indefinitely, so the executor drains instead of wedging permanently.

…og (headroomlabs-ai#575)

On Windows the first call into `headroom._core.detect_content_type` can park
forever in an ort/`Once` init (`WaitOnAddress`) at 0% CPU. A wedged native call
cannot be cancelled from Python, so it deadlocks the caller and — in the proxy —
permanently consumes a compression-executor worker, eventually saturating the
pool and stalling every request for the full compression timeout.

The Rust backend is already off by default on Windows (`_resolve_detect_backend`
returns "python" there), but an explicit `HEADROOM_DETECT_BACKEND=rust`, or any
regression of that default, re-exposes the hang with no escape hatch.

Add a Windows-only watchdog around the native detect call: run it on a daemon
thread and bound the caller's wait (`HEADROOM_DETECT_TIMEOUT_SECS`, default 5s).
On timeout it raises `TimeoutError`, which the existing handler degrades to the
pure-Python regex detector — so detection always returns instead of deadlocking.
The native call releases the GIL while parked, so the watchdog thread runs. Other
platforms keep the direct call with no per-call thread overhead.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jun 29, 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 the status: ready for review Pull request body is complete and the author marked it ready for human review label Jun 29, 2026

@JerrettDavis JerrettDavis left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The Windows watchdog is the right mitigation for the immediate deadlock, but it needs one more operational guard before I’d be comfortable merging it. If the native detector hangs once, subsequent calls will still try the same native path, wait the full watchdog budget, and leave another daemon thread blocked in the native call. Under proxy traffic that turns the fix into repeated 5s latency plus unbounded stuck-thread growth. Please add a process-level circuit breaker after the first watchdog timeout (for example mark native detection unhealthy and route future detections directly to the Python fallback), and cover that with a test that two Windows detections after a simulated hang only create/enter the native detector once.

@Parideboy Parideboy marked this pull request as draft June 29, 2026 21:41
@github-actions github-actions Bot removed the status: ready for review Pull request body is complete and the author marked it ready for human review label Jun 29, 2026
…eout (headroomlabs-ai#575)

The Windows watchdog frees the caller but not the native path: if the
native detector hangs once, every later call still enters it, waits the
full watchdog budget (5s each), and strands another daemon thread in the
wedged native call. Under proxy traffic that is repeated latency plus
unbounded stuck-thread growth.

Add a process-level circuit breaker: the first watchdog TimeoutError marks
native detection unhealthy, and all later detections route straight to the
pure-Python fallback without re-entering native. Only TimeoutError trips it
(the only thing the watchdog raises); panics/bad tags keep their existing
transient degrade since they are fast failures, not stuck threads.

Test: two Windows detections after a simulated hang enter the native
detector exactly once. Added an autouse fixture resetting the module-level
detect flags so the process-wide breaker does not leak across tests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Parideboy Parideboy requested a review from JerrettDavis June 30, 2026 10:06
@Parideboy Parideboy marked this pull request as ready for review June 30, 2026 10:06
@github-actions github-actions Bot added the status: ready for review Pull request body is complete and the author marked it ready for human review label Jun 30, 2026

@JerrettDavis JerrettDavis left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed the latest circuit-breaker update. This addresses the blocker I raised.

The watchdog is now Windows-scoped, the first timeout disables the native detector process-wide, and subsequent calls go straight to the pure-Python detector instead of spending the full timeout and leaving another stuck daemon thread behind. The tests cover env parsing, fast native success, native exception propagation, timeout degrade, and the circuit breaker skip path.

I attempted a local targeted run of python -m pytest tests/test_transforms_content_router.py -q, but this review worktree cannot import headroom._core locally. The full GitHub CI matrix is green for this PR.

@JerrettDavis JerrettDavis merged commit 95abca3 into headroomlabs-ai:main Jul 2, 2026
30 checks passed
@github-actions github-actions Bot mentioned this pull request Jul 2, 2026
chopratejas pushed a commit that referenced this pull request Jul 3, 2026
🤖 I have created a release *beep* *boop*
---


<details><summary>0.29.0</summary>

##
[0.29.0](v0.28.0...v0.29.0)
(2026-07-03)


### Features

* **proxy:** add --lossless no-CCR mode with format-native compaction
([#1721](#1721))
([c75ebde](c75ebde))
* **stats:** surface Codex WS compression counters in /stats summary
([#1680](#1680))
([2fe19c3](2fe19c3))
* **transforms:** adaptive Otsu KEEP/DROP threshold (+ land relevance
split on main)
([#1726](#1726))
([eea667a](eea667a))


### Bug Fixes

* **bedrock:** fail fast when session-token auth lacks botocore
([#1553](#1553))
([54cfa36](54cfa36))
* **bedrock:** route ARNs via converse, named AWS profiles, and au. re…
([#1456](#1456))
([7d87aa2](7d87aa2))
* **ccr:** honor workspace dir for sqlite store
([#1564](#1564))
([96e1dfe](96e1dfe))
* **claude:** surface Remote Control proxy incompatibility
([#1610](#1610))
([4bf7f92](4bf7f92))
* **cli:** stop advertising unwired compression tuning env vars in
banner
([#1634](#1634))
([d5bf98d](d5bf98d))
* **codex:** avoid duplicate headroom provider config
([#1431](#1431))
([ddd4adf](ddd4adf))
* **compression:** reject lossy unmarked tool output in unit router path
([#1479](#1479))
([de24cd5](de24cd5))
* **cortex-code:** migrate to current Cortex REST API endpoints + add
e2e benchmarks
([#1474](#1474))
([f00ace6](f00ace6))
* **dashboard:** align token savings headline denominator
([#1653](#1653))
([646e705](646e705))
* **dashboard:** derive per-project setup URL from live origin
([#1511](#1511))
([e035aef](e035aef))
* **detection:** contain unidiff panic on orphaned +++ target line
([#1548](#1548))
([e386c09](e386c09))
* **evals:** CJK-aware F1 tokenization + token estimation
([#1527](#1527))
([99a8540](99a8540))
* **install:** close parent log fd in start_detached_agent
([#1576](#1576))
([816cb85](816cb85))
* **install:** use Windows-safe PID liveness probe in runtime_status
([#1544](#1544))
([#1560](#1560))
([6b227b9](6b227b9))
* **learn:** aggregate verbosity baselines across projects instead of
overwriting
([#1288](#1288))
([27a5468](27a5468))
* **mcp:** show lifetime totals and label rolling session scope in
headroom_stats
([#1428](#1428))
([1c0e152](1c0e152))
* **memory:** cap local embedder CPU thread oversubscription
([#198](#198))
([#1559](#1559))
([b84afbf](b84afbf))
* **memory:** singleflight LocalBackend init to stop cold-start races
([#1691](#1691))
([bec47a1](bec47a1))
* **openclaw:** detect uv-installed headroom binary in ~/.local/bin
([#1459](#1459))
([adaeb88](adaeb88))
* **opencode:** preserve custom OpenAI gateway paths
([#1596](#1596))
([c19347c](c19347c))
* **opencode:** route native providers + load transport plugin, fix
Serena context
([#1573](#1573))
([ad0034f](ad0034f))
* preserve anthropic passthrough tool order
([#1427](#1427))
([a932247](a932247))
* **proxy/auth:** match real Anthropic OAuth token prefix (sk-ant-oat)
([#1672](#1672))
([8cddf9b](8cddf9b))
* **proxy:** expose persistent savings metrics
([#1647](#1647))
([5fe4e7b](5fe4e7b))
* **proxy:** fail open when kompress saturation would exhaust
pre-upstream budget
([#1430](#1430))
([15ac650](15ac650))
* **proxy:** handle streaming CCR retrieval
([#1451](#1451))
([d337e3b](d337e3b))
* **proxy:** include system/tools/sampling in cache key
([#1473](#1473))
([312129a](312129a))
* **proxy:** preserve Responses passthrough bytes
([#1598](#1598))
([2a34a82](2a34a82))
* **proxy:** strip Codex lite header on the HTTP /responses path
([#1663](#1663))
([9fbd47b](9fbd47b))
* **proxy:** wire --compression-max-workers /
HEADROOM_COMPRESSION_MAX_WORKERS
([#1632](#1632))
([814ffa3](814ffa3))
* **savings:** count cache-read tokens in input cost estimate
([#1429](#1429))
([72ade37](72ade37))
* skip Magika backend on x86 CPUs without AVX2
([#1162](#1162))
([64783d8](64783d8))
* **transforms/content-router:** route grep/log output away from HTML
extractor
([#1719](#1719))
([0d18ef2](0d18ef2))
* **transforms:** bound native content detection with a Windows watchdog
([#575](#575))
([#1563](#1563))
([95abca3](95abca3))
* Vertex AI support for Claude Code with ANTHROPIC_VERTEX_BASE_URL
([#1393](#1393))
([cff7247](cff7247))
* **wrap:** detach the shared proxy on Windows so it survives an
ungraceful agent close
([#1464](#1464))
([6cba441](6cba441))
* **wrap:** preserve custom Vertex base URL
([#1477](#1477))
([75427bb](75427bb))
* **wrap:** remove rtk instructions from Codex AGENTS.md on unwrap
([#1604](#1604))
([c9d717c](c9d717c))
</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>
JerrettDavis pushed a commit to peterlodri-sec/headroom that referenced this pull request Jul 14, 2026
…og (headroomlabs-ai#575) (headroomlabs-ai#1563)

## Description

On Windows, the first call into the native
`headroom._core.detect_content_type` can park forever in an ort/`Once`
initialization (`WaitOnAddress`) at 0% CPU. A wedged native call cannot
be cancelled from Python, so it deadlocks the caller. In the proxy it is
worse: each affected request permanently consumes a compression-executor
worker, eventually saturating the pool (`running == max_workers`,
`leaked_threads_total == 0` because the worker never finishes) and
stalling every subsequent request for the full
`COMPRESSION_TIMEOUT_SECONDS` before passthrough.

The Rust backend is already off by default on Windows —
`_resolve_detect_backend()` returns `"python"` there — but an explicit
`HEADROOM_DETECT_BACKEND=rust`, or any future regression of that
default, re-exposes the hang with no escape hatch. This implements the
issue's third ask: a timeout/watchdog so a hung native init degrades
gracefully instead of deadlocking the agent / MCP server / proxy.

Closes headroomlabs-ai#575

## 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

- Added a Windows-only watchdog around the native detect call in
`transforms/content_router.py`. `_rust_detect_watchdogged()` runs
`detect_content_type` on a daemon thread and bounds the caller's wait;
on timeout it raises `TimeoutError`, which the existing `except
BaseException` handler degrades to the pure-Python regex detector.
Detection therefore always returns instead of deadlocking (and, in the
proxy, instead of permanently consuming a compression-executor worker).
- Added `_detect_timeout_secs()` reading `HEADROOM_DETECT_TIMEOUT_SECS`
(default 5s; blank / non-numeric / non-positive values fall back to the
default).
- Gated the watchdog to `sys.platform == "win32"` — the only platform
where the hang is observed. Other platforms keep the direct native call
with no per-call thread overhead (the trusted hot path is unchanged).
- Added regression tests for the watchdog, env parsing, error relay, the
Windows degrade-on-hang path, and the Windows happy path.

## Testing

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

### Test Output

```text
$ ruff check headroom/transforms/content_router.py tests/test_transforms_content_router.py
All checks passed!

$ ruff format --check headroom/transforms/content_router.py tests/test_transforms_content_router.py
2 files already formatted

$ mypy headroom --ignore-missing-imports
(exit 0)

$ pytest tests/test_transforms_content_router.py -q
33 passed
```

## Real Behavior Proof

- Environment: Windows 11, Python 3.13, ruff 0.15.17 / mypy 1.20.2 /
pytest 9.1.0, `headroom._core` built locally, branch
`fix/575-native-detect-watchdog`.
- Exact command / steps: ran the four checks above.
`test_detect_content_watchdog_degrades_on_windows_hang` forces
`HEADROOM_DETECT_BACKEND=rust`, patches `sys.platform` to `"win32"`,
sets `HEADROOM_DETECT_TIMEOUT_SECS=0.1`, and injects a native
`detect_content_type` that blocks on an `Event` (simulating the
`WaitOnAddress` park, GIL released) — then asserts detection still
returns. The companion tests cover env parsing, error relay through the
watchdog, and the fast-native Windows path.
- Observed result: with a hung native detector,
`_detect_content('[{"id": 1}]')` returns `ContentType.JSON_ARRAY` (the
pure-Python degrade path) within the 0.1s budget instead of hanging;
with a fast native detector on Windows it returns the native result
unchanged; non-Windows behavior (direct call) is untouched and the
existing rust-delegation test still passes. All 33 tests in the file
pass; ruff / format / mypy clean.
- Not tested: the live `from headroom._core import detect_content_type;
detect_content_type("hello world")` deadlock on an affected Windows 11
24H2 machine was not reproduced end to end (it requires the specific
System32 ONNX Runtime build). The fix is instead covered by the
deterministic hung-detector injection test, which exercises the exact
degrade path the watchdog adds. This PR does not attempt the Rust-side
fix for the underlying first-call init deadlock (asks headroomlabs-ai#1) — it is the
Python-side watchdog (ask headroomlabs-ai#3); the existing `HEADROOM_DETECT_BACKEND`
flag already covers ask headroomlabs-ai#2.

## 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
- [ ] 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

- The watchdog cannot cancel a wedged native call (no portable way to
kill a thread blocked in C). It frees the *caller* and leaves the stuck
daemon thread to die with the process; this is marked with a `ponytail:`
comment naming the upgrade path (the Rust-side non-blocking first-call
init). For the saturation scenario this is still a strict improvement:
callers no longer block indefinitely, so the executor drains instead of
wedging permanently.

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
JerrettDavis pushed a commit to peterlodri-sec/headroom that referenced this pull request Jul 14, 2026
🤖 I have created a release *beep* *boop*
---


<details><summary>0.29.0</summary>

##
[0.29.0](headroomlabs-ai/headroom@v0.28.0...v0.29.0)
(2026-07-03)


### Features

* **proxy:** add --lossless no-CCR mode with format-native compaction
([headroomlabs-ai#1721](headroomlabs-ai#1721))
([c75ebde](headroomlabs-ai@c75ebde))
* **stats:** surface Codex WS compression counters in /stats summary
([headroomlabs-ai#1680](headroomlabs-ai#1680))
([2fe19c3](headroomlabs-ai@2fe19c3))
* **transforms:** adaptive Otsu KEEP/DROP threshold (+ land relevance
split on main)
([headroomlabs-ai#1726](headroomlabs-ai#1726))
([eea667a](headroomlabs-ai@eea667a))


### Bug Fixes

* **bedrock:** fail fast when session-token auth lacks botocore
([headroomlabs-ai#1553](headroomlabs-ai#1553))
([54cfa36](headroomlabs-ai@54cfa36))
* **bedrock:** route ARNs via converse, named AWS profiles, and au. re…
([headroomlabs-ai#1456](headroomlabs-ai#1456))
([7d87aa2](headroomlabs-ai@7d87aa2))
* **ccr:** honor workspace dir for sqlite store
([headroomlabs-ai#1564](headroomlabs-ai#1564))
([96e1dfe](headroomlabs-ai@96e1dfe))
* **claude:** surface Remote Control proxy incompatibility
([headroomlabs-ai#1610](headroomlabs-ai#1610))
([4bf7f92](headroomlabs-ai@4bf7f92))
* **cli:** stop advertising unwired compression tuning env vars in
banner
([headroomlabs-ai#1634](headroomlabs-ai#1634))
([d5bf98d](headroomlabs-ai@d5bf98d))
* **codex:** avoid duplicate headroom provider config
([headroomlabs-ai#1431](headroomlabs-ai#1431))
([ddd4adf](headroomlabs-ai@ddd4adf))
* **compression:** reject lossy unmarked tool output in unit router path
([headroomlabs-ai#1479](headroomlabs-ai#1479))
([de24cd5](headroomlabs-ai@de24cd5))
* **cortex-code:** migrate to current Cortex REST API endpoints + add
e2e benchmarks
([headroomlabs-ai#1474](headroomlabs-ai#1474))
([f00ace6](headroomlabs-ai@f00ace6))
* **dashboard:** align token savings headline denominator
([headroomlabs-ai#1653](headroomlabs-ai#1653))
([646e705](headroomlabs-ai@646e705))
* **dashboard:** derive per-project setup URL from live origin
([headroomlabs-ai#1511](headroomlabs-ai#1511))
([e035aef](headroomlabs-ai@e035aef))
* **detection:** contain unidiff panic on orphaned +++ target line
([headroomlabs-ai#1548](headroomlabs-ai#1548))
([e386c09](headroomlabs-ai@e386c09))
* **evals:** CJK-aware F1 tokenization + token estimation
([headroomlabs-ai#1527](headroomlabs-ai#1527))
([99a8540](headroomlabs-ai@99a8540))
* **install:** close parent log fd in start_detached_agent
([headroomlabs-ai#1576](headroomlabs-ai#1576))
([816cb85](headroomlabs-ai@816cb85))
* **install:** use Windows-safe PID liveness probe in runtime_status
([headroomlabs-ai#1544](headroomlabs-ai#1544))
([headroomlabs-ai#1560](headroomlabs-ai#1560))
([6b227b9](headroomlabs-ai@6b227b9))
* **learn:** aggregate verbosity baselines across projects instead of
overwriting
([headroomlabs-ai#1288](headroomlabs-ai#1288))
([27a5468](headroomlabs-ai@27a5468))
* **mcp:** show lifetime totals and label rolling session scope in
headroom_stats
([headroomlabs-ai#1428](headroomlabs-ai#1428))
([1c0e152](headroomlabs-ai@1c0e152))
* **memory:** cap local embedder CPU thread oversubscription
([headroomlabs-ai#198](headroomlabs-ai#198))
([headroomlabs-ai#1559](headroomlabs-ai#1559))
([b84afbf](headroomlabs-ai@b84afbf))
* **memory:** singleflight LocalBackend init to stop cold-start races
([headroomlabs-ai#1691](headroomlabs-ai#1691))
([bec47a1](headroomlabs-ai@bec47a1))
* **openclaw:** detect uv-installed headroom binary in ~/.local/bin
([headroomlabs-ai#1459](headroomlabs-ai#1459))
([adaeb88](headroomlabs-ai@adaeb88))
* **opencode:** preserve custom OpenAI gateway paths
([headroomlabs-ai#1596](headroomlabs-ai#1596))
([c19347c](headroomlabs-ai@c19347c))
* **opencode:** route native providers + load transport plugin, fix
Serena context
([headroomlabs-ai#1573](headroomlabs-ai#1573))
([ad0034f](headroomlabs-ai@ad0034f))
* preserve anthropic passthrough tool order
([headroomlabs-ai#1427](headroomlabs-ai#1427))
([a932247](headroomlabs-ai@a932247))
* **proxy/auth:** match real Anthropic OAuth token prefix (sk-ant-oat)
([headroomlabs-ai#1672](headroomlabs-ai#1672))
([8cddf9b](headroomlabs-ai@8cddf9b))
* **proxy:** expose persistent savings metrics
([headroomlabs-ai#1647](headroomlabs-ai#1647))
([5fe4e7b](headroomlabs-ai@5fe4e7b))
* **proxy:** fail open when kompress saturation would exhaust
pre-upstream budget
([headroomlabs-ai#1430](headroomlabs-ai#1430))
([15ac650](headroomlabs-ai@15ac650))
* **proxy:** handle streaming CCR retrieval
([headroomlabs-ai#1451](headroomlabs-ai#1451))
([d337e3b](headroomlabs-ai@d337e3b))
* **proxy:** include system/tools/sampling in cache key
([headroomlabs-ai#1473](headroomlabs-ai#1473))
([312129a](headroomlabs-ai@312129a))
* **proxy:** preserve Responses passthrough bytes
([headroomlabs-ai#1598](headroomlabs-ai#1598))
([2a34a82](headroomlabs-ai@2a34a82))
* **proxy:** strip Codex lite header on the HTTP /responses path
([headroomlabs-ai#1663](headroomlabs-ai#1663))
([9fbd47b](headroomlabs-ai@9fbd47b))
* **proxy:** wire --compression-max-workers /
HEADROOM_COMPRESSION_MAX_WORKERS
([headroomlabs-ai#1632](headroomlabs-ai#1632))
([814ffa3](headroomlabs-ai@814ffa3))
* **savings:** count cache-read tokens in input cost estimate
([headroomlabs-ai#1429](headroomlabs-ai#1429))
([72ade37](headroomlabs-ai@72ade37))
* skip Magika backend on x86 CPUs without AVX2
([headroomlabs-ai#1162](headroomlabs-ai#1162))
([64783d8](headroomlabs-ai@64783d8))
* **transforms/content-router:** route grep/log output away from HTML
extractor
([headroomlabs-ai#1719](headroomlabs-ai#1719))
([0d18ef2](headroomlabs-ai@0d18ef2))
* **transforms:** bound native content detection with a Windows watchdog
([headroomlabs-ai#575](headroomlabs-ai#575))
([headroomlabs-ai#1563](headroomlabs-ai#1563))
([95abca3](headroomlabs-ai@95abca3))
* Vertex AI support for Claude Code with ANTHROPIC_VERTEX_BASE_URL
([headroomlabs-ai#1393](headroomlabs-ai#1393))
([cff7247](headroomlabs-ai@cff7247))
* **wrap:** detach the shared proxy on Windows so it survives an
ungraceful agent close
([headroomlabs-ai#1464](headroomlabs-ai#1464))
([6cba441](headroomlabs-ai@6cba441))
* **wrap:** preserve custom Vertex base URL
([headroomlabs-ai#1477](headroomlabs-ai#1477))
([75427bb](headroomlabs-ai@75427bb))
* **wrap:** remove rtk instructions from Codex AGENTS.md on unwrap
([headroomlabs-ai#1604](headroomlabs-ai#1604))
([c9d717c](headroomlabs-ai@c9d717c))
</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>
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

2 participants