Skip to content

Commit fca159c

Browse files
committed
merge the fork-local config
2 parents 23346ac + 50e9bbb commit fca159c

3 files changed

Lines changed: 186 additions & 0 deletions

File tree

.claude/deploy.sh

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#!/bin/bash
2+
# CCF — put THIS machine on origin/integrated.
3+
#
4+
# Contract: exit 0 = on the branch; non-zero = not, reason on stdout; one line
5+
# naming the host and the sha.
6+
set -eu
7+
D="$HOME/.local/share/cache-fix-fork"
8+
9+
[ -d "$D/.git" ] || { echo "REFUSE: $(hostname -s):$D is not a checkout"; exit 1; }
10+
11+
# Refuse rather than resolve. `reset --hard` would answer a wrong-branch tree by
12+
# discarding whatever is there, and on this machine that tree is what every live
13+
# session's launcher runs from.
14+
branch=$(git -C "$D" rev-parse --abbrev-ref HEAD)
15+
[ "$branch" = "integrated" ] || {
16+
echo "REFUSE: $(hostname -s):$D is on '$branch' — a human decides this"; exit 1; }
17+
18+
git -C "$D" fetch origin integrated --quiet
19+
# reset, not merge --ff-only: the rebuild force-pushes `integrated` (it is
20+
# rebuilt from upstream/main every time, never patched), so the deployed copy is
21+
# routinely NOT a fast-forward from its own HEAD. --ff-only would refuse every
22+
# rebuild that dropped a merged PR. Safe here because nothing edits this tree by
23+
# hand — the wrong-branch guard above is what protects the case that matters.
24+
git -C "$D" reset --hard -q origin/integrated
25+
echo "$(hostname -s) @ $(git -C "$D" rev-parse --short HEAD)"
26+
27+
# Re-apply the usage-log opt-in. `usage-log` ships enabled:false in its own
28+
# export default — upstream's deliberate opt-in, activated by an entry in
29+
# proxy/extensions.json. That file is TRACKED, so the reset above reverts it and
30+
# the extension goes quiet with nothing to say it did.
31+
#
32+
# Measured 2026-08-01: ~/.claude/usage.jsonl last written 2026-07-04 — four weeks
33+
# of per-call token accounting missing while the proxy itself was healthy at 96%
34+
# cache hit rate, so /check-usage could not attribute a 5h window that had
35+
# reached 85%. Then measured again the same day: running the one-line
36+
# `reset --hard` deploy took usage-log from {"enabled":true} back to absent.
37+
# This block is why deploy is a script and not a conf string.
38+
python3 - "$D/proxy/extensions.json" <<'PY' || echo "WARN: $(hostname -s) could not enable usage-log (accounting only, proxy unaffected)"
39+
import json, sys
40+
p = sys.argv[1]
41+
with open(p) as f:
42+
cfg = json.load(f)
43+
if cfg.get("usage-log", {}).get("enabled") is not True:
44+
cfg["usage-log"] = {"enabled": True, "order": 650}
45+
with open(p, "w") as f:
46+
json.dump(cfg, f, indent=2)
47+
f.write("\n")
48+
PY
49+
50+
# Extensions are read ONCE at proxy boot and hot-reload is opt-in and off, so
51+
# flipping usage-log on disk does nothing for a proxy already running. Report it;
52+
# restarting drops in-flight requests for every session on that port and is a
53+
# separate, confirmed step.
54+
pgrep -f 'cache-fix-fork/proxy/server.mjs' >/dev/null 2>&1 &&
55+
echo "NOTE: $(hostname -s) has a live proxy holding pre-deploy code — it keeps it until relaunch"
56+
57+
exit 0

.claude/integrated.conf

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# CCF — <repo>/.claude/integrated.conf
2+
#
3+
# Committed on `integrated-config`, the first input to every rebuild. Reaches
4+
# upstream never: every PR branch is cut from upstream/main, so there is no path
5+
# for this file onto one. Measured before relying on it —
6+
# git ls-tree ca-trust-guard .claude/ -> agent-name, github-app only
7+
# git reset --hard upstream/main -> a conf committed on `integrated`
8+
# is DESTROYED, which is why it lives
9+
# on its own branch instead.
10+
11+
UPSTREAM_REPO=cnighswonger/claude-code-cache-fix
12+
UPSTREAM_REMOTE=upstream
13+
UPSTREAM_BRANCH=main
14+
FORK_REMOTE=origin
15+
16+
INTEGRATED_BRANCH=integrated
17+
18+
PR_AUTHOR=codeslake
19+
20+
# The proxy prefix is load-bearing, not decoration: without it a test in
21+
# test/proxy-server.test.mjs makes a real api.anthropic.com request and hangs on
22+
# this network until it times out.
23+
TEST_CMD='HTTPS_PROXY=http://127.0.0.1:8118 NO_PROXY=localhost,127.0.0.1,::1 npm test'
24+
25+
TEST_CAVEAT='EMFILE in test/proxy-server.test.mjs is fs.inotify.max_user_instances (128 on lmd42), not a regression — confirm it fails identically at the merge base before calling it ours'
26+
27+
DEPLOY_HOSTS='lmd42-docker via-work-mac via-personal-mac'
28+
29+
POLL=300

.claude/verify.sh

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
#!/bin/bash
2+
# CCF — is the deploy actually LIVE on this machine?
3+
# One line per check: <name>\tOK|FAIL\t<detail>. Non-zero exit if any FAIL.
4+
set -u
5+
D="$HOME/.local/share/cache-fix-fork"
6+
CFG="${CLAUDE_CONFIG_DIR:-$HOME/.claude}"
7+
fail=0
8+
say() { printf '%s\t%s\t%s\n' "$1" "$2" "$3"; [ "$2" = FAIL ] && fail=1; return 0; }
9+
10+
# 1. The launcher parses at all. A tree that cannot even be loaded is the one
11+
# failure that makes every other probe meaningless.
12+
launcher="$D/bin/claude-via-proxy.mjs"
13+
if [ ! -r "$launcher" ]; then say launcher FAIL "absent: $launcher"
14+
elif out=$(node --check "$launcher" 2>&1); then say launcher OK "parses"
15+
else say launcher FAIL "${out:-parse failed}"; fi
16+
17+
# 2. The guard agrees with this machine's LIVE bundle.
18+
#
19+
# This is the check that earns its place: the bundle is written by a third
20+
# component (cc-wrapper's cachefix-ensure) from inputs neither this repo nor
21+
# the deploy controls, so a tree that is correct can still meet a bundle it
22+
# refuses. Probing bin/ca-trust.mjs — the module the launcher imports, not a
23+
# copy — is the point of it living in its own file.
24+
#
25+
# Absent bundle is OK, not FAIL: a host with no builder is a supported state
26+
# and the launcher falls back to its own CA. Absent CA is FAIL — forward-proxy
27+
# mode cannot work without one.
28+
if [ ! -r "$CFG/cache-fix-ca/ca.pem" ]; then
29+
say ca-trust FAIL "no proxy CA at $CFG/cache-fix-ca/ca.pem"
30+
elif [ ! -s "$CFG/ca-trust.pem" ]; then
31+
say ca-trust OK "no merged bundle on this host — launcher uses its own CA"
32+
else
33+
out=$(node -e '
34+
import(process.argv[1] + "/bin/ca-trust.mjs").then(async m => {
35+
const fs = await import("node:fs");
36+
const cfg = process.argv[2];
37+
const ca = fs.readFileSync(cfg + "/cache-fix-ca/ca.pem");
38+
const merged = fs.readFileSync(cfg + "/ca-trust.pem", "utf8");
39+
const n = (merged.match(/^-----BEGIN CERTIFICATE-----$/gm) || []).length;
40+
const v = m.bundleCarriesOurCA(merged, ca);
41+
console.log(n + " certs: " + (v.ok ? "accepted" : "REFUSED — " + v.reason));
42+
process.exit(v.ok ? 0 : 1);
43+
}).catch(e => { console.log("threw: " + e.message); process.exit(1); });
44+
' "$D" "$CFG" 2>&1)
45+
if [ $? -eq 0 ]; then say ca-trust OK "$out"; else say ca-trust FAIL "$out"; fi
46+
fi
47+
48+
# 3. A proxy answers, on the port the sessions were actually built against —
49+
# a session that started during a reload window baked whatever port it got,
50+
# and asserting the default would pass while every live session dialled a
51+
# dead one.
52+
#
53+
# The run dir `<TMPDIR-or-/tmp>/cachefix-<port>` is where that port is
54+
# recorded; it is the same discovery cc-check-ccf's probe uses. This read
55+
# ~/.claude.json for CLAUDE_CODE_CACHE_FIX_PORT until 2026-08-01, and no
56+
# such key exists — the launcher's variable is CACHE_FIX_PROXY_PORT and it
57+
# lives in the proxy's own env. Measured on all three machines: 0 matches,
58+
# so the sed produced nothing and `${port:-9901}` supplied the default every
59+
# single run. The check asserted precisely the assumption the paragraph
60+
# above forbids, and would have said OK about a dead port on any machine
61+
# whose proxy had moved.
62+
#
63+
# No run dir ⇒ FAIL, never a default. A check that cannot find its subject
64+
# has not looked; reporting that as OK is the whole failure mode.
65+
#
66+
# Collected in a plain loop, NOT `$(for ... done | sort -u)`: bash 3.2 (which
67+
# is what macOS ships, and two of the three machines here run) mis-parses a
68+
# `case` pattern inside `$( )` — it reads the pattern's own `)` as the end of
69+
# the command substitution and dies on the following `;;`. Measured: both
70+
# macs exited 2 with "syntax error near unexpected token `;;'" while lmd42's
71+
# bash 5 ran it fine. The check failed loudly rather than passing, which is
72+
# the right failure mode, but it still could not do its job on the hosts that
73+
# had it.
74+
tmp=${TMPDIR:-/tmp}; tmp=${tmp%/}
75+
ports=
76+
for d in "$tmp"/cachefix-* /tmp/cachefix-*; do
77+
[ -d "$d" ] || continue
78+
p=${d##*cachefix-}
79+
case "$p" in ''|*[!0-9]*) continue ;; esac
80+
case " $ports " in *" $p "*) continue ;; esac # TMPDIR may already be /tmp
81+
ports="$ports $p"
82+
done
83+
if [ -z "$ports" ]; then
84+
say proxy-live FAIL "no cachefix-<port> run dir under $tmp or /tmp — nothing to probe"
85+
else
86+
for port in $ports; do
87+
if out=$(curl -sf --max-time 3 --noproxy '*' "http://127.0.0.1:$port/health" 2>&1); then
88+
case "$out" in
89+
*'"forward_proxy":true'*) say proxy-live OK "port $port: $out" ;;
90+
# Answering in reverse-proxy mode is not "up": that mode sets
91+
# ANTHROPIC_BASE_URL, which is what disables Remote Control.
92+
*) say proxy-live FAIL "port $port answers but forward_proxy is not true: $out" ;;
93+
esac
94+
else
95+
say proxy-live FAIL "run dir $tmp/cachefix-$port exists but nothing answers 127.0.0.1:$port"
96+
fi
97+
done
98+
fi
99+
100+
exit $fail

0 commit comments

Comments
 (0)