Skip to content

feat(gateway): add compaction checkpoints#62146

Merged
scoootscooob merged 8 commits intoopenclaw:mainfrom
scoootscooob:codex/compaction-checkpoints
Apr 7, 2026
Merged

feat(gateway): add compaction checkpoints#62146
scoootscooob merged 8 commits intoopenclaw:mainfrom
scoootscooob:codex/compaction-checkpoints

Conversation

@scoootscooob
Copy link
Copy Markdown
Contributor

@scoootscooob scoootscooob commented Apr 6, 2026

Summary

  • Problem: compaction rewrote long-running sessions without a first-class recovery surface, so operators could not inspect what changed or safely return to the pre-compaction state.
  • Why it matters: long sessions felt opaque and risky, and the new compaction flow did not yet have the trust/recovery affordances we wanted.
  • What changed: added persisted compaction checkpoints, new sessions.compaction.* RPCs for list/get/branch/restore, session-row checkpoint metadata, and Sessions UI cards with branch/restore actions.
  • What did NOT change (scope boundary): this does not add the ambient context bus, does not change memory architecture, and preserves legacy sessions.compact line-trim behavior when callers pass maxLines.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #
  • Related #
  • This PR fixes a bug or regression

Root Cause (if applicable)

  • Root cause: N/A
  • Missing detection / guardrail: N/A
  • Contributing context (if known): N/A

UX Walkthrough

Before

Manual or automatic compaction could rewrite the active session transcript, but there was no first-class operator surface for understanding what got compacted or recovering the pre-compaction state. In practice that meant compaction worked, but it still felt risky because the user-visible model of the session stayed opaque.

After

This PR makes compaction a visible, inspectable, and recoverable workflow:

  1. A successful real compaction now persists a checkpoint record alongside the session store.
  2. The checkpoint captures the compaction reason, timestamp, summary, token delta, and pre/post transcript refs.
  3. The Sessions table surfaces that state directly through a new Compaction column, so operators can see whether a session has checkpoints without leaving the table.
  4. Expanding Show checkpoints reveals a card per checkpoint with the saved summary and direct recovery actions.
  5. Branch from checkpoint is the safe default recovery path because it preserves the current session while reopening the pre-compaction state in a child session.
  6. Restore rewinds the active session to the pre-compaction snapshot for operators/admins who want an in-place undo.

One important UX detail: Control UI /compact now routes through the embedded manual compaction path when maxLines is omitted, so the normal operator flow creates real checkpoints instead of only trimming transcript lines.

Screenshots

Sanitized local-dev data from the authenticated Control UI:

Sessions table overview

This is the new at-a-glance signal: operators can see checkpoint count and latest checkpoint metadata directly in the Sessions table.

Sessions table showing the new Compaction column and checkpoint count

Expanded checkpoint detail

This is the recovery UX: expanding a row shows the saved checkpoint summaries and exposes Branch from checkpoint plus Restore inline.

Expanded checkpoint cards showing summary, token delta, and recovery actions

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: src/gateway/server.sessions.gateway-server-sessions-a.test.ts
  • Scenario the test should lock in: real checkpoint metadata is listed, checkpoint branch/restore work, and sessions.compact without maxLines routes through embedded manual compaction.
  • Why this is the smallest reliable guardrail: the feature spans gateway session storage, protocol methods, transcript snapshots, and UI-facing RPC semantics.
  • Existing test that already covers this (if any): src/agents/pi-embedded-runner/compact.hooks.test.ts covers the embedded compaction hook/runtime path.
  • If no new test is added, why not: N/A

User-visible / Behavior Changes

  • Sessions tab now shows a Compaction column with checkpoint count and latest checkpoint metadata.
  • Operators can expand checkpoint cards and use Branch from checkpoint or Restore without digging through transcript files.
  • sessions.compaction.list, sessions.compaction.get, sessions.compaction.branch, and sessions.compaction.restore are now available.
  • Chat /compact in Control UI now uses real embedded manual compaction when called without maxLines, so the default manual UI flow can create checkpoints.
  • Restore preserves checkpoint history on the original session; branch starts a child session from the pre-compaction snapshot instead of mutating the current one.

Diagram (if applicable)

Before:
[user runs /compact] -> [session compacted] -> [history rewritten silently]

After:
[user runs /compact] -> [embedded compaction] -> [checkpoint persisted]
                                     -> [Sessions UI shows checkpoint metadata]
                                     -> [operator inspects summary]
                                     -> [branch or restore from pre-compaction snapshot]

Security Impact (required)

  • New permissions/capabilities? (Yes/No): Yes
  • Secrets/tokens handling changed? (Yes/No): No
  • New/changed network calls? (Yes/No): No
  • Command/tool execution surface changed? (Yes/No): Yes
  • Data access scope changed? (Yes/No): No
  • If any Yes, explain risk + mitigation: adds new operator-facing gateway methods for checkpoint inspection and recovery, and routes sessions.compact without maxLines through the existing embedded compaction runner. Risk is limited by existing gateway operator scope enforcement (sessions.compaction.restore remains admin-only) and by reusing the already-owned compaction/runtime path instead of inventing a broader new execution surface.

Repro + Verification

Environment

  • OS: macOS
  • Runtime/container: local repo dev run
  • Model/provider: targeted tests cover mocked embedded compaction; screenshots were captured against a live local Control UI session
  • Integration/channel (if any): Control UI
  • Relevant config (redacted): loopback gateway on default port

Steps

  1. Start the local gateway from the repo.
  2. Run /compact in a real chat session or call sessions.compact without maxLines.
  3. Open /sessions, confirm the Compaction column updates, expand Show checkpoints, then branch/restore from the checkpoint.

Expected

  • A checkpoint is created and visible in the Sessions UI.
  • Branch creates a child session from the pre-compaction snapshot.
  • Restore rewinds the session while preserving checkpoint history.
  • The session row exposes enough metadata that operators can tell a session was compacted without drilling into transcript files.

Actual

  • Matches expected in targeted verification and live local UI capture.

Evidence

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

  • Verified scenarios: built the repo, ran the targeted embedded compaction test, ran the checkpoint branch/restore gateway test, ran the manual-sessions.compact gateway test, and captured authenticated Sessions UI screenshots against the live local gateway.
  • Edge cases checked: restore preserves checkpoint history, branch clears checkpoint history on the child session, and legacy sessions.compact with maxLines remains the old trim path.
  • What you did not verify: a final browser clickthrough that actually executes Branch from checkpoint and Restore against a personal live session after the screenshot/PR packaging step.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? (Yes/No): Yes
  • Config/env changes? (Yes/No): No
  • Migration needed? (Yes/No): No
  • If yes, exact upgrade steps:

Risks and Mitigations

  • Risk: checkpoint snapshots are stored alongside session metadata and could accumulate if compaction is heavily used.
    • Mitigation: checkpoints are capped per session and follow existing session retention.
  • Risk: manual sessions.compact now has two behaviors depending on whether maxLines is supplied.
    • Mitigation: preserved the old maxLines behavior exactly for existing callers and tests; only the default UI/manual path upgrades to the embedded checkpoint-capable flow.
  • Risk: repo-wide pnpm check is currently blocked by an unrelated existing parse error in src/gateway/server.talk-config.test.ts:560.
    • Mitigation: ran targeted verification for the touched surface plus pnpm build, and called out the unrelated blocker explicitly here.

@openclaw-barnacle openclaw-barnacle Bot added app: web-ui App: web-ui gateway Gateway runtime agents Agent runtime and tooling size: XL maintainer Maintainer-authored PR labels Apr 6, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 6, 2026

Greptile Summary

Adds persisted compaction checkpoints, four new sessions.compaction.* RPCs (list/get/branch/restore), session-row checkpoint metadata, and a Sessions UI panel with branch/restore actions. sessions.compact now routes checkpoint-capable flows through the embedded compaction runner when called without maxLines, preserving the legacy line-trim path for callers that pass maxLines.

  • captureCompactionCheckpointSnapshot returns the wrong path (sessionFile, the original file) instead of snapshotFile (the pre-compaction copy it just created). All stored checkpoints therefore record the live transcript path in preCompaction.sessionFile. When a user invokes branch or restore, both handlers open and fork from the post-compaction file — the core recovery promise of checkpoints is silently broken. The unit test seeds the checkpoint fixture with the correct copy path directly, so the bug is not caught by the new test."

Confidence Score: 4/5

Not safe to merge until the snapshot path bug is fixed; branch and restore will always reconstruct from post-compaction content.

One P1 defect in captureCompactionCheckpointSnapshot makes the branch and restore operations functionally broken in production. All other surfaces — protocol schemas, scope assignments (read/write/admin), UI controller, the maxLines compact path, and checkpoint persistence logic — look correct.

src/gateway/session-compaction-checkpoints.ts lines 72-104: the return statement must use snapshotFile instead of sessionFile.

Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/gateway/session-compaction-checkpoints.ts
Line: 72-104

Comment:
**Snapshot path is lost — branch and restore silently use post-compaction content**

`captureCompactionCheckpointSnapshot` copies the live session file to `snapshotFile` (a unique `*.checkpoint.<uuid>.jsonl`), but returns `sessionFile` (the original path) in the result. Every checkpoint persisted by `persistSessionCompactionCheckpoint` therefore stores the live transcript path in `preCompaction.sessionFile`. By the time a user calls `sessions.compaction.branch` or `sessions.compaction.restore`, compaction has already rewritten that file, so both handlers call `SessionManager.forkFrom` on the **post**-compaction transcript — the pre-compaction state is never used.

Secondary effect: `cleanupCompactionCheckpointSnapshot` calls `fs.unlink(snapshot.sessionFile)` targeting the live transcript instead of the orphaned snapshot copy, which leaks on disk indefinitely.

The gateway test at line 1291 manually seeds `preCompaction.sessionFile` with `fixture.preCompactionSessionFile` (the actual copy path), so it does not catch this.

```suggestion
  return {
    sessionId: getSessionId(),
    sessionFile: snapshotFile,
    leafId,
  };
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "Gateway: add compaction checkpoints" | Re-trigger Greptile

Comment thread src/gateway/session-compaction-checkpoints.ts
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d057fc1527

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/gateway/session-compaction-checkpoints.ts
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0d61ac5fa3

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

store[target.canonicalKey] = {
...existing,
updatedAt: Math.max(existing.updatedAt ?? 0, createdAt),
compactionCheckpoints: trimSessionCheckpoints(checkpoints),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Remove orphaned snapshot files when trimming checkpoints

Each successful compaction creates a copied transcript snapshot, but this update only trims the in-store compactionCheckpoints array and never deletes snapshot files for checkpoints that fall out of retention. After many compactions, sessions will accumulate unreachable .checkpoint.*.jsonl files even though metadata is capped, so disk usage can grow without bound and eventually impact gateway stability on smaller disks.

Useful? React with 👍 / 👎.

Comment on lines +181 to +182
if (state.sessionsCheckpointItemsByKey[trimmedKey]) {
return;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Re-fetch checkpoints when reopening expanded session rows

This early return makes checkpoint details a one-time fetch per session key, so later compactions are not reflected in the expanded checkpoint cards even after loadSessions refreshes the row-level counters. In practice, users can see updated checkpoint counts in the table but stale checkpoint actions/details underneath until they hard-reload the page, which is a correctness issue for recovery UX.

Useful? React with 👍 / 👎.

@scoootscooob scoootscooob force-pushed the codex/compaction-checkpoints branch 2 times, most recently from 3d5ab81 to 7e69cac Compare April 6, 2026 22:19
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7e69cace5a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +1198 to +1201
checkpointSnapshot = engineOwnsCompaction
? captureCompactionCheckpointSnapshot({
sessionManager: SessionManager.open(params.sessionFile),
sessionFile: params.sessionFile,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep engine-owned compaction alive when snapshot open fails

When contextEngine.info.ownsCompaction === true, checkpoint capture now calls SessionManager.open(params.sessionFile) inline before captureCompactionCheckpointSnapshot. If that open throws (for example on a partially repaired/corrupt transcript), the whole compaction request fails even though checkpointing is intended to be best-effort. This creates a hard failure path that did not exist before and blocks compaction in cases where skipping checkpoint capture would have been acceptable.

Useful? React with 👍 / 👎.

@scoootscooob scoootscooob force-pushed the codex/compaction-checkpoints branch 2 times, most recently from 6fe1453 to 83dca67 Compare April 6, 2026 22:42
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 83dca67013

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

preserveCompactionCheckpoints?: boolean;
}): SessionEntry {
return {
...params.currentEntry,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reset compaction counters when branching from checkpoints

cloneCheckpointSessionEntry starts from ...params.currentEntry, and the branch path (sessions.compaction.branch) uses it with preserveCompactionCheckpoints unset, so the new child session drops checkpoint history but still inherits compactionCount (and related compaction-derived fields). This makes the branched session look like it has already been compacted before any child compaction runs, and later sessions.compact increments from that stale baseline, which can skew compaction-triggered behavior for the child session.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a83a77b28f

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +719 to +722
ok: true,
key: canonicalKey,
checkpoints: listSessionCompactionCheckpoints(entry),
},
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Redact checkpoint transcript paths from read-scope responses

sessions.compaction.list returns raw SessionCompactionCheckpoint objects, which include preCompaction.sessionFile/postCompaction.sessionFile absolute paths captured on the gateway host. Because these methods were added to operator.read scope, any read-scoped client can enumerate local filesystem layout and checkpoint file locations, which is unnecessary for list/get UI workflows (they only need IDs/metadata) and expands sensitive host metadata exposure.

Useful? React with 👍 / 👎.

@scoootscooob scoootscooob force-pushed the codex/compaction-checkpoints branch from a83a77b to e375425 Compare April 7, 2026 00:24
@scoootscooob scoootscooob merged commit f4fcaa0 into openclaw:main Apr 7, 2026
8 checks passed
@scoootscooob
Copy link
Copy Markdown
Contributor Author

Merged via squash.

Thanks @scoootscooob!

@scoootscooob scoootscooob deleted the codex/compaction-checkpoints branch April 7, 2026 00:27
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e37542554a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +1157 to +1159
await updateSessionStore(storePath, (store) => {
store[canonicalKey] = nextEntry;
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Archive superseded transcript when restoring checkpoints

This replaces the active session entry with a freshly forked transcript but never archives or deletes the previously active entry.sessionFile. After the first restore, repeated sessions.compaction.restore calls from the same checkpoint keep creating new transcript files while dropping references to the prior restored file, so disk usage grows with unreachable transcripts over time.

Useful? React with 👍 / 👎.

Comment on lines +1370 to +1371
compactionCheckpointCount: entry?.compactionCheckpoints?.length,
latestCompactionCheckpoint,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Strip checkpoint internals from session list rows

Fresh evidence of the path-exposure issue exists in the session row builder: it attaches the full checkpoint object (including preCompaction.sessionFile / postCompaction.sessionFile) to latestCompactionCheckpoint. Because sessions.list and sessions.changed return this row to read-scoped clients, they can still enumerate gateway host filesystem paths even without calling sessions.compaction.list/get.

Useful? React with 👍 / 👎.

100yenadmin pushed a commit to electricsheephq/openclaw-local-test that referenced this pull request Apr 16, 2026
…e, activeForm, hydration

Ports three Hermes todo-tool features that OpenClaw's update_plan
was missing, plus adds plan hydration for post-compaction recovery.

## cancelled status (Hermes parity)
Add "cancelled" as a fourth plan step status. Hermes uses this to
mark steps that were started but abandoned due to failure, keeping
them visible in history instead of silently dropping them.
Ref: Hermes tools/todo_tool.py Status enum.

## merge mode (Hermes parity)
Add optional merge: boolean parameter (default false). When true,
incoming steps update existing ones by matching step text and new
steps are appended. When false, the entire plan is replaced.
Ref: Hermes tools/todo_tool.py write(todos, merge=False).

## activeForm field (Claude Code TodoWrite parity)
Add optional activeForm: string field on plan steps. Shows the
present-continuous form while in_progress (e.g. "Running tests"
instead of "Run tests"). Small schema addition with disproportionate
UX impact for plan rendering.

## Post-compaction plan hydration (Hermes parity)
New src/agents/plan-hydration.ts helper that formats active
(pending/in_progress) plan items for injection after context
compression. The injected text uses factual phrasing ("Your active
plan was preserved...") to avoid triggering the planning-only retry
guard's promise-language detection.
Ref: Hermes run_agent.py:6754-6756 + tools/todo_tool.py:format_for_injection().

Note: the compaction hook point in compact.ts is not wired in this
PR — that requires a follow-up to integrate with the compaction
checkpoint system (openclaw#62146). This PR provides the formatter; the
hook wiring is the next step.

Part of GPT 5.4 Enhancement v3 sprint. Tracking: openclaw#66345.
100yenadmin pushed a commit to electricsheephq/openclaw-local-test that referenced this pull request Apr 19, 2026
…e, activeForm, hydration

Ports three Hermes todo-tool features that OpenClaw's update_plan
was missing, plus adds plan hydration for post-compaction recovery.

## cancelled status (Hermes parity)
Add "cancelled" as a fourth plan step status. Hermes uses this to
mark steps that were started but abandoned due to failure, keeping
them visible in history instead of silently dropping them.
Ref: Hermes tools/todo_tool.py Status enum.

## merge mode (Hermes parity)
Add optional merge: boolean parameter (default false). When true,
incoming steps update existing ones by matching step text and new
steps are appended. When false, the entire plan is replaced.
Ref: Hermes tools/todo_tool.py write(todos, merge=False).

## activeForm field (Claude Code TodoWrite parity)
Add optional activeForm: string field on plan steps. Shows the
present-continuous form while in_progress (e.g. "Running tests"
instead of "Run tests"). Small schema addition with disproportionate
UX impact for plan rendering.

## Post-compaction plan hydration (Hermes parity)
New src/agents/plan-hydration.ts helper that formats active
(pending/in_progress) plan items for injection after context
compression. The injected text uses factual phrasing ("Your active
plan was preserved...") to avoid triggering the planning-only retry
guard's promise-language detection.
Ref: Hermes run_agent.py:6754-6756 + tools/todo_tool.py:format_for_injection().

Note: the compaction hook point in compact.ts is not wired in this
PR — that requires a follow-up to integrate with the compaction
checkpoint system (openclaw#62146). This PR provides the formatter; the
hook wiring is the next step.

Part of GPT 5.4 Enhancement v3 sprint. Tracking: openclaw#66345.
100yenadmin pushed a commit to electricsheephq/openclaw-local-test that referenced this pull request Apr 25, 2026
…e, activeForm, hydration

Ports three Hermes todo-tool features that OpenClaw's update_plan
was missing, plus adds plan hydration for post-compaction recovery.

## cancelled status (Hermes parity)
Add "cancelled" as a fourth plan step status. Hermes uses this to
mark steps that were started but abandoned due to failure, keeping
them visible in history instead of silently dropping them.
Ref: Hermes tools/todo_tool.py Status enum.

## merge mode (Hermes parity)
Add optional merge: boolean parameter (default false). When true,
incoming steps update existing ones by matching step text and new
steps are appended. When false, the entire plan is replaced.
Ref: Hermes tools/todo_tool.py write(todos, merge=False).

## activeForm field (Claude Code TodoWrite parity)
Add optional activeForm: string field on plan steps. Shows the
present-continuous form while in_progress (e.g. "Running tests"
instead of "Run tests"). Small schema addition with disproportionate
UX impact for plan rendering.

## Post-compaction plan hydration (Hermes parity)
New src/agents/plan-hydration.ts helper that formats active
(pending/in_progress) plan items for injection after context
compression. The injected text uses factual phrasing ("Your active
plan was preserved...") to avoid triggering the planning-only retry
guard's promise-language detection.
Ref: Hermes run_agent.py:6754-6756 + tools/todo_tool.py:format_for_injection().

Note: the compaction hook point in compact.ts is not wired in this
PR — that requires a follow-up to integrate with the compaction
checkpoint system (openclaw#62146). This PR provides the formatter; the
hook wiring is the next step.

Part of GPT 5.4 Enhancement v3 sprint. Tracking: openclaw#66345.
lovewanwan pushed a commit to lovewanwan/openclaw that referenced this pull request Apr 28, 2026
Merged via squash.

Prepared head SHA: e375425
Co-authored-by: scoootscooob <167050519+scoootscooob@users.noreply.github.com>
Co-authored-by: scoootscooob <167050519+scoootscooob@users.noreply.github.com>
Reviewed-by: @scoootscooob
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
Merged via squash.

Prepared head SHA: e375425
Co-authored-by: scoootscooob <167050519+scoootscooob@users.noreply.github.com>
Co-authored-by: scoootscooob <167050519+scoootscooob@users.noreply.github.com>
Reviewed-by: @scoootscooob
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
Merged via squash.

Prepared head SHA: e375425
Co-authored-by: scoootscooob <167050519+scoootscooob@users.noreply.github.com>
Co-authored-by: scoootscooob <167050519+scoootscooob@users.noreply.github.com>
Reviewed-by: @scoootscooob
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling app: web-ui App: web-ui gateway Gateway runtime maintainer Maintainer-authored PR size: XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant