Skip to content

feat(cli-runner): opt-in flag to reseed from raw transcript when no compaction exists#77583

Closed
eduardm23 wants to merge 1 commit into
openclaw:mainfrom
eduardm23:fix/cli-reseed-without-compaction
Closed

feat(cli-runner): opt-in flag to reseed from raw transcript when no compaction exists#77583
eduardm23 wants to merge 1 commit into
openclaw:mainfrom
eduardm23:fix/cli-reseed-without-compaction

Conversation

@eduardm23

Copy link
Copy Markdown

Summary

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 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 CliBackendConfig field reseedFromRawTranscriptWhenUncompacted (default false) plus a matching allowRawTranscriptReseed?: boolean parameter on loadCliSessionReseedMessages. 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 recent MAX_CLI_SESSION_HISTORY_MESSAGES from the raw transcript, mirroring what loadCliSessionHistoryMessages already does for hooks.

prepare.ts reads the flag off backendResolved.config.reseedFromRawTranscriptWhenUncompacted and 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:

  • Existing: "does not reseed fresh CLI sessions from raw transcript history before compaction" — unchanged. Asserts [] is still returned by default. Still passes.
  • New: "reseeds from raw transcript tail when allowRawTranscriptReseed is opted in" — asserts the opt-in returns the recent message tail in the no-compaction case.
  • New: "falls back to raw transcript tail when compaction summary is empty and opt-in is set" — asserts the opt-in branch also covers the existing if (!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:startup or 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.

…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.
@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: S labels May 4, 2026
@clawsweeper

clawsweeper Bot commented May 4, 2026

Copy link
Copy Markdown
Contributor

Thanks for the context here. I did a careful shell check against current main, and this is already implemented.

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 details

Best 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.

  • [medium] Raw reseed can cross auth-boundary resets — src/agents/cli-runner/prepare.ts:410
    Because the branch only checks the opt-in flag, changed auth profile or credential epoch resets can still replay raw pre-compaction transcript history into a fresh CLI session. That is a privacy/security boundary issue for this patch, even though current main’s merged successor now gates it.
    Confidence: 0.86

What I checked:

Likely related people:

  • steipete: Provided maintainer direction on the successor PR and authored the raw-transcript gate commit that shaped the current main behavior. (role: reviewer and recent adjacent owner; confidence: high; commits: 92cef04847bb, aeb7d0736446; files: src/agents/cli-runner/session-history.ts, src/agents/cli-runner/prepare.ts, src/config/zod-schema.core.ts)
  • hclsys: Opened and implemented the merged successor PR that completed the config contract, docs, tests, and changelog for this feature. (role: successor implementation author; confidence: high; commits: 7f2ba4d69428, b63f3afdc44c, aeb7d0736446; files: src/agents/cli-runner/session-history.ts, src/agents/cli-runner/prepare.ts, src/config/types.agent-defaults.ts)
  • obviyus: The earlier fix(cli): bound fresh session reseed commit is tied to the fresh-session reseed and compaction-boundary behavior this PR changes. (role: introduced related reseed boundary behavior; confidence: medium; commits: 8559a84e4ea5; files: src/agents/cli-runner/session-history.ts, src/agents/cli-runner/session-history.test.ts, src/agents/cli-runner/prepare.ts)

Codex review notes: model gpt-5.5, reasoning high; reviewed against bb8aa0cfe2b0; fix evidence: commit aeb7d0736446, main fix timestamp 2026-05-09T14:52:30Z.

steipete pushed a commit to hclsys/moltbot that referenced this pull request May 9, 2026
…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>
steipete pushed a commit to hclsys/moltbot that referenced this pull request May 9, 2026
…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>
steipete pushed a commit to hclsys/moltbot that referenced this pull request May 9, 2026
…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>
@clawsweeper clawsweeper Bot closed this May 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant