feat(cli-runner): opt-in flag to reseed from raw transcript when no compaction exists#77583
feat(cli-runner): opt-in flag to reseed from raw transcript when no compaction exists#77583eduardm23 wants to merge 1 commit into
Conversation
…ompaction exists Today loadCliSessionReseedMessages returns [] for any CLI session that has not yet compacted, even after a gateway restart. This is the intentional safety property asserted by the existing test "does not reseed fresh CLI sessions from raw transcript history before compaction" — pre-compaction transcripts may contain raw operator context that should not bleed into a resumed session, and compaction is treated as the filtering boundary. The cost of that safety default is restart amnesia for operators in trusted single-user, single-consumer environments: a gateway restart that invalidates the resumeSession (mcp/system-prompt hash mismatch is routine) drops all prior thread state with no way to opt back in. This change introduces an opt-in CliBackendConfig field `reseedFromRawTranscriptWhenUncompacted` (default `false`) plus a matching `allowRawTranscriptReseed` parameter on `loadCliSessionReseedMessages`. The default keeps the existing safety property — pre-compaction transcripts are still filtered out when no flag is set, and the existing test continues to pass unchanged. When opted in, the function falls back to the most recent MAX_CLI_SESSION_HISTORY_MESSAGES from the raw transcript, mirroring what loadCliSessionHistoryMessages already does for hooks. Two new tests assert the opt-in behavior covers both branches that previously short-circuited to []: - no compaction entry at all - a compaction entry whose summary is empty prepare.ts reads the flag off backendResolved.config and passes it through, so a per-backend setting in agents.defaults.cliBackends controls the behavior. Why this matters in practice: the team running OpenClaw on a single operator's workstation, where the agent is the only consumer of its own transcripts, currently has to maintain a vendored patch over this function to survive gateway restarts. An opt-in flag removes the need for that vendored patch upstream-permanently, while preserving the safety default for everyone else.
|
Thanks for the context here. I did a careful shell check against current Current main already contains the useful PR behavior via the merged successor implementation, and it also fixes this branch’s missing schema/docs and raw-transcript auth-boundary gaps. This branch should close rather than be revived. So I’m closing this as already implemented rather than keeping a duplicate issue open. Review detailsBest possible solution: Keep the current main implementation from the merged successor PR and close this stale branch rather than merge its incomplete version. Do we have a high-confidence way to reproduce the issue? Yes for the PR review findings: source inspection shows this branch exposes a backend config key without the strict schema and does not preserve auth-boundary no-raw behavior. A runtime repro is not needed to close because current main already contains the completed successor implementation. Is this the best way to solve the issue? No for this branch; it is not the best way to solve the issue because it omits schema/docs and auth-boundary gating. Yes for current main’s successor implementation, which keeps the opt-in explicit, bounded, documented, and no-raw for auth-profile or credential-epoch resets. Security review: Security review needs attention: The branch introduces a raw transcript replay path without enough auth-boundary gating; current main’s successor implementation addresses that before closure.
What I checked:
Likely related people:
Codex review notes: model gpt-5.5, reasoning high; reviewed against bb8aa0cfe2b0; fix evidence: commit aeb7d0736446, main fix timestamp 2026-05-09T14:52:30Z. |
…penclaw#79713) loadCliSessionReseedMessages returned [] for any session that had never been compacted, making the historyPrompt fallback silently inert. On short sessions (the common case for Discord/Telegram DMs), this meant every CLI invalidation (idle timeout, system-prompt change) restarted the agent with no prior context. Return limitAgentHookHistoryMessages(rawTail) instead, mirroring the same cap already applied to the post-compaction tail messages. The rival opt-in config approach (openclaw#77583) stalled on a missing CliBackend schema key; always-on is simpler and matches the issue author's suggested fix. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…penclaw#79713) loadCliSessionReseedMessages returned [] for any session that had never been compacted, making the historyPrompt fallback silently inert. On short sessions (the common case for Discord/Telegram DMs), this meant every CLI invalidation (idle timeout, system-prompt change) restarted the agent with no prior context. Return limitAgentHookHistoryMessages(rawTail) instead, mirroring the same cap already applied to the post-compaction tail messages. The rival opt-in config approach (openclaw#77583) stalled on a missing CliBackend schema key; always-on is simpler and matches the issue author's suggested fix. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…penclaw#79713) loadCliSessionReseedMessages returned [] for any session that had never been compacted, making the historyPrompt fallback silently inert. On short sessions (the common case for Discord/Telegram DMs), this meant every CLI invalidation (idle timeout, system-prompt change) restarted the agent with no prior context. Return limitAgentHookHistoryMessages(rawTail) instead, mirroring the same cap already applied to the post-compaction tail messages. The rival opt-in config approach (openclaw#77583) stalled on a missing CliBackend schema key; always-on is simpler and matches the issue author's suggested fix. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Summary
Today
loadCliSessionReseedMessagesreturns[]for any CLI session that has not yet compacted, even after a gateway restart. This is the intentional safety property asserted by the existing test"does not reseed fresh CLI sessions from raw transcript history before compaction"— pre-compaction transcripts may contain raw operator context that should not bleed into a resumed session, and compaction is treated as the filtering boundary. The literal"raw secret"test data makes that intent unambiguous.The cost of that safety default is restart amnesia for operators in trusted single-user / single-consumer environments: a gateway restart that invalidates the resumeSession (mcp/system-prompt hash mismatch is routine) drops all prior thread state with no way to opt back in.
Change
This PR adds an opt-in
CliBackendConfigfieldreseedFromRawTranscriptWhenUncompacted(defaultfalse) plus a matchingallowRawTranscriptReseed?: booleanparameter onloadCliSessionReseedMessages. The default behavior is unchanged — pre-compaction transcripts still short-circuit to[]when the flag is not set, and the existing safety test passes untouched. When opted in, the function falls back to the most recentMAX_CLI_SESSION_HISTORY_MESSAGESfrom the raw transcript, mirroring whatloadCliSessionHistoryMessagesalready does for hooks.prepare.tsreads the flag offbackendResolved.config.reseedFromRawTranscriptWhenUncompactedand threads it through, so a per-backend setting like:{ "agents": { "defaults": { "cliBackends": { "claude-cli": { "reseedFromRawTranscriptWhenUncompacted": true } } } } }…controls the behavior without any code changes from the operator.
Why this matters in practice
A team running OpenClaw on a single operator's workstation (where the agent is the only consumer of its own transcripts) currently has to maintain a vendored patch over this function to survive gateway restarts. An opt-in flag removes the need for that vendored patch upstream-permanently while preserving the safety default for everyone else.
Tests
Three test cases cover this code path:
"does not reseed fresh CLI sessions from raw transcript history before compaction"— unchanged. Asserts[]is still returned by default. Still passes."reseeds from raw transcript tail when allowRawTranscriptReseed is opted in"— asserts the opt-in returns the recent message tail in the no-compaction case."falls back to raw transcript tail when compaction summary is empty and opt-in is set"— asserts the opt-in branch also covers the existingif (!summary) return [];short-circuit.Considered alternative
A larger architectural option is "force a compaction at restart time, then reseed the compacted summary" — that preserves the safety boundary AND solves the amnesia problem without an opt-in flag at all. More invasive (needs a compaction trigger on
gateway:startupor just-before-resume). I'd be happy to file that as a follow-up issue if maintainers prefer that direction long-term; this PR is the smallest change that unblocks the use case while being explicit about the safety tradeoff via the flag name and docstring.