Commit graph

826 commits

Author SHA1 Message Date
JerrettDavis
f7e3450381 docs: add codecov badge
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-22 22:05:17 -05:00
JerrettDavis
77af5aa996 docs: restore readme formatting
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-22 22:01:41 -05:00
JerrettDavis
b4a1d4b1ee docs: add codecov badge
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-22 22:00:31 -05:00
JerrettDavis
7831620eca test: expand provider slice coverage
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-22 21:58:03 -05:00
Tejas Chopra
1fd8760a89
Merge pull request #227 from JerrettDavis/feat/canonical-pipeline
feat(pipeline): Introduce canonical pipeline lifecycle contract
2026-04-22 17:12:52 -07:00
JerrettDavis
ba4505074e fix: fall back from stale persistent wrap manifests
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-22 19:00:39 -05:00
JerrettDavis
88dc15ea85 Merge upstream/main into feat/canonical-pipeline
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-22 18:47:41 -05:00
Tejas Chopra
4c9c29c421
Merge pull request #233 from Kayzo/fix/dashboard-stats-snapshot-cache
fix: cache dashboard stats snapshots
2026-04-22 12:33:19 -07:00
Kayzo
af9af3d2b5 chore(merge): resolve upstream main conflicts 2026-04-22 19:22:40 +00:00
Tejas Chopra
e71ebd5dfb
Merge pull request #230 from JerrettDavis/fix/copilot-oauth-runtime
fix: support live copilot oauth runtime
2026-04-22 11:47:37 -07:00
Tejas Chopra
40f11d8dff
Merge pull request #232 from gglucass/fix/learn-preserve-prior-recommendations
fix(learn): preserve prior recommendations across runs
2026-04-22 11:47:20 -07:00
Tejas Chopra
f5e8beadb2
Merge pull request #236 from gglucass/fix/streaming-anthropic-logger
fix(proxy): log streaming Anthropic requests so /transformations/feed populates
2026-04-22 11:38:08 -07:00
Garm
aad799d76e test(learn): cover _parse_prior_recommendations edge cases
Closes the codecov gap flagged on PR 232 (88.89% → near 100% on the patch):

- A file with no marker block returns no prior recommendations.
- A marker block with nothing between the markers yields an empty list
  (the re.split fast-path with zero sections).
- A stray `### ` with no heading text inside the block is silently
  skipped (the `if not heading: continue` branch, previously
  unexercised in tests) — a real section after it still parses cleanly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 20:13:49 +02:00
JerrettDavis
87a13ef2cd Merge upstream/main into feat/canonical-pipeline
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-22 13:10:53 -05:00
Garm
934345d81b Merge remote-tracking branch 'upstream/main' into fix/streaming-anthropic-logger 2026-04-22 19:51:59 +02:00
Garm
aa5e5ae817 Merge remote-tracking branch 'upstream/main' into fix/learn-preserve-prior-recommendations 2026-04-22 19:51:58 +02:00
JerrettDavis
3f30474fb7 Merge upstream/main into fix/copilot-oauth-runtime
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-22 12:43:51 -05:00
Tejas Chopra
706c5e948d
Merge pull request #235 from gglucass/fix/cli-submodule-binding
fix: unblock CI on main (cli submodule binding + test sys.modules hygiene)
2026-04-22 10:27:28 -07:00
Garm
9bde245c43 fix(proxy): log streaming Anthropic requests so feed populates
`_finalize_stream_response` recorded metrics, cost, and prefix-cache stats
but never appended a `RequestLog` to the request logger. Because the
streaming Anthropic path is what Claude Code uses, this meant
`/stats.recent_requests` and `/transformations/feed` were permanently
empty for typical traffic — even when the proxy was started with
`--log-messages`. Only the non-streaming Anthropic path
(`anthropic.py:1167, 1599`) and the Bedrock streaming finalizer
(`streaming.py:_stream_response_bedrock`) were logged.

Wire the same `RequestLog` shape the other paths build, plumbing `tags`
through both `_finalize_stream_response` call sites in `_stream_response`
and respecting `config.log_full_messages` for `request_messages`.

Adds `tests/test_proxy_streaming_request_logger.py` covering the happy
path, both `log_full_messages` branches, the zero-original-tokens edge,
and the logger-disabled no-op.
2026-04-22 14:16:35 +02:00
Kayzo
3045b36b52 fix: stabilize cli test isolation 2026-04-22 11:28:30 +00:00
Kayzo
d17aea2fe2 Merge remote-tracking branch 'upstream/main' into fix/dashboard-stats-snapshot-cache 2026-04-22 10:46:37 +00:00
Garm
1788d907f0 fix(tests): scope sys.modules mutation and unpin hardcoded version
Three independent pre-existing test-hygiene regressions on main, all
surfaced as cascading CI failures:

1. tests/test_cli/test_wrap_copilot.py (from #229) mutated
   sys.modules["headroom.cli.main"] with a fake click.Group() at
   module-import time and never restored it. Any later test that did
   `from headroom.cli.main import main` got an empty group with no
   version option and no registered subcommands, breaking ~20
   test_cli/* and test_cli_proxy_env.py tests. Rewrite to import the
   real `main` directly — the fake-group indirection served no
   purpose.

2. tests/test_proxy_copilot_auth_hooks.py (from #229) installed fake
   httpx / fastapi.responses / headroom.proxy.* modules into
   sys.modules inside a helper called from test functions, never
   cleaned up. Later tests that imported ASGITransport or JSONResponse
   hit the fakes and failed with ImportError. Switch the helper to
   monkeypatch.setitem so the fakes are scoped to the owning test.

3. tests/test_release_version.py hardcoded canonical=0.5.25 in the
   subprocess-output assertion; the project version in pyproject.toml
   has since bumped to 0.9.1. Compute the expected value dynamically
   via get_canonical_version(ROOT) so the test tracks pyproject.
2026-04-22 12:37:22 +02:00
Garm
796afd085b chore: apply ruff format to tests/test_release_workflows.py
Drive-by: main is currently failing `ruff format --check .` because of
two missing blank lines between two top-level functions in this file
(introduced in 8bf11d2). Fixing it here so this PR's CI can go green —
no other way to unblock the format check without landing a separate PR
first.
2026-04-22 12:06:45 +02:00
Kayzo
bb5b676dd7 fix: satisfy dashboard stats cache typing 2026-04-22 10:04:15 +00:00
Garm
3680707e60 fix(cli): eagerly bind subcommand submodules to headroom.cli
Tests that do `patch("headroom.cli.<sub>.<attr>")` resolve the target by
walking attributes on the `headroom.cli` package object. That lookup
fails when `tests/test_cli/test_wrap_copilot.py` pops `headroom.cli`
from `sys.modules` at import time and re-imports it with a fake
`headroom.cli.main` — the re-imported package only has `.wrap` bound
because `_register_commands()` in `main.py` never runs against the fake.

Eagerly importing the subcommand submodules from `__init__.py` binds
them as package attributes regardless of how `main.py` is loaded, so
the patch lookup survives that kind of sys.modules mutation.

Fixes #234
2026-04-22 11:56:59 +02:00
Kayzo
2b1ab269ca fix: cache dashboard stats snapshots 2026-04-22 09:30:19 +00:00
Garm
72ae0a9e03 chore: apply ruff format + add CHANGELOG entry 2026-04-22 11:28:11 +02:00
Garm
0123e49939 fix(learn): preserve prior recommendations across runs (#231)
`headroom learn` built the marker block from only the current run's
recommendations and wholesale-replaced any prior block via
`_MARKER_PATTERN.sub`. Sections learned weeks earlier that didn't
re-surface in a later run were silently dropped.

Fix: in `_merge_into_file`, parse recommendations out of the prior
block and union them with the new run's recommendations. Sections
re-surfaced by the new run take precedence (latest analysis wins);
sections not re-surfaced are carried forward so learnings accumulate
instead of getting clobbered.

To fully rebuild the block, delete it manually and re-run.

Tests: existing wholesale-replace test rewritten as a carry-forward
assertion. Added tests for same-section override, MEMORY.md
carry-forward, and round-trip of sections without a tokens annotation.

Closes #231
2026-04-22 10:22:36 +02:00
JerrettDavis
dcb3e8bdcb test: cover copilot auth branches
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-22 00:23:28 -05:00
JerrettDavis
71f38cbcba test: isolate copilot auth hook stubs
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-22 00:09:01 -05:00
JerrettDavis
7cfc891317 ci: scope codecov patch coverage
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-22 00:05:47 -05:00
JerrettDavis
42a8cefdf1 fix: normalize release workflow test formatting
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-21 23:55:01 -05:00
JerrettDavis
470bb6cfb9 fix: resolve rebased ci regressions
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-21 23:54:28 -05:00
JerrettDavis
1b377d8c43 test: add focused pipeline coverage
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-21 23:54:28 -05:00
JerrettDavis
93a1f2113f refactor: move install init logic into provider slices
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-21 23:54:28 -05:00
JerrettDavis
ce8a2f3cf8 test: expand provider pipeline coverage
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-21 23:54:28 -05:00
JerrettDavis
364a07228f fix: preserve lazy proxy backend imports
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-21 23:54:28 -05:00
JerrettDavis
846fca21b0 chore: normalize compress line endings
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-21 23:54:28 -05:00
JerrettDavis
8e72270432 fix: restore pipeline compatibility regressions
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-21 23:54:28 -05:00
JerrettDavis
7c86fa6b22 fix: avoid proxy registry import cycle
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-21 23:54:28 -05:00
JerrettDavis
49a8f80e9b chore: normalize proxy compatibility line endings
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-21 23:54:28 -05:00
JerrettDavis
7d74730606 fix: restore proxy compatibility surface
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-21 23:54:28 -05:00
JerrettDavis
5413e7af47 chore: normalize provider slice line endings
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-21 23:54:28 -05:00
JerrettDavis
b17c6d81cc refactor: extract provider logic into slices
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-21 23:54:28 -05:00
JerrettDavis
cd9c2e1d01 feat: introduce canonical pipeline lifecycle contract
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-21 23:54:28 -05:00
JerrettDavis
64fe9763f5 test: skip rtk in BYOK copilot assertion
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-21 23:53:30 -05:00
JerrettDavis
1d440023b6 Merge upstream/main into fix/copilot-oauth-runtime
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-21 23:44:58 -05:00
JerrettDavis
94cf57ac4d test: sync release workflow assertions
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-21 23:38:01 -05:00
JerrettDavis
0a8a6dca1e test: derive canonical release version
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-21 23:32:10 -05:00
Tejas Chopra
5738339524
Merge pull request #219 from JerrettDavis/fix/python-github-packages-publish
ci: publish Python distributions to GitHub releases
2026-04-21 21:30:16 -07:00