feat(opencode): /claude-start — warm a session's cache lane with one synthetic turn - #160
Open
iceteaSA wants to merge 2 commits into
Open
feat(opencode): /claude-start — warm a session's cache lane with one synthetic turn#160iceteaSA wants to merge 2 commits into
iceteaSA wants to merge 2 commits into
Conversation
iceteaSA
force-pushed
the
feat/claude-start-upstream
branch
from
August 20, 2026 20:01
0ba748d to
64ee83f
Compare
There was a problem hiding this comment.
Review completed against the latest diff
Tip: cubic can generate docs of your entire codebase and keep them up to date. Try it here.
Re-trigger cubic
…per request The plugin has sent cache-diagnosis-2026-04-07 in its beta list on every request without enabling the feature: the beta requires a request-body opt-in (diagnostics.previous_message_id), and nothing sent it or read the response. Turn the dormant channel on, measure-only. Request side: eligible OAuth requests gain the diagnostics opt-in inside the fail-closed rewriteRequestBody pipeline. The id sent is only ever one captured from a prior Anthropic response (bounded per-session tracker) - opencode mints its own msg_01-shaped ids for every provider, and a foreign id fails silently as previous_message_not_found. Response side: the existing SSE wrapper exposes message_start.message through a typed callback; per valid eligible response one MC-CACHE-DIAG single-line JSON record (schema v:2) is emitted via the logger with verbatim usage, TTL-bucket accounting, diag_state (absent|server_null|pending|populated, always a string), populated cache_miss_reason.type, and attribution fields: source (open set) + synthetic (closed machinery/traffic split with published mapping), account_id (opaque persisted identifier; consumer timelines key on (account_id, prefix) because sticky routing migrates sessions across account-scoped caches), betas_hash (xxh64 of the sorted sent beta list, resolved by a once-per-hash MC-CACHE-DIAG-BETAS side-channel line), and requested_model present only on request/served divergence. Dumps: responses gain artifacts (status/id/model/usage/diagnostics, never content); CacheKeep prewarms are dumped tagged -prewarm-cachekeep- and emit records through the same chain, since any write resets the server TTL clock. Canary: short-gap previous_message_not_found with a genuinely-sent id logs a warn - the id capture broke, not a fingerprint expiry. Every per-chunk stateful consumer in the response wrapper is bounded at 8 MiB with drain-before-cap semantics; complete frames are processed before overflow passthrough engages. Verified live: null(write=24831) -> null(read=24831, hit) -> system_changed(cache_missed_input_tokens=23963) on a forced system change against a warm prefix. Comparison engages only on cacheable requests; consumers classify hit-first (documented in README, which is the record contract). Closes cortexkit#157
…synthetic turn Adds an OpenCode-only /claude-start command: queue one synthetic one-token turn through the current session's normal model, agent, variant, quota, routing, cache, relay, signing, and response pipeline, so a resumed session's prompt cache is re-warmed and its TTL clock refreshed without an operator turn. The synthetic prompt ([lane start] - automated cache warm; no response needed.) is injected via the session SDK with synthetic:true and the session's context resolved from message history; OpenCode assembles the request exactly as a real turn, so the warm is byte-exact by construction. The fetch layer correlates the request by its synthetic message id (exact-match, one-shot, session-scoped, bounded) and shapes it fail-closed: max_tokens 1, thinking stripped, streaming kept. The terminal max_tokens stop is rewritten to end_turn for the correlated turn only, so the session records a clean micro-turn. CacheKeep adopts the session afterward; dumps tag start requests -start- on direct and relay paths; diagnostics records carry source:start with synthetic:true. API-key routes are unreachable by all of this. /claude-start off is persisted (and logged to the command audit trail); automatic is reserved and replies honestly that it is not yet wired. Verified live on a ~460K-token session: start read=459,602 write=419; next real turn read=460,021 = start read + write exactly - shaping does not fork the cache key. ~$0.48 per start vs ~$9.26 for a cold rewrite. Stacked on the cache-diagnostics capture branch (cortexkit#159).
iceteaSA
force-pushed
the
feat/claude-start-upstream
branch
from
August 20, 2026 20:19
64ee83f to
c1f9bfb
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds
/claude-start(OpenCode-only): fire one synthetic, one-token turn through the current session's normal pipeline, so a resumed session's prompt cache gets re-warmed and its TTL clock refreshed without the operator typing a turn. The manual habit it replaces is typing "stand by" into a session after a restart.Stacked on #159 — the branch is #159's head plus one squashed lane-start commit (the start turn emits
source:"start"diagnostics records and rides #159's dump-handle machinery, so it cannot build without it). Review here = the single commit afterfeat(opencode): capture cache-diagnostics…; once #159 merges, this rebases to a lane-start-only diff.How it works
/claude-start(palette or typed) queues one synthetic prompt into the session via the SDK —parts:[{type:"text", text:"[lane start] — automated cache warm; no response needed.", synthetic:true}], with the session's current model/agent/variant resolved from message history. OpenCode assembles the request exactly as a real turn — no stored bodies, no staleness.max_tokens: 1, thinking stripped, streaming kept. Correlation is by message identity, not text, so a real operator turn in flight can never be shaped — the race is pinned by tests binding two sessions and an interleaved real turn with different payloads.stop_reason: "max_tokens"is rewritten toend_turnfor the correlated OAuth-served turn only, so the session records a clean micro-turn instead of a length error.-start-marker on both direct and relay paths./claude-start automaticis reserved: it repliesAutomatic lane start is not yet wired in this build; no setting was changed.(no racy event-hook trigger shipped)./claude-start offpersists the flag and emits the same command-audit INFO record as the other persistentclaude-*actions. Pi gets no command — it has no session SDK to inject a turn.Verified live
Two production runs on a ~460K-token session, records from the cache-diagnostics stream:
The second line is the acceptance gate for Anthropic's prompt-affecting-config caveat: shaping (max_tokens/thinking changes) does not fork the cache key — the real turn hit everything the start turn touched. Cost per start on that session: ~$0.48 (prefix read + marker-delta write) vs ~$9.26 for a cold rewrite if the entry had expired.
API-key boundary
Shaping, dump tags, diagnostics source, and the finish rewrite apply to OAuth routes only. API-key fallback routes send ordinary bodies even with a start pending, and their responses are never rewritten — pinned by tests (fallback-first ordinary body; API-key-fails→OAuth-fallback leg does shape; API-key-served response bytes untouched).
Gates
bun run testfull suite green (0 fail) ·typecheckclean ·lintclean · e2e 26/27 (the one failure is the pre-existingtool-prefix.test.tsstale-Opus-bridge case, which fails identically at the base commit — unrelated to this diff).Tests written red-first throughout; every guard was proven to redden by breaking its seam (correlation module absent, shaping reversed, one-shot leak into the API-key path, no-op clearSession, finish-rewrite removed).
Greptile Summary
The PR adds an OpenCode-only
/claude-startcommand that injects a correlated synthetic one-token turn to warm the current session’s cache lane.Confidence Score: 5/5
The PR appears safe to merge.
No blocking failure remains; both previously reported issues are fixed at the current HEAD.
Important Files Changed
/claude-startinto command handling and emits the persistent-off audit record after successful persistence.Sequence Diagram
Reviews (4): Last reviewed commit: "feat(opencode): /claude-start — warm a s..." | Re-trigger Greptile