Skip to content

fix(commitments): preserve extraction batch on transient failure#89817

Merged
vincentkoc merged 1 commit into
openclaw:mainfrom
masatohoshino:fix/commitment-extraction-batch-loss
Jun 29, 2026
Merged

fix(commitments): preserve extraction batch on transient failure#89817
vincentkoc merged 1 commit into
openclaw:mainfrom
masatohoshino:fix/commitment-extraction-batch-loss

Conversation

@masatohoshino

@masatohoshino masatohoshino commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

drainCommitmentExtractionQueue takes a batch off the queue with queue.splice(0, batchMaxItems) and runs the extractor. On a non-terminal extractor error (a transient model or network error), the catch only re-threw — the already-dequeued batch was never put back, so those items were silently lost and never retried.

A follow-up review found the first fix was incomplete: a drain started by the debounce timer clears the pending timer before running, so the restore-only fix left the recovered batch queued with no scheduled drain. It would then not retry until some later enqueue happened to reschedule one, and would be lost if the process exited first.

Why This Change Was Made

  • The dequeued batch is restored to the front in original order (queue.unshift(...batch)) and the error is rethrown, so the existing caller still logs it.
  • The restore path re-arms the drain (scheduleDrainSoon), so a timer-fired transient failure retries on its own without depending on a later enqueue.
  • Terminal failures (auth or model errors, as classified by isTerminalExtractionError) are unchanged: they still cool down and drop the agent's queued items via openTerminalFailureCooldown.
  • The existing debounce is factored into one scheduleDrainSoon(debounceMs) helper and reused by enqueue, the overflow branch, and the restore path — mechanical reuse, not new scheduling behavior. The if (timer) return guard keeps at most one pending drain timer, so retries fire at the existing debounce cadence (default 15s), not in a loop.

User Impact

Inferred follow-up commitments are no longer silently dropped when extraction hits a transient error; the batch is retried and persisted instead of lost. No config, API, or channel surface changes; terminal auth or model failures behave exactly as before.

Evidence

pnpm test src/commitments/runtime.test.ts — focused regression suite, 12 tests passing. Highest-value cases:

  • restores and reprocesses a batch after a non-terminal extractor failure (restore plus retry, no duplicate persistence);
  • restores a failed batch to the front, preserving order across batches (ordering);
  • re-arms the drain after a timer-fired non-terminal failure with no later enqueue (the completeness fix; fails if the re-arm is removed).

Terminal behavior is held unchanged by keeps the existing drop/stop behavior on terminal extraction failures. Typecheck (pnpm tsgo:core, pnpm tsgo:core:test), oxfmt, and oxlint pass on the touched files.

Production change is limited to src/commitments/runtime.ts; the rest is tests in src/commitments/runtime.test.ts. A local, uncommitted Node script additionally drove the production queue, persistence, dedupe, and cooldown paths (only the extractBatch call injected to throw) and confirmed: the transient failure retained the batch with nothing persisted, the retry reprocessed exactly the two items once, a third drain did nothing, and a terminal No API key found failure dropped and did not retry. No live channel or provider run was performed.

Scope

This change is limited to the non-terminal extractor-failure path in drainCommitmentExtractionQueue (src/commitments/runtime.ts) and its colocated test. No CHANGELOG.md edit: this is an internal queue bug fix and release notes are generated at release time.

@openclaw-barnacle openclaw-barnacle Bot added size: M triage: mock-only-proof Candidate: PR proof only shows tests, mocks, snapshots, lint, typecheck, or CI. labels Jun 3, 2026
@clawsweeper

clawsweeper Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed June 28, 2026, 9:05 PM ET / 01:05 UTC.

Summary
The PR refactors commitment extraction drain scheduling, restores non-terminal failed batches to the front of the in-memory queue, re-arms retry scheduling, and adds colocated regression tests.

PR surface: Source +22, Tests +309. Total +331 across 2 files.

Reproducibility: yes. Current main has a source-reproducible path where drainCommitmentExtractionQueue removes a batch before extractor execution and rethrows a non-terminal error before restoration or persistence.

Review metrics: none identified.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🐚 platinum hermit
Patch quality: 🦞 diamond lobster
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:

  • [P2] Let the latest head finish required CI before merge.

Risk before merge

  • [P1] Required CI was still partly pending on head 183579b at review time, so merge should wait for the normal green-check gate.

Maintainer options:

  1. Decide the mitigation before merge
    Land the narrow restore-and-rearm fix after maintainer review and green required checks, while leaving durable queue persistence as a separate product decision.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge

  • No ClawSweeper repair lane is needed; the branch is focused and the remaining action is maintainer review plus required check completion.

Security
Cleared: The diff only changes in-memory commitment queue scheduling and colocated tests; it does not touch dependencies, CI, packaging, permissions, or secret handling.

Review details

Best possible solution:

Land the narrow restore-and-rearm fix after maintainer review and green required checks, while leaving durable queue persistence as a separate product decision.

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

Yes. Current main has a source-reproducible path where drainCommitmentExtractionQueue removes a batch before extractor execution and rethrows a non-terminal error before restoration or persistence.

Is this the best way to solve the issue?

Yes. Restoring the original batch at the extraction failure boundary and reusing the existing single-slot debounce is the narrowest maintainable fix; durable retry storage would be a larger follow-up design.

AGENTS.md: found and applied where relevant.

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

Label changes

Label justifications:

  • P2: This fixes a real hidden commitment extraction retry/data-loss bug with a focused runtime and test blast radius.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🦞 diamond lobster.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): The PR body includes focused test output and a local production-path Node run through enqueue, drain, store, retry, dedupe, and terminal cooldown behavior with only extractor failure injection.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes focused test output and a local production-path Node run through enqueue, drain, store, retry, dedupe, and terminal cooldown behavior with only extractor failure injection.
Evidence reviewed

PR surface:

Source +22, Tests +309. Total +331 across 2 files.

View PR surface stats
Area Files Added Removed Net
Source 1 30 8 +22
Tests 1 309 0 +309
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 2 339 8 +331

What I checked:

  • Current main behavior: Current main splices the batch before extractor execution and rethrows non-terminal extractor errors without restoring the removed items. (src/commitments/runtime.ts:295, 081f8fd1fa68)
  • Latest release behavior: Latest release v2026.6.10 has the same splice-then-rethrow path and no non-terminal restore/retry branch, so the fix is not already shipped. (src/commitments/runtime.ts:295, aa69b12d0086)
  • PR implementation: The PR head adds a shared single-slot debounce helper and restores non-terminal failed batches with queue.unshift(...batch) before scheduling another drain and rethrowing for logging. (src/commitments/runtime.ts:80, 183579b15e6a)
  • Regression coverage: The added tests cover restore and retry after transient failure, order preservation across batches, unchanged terminal drop behavior, overflow retry scheduling, and timer-fired retry without a later enqueue. (src/commitments/runtime.test.ts:422, 183579b15e6a)
  • Real caller path: Agent replies enqueue hidden commitment extraction after completed non-heartbeat turns, so losing a batch can suppress inferred follow-up commitments in real sessions. (src/auto-reply/reply/agent-runner.ts:1097, 081f8fd1fa68)
  • History and routing: GitHub path history shows the inferred commitments feature and follow-up fixes came through commits by vignesh07, with later runtime/test maintenance by steipete and shakkernerd. (src/commitments/runtime.ts:285, de19854cf42b)

Likely related people:

  • vignesh07: Authored and merged the inferred commitments feature and later commitments safety/model-selection fixes that established this runtime path. (role: feature owner / introduced behavior; confidence: high; commits: de19854cf42b, 347274ab9364, 8ffa3a8291e3; files: src/commitments/runtime.ts, src/commitments/runtime.test.ts, src/commitments/extraction.ts)
  • steipete: Recent commits touched commitment runtime cooldown behavior, documentation, normalization imports, and adjacent commitment tests. (role: recent area contributor; confidence: medium; commits: a4f62400a78b, 6f358fd8e0be, 6bc3458222aa; files: src/commitments/runtime.ts, src/commitments/runtime.test.ts, src/commitments/extraction.ts)
  • shakkernerd: Recent commits touched commitment runtime test isolation and import speed, making this person relevant if the regression suite needs follow-up. (role: adjacent test contributor; confidence: medium; commits: 1c5099803fdd, 72c789a8e53b, 7f0cde8d16dc; files: src/commitments/runtime.test.ts, src/commitments/runtime.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.

@clawsweeper clawsweeper Bot added 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. labels Jun 3, 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 3, 2026
@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. P2 Normal backlog priority with limited blast radius. 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. labels Jun 3, 2026
@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. 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. and removed rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. 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. labels Jun 14, 2026
@masatohoshino
masatohoshino force-pushed the fix/commitment-extraction-batch-loss branch from d6360b1 to 993d49a Compare June 20, 2026 06:31
@clawsweeper clawsweeper Bot added 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: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 🛠️ actively grinding The PR author has acted after the latest ClawSweeper review and work remains. 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. 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. labels Jun 20, 2026
@clawsweeper clawsweeper Bot added status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed status: 🛠️ actively grinding The PR author has acted after the latest ClawSweeper review and work remains. labels Jun 20, 2026
A drained extraction batch is spliced off the queue before the extractor
runs. On a non-terminal failure the batch was never restored, so those
items were silently lost and never retried. Restore the batch to the
front of the queue (original order) on non-terminal errors and rethrow so
the caller still logs; terminal model/auth errors keep the existing
cooldown drop/stop behavior. Also ensure the single-slot debounce
schedules a drain from the overflow branch, so a queue left full by a
restored batch still gets retried instead of being stuck.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vincentkoc
vincentkoc force-pushed the fix/commitment-extraction-batch-loss branch from 993d49a to 183579b Compare June 29, 2026 01:01
@vincentkoc
vincentkoc merged commit be0c40b into openclaw:main Jun 29, 2026
93 checks passed
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jun 29, 2026
…nclaw#89817)

A drained extraction batch is spliced off the queue before the extractor
runs. On a non-terminal failure the batch was never restored, so those
items were silently lost and never retried. Restore the batch to the
front of the queue (original order) on non-terminal errors and rethrow so
the caller still logs; terminal model/auth errors keep the existing
cooldown drop/stop behavior. Also ensure the single-slot debounce
schedules a drain from the overflow branch, so a queue left full by a
restored batch still gets retried instead of being stuck.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
QiuYuang pushed a commit to QiuYuang/openclaw that referenced this pull request Jul 1, 2026
…nclaw#89817)

A drained extraction batch is spliced off the queue before the extractor
runs. On a non-terminal failure the batch was never restored, so those
items were silently lost and never retried. Restore the batch to the
front of the queue (original order) on non-terminal errors and rethrow so
the caller still logs; terminal model/auth errors keep the existing
cooldown drop/stop behavior. Also ensure the single-slot debounce
schedules a drain from the overflow branch, so a queue left full by a
restored batch still gets retried instead of being stuck.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
@masatohoshino
masatohoshino deleted the fix/commitment-extraction-batch-loss branch July 1, 2026 14:53
chenyangjun-xy pushed a commit to chenyangjun-xy/openclaw that referenced this pull request Jul 1, 2026
…nclaw#89817)

A drained extraction batch is spliced off the queue before the extractor
runs. On a non-terminal failure the batch was never restored, so those
items were silently lost and never retried. Restore the batch to the
front of the queue (original order) on non-terminal errors and rethrow so
the caller still logs; terminal model/auth errors keep the existing
cooldown drop/stop behavior. Also ensure the single-slot debounce
schedules a drain from the overflow branch, so a queue left full by a
restored batch still gets retried instead of being stuck.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
chenyangjun-xy pushed a commit to chenyangjun-xy/openclaw that referenced this pull request Jul 3, 2026
…nclaw#89817)

A drained extraction batch is spliced off the queue before the extractor
runs. On a non-terminal failure the batch was never restored, so those
items were silently lost and never retried. Restore the batch to the
front of the queue (original order) on non-terminal errors and rethrow so
the caller still logs; terminal model/auth errors keep the existing
cooldown drop/stop behavior. Also ensure the single-slot debounce
schedules a drain from the overflow branch, so a queue left full by a
restored batch still gets retried instead of being stuck.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Rorqualx pushed a commit to Rorqualx/cortex that referenced this pull request Jul 4, 2026
…nclaw#89817)

A drained extraction batch is spliced off the queue before the extractor
runs. On a non-terminal failure the batch was never restored, so those
items were silently lost and never retried. Restore the batch to the
front of the queue (original order) on non-terminal errors and rethrow so
the caller still logs; terminal model/auth errors keep the existing
cooldown drop/stop behavior. Also ensure the single-slot debounce
schedules a drain from the overflow branch, so a queue left full by a
restored batch still gets retried instead of being stuck.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
(cherry picked from commit be0c40b)
Rorqualx pushed a commit to Rorqualx/cortex that referenced this pull request Jul 8, 2026
…nclaw#89817)

A drained extraction batch is spliced off the queue before the extractor
runs. On a non-terminal failure the batch was never restored, so those
items were silently lost and never retried. Restore the batch to the
front of the queue (original order) on non-terminal errors and rethrow so
the caller still logs; terminal model/auth errors keep the existing
cooldown drop/stop behavior. Also ensure the single-slot debounce
schedules a drain from the overflow branch, so a queue left full by a
restored batch still gets retried instead of being stuck.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
(cherry picked from commit be0c40b)
wheakerd pushed a commit to wheakerd/clawdbot that referenced this pull request Jul 15, 2026
…nclaw#89817)

A drained extraction batch is spliced off the queue before the extractor
runs. On a non-terminal failure the batch was never restored, so those
items were silently lost and never retried. Restore the batch to the
front of the queue (original order) on non-terminal errors and rethrow so
the caller still logs; terminal model/auth errors keep the existing
cooldown drop/stop behavior. Also ensure the single-slot debounce
schedules a drain from the overflow branch, so a queue left full by a
restored batch still gets retried instead of being stuck.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
(cherry picked from commit be0c40b)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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: M 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.

2 participants