Skip to content

test(claude-code): cover synthetic-to-real session binding end to end - #31

Merged
Xubqpanda merged 6 commits into
zjunlp:mainfrom
wwwaken:claude-overlay-next
Aug 10, 2026
Merged

test(claude-code): cover synthetic-to-real session binding end to end#31
Xubqpanda merged 6 commits into
zjunlp:mainfrom
wwwaken:claude-overlay-next

Conversation

@wwwaken

@wwwaken wwwaken commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

CLA-01 requires the overlay to bind a synthetic session id to the real Claude Code session observed by the hook, and to persist that mapping. The unit tests in session-map cover recordSessionMapping in isolation, but no gateway-level test exercised the resolve path: a claude-synth- request landing, being resolved to the latest real hook session, and the binding being written.

Add a gateway e2e test: seed a real hook session, send a synthetic-id request, assert it binds to the real id, then confirm the binding stays anchored to the first real id even after a newer session becomes latest.

Adapter suite 146/146, typecheck clean. No production code changed.

wwwaken added 6 commits August 9, 2026 22:11
CLA-01 requires the overlay to bind a synthetic session id to the real
Claude Code session observed by the hook, and to persist that mapping.
The unit tests in session-map cover recordSessionMapping in isolation,
but no gateway-level test exercised the resolve path: a claude-synth-
request landing, being resolved to the latest real hook session, and the
binding being written.

Add a gateway e2e test: seed a real hook session, send a synthetic-id
request, assert it binds to the real id, then confirm the binding stays
anchored to the first real id even after a newer session becomes latest.

Adapter suite 146/146, typecheck clean. No production code changed.
…ssion report

CLA-05 requires the report to show per-turn and cumulative saved chars.
The report already renders 'Latest eviction savings' (from the snapshot)
and 'Cumulative eviction savings' (summed across recent turn bindings),
but no test asserted the eviction lines — only reduction metrics were
covered.

Add a test: seed a snapshot + two turn bindings (300, 200 saved chars),
assert 'Latest eviction savings: 200' (most recent turn) and
'Cumulative eviction savings: 500' (sum). No production code changed.
Stage 4 semantic-delta wiring needs a turnSeq — a per-session,
monotonically increasing real turn number to slice DeltaViews across
requests. It cannot be derived from the message array (resent whole each
request and rewritten by eviction, so not monotonic), and nothing else in
the codebase maintains one (bindings have no absolute turn number; gateway
only has revision = content sha256).

Add turn-counter.ts: readClaudeTurnSeq (0 when missing/corrupt, fail-open)
and bumpClaudeTurnSeq (load -> +1 -> atomic persist under claude-context/).
Storage only — NOT yet wired into the gateway; the wiring waits on
supervisor confirmation that turnSeq = a persisted per-session counter.

5 unit tests: default 0, monotonic increment, survives restart, per-session
isolation, corrupt-file fail-open. Adapter suite 152/152, typecheck clean.
…eway)

Encapsulate the whole per-request V2 semantic flow in one fail-open
function runSemanticPipeline: bump turn counter -> build+persist this
turn's RawSemanticTurnRecord -> load registry -> rebuild the
(lastProcessedTurnSeq, now] interval into a DeltaView -> updateRegistryFromDelta
-> persist the registry with expectedVersion, advancing the watermark only
when the registry actually changed.

Watermark note: the shared mapper already sets lastProcessedTurnSeq =
delta.toTurnSeqInclusive in its patch, so a successful update returns a
registry whose watermark is advanced — persisted as-is. changed=false
(estimator failed / no updates / version conflict) leaves the watermark
put so the next request re-covers the same interval.

updateRegistryFromDelta is injected (like applyArchivePlan's archiveFn) so
tests drive the branches with a fake, no live LLM. 5 unit tests: changed
persists + advances watermark, unchanged does not persist, version conflict
abandons, interval covers only (from, now], internal error fails open
(ran=false). STORAGE/ORCHESTRATION ONLY — the gateway if(estimator) call
block (PART 2) is a separate main-flow change. Adapter suite 157 green.
Add a feature-gated, fail-open semantic block in handleRequest, right after
the session id is resolved and before eviction planning. When an estimator
is configured (resolveClaudeTaskStateEstimator, env-driven, default off) it
runs runSemanticPipeline over the inbound envelope.messages; any error is
caught and logged, never propagated — the request proceeds unchanged.

Uses envelope.messages (the real inbound history) rather than the
eviction-rewritten overlayMessages, since the semantic delta must reflect
true turns. With no estimator configured the block is a no-op, so all 157
existing tests stay green — proving the wiring doesn't disturb the existing
request flow. typecheck clean.
…en when wired

Add an optional resolveEstimator injection seam to the gateway dependencies
(mirrors the existing cloneRequestPayload seam) so tests can drive the
semantic block with a fake estimator instead of a live LLM.

Two gateway e2e tests: (1) an injected estimator returning task updates ->
the request succeeds and a task registry is persisted at
task-state/<sessionId>/registry.json with version>=1, proving the semantic
block actually ran; (2) an injected estimator whose estimate() throws ->
the request still forwards 200 unchanged, proving the block is fail-open and
never blocks the request path. With no estimator configured (default) the
block is a no-op, already covered by the existing 157 green tests.

Adapter suite 159 green, typecheck clean.
@Xubqpanda
Xubqpanda merged commit 81f358f into zjunlp:main Aug 10, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants