Skip to content

T9: daemon backfill sweep driver on the existing tick loop - #568

Merged
philcunliffe merged 1 commit into
integration/openclaw-two-lane-capturefrom
task/openclaw-two-lane-capture/T9
Aug 1, 2026
Merged

T9: daemon backfill sweep driver on the existing tick loop#568
philcunliffe merged 1 commit into
integration/openclaw-two-lane-capturefrom
task/openclaw-two-lane-capture/T9

Conversation

@philcunliffe

Copy link
Copy Markdown
Contributor

Implements task T9 of openclaw-two-lane-capture.

New src/core/daemon/backfill_sweep.js: createBackfillSweepDriver({backfills, backfillMaterializers, env, config, storage}) whose tick({now}) walks backfills.list(), skips contributions with no sweep field or a not-due cronMatches (imported from src/core/sinks/driver.js), and fires runBackfillProvider per due contribution with a sweep-<name>-<now> dev run id. The fired promise's rejection is logged (component openclaw, operation backfill.sweep, error_kind) rather than left unhandled.

src/core/daemon/runtime.js's runTick() calls await sweepDriver.tick({now}) right after the existing sink-driver tick, inside the same DEFAULT_TICK_INTERVAL_MS = 60_000 loop. No new timer.

Also repairs the typecheck the branch point already failed on: T7's opts.config?.backfill?.sweep_cron does not compile against a JsonObject config slice; it now reads through a resolveSweepCron mirroring the resolveQuiesceMs helper beside it, behavior unchanged.

Externally blocked for real capture (PR #552): until the LLP 0158 reader projects OpenClaw v3's nested message envelope, a sweep captures nothing from a real transcript. These tests passing is not evidence that it does.

npm test (3326 pass, 0 fail), npm run typecheck, and npm run smoke -- daemon_foreground_start_stop all pass.

Task-Id: T9

… loop

New `src/core/daemon/backfill_sweep.js`. `createBackfillSweepDriver({backfills,
backfillMaterializers, env, config, storage})`'s `tick({now})` walks
`backfills.list()`, skips any contribution with no `sweep` field or a cron that
is not due (`cronMatches`, the sink driver's own due-check), and fires
`runBackfillProvider` per due contribution with a `sweep-<name>-<now>` dev run
id. Runs are fired unblocked: `tick()` resolves once each run has been started,
never once one finishes, so a provider's transcript scan cannot stall the sink
snapshots, the source-detail refresh, or `persist()` later in the same tick. Both
settlements are handled, so a failing run is a logged `backfill.sweep_failed`
record (component `openclaw`, operation `backfill.sweep`, `error_kind`) rather
than an unhandled rejection that would take the daemon process down. A malformed
`sweep.cron` is logged and treated as not due rather than thrown, so one
provider's bad metadata cannot skip the rest of the list.

`runtime.js`'s `runTick()` calls `await sweepDriver.tick({now})` directly after
the existing sink-driver tick, riding the same `DEFAULT_TICK_INTERVAL_MS`
60-second loop: a `*/5 * * * *` schedule only needs a due-check once a minute, so
this opens no second timer to start, drain, and account for at shutdown.

Also repairs the typecheck this task's branch point already failed: T7's
`sweep: { cron: opts.config?.backfill?.sweep_cron ?? ... }` does not compile,
because the plugin's config slice is a `JsonObject` and every step below its root
is a `JsonValue`. Read through a `resolveSweepCron` mirroring the
`resolveQuiesceMs` helper already sitting beside it; behavior is unchanged.

Externally blocked for real capture: until PR #552 (issue #543) merges, the
LLP 0158 reader still reads OpenClaw v3 fields flat, so a sweep projects nothing
from a real transcript. These tests passing is not evidence that it does.

Tests: the due-check fires only sweep-bearing, cron-due contributions and builds
the narrowed `BackfillRunnerContext` from the daemon's own runtime fields; a
rejected run neither throws out of `tick()` nor lands as an unhandled rejection,
and a never-settling run does not block the tick. A separate wiring test boots a
real daemon with a fixture plugin whose contribution opts into a sweep and proves
the tick actually runs it, which no unit test of the driver can show.

Task-Id: T9
@philcunliffe
philcunliffe merged commit 20f3a15 into integration/openclaw-two-lane-capture Aug 1, 2026
7 of 9 checks passed
@philcunliffe
philcunliffe deleted the task/openclaw-two-lane-capture/T9 branch August 1, 2026 00:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant