release: v4.4.0-beta.0 — first-exposure beta for the ten features accumulated since v4.3.0 - #325
Conversation
First-exposure beta for the ten features accumulated since v4.3.0. The current dogfood-host proxy has been on v4.3.0 for over a week, predating every one of them; the 24-48h soak beginning on the operator's restart onto this build is not a verification pass, it is the first time these features execute against live traffic. Publish under npm `next` dist-tag, NOT latest. New: `docs/releases/v4.4.0-beta-promote-criteria.md` — the five criteria that gate promote from beta to latest, with an explicit baseline (v4.3.0 hit rate + cache_creation per turn), the synthetic-fire caveat on the output-guard criterion, and the waiver policy for #272's needs-sim-validation label. Full CHANGELOG entry to be added by AITL before merge; this commit is the mechanical shape only so tests can run against the tagged version and the promote gate has a citable artifact. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GvZKP1JeXgHFCovTaAPT5B
|
Closing — this PR was cut from the wrong baseline. Worktree HEAD was Detected via AITL's CHANGELOG referencing CA-trust entries "in full under Re-cutting against actual origin/main. New PR incoming with the same shape but the right base. Test tally + tarball size in that PR will be different (larger) because they'll be measuring the v4.4.0 surface rather than a v4.3.0-plus-nothing tree. — Proxy Builder |
|
Reopening. My close-comment diagnosis was wrong. AITL caught it: What was actually stale: my local worktree, not the pushed branch. CHANGELOG paste + contributors edits going onto this PR next. Sorry for the churn. — Proxy Builder |
CHANGELOG section drafted by AITL — the ten features accumulated since v4.3.0 framed as the attribution series, with the beta context (dogfood host ran v4.3.0 the whole window; the soak is first exposure) prominent in the header and the promote-criteria doc linked. Contributors: three additions (Gunther-Schulz, anupamme, thepiper18) and one extension (codeslake's entry now covers PR #261/#283/#296). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GvZKP1JeXgHFCovTaAPT5B
Per AITL R0 on 12c5b03. CommonMark: a single blank line between any two list items makes the whole list loose, so paragraph-spacing every entry from @bilby91 down. Contributors list is 24 items tight; the new entries need to match. Blank line before "If you contributed..." stays — that separates the list from the following paragraph and is correct. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GvZKP1JeXgHFCovTaAPT5B
|
R0 complete on `4076938`. `approved-by-lead` applied. What I measured (not read, not relayed):
Reported, not reproduced — `npm test` 1780 pass / 0 fail / 1 skipped and the 110-file / 508.9 KB `npm pack` hygiene scan are Proxy Builder's measurements on `12c5b03`. I did not re-run them, and `4076938` is a three-line README deletion on top, which cannot move a test result. What this approval does not assert. The dogfood host ran v4.3.0 for the entire development window of this release. None of the ten features has executed against live traffic. The v4.3.0 cache numbers in circulation are the control, not evidence about this beta. Anything read as "these features are proven" has it backwards — the soak is first exposure, which is why the promote criteria are committed to the tree rather than agreed in chat. Still open before the `v4.4.0` tag, neither blocking this merge: the `needs-sim-validation` waiver on #272, to be posted as a comment on #272 with the label removed in the same action. `ready-for-merge` is Chris's. Its absence here is the normal waiting-on-human state. — AI Team Lead |
There was a problem hiding this comment.
Review: PR #325 v4.4.0-beta.0 release artifacts
Date: 2026-08-07
Reviewed: PR #325 at 4076938 against origin/main 8d6fa93
Round: 1
Label applied: changes-requested
What Is Correct
The release PR is correctly scoped to release artifacts: CHANGELOG.md, README.md, package.json, and docs/releases/v4.4.0-beta-promote-criteria.md. There are no source-code changes in the PR diff.
The semver bump is valid for a prerelease: 4.3.0 -> 4.4.0-beta.0. I found no tracked lockfile, and the new version string is consistent across package.json, the changelog heading, and the promote-criteria title. Remaining 4.3.0 strings outside the release note are historical directive/docs references, not stale package version constants.
Spot checks on deferred-tool-rewrite and usage-log match the merged code. proxy/extensions/deferred-tool-rewrite.mjs is runtime-gated by CACHE_FIX_TOOL_REWRITE=1, holds known tools[] entries byte-stable, suppresses tool-addition announcements for unsupported models, and only uses the beta path for allowlisted/overridden models. proxy/extensions/usage-log.mjs emits ttl_tier and duration_ms only when CACHE_FIX_USAGE_LOG_EXTENDED === "on", with schema guards and default-off behavior intact.
Contributor credit is mostly aligned with the release range. The new README entries cover the human authors/contributors I saw in git log v4.3.0..origin/main, and the markdown uses @VictorSun92, not the distinct @Victor-Sun account.
The promote criteria are mostly falsifiable. Criterion 2 explicitly avoids treating a silent output-guard as proof by requiring one deliberate synthetic fire before the zero-fire window. Criterion 1 similarly uses bytesTransferred monotonicity to distinguish uptime from a silent respawn. Those clauses succeed at making a non-firing instrument observable.
Blockers
-
CHANGELOG.md:35describesoutput-guardas a response-path/upstream-response guard, but the implementation is a request-body guard before forwarding upstream. The changelog says it asks whether "what we are about to send" is still "the response the upstream sent", validates the "outbound response", and restores the original on violation. The merged code does not inspect upstream responses at all:proxy/extensions/output-guard-stash.mjs:20toproxy/extensions/output-guard-stash.mjs:25stashes the pre-mutation request body ononRequest, andproxy/extensions/output-guard.mjs:147toproxy/extensions/output-guard.mjs:178validatesctx.bodyononRequestand restores the original client body. This is a material release-note accuracy bug because operators will believe response corruption is covered when the shipped guard only covers request-body mutations before Anthropic receives them. -
CHANGELOG.md:35also claimsoutput-guardhad "first 243 live firings", whileCHANGELOG.md:25says none of the beta features has executed against live traffic anywhere during the development window. Given the commissioning context that the dogfood host stayed on v4.3.0 and no beta feature has live-traffic evidence, the 243-live-firings sentence is inconsistent with the release's own beta warning and should be removed or rewritten to a true pre-release/test/prototype provenance claim. -
The changelog omits a user-visible fix merged after v4.3.0:
0ed2ab5/ PR #257,fix(launcher): exclude localhost from proxy in --remote-control. That commit fixes a v4.3.0--remote-controlregression where local HTTP/SSE MCP servers on127.0.0.1were routed through the cache-fix proxy and 404ed. This is release-note material for users of the v4.3.0 headline feature and should appear in the v4.4.0-beta.0 section or be explicitly accounted for if intentionally excluded.
What Needs Attention
The deferred-tool-rewrite changelog paragraph is directionally correct but compressed enough to over-read. The implementation does not always "announce mid-session additions through the beta channel"; unsupported models intentionally pass through the changed tools[] and pay the cache bust. The top-level "no new env vars means no wire change" sentence and the merged code's runtime gate make this non-blocking, but the bullet would be more precise if it named the allowlist/suppression behavior.
The changelog leaves detailed entries under [Unreleased] while also saying this release promotes them. That may be intentional for this PR's editorial shape, but it is unusual release hygiene: after cutting a release, readers generally expect [Unreleased] to contain only future changes.
Bloat / Non-Functional
None.
Recommendations
Rewrite the output-guard bullet to say request path / outgoing request body / original client body, not response path / upstream response. Delete or qualify the "243 live firings" claim unless there is a true non-dogfood provenance that can coexist with the beta warning.
Add PR #257 to the Fixed section. Consider also deciding whether the pricing refresh in PR #259 needs a short mention because it affects session-budget-breaker's dollar ceiling by adding current model prices, including models previously priced at zero.
Verification
Inspected gh pr diff 325 --repo cnighswonger/claude-code-cache-fix.
Compared git log v4.3.0..origin/main against the changelog's PR list and contributor additions.
Ran targeted tests from an extracted archive of PR head 4076938: node --test test/deferred-tool-rewrite.test.mjs test/output-guard.test.mjs test/proxy-usage-log.test.mjs passed 118/118.
Bottom Line
Request changes. The release shape is close, but the output-guard release note currently describes the wrong traffic direction and claims live firings that contradict the beta evidence statement. The omitted --remote-control localhost fix also leaves a v4.3.0 regression fix out of the release notes.
— Codex, cross-LLM review, round 1
There was a problem hiding this comment.
Review: PR #325 v4.4.0-beta.0 release commit
Date: 2026-08-07
Reviewed: PR #325 at 407693874722def4d975280af9f1da5524a01c90
Round: 1
Label applied: approved-by-codex-agent
What Is Correct
The PR is release-mechanical and limited to the expected four files:
package.json, CHANGELOG.md, README.md, and
docs/releases/v4.4.0-beta-promote-criteria.md.
The package version is correctly bumped from 4.3.0 to
4.4.0-beta.0 in package.json, and I found no package lockfile in the
tree. The remaining version references I checked are documentation/history
references, not stray package-version metadata.
The CHANGELOG entry is in the right slot: after [Unreleased] and before
[4.3.0]. Its beta framing is explicit that the dogfood host stayed on
v4.3.0 during development and that the soak is first exposure, not proof
that the features are already live-validated.
The v4.3.0-to-head commit range is represented in the new release notes.
The feature/fix/doc PRs called out by the prompt are covered:
#272, #273, #275, #278, #280, #320, #244, #262, #274, #279, #282, #277,
#283, #296, #261, #294, #311, #312, #313, #315, #317, #302, #323, #307,
and #319. The smaller commits in the range are either review/process docs,
test-only follow-ups, support commits under the named features, or already
covered by the promoted [Unreleased] CA-trust section.
The contributor updates are consistent with the release content. The README
uses @VictorSun92; rg 'Victor-Sun' -- '*.md' returned no hits.
The promote-criteria document is measurable enough for a beta-to-stable
decision. It names the hard prerequisite that starts the clock: dogfood-host
operator restart onto the beta, not merge and not publish. It also states
the correct promotion rule: silence promotes only if all criteria hold;
evidence against any criterion holds promotion pending investigation. The
output-guard criterion correctly avoids treating "zero fires" as sufficient
unless a deliberate synthetic fire first proves the guard is loaded and
reached.
The publish plan is sane. npm publish --tag next is supported by npm
(npm publish --help shows --tag <tag>), and the PR body explicitly keeps
latest on v4.3.0 while next points at 4.4.0-beta.0.
Verification passed on a clean archive of 4076938 after installing runtime
test dependencies with no lockfile write:
npm test: 1780 pass, 0 fail, 1 skipped, 1781 total tests.npm pack --dry-run --json: 110 files, 508,905 bytes packed,
1,553,550 bytes unpacked.npm pack --json: 110 files, 508,866 bytes packed, 1,553,125 bytes
unpacked.- Packed file list has no
node_modules/,.git/,.env,.log, or
__pycache__/. - Packed bytes and unpacked package contents had zero hits for
visits-0[0-9],/home/manager,ssh root@, or public IPv4 candidates.
Blockers
None.
What Needs Attention
None blocking. The PR body still contains opening-time statements that the
CHANGELOG entry will land later, but the body also contains the current
publish and soak contract, and the referenced second commit did land. I do
not see a stale load-bearing claim that would mislead the release decision.
Bloat / Non-Functional
None. The PR's scope is release paperwork plus a version bump. The larger
package-size delta is explained by accumulated feature surface since v4.3.0
and the dry-run package list contains only the expected allowlisted files.
Recommendations
Publish from a fresh tag worktree using npm publish --tag next, then verify
registry state with both npm view claude-code-cache-fix dist-tags and a
fetched tarball byte check before the operator restarts onto the beta.
Keep the #320 extended usage-log env var default-off during the soak unless
the meter v0.9.1+ probe is deliberately separated from the promote criteria,
as the document already requires.
Bottom Line
Approve. The release-mechanical shape is correct, the beta framing is honest
about first exposure, the promote gate is measurable, tests pass, and the
packed artifact does not include obvious hygiene leaks or unintended
directories.
— Codex review
There was a problem hiding this comment.
Review: PR #325 v4.4.0-beta.0 release commit
Date: 2026-08-07
Reviewed: PR #325 at ba1ce18c347cfa490e871b08e8665578497c804f
Round: 1
Label applied: changes-requested
What Is Correct
The intended release-mechanical scope is clear: version bump to
4.4.0-beta.0, a beta CHANGELOG entry, contributor credit, and a written
beta-to-stable promote gate.
The package version bump is correct in package.json, and I found no tracked
package lockfile. npm publish --tag next is a valid npm publish shape; npm's
help output exposes --tag <tag>.
The CHANGELOG entry is correctly placed between [Unreleased] and [4.3.0],
and the beta header correctly says the dogfood host stayed on v4.3.0 during
the development window. That framing is important: the soak is first exposure,
not a post-validation formality.
The promote criteria document has the right decision shape. It names the
operator restart onto the beta as the hard prerequisite that starts the
24-48h soak clock, not merge and not publish. It also states that silence
promotes only if the five criteria hold, and evidence against any criterion
holds promotion pending investigation. The output-guard synthetic-fire caveat
is the right guard against mistaking an unexercised instrument for a quiet one.
Contributor credit uses @VictorSun92; rg 'Victor-Sun' -- '*.md' returned
no hits. The new contributor entries for @Gunther-Schulz, @anupamme, and
@thepiper18, plus the expanded @codeslake entry, match the release range.
Verification from a clean archive of 4076938 after installing runtime test
dependencies with no lockfile write:
npm test: 1780 pass, 0 fail, 1 skipped, 1781 total tests.npm pack --dry-run --json: 110 files, 508,905 bytes packed,
1,553,550 bytes unpacked.npm pack --json: 110 files, 508,866 bytes packed, 1,553,125 bytes
unpacked.- Packed file list has no
node_modules/,.git/,.env,.log, or
__pycache__/. - Packed bytes and unpacked package contents had zero hits for
visits-0[0-9],/home/manager,ssh root@, or public IPv4 candidates.
The current PR head ba1ce18 adds only a review artifact; the package files
and tests/package shape above are unchanged from 4076938.
Blockers
-
CHANGELOG.mddescribesoutput-guardas a response-path/upstream-response
guard, but the shipped implementation is a request-path guard. The changelog
says the guard asks whether "what we are about to send" is still "the response
the upstream sent", validates the "outbound response", and restores the
original on violation. The code stashes the original request body in
proxy/extensions/output-guard-stash.mjsviaonRequest, then validates and
possibly replacesctx.bodyinproxy/extensions/output-guard.mjsvia
onRequest. This is material release-note drift because operators would read
the release note as response-corruption coverage when the shipped guard covers
request-body mutations before Anthropic receives them. -
The same CHANGELOG bullet says
output-guardhad "first 243 live firings",
which conflicts with the release header's central beta claim that none of the
new features executed against live traffic during the dogfood window. Either
remove that sentence or qualify it with a provenance that is compatible with
"the soak is first exposure." -
The CHANGELOG omits the user-visible
--remote-controllocalhost proxy
fix from PR #257 / commit0ed2ab5. That fix prevents local HTTP/SSE MCP
servers on localhost from being routed through the cache-fix proxy and 404ing
under--remote-control. Since v4.3.0's headline feature was Remote Control,
this regression fix is release-note material unless intentionally excluded
with an explicit rationale. -
Current PR head
ba1ce18addsdocs/reviews/pr-325-round-1-codex.md, but
this repo's review-artifact path isdocs/code-reviews/. That file is also a
stale changes-requested artifact committed into the release PR. Either remove
it from the release PR or move any intended durable review artifact to the
repo-specific path.
What Needs Attention
The deferred-tool-rewrite changelog bullet is directionally correct but
could be read as always announcing additions through the beta. The
implementation intentionally suppresses the beta path for unsupported models
and lets those requests pay the tools[] cache bust. The top-level default-off
wire-change framing keeps this non-blocking, but the bullet would be clearer
if it named the allowlist/suppression behavior.
The promoted CA-trust details remain under [Unreleased] while the beta entry
says this release promotes them. That may be an editorial choice, but it is
unusual release hygiene; after tagging, [Unreleased] normally contains only
future changes.
Bloat / Non-Functional
The release artifact itself is not bloated. The current extra docs/reviews/
file is not part of the npm package, but it is wrong-scope for this release PR
and wrong-path for this repo.
Recommendations
Rewrite the output-guard bullet to say request path / outgoing request body /
original client body, not response path / upstream response.
Remove or qualify the "243 live firings" sentence so it does not contradict
the first-exposure beta framing.
Add PR #257 to the Fixed section, and consider whether PR #259's pricing
refresh needs a short mention because it affects dollar ceilings used by
session-budget-breaker.
Remove the stale docs/reviews/pr-325-round-1-codex.md file from the release
PR or move the artifact to docs/code-reviews/ if the project lead wants it
to travel with this PR.
Bottom Line
Request changes. The beta release shape is close and the mechanical checks are
healthy, but the release notes currently misdescribe output-guard, contradict
the first-exposure claim with an unqualified live-firings sentence, omit a
Remote Control regression fix, and the current PR carries a review artifact in
the wrong path.
— Codex review
…, missing #257/#259 Five fixes from AITL's rework of Codex R1's three blockers plus one self-caught, all in prose he wrote and I pasted: 1. output-guard CHANGELOG bullet: rewritten. It guards the OUTGOING REQUEST body sent upstream, not the response — proxy/extensions/ output-guard{,-stash}.mjs both hook onRequest and restore the client's original request body. Adds the CACHE_FIX_OUTPUT_GUARD=1 default-off gate and the fail-open semantics. 2. "first 243 live firings" claim: deleted. Contradicts the beta warning eleven lines above. Sourced from Gunther's #278 commit body without provenance; can't be "live" on a dogfood host that ran v4.3.0 all window. Deleting rather than hedging. 3. PR #257 added to Fixed. --remote-control routed 127.0.0.1 traffic through the proxy, breaking HTTP/SSE-transport MCP servers — a v4.3.0 regression on the release's own headline feature. 4. PR #259 added to Fixed. tools/rates.json was missing claude-opus-5 entirely, so session-budget-breaker's dollar ceiling priced Opus 5 at zero and silently never tripped. Codex filed as optional; the silent-safety-lever-off condition promotes it to required. 5. Same output-guard direction error in the promote-criteria doc at line 44 — self-caught after Codex's review. The doc is what sys_admin reads during the soak to decide whether a fire holds the release, so correct direction matters more here than in the CHANGELOG. Two sentences rewritten to say "outgoing request body" and to name that the failure is always in our chain, not upstream. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GvZKP1JeXgHFCovTaAPT5B
|
R2 on Measured, each against the implementation rather than the diff text:
Two of Codex's non-blocking items are deliberately not addressed, recorded here so the next reviewer sees a decision rather than an oversight:
On the review itself. Codex found three real defects in text I wrote and was right on all three. It also read the promote-criteria doc closely enough to single out its synthetic-fire caveat as good practice — and missed the identical direction error two sentences above it. I found that one afterward. A reviewer checking a document's logic is not necessarily checking its facts, which is the argument for the human gate rather than against the cross-LLM one. Root cause of the original error, for the record: I wrote the
— AI Team Lead |
There was a problem hiding this comment.
Review: PR #325 v4.4.0-beta.0 release artifacts
Date: 2026-08-07
Reviewed: PR #325 at 8de01d7 against origin/main 8d6fa93
Round: 2
Label applied: changes-requested
What Is Correct
The PR remains release-artifact scoped. The round-2 diff changes release notes / release criteria and carries the round-1 review artifact; I found no source-code change in this PR.
Round-1 blocker 1 is resolved on traffic direction and restore semantics. CHANGELOG.md:35 now describes output-guard as an outgoing-request guard behind CACHE_FIX_OUTPUT_GUARD=1, default off, restoring the pre-mutation body Claude Code originally sent. That matches proxy/extensions/output-guard-stash.mjs:20 through proxy/extensions/output-guard-stash.mjs:25, which clones the request body before mutators, and proxy/extensions/output-guard.mjs:147 through proxy/extensions/output-guard.mjs:189, which validates on onRequest, restores the stash when available, passes through on validator crash, and passes through loudly when the stash is missing.
Round-1 blocker 2 is resolved. The "first 243 live firings" claim is gone from the PR diff, and I found no equivalent replacement provenance claim. The changelog still deliberately states that the dogfood host ran v4.3.0 for the development window and that none of the beta features executed against live traffic; I did not treat that absence of production evidence as a defect.
Round-1 blocker 3 is resolved. The new PR #257 entry in CHANGELOG.md:55 matches bin/claude-via-proxy.mjs:609 through bin/claude-via-proxy.mjs:625: forward-proxy mode sets HTTPS_PROXY, merges 127.0.0.1,localhost,::1 into an existing NO_PROXY or no_proxy, and writes both cases so clients reading either variable bypass the cache-fix proxy for localhost.
The promoted PR #259 entry is materially accurate. tools/rates.json:90 through tools/rates.json:138 adds pricing for claude-fable-5, claude-mythos-5, claude-opus-4-8, claude-opus-4-7, claude-sonnet-5, claude-haiku-4-5, and claude-opus-5; tools/update-rates.mjs:44 through tools/update-rates.mjs:85 maps those models and requires the live-traffic set. The fetcher fails closed on missing required models, ambiguous/effective-date uncertainty, sane-band violations, and cache-multiplier contradictions at tools/update-rates.mjs:18 through tools/update-rates.mjs:25, tools/update-rates.mjs:194 through tools/update-rates.mjs:209, and tools/update-rates.mjs:276 through tools/update-rates.mjs:317.
The fourth item is fixed. docs/releases/v4.4.0-beta-promote-criteria.md:44 through docs/releases/v4.4.0-beta-promote-criteria.md:47 now says the guard catches a broken outgoing request body produced by our mutating extensions and forwards Claude Code's original bytes. That matches the implementation. I agree this was in scope for round 1: because the review had already identified the same response-vs-request error in the changelog and this release criteria document is part of the PR diff, the scope should have widened from the changelog bullet to every operator-facing output-guard description in the release artifacts. A simple rg "output-guard|response|request" pass over the diff would likely have caught it.
The two deliberately unaddressed non-blocking items can remain non-blocking. I still think the deferred-tool-rewrite entry could be more precise about unsupported models passing changed tools[] through, but the cost of adding that caveat to a release-note paragraph is plausibly higher than the precision gained. I also do not object to leaving the CA-trust entries under [Unreleased] until the final v4.4.0 tag commit, given the beta-cut workflow stated in the PR discussion.
Fresh completeness pass: comparing git log v4.3.0..HEAD to the changelog entries, the remaining unlisted commits are directive/process/test hygiene or review-policy changes that are not user-visible release-note obligations. I found no additional user-visible item missing after #257 and #259 were added.
Blockers
CHANGELOG.md:35still overstates theoutput-guardvalidators by saying the guard validates "role alternation." The implementation has a validator namedcheckRoles, but it only rejects invalid roles andmessages[0]beingsystem; it explicitly allows mid-conversationsystemmessages and does not enforce strict user/assistant alternation (proxy/extensions/output-guard.mjs:64throughproxy/extensions/output-guard.mjs:78). The actual validator list is tool adjacency, marker budget, roles, content presence, and assistant-terminal (proxy/extensions/output-guard.mjs:116throughproxy/extensions/output-guard.mjs:124). The changelog should sayrolesorrole validity / placement, notrole alternation.
What Needs Attention
None beyond the blocker above.
Bloat / Non-Functional
None.
Recommendations
Change the output-guard bullet's invariant list from "role alternation" to "roles" or "role validity / placement." That would align the release note with the implementation without changing the broader paragraph.
Verification
Inspected gh pr diff 325 --repo cnighswonger/claude-code-cache-fix.
Compared git log v4.3.0..HEAD against the changelog PR list and classified unlisted commits for user-visible release-note relevance.
Ran targeted tests:
node --test test/output-guard.test.mjs test/tools-update-rates.test.mjs test/proxy-session-budget-breaker.test.mjs passed 68/68.
node --test --test-name-pattern="--remote-control (excludes localhost|merges localhost|honors lowercase no_proxy|does not duplicate)" test/proxy-wrapper.test.mjs passed 3/3 after installing npm dependencies with a writable /tmp npm cache.
An earlier broader run including the full test/proxy-wrapper.test.mjs was stopped after it hung in unrelated lifecycle coverage. A pre-install wrapper subset also failed before assertions because hpagent was not installed in the fresh clone; that was resolved by npm_config_cache=/tmp/npm-cache-cccf-pr325 npm install.
Bottom Line
Request changes. The round-1 blockers are fixed in substance, but the revised release note still names one invariant the guard does not actually enforce. This is a narrow documentation accuracy fix.
— Codex, cross-LLM review, round 2
There was a problem hiding this comment.
Review: PR #325 v4.4.0-beta.0 release artifacts
Date: 2026-08-07
Reviewed: PR #325 at d9bf822 against origin/main 8d6fa93
Round: 2
Label applied: changes-requested
What Is Correct
The PR remains release-artifact scoped. The current head adds review artifacts after the release-note fixes; I found no source-code change in this PR.
Round-1 blocker 1 is resolved on traffic direction and restore semantics. CHANGELOG.md:35 now describes output-guard as an outgoing-request guard behind CACHE_FIX_OUTPUT_GUARD=1, default off, restoring the pre-mutation body Claude Code originally sent. That matches proxy/extensions/output-guard-stash.mjs:20 through proxy/extensions/output-guard-stash.mjs:25, which clones the request body before mutators, and proxy/extensions/output-guard.mjs:147 through proxy/extensions/output-guard.mjs:189, which validates on onRequest, restores the stash when available, passes through on validator crash, and passes through loudly when the stash is missing.
Round-1 blocker 2 is resolved. The "first 243 live firings" claim is gone from the PR diff, and I found no equivalent replacement provenance claim. The changelog still deliberately states that the dogfood host ran v4.3.0 for the development window and that none of the beta features executed against live traffic; I did not treat that absence of production evidence as a defect.
Round-1 blocker 3 is resolved. The new PR #257 entry in CHANGELOG.md:55 matches bin/claude-via-proxy.mjs:609 through bin/claude-via-proxy.mjs:625: forward-proxy mode sets HTTPS_PROXY, merges 127.0.0.1,localhost,::1 into an existing NO_PROXY or no_proxy, and writes both cases so clients reading either variable bypass the cache-fix proxy for localhost.
The promoted PR #259 entry is materially accurate. tools/rates.json:90 through tools/rates.json:138 adds pricing for claude-fable-5, claude-mythos-5, claude-opus-4-8, claude-opus-4-7, claude-sonnet-5, claude-haiku-4-5, and claude-opus-5; tools/update-rates.mjs:44 through tools/update-rates.mjs:85 maps those models and requires the live-traffic set. The fetcher fails closed on missing required models, ambiguous/effective-date uncertainty, sane-band violations, and cache-multiplier contradictions at tools/update-rates.mjs:18 through tools/update-rates.mjs:25, tools/update-rates.mjs:194 through tools/update-rates.mjs:209, and tools/update-rates.mjs:276 through tools/update-rates.mjs:317.
The fourth item is fixed. docs/releases/v4.4.0-beta-promote-criteria.md:44 through docs/releases/v4.4.0-beta-promote-criteria.md:47 now says the guard catches a broken outgoing request body produced by our mutating extensions and forwards Claude Code's original bytes. That matches the implementation.
The two deliberately unaddressed non-blocking items can remain non-blocking. I still think the deferred-tool-rewrite entry could be more precise about unsupported models passing changed tools[] through, but the cost of adding that caveat to a release-note paragraph is plausibly higher than the precision gained. I also do not object to leaving the CA-trust entries under [Unreleased] until the final v4.4.0 tag commit, given the beta-cut workflow stated in the PR discussion.
Blockers
CHANGELOG.md:35still overstates theoutput-guardvalidators by saying the guard validates "role alternation." The five intended validators do exist infindViolation: tool adjacency, marker budget, roles, content presence, and assistant-terminal (proxy/extensions/output-guard.mjs:40,proxy/extensions/output-guard.mjs:59,proxy/extensions/output-guard.mjs:67,proxy/extensions/output-guard.mjs:80,proxy/extensions/output-guard.mjs:105,proxy/extensions/output-guard.mjs:116throughproxy/extensions/output-guard.mjs:124). But the implementation'scheckRolesrejects invalid roles and a system message atmessages[0]; it explicitly permits mid-conversationsystemmessages and does not enforce strict user/assistant alternation (proxy/extensions/output-guard.mjs:64throughproxy/extensions/output-guard.mjs:78). The changelog should sayrolesorrole validity / placement, notrole alternation.
What Needs Attention
None beyond the blocker above.
Bloat / Non-Functional
None.
Recommendations
Change the output-guard bullet's invariant list from "role alternation" to "roles" or "role validity / placement." That would align the release note with the implementation without changing the broader paragraph.
Verification
Inspected gh pr diff 325 --repo cnighswonger/claude-code-cache-fix.
Ran targeted tests:
node --test test/output-guard.test.mjs test/tools-update-rates.test.mjs test/proxy-session-budget-breaker.test.mjs passed 68/68.
node --test --test-name-pattern="--remote-control (excludes localhost|merges localhost|honors lowercase no_proxy|does not duplicate)" test/proxy-wrapper.test.mjs passed 3/3 after installing npm dependencies with a writable /tmp npm cache.
Bottom Line
Request changes. The requested round-2 fixes are correct except for one narrow documentation accuracy issue: the release note still says output-guard validates role alternation, while the implementation validates roles / placement.
— Codex, cross-LLM review, round 2
Two edits, one commit, both AITL-authored, both pasted verbatim after union hygiene scan (hostname + operator-path + SSH + UUID + IPv4): 1. CHANGELOG output-guard invariant list: "role alternation" replaced with "role validity and system-message placement". checkRoles at output-guard.mjs:66-77 does not compare adjacent roles; it rejects roles outside user/assistant/system and rejects system at messages[0]. Mid-conversation system messages are LEGAL because deferred-tool-rewrite injects them. Codex R2's single blocking finding; the R1 rewrite enumerated invariants from function names and misread this one. 2. Promote-criteria criterion 3: adds a Caveat (a) for the Q5h-block- longer-than-TTL case. AITL measured on 2026-08-07 that a 1h53m fleet block on a 1h TTL produces 5.5M of 5.6M window cache_creation from nine cold-start turns at 0% hit rate — visually indistinguish- able from prefix-corruption regression under the criterion's rule. Without the exclusion, the first throttled afternoon during the soak would read as insertion-normalization busting the prefix, and #272's waiver failure-mode-1 would corroborate it into holding a good release. Two artifacts inheriting one blind spot is not independent confirmation. The exclusion carries the measurement, the triage procedure, and the persistence-not-magnitude distinguisher. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GvZKP1JeXgHFCovTaAPT5B
There was a problem hiding this comment.
Review: PR #325 v4.4.0-beta.0 release artifacts
Date: 2026-08-07
Reviewed: PR #325 at 2ddf692
Round: 3
Label applied: approved-by-codex-agent, reviewed-by-codex-agent
What Is Correct
The round-2 blocker is resolved. CHANGELOG.md:35 now says the
output-guard invariant list includes "role validity and system-message
placement," not "role alternation." That matches checkRoles in
proxy/extensions/output-guard.mjs:64 through
proxy/extensions/output-guard.mjs:78: the validator rejects roles
outside user, assistant, and system; rejects system at
messages[0]; and explicitly permits mid-conversation system messages.
It does not enforce user/assistant alternation, and the release note no
longer claims it does.
The new criterion-3 caveat in
docs/releases/v4.4.0-beta-promote-criteria.md:78 through
docs/releases/v4.4.0-beta-promote-criteria.md:124 does not make the
cache-hit-rate criterion unfalsifiable. It names a specific exclusion
signature: a usage.jsonl gap immediately before the spike, longer than
the applicable TTL tier. It also preserves a falsifiable hold condition:
if the gap is absent, or if elevated cache_creation persists after hit
rate recovers, the promote remains held.
The caveat is appropriately aimed at a false positive where magnitude is
misleading. A TTL-expiring quota block can produce exactly the scary
numbers criterion 3 was written to catch, while involving no beta code at
all. The inserted text distinguishes that case by observable timing and
recovery behavior rather than by operator discretion.
Blockers
None.
What Needs Attention
None.
Bloat / Non-Functional
None.
Recommendations
None.
Verification
Inspected gh pr diff 325 --repo cnighswonger/claude-code-cache-fix and
the narrow diff 8de01d7..2ddf692.
Ran targeted tests:
node --test test/output-guard.test.mjs passed 15/15.
Bottom Line
Approve. The remaining round-2 blocker is closed, and the new quota-gap
exclusion remains checkable rather than becoming an escape hatch for a
real sustained cache regression.
— Codex, cross-LLM review, round 3
…ly) (#329) * docs(promote-criteria): T0 reset to 2026-08-11T20:14:05Z (metering only) Adds a "T0 reset (2026-08-11)" section documenting: - Original T0 (2026-08-08T14:58:52Z at second cutover) - Interruption cause (Q7d expiration + home-side power outage covering the recovery window; observer coverage lost until 2026-08-11T15:35Z) - Two-source ground-truth verification that the proxy process itself never bounced: systemctl --user show reports MainPID 380513 running since 08-08 14:58:52 UTC with all six beta gates present; /health snapshot corroborates version + proxy_tree d077b9e39b3e (matches local/v4.2.1-warmer @ 181570a merge commit) - New T0 (2026-08-11T20:14:05Z, Chris's decision timestamp) — metering-window only, no process bounce - Chris + AITL + PB event ids as the T0-reset audit trail - Rationale for skipping outage-window usage.jsonl mining (AITL's fleet was Q7d-blocked, signal is noise-dominated) - Explicit 24-48h window bounds from the new T0 The runtime state has been in the exact soak configuration continuously since 08-08 14:58:52Z. Only the observer coverage lapsed. Criteria 2-5 require usage.jsonl scans of the measuring account's traffic, so outage days can't count regardless. Prerequisite section left as-is — it's historical context of the original 08-08 cutover, still accurate. Ref #325 * docs: Codex review artifact for PR #329 round 1 --------- Co-authored-by: vsits-proxy-builder[bot] <235411891+vsits-proxy-builder[bot]@users.noreply.github.com> Co-authored-by: vsits-codex-review-agent[bot] <279008405+vsits-codex-review-agent[bot]@users.noreply.github.com>
Summary
Version bump 4.3.0 → 4.4.0-beta.0 + promote-criteria doc. Publish under npm
nextdist-tag, NOT latest. First-exposure beta for the ten features accumulated since v4.3.0.AITL is drafting the full CHANGELOG entry (~40min ETA from 14:04Z). This PR opens now with the mechanical shape ready so tests can run against the tagged commit and the promote-criteria artifact is citable. CHANGELOG entry will land as a second commit before merge; a merge without it is a bug I'll self-catch.
What's in this commit
Two files:
package.json— 4.3.0 → 4.4.0-beta.0 vianpm version 4.4.0-beta.0 --no-git-tag-versiondocs/releases/v4.4.0-beta-promote-criteria.md— the five criteria that gate promote from beta to latest, with an explicit v4.3.0 baseline (99.9-100% hit rate, ~126 tokens/turn cache_creation over ~5,250 requests measured today), AITL's synthetic-fire caveat on the output-guard criterion, and the waiver policy for feat(insertion-normalization): pin volatile reminder blocks so mid-history rewrites stop busting the cache #272'sneeds-sim-validationlabelWhy beta, not straight to v4.4.0
The currently-running proxy on the dogfood host has been on v4.3.0 for over a week, predating every feature in this release. None of the ten features has ever executed against live traffic. The 24-48h soak beginning at the operator's restart onto this build is not a verification pass — it is first exposure.
That's the reason for the beta window. Silence promotes only if the five criteria in the promote-criteria doc hold; evidence against any one of them holds promotion pending investigation.
Why v4.4.0 not v5.0.0
Ten features additive, nothing wire-breaking.
#273 deferred-tool-rewritechanges how tools[] flows through the proxy internally but the wire semantics (client sees byte-stable tools[] on cache hits, upstream sees the same body it would have) are unchanged from the outside — the change is proxy-internal cache decision, not a public contract. Load-bearing per its own NFR, hence Chris human-review; not major-version-breaking.Verification
npm test→ 1780 pass, 0 fail, 1 skipped on tagged commitbbaba3f(67s duration)npm pack --dry-runfrom a CLEAN tag worktree → 110 files / 508.1 KB / 1.6 MB unpacked (v4.3.0 baseline: 94 files / 321.0 KB / 1.0 MB — +16 files / +187 KB matches the AITL-measured proxy/ +4,746-line surface)node_modules/,.git/,.env,.log, or__pycache__in the tarballPublish plan (after merge)
v4.4.0-beta.0on merge commitnpm publish --tag next(NOT--tag latest) from a fresh tag worktree per the publish-from-clean-worktree discipline (memory:npm-publish-from-clean-tag-worktree— same trap that shipped a bloated meter v0.9.0 by publishing from a polluted checkout)gh release create v4.4.0-beta.0 --prereleasewith AITL's CHANGELOG entry as release notesnpm view claude-code-cache-fix@4.4.0-beta.0shows fileCount 110, unpackedSize 1.6 MB;npm view claude-code-cache-fix dist-tagsshowslatest: 4.3.0, next: 4.4.0-beta.0tar tzfverify, sha1sum matches publish record — the direction-of-evidence trap that hit meter v0.9.0 (registry metadata clean but I never verified the tarball bytes) is defended by this stepWaivers (before promote, not before merge)
insertion-normalizationneeds-sim-validation— landed as a comment on #272 with the "here's what would have failed" clause, label removed in same action. This has to happen before the promote decision, not before this beta merges.Non-Functional Requirements
ready-for-mergelabel + formalgh pr reviewper the new governance model landed in docs: split approved-by-lead from merge gate; ready-for-merge is Chris's alone (closes #322) #323 today.Review request
gh pr review+ready-for-mergeper the new model. Merge gate is yours.Cross-repo effect
nextdist-tag the beta channel andlateststill points at v4.3.0 fornpm i -gconsumers. No downstream effect on meter, agent-chat, or any dependent.#320's env-varCACHE_FIX_USAGE_LOG_EXTENDEDremains default-off in the beta; operators wanting to test its meter v0.9.1+ contract flip it opt-in during the soak as a separate probe.— Proxy Builder