Skip to content

fix: keep yielded parent turns nonterminal#95996

Merged
fuller-stack-dev merged 5 commits into
openclaw:mainfrom
kklouzal:p1/sessions-yield-cron-lifecycle
Jul 15, 2026
Merged

fix: keep yielded parent turns nonterminal#95996
fuller-stack-dev merged 5 commits into
openclaw:mainfrom
kklouzal:p1/sessions-yield-cron-lifecycle

Conversation

@kklouzal

@kklouzal kklouzal commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Define one internal lifecycle contract for a model turn that ended via registered sessions_yield while its parent task is still waiting.
  • Emit that contract from the Codex harness and preserve cancellation, timeout, and error precedence.
  • Keep the Gateway session status running, project an additive yielded: true chat final, and let Control UI clear the completed model turn without announcing Done.
  • Preserve overlapping active runs and ordinary non-yielded end_turn completion behavior.

This replaces the former broad cron/Discord/public-deferred proposal with the narrow shared invariant needed by Gateway session state and Control UI. It does not introduce a public status or Plugin SDK contract.

What Problem This Solves

A Codex model turn can emit final_answer and turn/completed after explicitly registering continuation work through sessions_yield. Before this patch, Gateway and Control UI treated that transport-level turn completion as user-task completion, moved the session to done, and announced Done even though OpenClaw still owned pending work.

The July 14, 2026 Wilfred sequence demonstrated the false completion projection: final_answer arrived at 17:28:11 MDT and task_complete followed 29 ms later while activation was still staging and live browser QA remained pending. The raw incident used detached scripts rather than sessions_yield; this PR fixes the same projection bug only for continuation work registered through the supported lifecycle contract.

Evidence

  • Focused Codex, protocol, Gateway, session, and Control UI tests reproduce a yielded final event and verify the parent remains running without a Done announcement.
  • The Playwright Control UI regression verifies the final assistant text stays visible while the completed model-turn spinner and Stop control clear.
  • Protocol generators reproduce the committed schema, Swift, and Kotlin outputs byte-for-byte.
  • pnpm build, pnpm check, focused Vitest shards, exact-head GitHub CI, and autoreview provide the implementation gates described below.

Behavior

turn/completed and final_answer end a Codex model turn. They complete the OpenClaw parent task only when no registered continuation remains.

The nonterminal parent state requires the clean internal tuple:

phase=end
yielded=true
livenessState=paused
stopReason=end_turn

Cancellation, timeout, error, or contradictory status metadata remains terminal.

Scope

This fixes the Control UI/Gateway projection for correctly registered sessions_yield continuation work.

The July 14, 2026 Wilfred session exposed the false-Done symptom: a Codex final answer and task-complete projection arrived while activation and browser verification were still pending. That raw incident launched detached screen/wake scripts and did not call sessions_yield, so arbitrary detached process ownership remains outside this PR. The patch deliberately does not infer pending work from prose, shell processes, or promises in assistant text.

Related lifecycle ownership:

Verification

Focused lifecycle, protocol, Gateway, Codex, and Control UI tests:

node scripts/run-vitest.mjs \
  src/agents/agent-lifecycle-parent-state.test.ts \
  extensions/codex/src/app-server/run-attempt-lifecycle-controller.test.ts \
  packages/gateway-protocol/src/index.test.ts \
  src/gateway/session-lifecycle-state.test.ts \
  src/gateway/server-chat.agent-events.test.ts \
  ui/src/lib/sessions/index.test.ts \
  ui/src/lib/sessions/run-terminal.test.ts \
  ui/src/pages/chat/run-lifecycle.test.ts \
  ui/src/pages/chat/chat-gateway.test.ts \
  ui/src/e2e/chat-run-lifecycle.e2e.test.ts

Also run:

pnpm build
pnpm check

pnpm build and pnpm check passed. The focused non-browser suites
passed again after the final patch-identical rebase; the Playwright
Control UI regression passed on the same patch before the rebase.

Final autoreview: clean, no accepted/actionable findings. Exact-head
GitHub CI is the authoritative broad gate. A local exploratory
pnpm test run was not used as a gate because unrelated macOS
resource/path failures eventually exhausted the temporary volume.

Behavior addressed: Control UI must not announce Done when an explicitly yielded parent is still waiting on registered continuation work.

Real environment tested: Playwright Control UI browser flow against a mocked Gateway WebSocket; exact-head GitHub CI on the published PR branch.

Exact steps or command run after this patch: Start a chat run, publish an active session row, send a final chat event with yielded: true and stopReason: "end_turn", then inspect the transcript, composer, session activity, and live status announcement.

Evidence after fix: The final assistant text remains visible, the completed model-run Stop control and spinner clear, the parent session remains running, and .agent-chat__run-status-announcement stays empty instead of saying Done.

Observed result after fix: Registered yielded work is represented as a waiting parent task; ordinary end_turn without yielded metadata still publishes Done, stale cancellation/error metadata stays terminal, and overlapping active run IDs are preserved.

What was not tested: This PR does not claim ownership or detection of arbitrary detached screen jobs, wake scripts, or other background processes that were not registered through sessions_yield. No live model-provider call was required for the deterministic projection fix. The local full-suite attempt was not a passing gate; exact-head hosted checks own broad verification.

Co-authored concept and original report/fix direction by @kklouzal.

@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation channel: discord Channel integration: discord app: web-ui App: web-ui gateway Gateway runtime cli CLI command changes agents Agent runtime and tooling size: L labels Jun 23, 2026
@kklouzal
kklouzal force-pushed the p1/sessions-yield-cron-lifecycle branch 4 times, most recently from 9c722dd to a8aa8bf Compare June 23, 2026 16:18
@openclaw-barnacle openclaw-barnacle Bot added scripts Repository scripts size: XL and removed size: L labels Jun 23, 2026
@kklouzal

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 23, 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.

@clawsweeper

clawsweeper Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 13, 2026, 9:30 PM ET / July 14, 2026, 01:30 UTC.

Summary
The PR adds shared yielded-parent lifecycle classification, a persisted deferred cron status, descendant-settlement reconciliation, and Discord progress preservation across the associated protocol, CLI, UI, SDK, docs, and tests.

Reproducibility: no. not yet with high confidence against current main and the exact PR head. Source inspection and the older redacted live cron run strongly support the failure mode, but exact-head Discord, best-effort delivery, final-synthesis, and upgrade paths remain unproven.

Review metrics: 2 noteworthy metrics.

  • Public cron status surface: 1 status added. deferred propagates through persisted run history, Gateway validation, CLI exit behavior, hooks, QA consumers, and Control UI filters.
  • Plugin SDK lifecycle surface: 4 exports added. Two functions and two types become supported third-party API through openclaw/plugin-sdk/reply-runtime.

Stored data model
Persistent data-model change detected: durable storage schema: src/plugins/worker-provider-registry.ts, durable storage schema: src/plugins/worker-provider-types.ts, serialized state: src/agents/sessions-spawn-hooks.test.ts, serialized state: src/sessions/session-state-events.ts, unknown-data-model-change: packages/gateway-protocol/src/schema/cron.ts, unknown-data-model-change: src/plugins/worker-provider-types.ts, and 1 more. Confirm migration or upgrade compatibility proof before merge.

Merge readiness
Overall: 🦐 gold shrimp
Proof: 🦐 gold shrimp
Patch quality: 🐚 platinum hermit
Result: blocked until stronger real behavior proof is added.

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

Rank-up moves:

  • [P1] Add exact-head redacted Discord status-reaction proof showing the yielded parent remains active until the matching descendant branch settles.
  • Demonstrate exact-head best-effort cron delivery, eventual parent synthesis, and fresh-install versus upgrade handling for persisted deferred status.
  • Obtain maintainer confirmation for the permanent cron status and Plugin SDK contract.

Proof guidance:

  • [P1] Needs stronger real behavior proof before merge: The redacted cron transcript is useful, but it ran an older installed commit and does not show the exact head's Discord status settlement, best-effort delivery, final synthesis, or upgrade behavior; add redacted exact-head recordings, terminal output, or logs, update the PR body, and request @clawsweeper re-review if a fresh review does not trigger.

Mantis proof suggestion
A short live Discord proof can directly verify that yielded-parent status reactions remain in progress and settle only after the matching descendant branch completes. A maintainer can ask Mantis to capture proof by posting this exact PR comment:

@openclaw-mantis discord status reactions: verify and capture redacted proof that a yielded parent with active subagents remains visibly in progress and changes to done or error only after the matching descendant branch settles.

Risk before merge

  • [P1] deferred becomes a persisted Gateway, CLI, hook, QA, and UI status; older clients or plugins with exhaustive three-value handling may reject it or silently misclassify upgraded run history.
  • [P1] The branch exposes lifecycle classification through the public Plugin SDK, creating a contract that third-party plugins may depend on before its permanence and versioning expectations are confirmed.
  • [P1] Incorrect descendant ownership or settlement accounting could wake the wrong parent, finalize a cron task too early, or leave the original delivery path indefinitely deferred.
  • [P1] Discord status and draft cleanup now depend on persisted settlement keys and descendant-source accounting; without exact-head live proof, premature clearing or stale progress remains possible.
  • [P1] The current evidence does not demonstrate a fresh-install versus upgrade round trip for persisted deferred rows, filters, hooks, and external RPC consumers.

Maintainer options:

  1. Gate the public contract on exact-head proof (recommended)
    Confirm the additive status and SDK direction, then require exact-head upgrade, external-consumer, final-synthesis, best-effort delivery, and Discord settlement evidence before merge.
  2. Retain an internal waiting state
    Remove the public deferred and SDK expansion while keeping a shared internal lifecycle classifier that prevents premature completion.
  3. Pause the branch if no contract owner sponsors it
    Close or narrow the PR if maintainers do not want to own a permanent fourth cron status and public lifecycle API.

Next step before merge

  • [P1] A maintainer must decide the permanent public status and SDK contract, then require the missing exact-head behavior and upgrade evidence; there is no narrow mechanical repair for automation to apply.

Maintainer decision needed

  • Question: Should yielded parents with active descendants introduce deferred as a permanent public cron and Plugin SDK contract, or should waiting remain an internal lifecycle state projected through the existing public status model?
  • Rationale: Both shapes can fix premature completion, but the branch changes persisted status values, Gateway schemas, CLI exit behavior, hook-visible types, UI filters, and public SDK exports; code review cannot choose that long-term compatibility contract without maintainer intent.
  • Likely owner: jalehman — The available discussion routing most directly connects jalehman to the parent/subagent lifecycle decision surface.
  • Options:
    • Adopt public deferred status (recommended): Accept deferred as an additive public contract after exact-head upgrade, external-client, best-effort delivery, final-synthesis, and Discord proof is attached.
    • Keep waiting internal: Preserve the existing public cron status enum and represent yielded waiting only through internal lifecycle/task state until a later versioned API design.

Security
Cleared: No concrete security or supply-chain regression was found; the patch adds no dependency or workflow execution source, and the approval-related edits appear limited to contract compatibility rather than authorization policy.

Review details

Best possible solution:

Use one canonical internal parent lifecycle state across cron, subagent, and channel projections; expose deferred publicly only after maintainers accept that permanent contract and exact-head fresh-install, upgrade, best-effort delivery, final-synthesis, and Discord settlement proof all pass.

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

No, not yet with high confidence against current main and the exact PR head. Source inspection and the older redacted live cron run strongly support the failure mode, but exact-head Discord, best-effort delivery, final-synthesis, and upgrade paths remain unproven.

Is this the best way to solve the issue?

Unclear. A shared parent lifecycle classifier and descendant-settlement reuse are the right structural direction, but the public deferred status and SDK API are not established as the narrowest compatible solution until maintainers choose the contract.

AGENTS.md: found and applied where relevant.

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

Label changes

Label justifications:

  • P1: The PR targets active cron and subagent workflows where premature completion can suppress or misrepresent final delivery for real users.
  • merge-risk: 🚨 compatibility: Merging adds a persisted fourth cron status and public Plugin SDK exports that existing clients and plugins may not recognize.
  • merge-risk: 🚨 session-state: The change alters when yielded parents remain paused, wake after descendant settlement, and finalize shared task state.
  • merge-risk: 🚨 message-delivery: The change deliberately suppresses interim cron delivery and preserves Discord progress until later settlement, so ownership mistakes could drop, duplicate, or mistime user-visible delivery.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦐 gold shrimp and patch quality is 🐚 platinum hermit.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs stronger real behavior proof before merge: The redacted cron transcript is useful, but it ran an older installed commit and does not show the exact head's Discord status settlement, best-effort delivery, final synthesis, or upgrade behavior; add redacted exact-head recordings, terminal output, or logs, update the PR body, and request @clawsweeper re-review if a fresh review does not trigger.
Evidence reviewed

What I checked:

  • Current main lacks the proposed public status: Current main still defines CronRunStatus as ok | error | skipped, so the branch's deferred status is a new public and persisted contract rather than redundant work. (raw.githubusercontent.com) (src/cron/types.ts:92, b9c48154034f)
  • Current main has only part of the lifecycle machinery: Current main pauses explicit yielded subagent runs and contains a wakeOnDescendantSettle path, but the lifecycle listener does not classify yielded parents by active-descendant ownership as this branch proposes. (raw.githubusercontent.com) (src/agents/subagent-registry.ts, b9c48154034f)
  • Public protocol and persistence expansion: The branch adds deferred to cron runtime types, Gateway schemas and filters, run logs, CLI wait behavior, QA consumers, and Control UI filters; existing external clients with exhaustive status handling may require an upgrade path. (src/cron/types.ts:92, 376a02405665)
  • Plugin SDK expansion: The branch promotes two classifier functions and two lifecycle types through the public openclaw/plugin-sdk/reply-runtime entrypoint, making the lifecycle representation a third-party plugin contract subject to maintainer acceptance and compatibility review. The scoped SDK policy treats this directory as a public contract. (raw.githubusercontent.com) (src/plugin-sdk/reply-runtime.ts:59, 376a02405665)
  • Real cron proof is useful but not exact-head complete: The PR body includes a redacted live cron/subagent handoff showing deferred, but it identifies installed commit 5c1fd341c89b1493fed1ea6014388394291450c3, not current head 376a02405665a91abf03b2b0c79c49593889f8d9, and explicitly says Discord, best-effort delivery, and upgrade proof remain missing. (376a02405665)
  • Automated validation is broad and currently green: The provided check rollup reports successful build, lint, production and test types, compact test shards, UI, plugin/channel contracts, QA smoke, security guards, CodeQL-neutral, and real-behavior-proof workflow checks; these support patch quality but do not settle product or upgrade semantics. (376a02405665)

Likely related people:

  • jalehman: The PR's later review routing explicitly includes jalehman for the agent/subagent lifecycle surface; direct local git-history commands were unavailable, so this routing signal is lower confidence than normal blame/log provenance. (role: likely lifecycle decision owner; confidence: medium; files: src/agents/subagent-registry.ts, src/agents/subagent-registry-lifecycle.ts, src/agents/subagent-registry-run-manager.ts)
  • openperf: The discussion repeatedly routes the broad cron, agent, and gateway lifecycle change toward openperf, making them a useful adjacent reviewer for the public status and delivery semantics. (role: adjacent cron and runtime reviewer; confidence: medium; files: src/cron/isolated-agent/delivery-dispatch.ts, src/cron/service/timer.ts, src/cron/types.ts)
  • joshavant: The latest discussion routing includes joshavant alongside the agent lifecycle work, suggesting familiarity with the current orchestration and reconciliation paths. (role: adjacent agent lifecycle contributor; confidence: low; files: src/agents/subagent-registry.ts, src/agents/subagent-registry-completion.ts, src/tasks/task-executor-deferred-cron.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.
Review history (42 earlier review cycles; latest 8 shown)
  • reviewed 2026-07-13T00:46:51.006Z sha abd78a1 :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-13T04:02:20.530Z sha 203d95c :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-13T06:09:25.815Z sha c93574c :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-13T06:24:26.644Z sha c93574c :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-13T22:47:28.882Z sha d905ead :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-13T23:07:44.078Z sha d905ead :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-13T23:48:08.277Z sha 51f5124 :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-14T00:03:48.655Z sha 51f5124 :: needs real behavior proof before merge. :: none

@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. P1 High-priority user-facing bug, regression, or broken workflow. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. labels Jun 23, 2026
@kklouzal
kklouzal force-pushed the p1/sessions-yield-cron-lifecycle branch from 4dbd552 to 31d2476 Compare June 23, 2026 21:34
@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 24, 2026
@kklouzal
kklouzal force-pushed the p1/sessions-yield-cron-lifecycle branch from 31d2476 to 8e3dcf8 Compare June 24, 2026 22:29
@openclaw-barnacle openclaw-barnacle Bot removed the scripts Repository scripts label Jun 24, 2026
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. labels Jul 11, 2026
@kklouzal
kklouzal force-pushed the p1/sessions-yield-cron-lifecycle branch 5 times, most recently from e9d864b to 378f9f0 Compare July 11, 2026 17:59
@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. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jul 11, 2026
@kklouzal
kklouzal force-pushed the p1/sessions-yield-cron-lifecycle branch from 378f9f0 to 097fa6e Compare July 11, 2026 18:20
@clawsweeper clawsweeper Bot removed the rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. label Jul 11, 2026
@fuller-stack-dev

Copy link
Copy Markdown
Member

Maintainer preparation is rebuilding this branch on current main around the explicit yielded-parent invariant.

The refreshed PR will:

Scope note: this contract applies to correctly registered sessions_yield lifecycle events. It does not claim to detect arbitrary detached screen or wake-script work.

@fuller-stack-dev

Copy link
Copy Markdown
Member

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jul 15, 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:

@fuller-stack-dev

Copy link
Copy Markdown
Member

Merged via squash.

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 extensions: codex gateway Gateway runtime merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. P1 High-priority user-facing bug, regression, or broken workflow. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. size: L status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants