Skip to content

feat(manifest): seed a first boot from a declared start_block - #381

Merged
mfw78 merged 1 commit into
mainfrom
feat/event-trigger-start-block
Aug 31, 2026
Merged

mfw78 merged 1 commit into
mainfrom
feat/event-trigger-start-block

Conversation

@mfw78

@mfw78 mfw78 commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Why

An event trigger opens at head when no cursor is stored. A module whose state derives only from logs therefore starts blind, and stays blind about anything that happened before it first ran. History it never saw is history it can never rebuild, because a contract event emitted before the daemon's first boot is not recoverable from any later block.

resume fixed the restart case by persisting a cursor. It does not help the first boot, which has no cursor to resume from.

The motivating case is shepherd's ComposableCoW keeper. A conditional order is registered by a ConditionalOrderCreated log and can stay live for weeks. A TWAP created last month and halfway through execution is invisible to a daemon that starts at head, so it is never polled and never submitted.

What changed

[[trigger]] on = "event" gains an optional start_block, normally the contract's deployment block.

It seeds initial_cursor only while no stored cursor exists. Once the first bulk chunk commits its frontier, the store wins for good, so the seed is a one-time floor and not a rescan point.

The manifest refuses start_block without resume = true. Without a durable cursor the seed would apply on every open, turning a one-time backfill into a full rescan after every restart. That refusal is a typed variant with pinned operator wording, and start_block_without_resume joins the pinned error-kind label set.

What did not change

The backfill path is untouched. initial_cursor already drove the chunked bulk phase with a per-chunk durable frontier, so a deep first backfill chunks at the operator-declared range, commits as it goes, and resumes at the last completed chunk if interrupted. This PR only supplies the seed that path already accepted.

A trigger without start_block still opens at head, so no existing manifest changes behaviour. max_lookback still bounds how far back a backfill reaches and composes with the seed unchanged.

Verification

958 tests pass, fmt and clippy clean at -D warnings.

Three new tests cover the semantics rather than the plumbing: the seed reaches initial_cursor on an empty store; a stored cursor outranks it, so a restart never rescans; and a resuming trigger without a seed still starts at head. The manifest test pins both the accepted shape and the refusal wording.

AI Assistance: Claude Code used for the manifest field, the cursor seeding and the tests.

An event trigger opens at head when no cursor is stored, so a module
whose state derives only from logs starts blind. History it never saw
is history it can never rebuild: a contract event emitted before the
daemon first ran is not recoverable from any later block.

`resume` fixed the restart case by persisting a cursor, but the first
boot has no cursor to resume from. `start_block` supplies that seed,
normally the contract's deployment block, so a fresh daemon backfills
the contract's whole history before it goes live.

The seed applies only while no stored cursor exists. Once the first
bulk chunk commits, the store wins for good, so this is a one-time
floor rather than a rescan point. The manifest refuses `start_block`
without `resume`, which would otherwise re-apply the seed on every
open and rescan the whole range after each restart.

No behaviour changes without the new key: an absent `start_block`
still opens at head. The backfill path itself is untouched, since
`initial_cursor` already drove chunked bulk fetches with a per-chunk
durable frontier.

`start_block_without_resume` joins the pinned error-kind label set.

AI Assistance: Claude Code used for the manifest field, the cursor
seeding and the tests.
@mfw78
mfw78 force-pushed the feat/event-trigger-start-block branch from fc39572 to beba849 Compare August 31, 2026 04:37
@mfw78
mfw78 merged commit 2ed882f into main Aug 31, 2026
7 checks passed
@mfw78
mfw78 deleted the feat/event-trigger-start-block branch August 31, 2026 04:47
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