Problem
OpenCode forks receive a new session ID and copied message history. ACP only rebuilds fork pruning state by replaying completed historical compress tool parts whose state.input remains available. If the fork copy omits or strips those inputs, ACP reconstructs zero blocks, so the copied raw parent history remains visible and token usage can jump dramatically.
Observed impact
A runtime session reached 20,581+ messages and reported 925,103 tokens against a 400,000-token context limit. ACP repeatedly logged reason=no_executable_candidates with 9,284+ compressible ranges, but no rebuild: reconstructed ... event for that session.
Root cause
lib/state/state.ts invokes rebuildCompressionState() only for a new fork without a fork-local state file. lib/state/rebuild.ts replays only completed compress tool parts with object state.input; it has no parent-state transfer fallback.
Proposed direction
When a session has parentID, load the parent ACP state, map parent persisted message refs to the fork’s newly assigned refs/raw IDs across the copied shared prefix, translate block coverage/indexes, and save independent fork-local state. Fall back to current historical replay if parent state or mapping validation is unavailable. Do not inherit nudge cadence/current-turn state or mutate the parent.
Related PR: #341
Problem
OpenCode forks receive a new session ID and copied message history. ACP only rebuilds fork pruning state by replaying completed historical
compresstool parts whosestate.inputremains available. If the fork copy omits or strips those inputs, ACP reconstructs zero blocks, so the copied raw parent history remains visible and token usage can jump dramatically.Observed impact
A runtime session reached 20,581+ messages and reported 925,103 tokens against a 400,000-token context limit. ACP repeatedly logged
reason=no_executable_candidateswith 9,284+ compressible ranges, but norebuild: reconstructed ...event for that session.Root cause
lib/state/state.tsinvokesrebuildCompressionState()only for a new fork without a fork-local state file.lib/state/rebuild.tsreplays only completedcompresstool parts with objectstate.input; it has no parent-state transfer fallback.Proposed direction
When a session has
parentID, load the parent ACP state, map parent persisted message refs to the fork’s newly assigned refs/raw IDs across the copied shared prefix, translate block coverage/indexes, and save independent fork-local state. Fall back to current historical replay if parent state or mapping validation is unavailable. Do not inherit nudge cadence/current-turn state or mutate the parent.Related PR: #341