Skip to content

fix(subagent): preserve steered task text on restart redispatch#77539

Merged
vincentkoc merged 4 commits into
openclaw:mainfrom
amittell:fix/preserve-steered-task-on-restart
Jul 1, 2026
Merged

fix(subagent): preserve steered task text on restart redispatch#77539
vincentkoc merged 4 commits into
openclaw:mainfrom
amittell:fix/preserve-steered-task-on-restart

Conversation

@amittell

@amittell amittell commented May 4, 2026

Copy link
Copy Markdown
Contributor

Update 2026-06-02: addressed ClawSweeper P1 findings on cd6056478b:

  • Dropped the CHANGELOG.md hunk (release-owned per root AGENTS.md rules).
  • Reworked subagent-orphan-recovery.ts:158 to persist the stable original task instead of the synthetic resumeMessage wrapper, so repeated restarts no longer accumulate wrapped-resume-of-resume cascades.
  • Force-pushed and rebased to current upstream/main (was 478 commits behind; the new Dependency Guard check now applies).
  • Real behavior proof below has been redacted of private host names and absolute user paths per repo policy.

Summary

When a user steers an in-flight subagent task, the new task text is recorded in a steer event. If the gateway restarts before the subagent finishes, restart-redispatch resumes the run but the steered task text is lost; the subagent goes back to the original task.

This adds an optional task?: string parameter to replaceSubagentRunAfterSteer and threads it through subagent-control.ts, subagent-announce.ts, and subagent-orphan-recovery.ts. Backwards-compatible: omitted callers preserve the previous task.

Repro

  1. Start a subagent task ("draft a long blog post about X").
  2. Steer it ("focus only on the introduction").
  3. Restart the gateway before the subagent finishes (launchctl kickstart -k gui/$UID/ai.openclaw.gateway on macOS, equivalent on systemd).
  4. Observe: the subagent resumes with the original task ("draft a long blog post about X") instead of the steered task ("focus only on the introduction").

Test plan

  • node scripts/run-vitest.mjs run src/agents/subagent-registry.steer-restart.test.ts src/agents/subagent-orphan-recovery.test.ts src/agents/subagent-control.test.ts -- 3 files, 59 tests pass (includes two new regression tests in subagent-registry.steer-restart.test.ts).
  • node scripts/run-oxlint-shards.mjs --only=core --threads=4 clean.
  • pnpm build clean.
  • Backwards-compatible: existing call sites that omit task preserve the previous task field; new call sites pass the steered/wake/resume message explicitly.

Thanks @amittell.

Real behavior proof

  • Behavior addressed: Before this PR, when a user steered an in-flight subagent task, the new task text was recorded in the steer event but discarded by restart-redispatch; the resumed subagent went back to its original task. After this PR, replaceSubagentRunAfterSteer accepts a task?: string parameter that propagates the steered task text through restart redispatch so the subagent resumes the steered task, not the original one. The patch also guards the empty-string case so callers that pass task: "" fall back to the prior task instead of silently clobbering it.
  • Real environment tested: live OpenClaw gateway on gateway-host, pid (live gateway, redacted), build SHA (deployment fork checkout, redacted). The deployed bundle at ~/.openclaw/openclaw/dist/subagent-registry-CCMhICN7.js contains the patched line const nextTask = typeof replaceParams.task === "string" && replaceParams.task.length > 0 ? replaceParams.task : source.task; at line 1468. The proof script dynamic-imports that exact bundle and exercises its exported replaceSubagentRunAfterSteer (export m) and registerSubagentRun (export p). State is isolated via OPENCLAW_STATE_DIR redirected to a fresh tmpdir so the live gateway's runs.json is not touched.
  • Exact steps or command run after this patch:
    scp /tmp/proof-77539-amittell.mjs user@gateway-host:/tmp/proof-77539-amittell.mjs
    ssh user@gateway-host 'cd ~/.openclaw/openclaw && /opt/homebrew/bin/node /tmp/proof-77539-amittell.mjs'
    The script registers a synthetic subagent run with task: "do A: investigate widget metrics for last 24h", then exercises four scenarios against the live deployed bundle:
    1. Steer with new task "do B: steered instruction, switch to gauge reset" -> new run task = "do B".
    2. Steer without task param -> new run task preserves "do A" (back-compat).
    3. Steer with task: "" -> new run task preserves "do A" (empty-string fallback).
    4. Restart redispatch: feed the persisted run through buildResumeMessage (replicated verbatim from the deployed subagent-orphan-recovery-VcexvSiP.js lines 51-58) -> resume message wraps "do B", not "do A".
  • Evidence after fix:
    [PASS] steer-with-new-task replaces stored task -- replaced=true task="do B: steered instruction, switch to gauge reset"
    [PASS] no-task param preserves prior task -- replaced=true task="do A: investigate widget metrics for last 24h"
    [PASS] empty-string task falls back to prior task -- replaced=true task="do A: investigate widget metrics for last 24h"
    [PASS] restart-redispatch resume message wraps steered text, not stale task -- wrapsSteered=true dropsStale=true
    ---SUMMARY---
    {
      "scenarios": [
        { "name": "steer-with-new-task replaces stored task", "ok": true },
        { "name": "no-task param preserves prior task", "ok": true },
        { "name": "empty-string task falls back to prior task", "ok": true },
        { "name": "restart-redispatch resume message wraps steered text, not stale task", "ok": true }
      ],
      "failures": 0
    }
    RBP=pass (4 of 4 scenarios passed)
    
    Post-run sanity check confirms the live gateway's ~/.openclaw/subagents/runs.json was not touched: total runs: 0, proof-77539 keys: [].
  • Observed result after fix: On the live OpenClaw gateway at gateway-host, the deployed replaceSubagentRunAfterSteer honors the caller-supplied task param and falls back to the prior task for the no-arg and empty-string cases. The simulated restart redispatch (feeding the post-steer run into the same buildResumeMessage the gateway invokes during orphan recovery) wraps the steered text in the [Subagent Task] block, not the stale pre-steer instruction. The bug described in the PR summary is verifiably absent from the deployed bundle.
  • What was not tested: A full end-to-end gateway kill mid-steer with a real model in the loop. The harness drives the same exported function the live gateway calls during steer and during orphan-recovery redispatch; it does not perform a real launchctl kickstart of the rh-bot gateway because that would interrupt unrelated production traffic.

Real behavior proof addendum: completed-session reactivation (2026-06-12)

Covers the path added in 1607b5e8fe (now squashed into head 50eefdf243): sessions.send / agent.run follow-ups to a completed subagent session.

  • Behavior addressed: when a user sends a follow-up to a subagent session whose run already ended, sessions.send (src/gateway/server-methods/sessions.ts:913) calls reactivateCompletedSubagentSession with the follow-up message text. Before this head, the replacement run kept the stale original task, so a gateway restart redispatched the old prompt. After, the follow-up text is persisted as the replacement run's task and restart redispatch rewraps it.

  • Real environment tested: exact-head runtime bundle built locally from 50eefdf243 (pnpm build, macOS 26.5.1, node v26.3.0). The proof script dynamic-imports the built chunks directly -- session-subagent-reactivation-BiDNNsJe.js (export t = reactivateCompletedSubagentSession) and subagent-registry-D8kvjzdz.js (exports h/s/m = registerSubagentRun / getLatestSubagentRunByChildSessionKey / markSubagentRunTerminated) -- sharing the real in-memory registry module. State isolated via OPENCLAW_STATE_DIR redirected to a fresh tmpdir; no live gateway state touched. Same bundle-driving methodology as the accepted proof above.

  • Exact steps or command run after this patch:

    git checkout 50eefdf243 && pnpm build
    node /tmp/proof-77539-reactivation.mjs <checkout>/dist

    The script: (1) registers a run with task "do A: investigate widget metrics for last 24h" and drives it to ended state; (2) reactivates via the sessions.send path with follow-up "do B: follow-up, re-run the gauge reset against staging"; (3) feeds the replacement run through buildResumeMessage replicated verbatim from dist/subagent-orphan-recovery-CE6Tpah5.js:51-58; (4) asserts active (non-ended) runs are never replaced; (5) asserts whitespace-only follow-up preserves the prior task.

  • Evidence after fix:

    [PASS] ended run record retained with original task -- runId=run-original-1 endedAt=<ts> task="do A: investigate widget metrics for last 24h"
    [PASS] reactivation replaces ended run and persists follow-up text as task -- reactivated=true runId=run-followup-1 task="do B: follow-up, re-run the gauge reset against staging"
    [PASS] restart-redispatch resume message wraps follow-up text, not stale original -- wrapsFollowup=true dropsStale=true
    [PASS] active run is not replaced by completed-session reactivation -- reactivated=false runId=run-active-1 task="active task"
    [PASS] whitespace-only follow-up preserves prior task text -- reactivated=true runId=run-followup-3 task="do B: follow-up, re-run the gauge reset against staging"
    ---SUMMARY--- failures: 0
    
  • Observed result after fix: the replacement run record persists the follow-up text as task (scenario 2), restart-redispatch orphan recovery rewraps the follow-up rather than the stale original (scenario 3), the path refuses to touch active runs (scenario 4), and the empty/whitespace fallback contract from the original proof holds on this sibling path too (scenario 5).

  • What was not tested: a full live-gateway restart cycle (SIGUSR1 + orphan-recovery scan) around the reactivation; the orphan-recovery wrap is proven via the verbatim-replicated buildResumeMessage from the built chunk, as in the accepted base proof. A real sessions.send RPC through a running gateway was not driven; the call-site wiring (sessions.ts:913-917, agent.ts sibling) is covered by the unit tests on this head (322 passing).

Real behavior proof addendum: live gateway capture (2026-06-14)

Live capture on a real gateway process built from this PR head (50eefdf243), driving the actual reactivateCompletedSubagentSession over a real websocket against the qa-lab mock-openai model. This supersedes the 2026-06-12 in-process bundle addendum with a genuinely live run.

  • Behavior addressed: When a user sends a follow-up (sessions.send) to a subagent session whose run already ended, reactivateCompletedSubagentSession (src/gateway/session-subagent-reactivation.ts) now threads the follow-up text into replaceSubagentRunAfterSteer as task, so the replacement subagent run record persists the follow-up prompt. On a gateway restart, orphan-recovery redispatch (buildResumeMessage in src/agents/subagent-orphan-recovery.ts) then wraps the follow-up rather than the stale original task. Before this PR the replacement run kept the stale original task and the restart redispatched the old prompt.

  • Real environment tested: a real OpenClaw gateway child process spawned from the built dist/index.js at this PR head (50eefdf243); macOS 26.5.1, node v26.3.0, sqlite3 3.51.0. The gateway serves a real loopback websocket and runs the bundled qa-lab provider model mock-openai/gpt-5.5 (no external API key, no network egress); the harness boots it through startQaGatewayChild. A real parent agent turn emits a real sessions_spawn tool call, which spawns a real subagent run persisted in the live state/openclaw.sqlite. State is isolated to a fresh temp dir, so no live ~/.openclaw data is touched.

  • Exact steps or command run after this patch:

node --import tsx /tmp/proof-77539-live.mts
# 1. agent RPC: parent turn "subagent handoff" -> real sessions_spawn -> child subagent runs to ended
# 2. sessions.send follow-up to the completed child session (real reactivateCompletedSubagentSession over the wire)
# 3. read the live subagent_runs table from state/openclaw.sqlite with sqlite3 while the replacement run is in flight
# 4. SIGKILL + cold restart the real gateway process; re-read subagent_runs
  • Evidence after fix: redacted runtime logs and live sqlite output copied from the run:
[info] ended subagent childSessionKey=agent:qa:subagent:<redacted>
[info] original subagent task="Inspect the QA workspace and return one concise protocol note."
[step] sessions.send follow-up to the completed subagent session (parks in-flight)
[live] latest subagent run: task="subagent recovery worker: do B steered follow-up, switch to gauge reset against staging" ended_at=NULL
[PASS] reactivation persisted the follow-up as the run task in SQLite (inFlight=true)

# sqlite3 -readonly state/openclaw.sqlite "SELECT task, ended_reason FROM subagent_runs;" (after SIGKILL + cold restart)
task=subagent recovery worker: do B steered follow-up, switch to gauge reset against staging | ended_reason=subagent-error
  • Observed result after fix: Over a real websocket RPC to a live gateway, sessions.send of the follow-up drove reactivateCompletedSubagentSession, which persisted the follow-up text as the subagent run's task column in the live state/openclaw.sqlite, captured while the replacement run was still in flight (ended_at=NULL). The original subagent task ("Inspect the QA workspace...") was replaced by the follow-up text, confirming the fix's task threading end to end. After a real SIGKILL plus cold restart of the gateway process, the persisted subagent run still carries the follow-up task rather than the stale original, so the restart redispatch reads the follow-up text.

  • What was not tested: The literal buildResumeMessage wrap string was not captured across the cold restart. In this sandbox the restarted child reconciles the in-flight run to a terminal subagent-error (fresh ephemeral port, no parent delivery target), so the synthetic resume turn is not re-emitted to the model. The wrap behavior itself (orphan recovery reading run.task) is covered by the accepted base proof above and by the unit regression tests on this head (src/agents/subagent-registry.steer-restart.test.ts, src/gateway/session-subagent-reactivation.test.ts).

Copilot AI review requested due to automatic review settings May 4, 2026 21:29
@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

Codex review: needs maintainer review before merge. Reviewed July 1, 2026, 12:14 AM ET / 04:14 UTC.

Summary
The PR adds an optional replacement-run task override and threads it through subagent steer, descendant wake, orphan recovery, and completed-session follow-up paths with regression coverage.

PR surface: Source +61, Tests +127. Total +188 across 15 files.

Reproducibility: yes. at source level: current main preserves the previous task during replacement while orphan recovery reconstructs restart text from the persisted task. I did not run a live failing restart in this read-only review.

Review metrics: 1 noteworthy metric.

  • Persisted Task Semantics: 1 stored field behavior changed. Replacement runs now persist continuation prompt text in SubagentRunRecord.task, which restart recovery later rewraps.

Stored data model
Persistent data-model change detected: serialized state: src/gateway/server-methods/sessions.ts, serialized state: src/gateway/session-subagent-reactivation.test.ts, serialized state: src/gateway/session-subagent-reactivation.ts, unknown-data-model-change: src/gateway/session-subagent-reactivation.test.ts. Confirm migration or upgrade compatibility proof before merge.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🦞 diamond lobster
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • Maintainer acceptance of prompt-as-task persistence would remove the remaining session-state merge risk.

Risk before merge

  • [P1] Merging intentionally changes replacement-run SubagentRunRecord.task semantics: after steer, descendant wake, orphan resume, or completed-session follow-up, restart recovery treats the dispatched continuation prompt as canonical task text.
  • [P1] The live proof verifies persisted state through a real gateway and cold restart, but the exact model-visible post-restart resume transcript is supported by source inspection and focused tests rather than a literal transcript capture.

Maintainer options:

  1. Accept Prompt-As-Task Persistence (recommended)
    Approve the PR with explicit maintainer acceptance that replacement runs persist the dispatched continuation prompt for restart recovery.
  2. Request Literal Restart Transcript Proof
    Ask for a redacted kill/restart capture showing the model-visible resume message if persisted-state proof plus source and tests is not enough.
  3. Pause For Separate Continuation State
    Hold or close the PR if maintainers want original task identity preserved separately from continuation prompt text.

Next step before merge

  • No automated repair is needed; maintainers need to accept or reject the prompt-as-task replacement-run semantics before landing.

Security
Cleared: The diff changes agents/gateway session-state code and tests only; no dependency, CI, secret, permission, or supply-chain surface is introduced.

Review details

Best possible solution:

Land the focused registry-level task override after maintainers explicitly accept prompt-as-task persistence for replacement runs.

Do we have a high-confidence way to reproduce the issue?

Yes, at source level: current main preserves the previous task during replacement while orphan recovery reconstructs restart text from the persisted task. I did not run a live failing restart in this read-only review.

Is this the best way to solve the issue?

Yes as an implementation shape, pending maintainer acceptance. Adding the override at replaceSubagentRunAfterSteer and passing dispatched prompt text from each replacement caller is the narrowest maintainable fix I found; a separate continuation field would be a larger state-model decision.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 5a5913a98b03.

Label changes

Label justifications:

  • P2: This is a bounded agents/gateway bug fix for subagent restart behavior, with no emergency availability, security, or data-loss evidence.
  • merge-risk: 🚨 session-state: The diff changes what task text is persisted for replacement subagent runs and therefore what a restarted gateway associates with that session.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (logs): The PR body includes redacted live gateway and SQLite output showing the follow-up task persisted through a real follow-up and cold restart, supplemented by focused restart-wrap tests.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes redacted live gateway and SQLite output showing the follow-up task persisted through a real follow-up and cold restart, supplemented by focused restart-wrap tests.
Evidence reviewed

PR surface:

Source +61, Tests +127. Total +188 across 15 files.

View PR surface stats
Area Files Added Removed Net
Source 10 62 1 +61
Tests 5 127 0 +127
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 15 189 1 +188

What I checked:

  • Current main replacement behavior: Current main rebuilds the replacement SubagentRunRecord from source and does not override task, so replacement runs inherit the prior task text. (src/agents/subagent-registry-run-manager.ts:573, 5a5913a98b03)
  • Current main restart prompt source: Orphan recovery builds the restart resume message from params.task and remaps the restarted run without passing a replacement task, so it depends on the persisted run task. (src/agents/subagent-orphan-recovery.ts:73, 5a5913a98b03)
  • Current main steer caller: The active steer path dispatches params.message to the child session but currently calls replaceSubagentRunAfterSteer without passing that message as the replacement task. (src/agents/subagent-control.ts:574, 5a5913a98b03)
  • Current main completed-session reactivation: Completed-session reactivation swaps the run id for a new follow-up run but currently has no task parameter to carry the follow-up prompt into persisted subagent state. (src/gateway/session-subagent-reactivation.ts:13, 5a5913a98b03)
  • PR implementation surface: The PR adds task?: string to the replacement hook, stores non-empty caller-supplied task text in the replacement run, and passes task text from steer, wake, orphan-resume, and completed-session follow-up callers. (src/agents/subagent-registry-run-manager.ts:521, 9889feca8454)
  • Real behavior proof: The PR body includes redacted live gateway proof: a real websocket sessions.send follow-up persisted the follow-up text in state/openclaw.sqlite, and after SIGKILL plus cold restart the subagent row still carried the follow-up task rather than the stale original. (9889feca8454)

Likely related people:

  • joeykrug: Authored the merged SIGUSR1 orphan-recovery PR that introduced the restart resume/remap subsystem this PR amends. (role: introduced adjacent behavior; confidence: high; commits: 7b098ea79fc0, 745b01d7750a, 680eff63fbf8; files: src/agents/subagent-orphan-recovery.ts)
  • steipete: Recent GitHub path history shows repeated adjacent work on subagent recovery, steering, registry state, timeout math, and docs. (role: recent area contributor; confidence: high; commits: 0f120c09ba28, bddcf4448cde, 5e139e32dc5f; files: src/agents/subagent-orphan-recovery.ts, src/agents/subagent-control.ts, src/agents/subagent-registry-run-manager.ts)
  • vincentkoc: Authored recent subagent steering work on main and later force-pushed this PR branch with a maintainer validation comment. (role: recent adjacent owner; confidence: medium; commits: 28a719f3da96, 9889feca8454; files: src/agents/subagent-control.ts, src/gateway/session-subagent-reactivation.ts)
  • jalehman: Recent path history shows session accessor and transcript reader refactors touching the same gateway/agent session surfaces used by orphan recovery. (role: recent adjacent refactor contributor; confidence: medium; commits: 6f2869c296ff, d216f7c876dd, 8ded75628437; files: src/agents/subagent-orphan-recovery.ts, src/agents/subagent-control.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a restart-recovery correctness gap in the subagent registry: when a running subagent is steered (or woken/resumed) and the gateway restarts mid-flight, restart redispatch should continue with the steered instruction rather than reverting to the original task.

Changes:

  • Adds an optional task?: string override to replaceSubagentRunAfterSteer and threads it through steer/wake/orphan-resume call paths.
  • Updates the subagent run manager replacement logic to persist the caller-supplied replacement task (fallbacking to the prior task when omitted).
  • Adds regression tests to ensure task override is persisted and that legacy callers still preserve the prior task.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/agents/subagent-registry.ts Extends replaceSubagentRunAfterSteer wrapper params to include optional task.
src/agents/subagent-registry.steer-restart.test.ts Adds regression tests for task replacement/preservation during steer replacement runs.
src/agents/subagent-registry-steer-runtime.ts Documents and types the new optional task override in the steer runtime shim.
src/agents/subagent-registry-run-manager.ts Implements task override selection when replacing a run after steer/wake/resume.
src/agents/subagent-orphan-recovery.ts Passes the constructed orphan-resume message as the replacement run’s persisted task.
src/agents/subagent-control.ts Passes the steered message as the replacement run’s persisted task.
src/agents/subagent-announce.ts Passes the descendant-wake message as the replacement run’s persisted task.
src/agents/subagent-announce.format.e2e.test.ts Updates expectations to assert the wake replacement call includes a task string.
CHANGELOG.md Adds an entry describing the restart-redispatch steer-task preservation fix.

Comment thread src/agents/subagent-registry-run-manager.ts Outdated
Comment thread src/agents/subagent-registry.steer-restart.test.ts Outdated
@amittell
amittell force-pushed the fix/preserve-steered-task-on-restart branch from cfd90f4 to bcfdece Compare May 17, 2026 00:36
@openclaw-barnacle openclaw-barnacle Bot added the triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. label May 17, 2026
@clawsweeper clawsweeper Bot added the P2 Normal backlog priority with limited blast radius. label May 17, 2026
@amittell
amittell force-pushed the fix/preserve-steered-task-on-restart branch from bcfdece to a1384c5 Compare May 18, 2026 02:06
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. impact:message-loss Channel message delivery can be lost, duplicated, or misrouted. impact:session-state Session, memory, transcript, context, or agent state can drift or corrupt. labels May 18, 2026
@openclaw-barnacle openclaw-barnacle Bot added proof: supplied External PR includes structured after-fix real behavior proof. and removed triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. labels May 18, 2026
@clawsweeper clawsweeper Bot added the merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. label May 18, 2026
@amittell
amittell force-pushed the fix/preserve-steered-task-on-restart branch from a1384c5 to ee7bb27 Compare May 28, 2026 16:01
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. impact:session-state Session, memory, transcript, context, or agent state can drift or corrupt. impact:message-loss Channel message delivery can be lost, duplicated, or misrouted. labels May 28, 2026
@amittell
amittell force-pushed the fix/preserve-steered-task-on-restart branch from ee7bb27 to 2884472 Compare June 1, 2026 03:43
@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jun 1, 2026
@amittell
amittell force-pushed the fix/preserve-steered-task-on-restart branch from 2884472 to cd60564 Compare June 2, 2026 19:41
@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label Jun 11, 2026
@amittell
amittell force-pushed the fix/preserve-steered-task-on-restart branch from 0f14ccc to c09e0f8 Compare June 11, 2026 13:14
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label Jun 11, 2026
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Jun 11, 2026
@amittell
amittell force-pushed the fix/preserve-steered-task-on-restart branch from c09e0f8 to 50eefdf Compare June 11, 2026 13:35
@amittell

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

The requested latest-head runtime proof for the completed-session reactivation path is now in the PR body (addendum section, captured 2026-06-12 against exact head 50eefdf243): the built bundle's real reactivateCompletedSubagentSession + registry chunks, isolated state dir, five scenarios all PASS -- follow-up text persisted as the replacement run's task, restart-redispatch resume message wraps the follow-up and drops the stale original, active runs untouched, whitespace fallback preserved. Also note both Copilot inline threads are already fixed at this head (the redispatchSubagentRunAfterRestart symbol they flagged no longer exists in either file).

@clawsweeper

clawsweeper Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@openclaw-barnacle openclaw-barnacle Bot added triage: mock-only-proof Candidate: PR proof only shows tests, mocks, snapshots, lint, typecheck, or CI. and removed proof: supplied External PR includes structured after-fix real behavior proof. labels Jun 12, 2026
@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels Jun 12, 2026
@openclaw-barnacle openclaw-barnacle Bot added proof: supplied External PR includes structured after-fix real behavior proof. and removed triage: mock-only-proof Candidate: PR proof only shows tests, mocks, snapshots, lint, typecheck, or CI. labels Jun 14, 2026
@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. labels Jun 14, 2026
@vincentkoc
vincentkoc force-pushed the fix/preserve-steered-task-on-restart branch from 50eefdf to 9889fec Compare June 17, 2026 16:54
@vincentkoc

Copy link
Copy Markdown
Member

Clownfish 🐠 reef update

Thanks for the work here. Clownfish got this branch swimming again without needing a replacement PR.

Source PR: #77539
Validation: pnpm test src/agents/subagent-registry.steer-restart.test.ts src/agents/subagent-orphan-recovery.test.ts src/agents/subagent-control.test.ts src/gateway/session-subagent-reactivation.test.ts src/gateway/server-methods/agent.test.ts src/gateway/server-methods/sessions.send-followup-status.test.ts; pnpm check:changed; git diff --check
Contributor credit stays right here with this PR's history and changelog context. no lost treasure, no mystery bubbles.

fish notes: model gpt-5.5, reasoning medium; reviewed against 9889fec.

amittell and others added 4 commits July 1, 2026 12:42
Threads an optional task override through subagent run replacement so
restart redispatch rewraps the actual prompt dispatched on steer,
descendant wake, and orphan recovery instead of the stale `task` from
the original run record.

Also threads it through completed-session reactivation
(`reactivateCompletedSubagentSession` in
`src/gateway/session-subagent-reactivation.ts`), which `sessions.send`
and `agent.run` dispatch use to swap a completed subagent run id for a
new follow-up run id. Without this, a follow-up sent via
`sessions.send` or a fresh `agent.run` on a completed child session
would reactivate the prior runRecord with its old task; a later
gateway restart's orphan recovery would then rewrap the stale original
prompt instead of the follow-up text the operator just sent.

`expectSubagentFollowupReactivation` now accepts an optional `task`
parameter and propagates it into the `replaceSubagentRunAfterSteer`
assertion. The two existing callers (`agent.test.ts` and
`sessions.send-followup-status.test.ts`) pass `task: "follow-up"`
matching the dispatched message, so the focused gateway follow-up
tests now prove the new completed-session task-passing contract
instead of asserting the old `task`-free shape.

Test totals on the new head: 322 tests pass (helpers + sessions
follow-up + agent + reactivation).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling gateway Gateway runtime merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. proof: supplied External PR includes structured after-fix real behavior proof. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: S status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants