Files
alkstore/tasks/suite-opts-backoff-rows.md
T
glm-5.3-flash 21074bbcdb Review gate — wave-5 suite passed (task review-wave-5): the suite stands as the compatibility instrument and the engine specs flip to stable. All 25 mechanism rows per engine column read in full and verified against core-contract.md §Verification backlog item by item (the appendix map's every claim confirmed by the pinning row/text, incl. the combined-coverage claim for save_offset_tx exactly-once and the five engine-side pins — SQLite open row, watcher-cadence knob, M-1 sweep-rollback: SQLite trigger seam live + the pg frame's in_tx structure code-read; beyond-64 skip-forward; cap-curve); all 25 'Contract stamp:' markers checked against the cited ADR § bodies (ADR-008 §3/§5/§7/§8, 009 §1/§3/§4/§6, 010 §1-§5, 014 §1, 015 §1-§5, 016 §5, 020 §1-§4, 021 §1/§3/§4/§5, 023 §1/§2, 012 §2, 019, 007, 006) — the enqueue_opts_resolution amendment accumulation rides ADR-023 §2 per the convention; all six parked dispositions audited and recorded (M-1 engine-side, skip-forward engine-side twins, cap engine-side, fire-wake parity not demanded, lock busy-path no divergence, reconnect-success test taken); conformance spot-checks clean (no row pins beyond ADR text, determinism posture holds incl. the two documented extensions, cross-references not duplication). Green on both engines this session: workspace build/test/clippy -D warnings/fmt; SQLite column 25/25 server-less twice (isolated + concurrent); pg column 25/25 vs the harness server three full runs (two consecutive + one concurrent with the SQLite column) plus 6 focused --test-threads=6 stress runs of the two development-time flake rows — all clean, the two unreproducible pg failures recorded with the bounded investigation and a wave-6 watch flag in the task's Notes. Docs: engine-sqlite.md and engine-postgres.md frontmatter status draft → stable with dated annotations citing this gate; implementation.md wave-table row 5 and review-rounds entry; suite-opts-backoff-rows.md placeholder remnants removed. Wave 6 (release readiness) decomposition may proceed
2026-10-10 08:13:17 +00:00

152 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: suite-opts-backoff-rows
name: Contract-suite rows — backoff-curve equivalence + the deferred enqueue-opts clock legs
status: completed
depends_on: []
scope: narrow
risk: low
impact: phase
level: implementation
tags: [wave-5, contract-suite, queues]
---
## Description
Complete the arithmetic-equivalence backlog rows
(core-contract.md §Verification backlog): "Backoff-curve and
stamp-resolution equivalence across engines" and the two
wall-clock-adjacent legs the existing `enqueue_opts_resolution` row
explicitly deferred ("The `run_at`-alone-literal and
neither-field-resolves-to-now legs ... pin with wave 5's equivalence
row").
Work:
- **Extend `enqueue_opts_resolution` in place** (one owner per
property — the row's own doc comment names this wave-5 completion;
stamps accumulate per the convention): the `run_at`-alone literal
leg (a future `run_at` is the row's ready time verbatim; a past
`run_at` resolves to ready-now — the boundary-total rule, ADR-023
§2) and the neither-field leg (ready now — tolerance-bounded
proximity, never a tight timing assert).
- **Add `backoff_curve_equivalence`** — the equal-jitter exponential
curve (ADR-010 §3): `delay ∈ [base·2^(a−1)/2, base·2^(a−1)]` per
attempt, uniform jitter over the lower half — *the range, not a
jitter label, is the definition*. Drive claim → `retry(err, None)`
cycles on a queue with a small `backoff_base_s` stamp (2 s keeps
the integer-second row resolution honest: ranges [1,2], [2,4],
[4,8] across the first attempts; the inter-attempt waits stay
tolerance-bounded and sequential), reading the computed delay back
via `get_job`'s `run_at` minus now, asserting range membership per
attempt on both engines — identical bounds is the equivalence pin
(ADR-012 §2: engine-side arithmetic, suite-pinned identical
outputs). Include the explicit-delay override leg
(`retry(err, Some(d))` honored — a `Some(0)` resolves ready-now per
the boundary-total rule). **The 1-hour cap leg is not
suite-pinnable** (reaching capped attempts requires waiting out
minute-scale delays); it stays pinned engine-side (both engines'
unit tests already pin the curve against the ADR text — the
wave-3/4 reviews verified it) — record that disposition in Notes
for the review gate.
## Acceptance Criteria
- [ ] `enqueue_opts_resolution` extended with both clock legs; its
doc comment's deferral note updated (stamps accumulate)
- [ ] `backoff_curve_equivalence` exists, version-stamped (ADR-010 §3,
ADR-020 §1–§3, ADR-012 §2, ADR-023 §2)
- [ ] Rows wired into both engines' `contract_suite.rs` targets
- [ ] SQLite column green server-less; pg column green against the
harness server
- [ ] The cap-leg disposition recorded in Notes
- [ ] `cargo test -p alkstore-sqlite -p alkstore-postgres` green
(pg rows skip cleanly server-less); clippy `-D warnings`; fmt clean
## References
- docs/architecture/core-contract.md §Verification backlog (backoff-curve
and stamp-resolution equivalence; enqueue-opts resolution equivalence)
- docs/architecture/decisions/010-queue-semantics-depth.md §3
- docs/architecture/decisions/020-enqueue-opt-semantics-and-bridges.md §1–§3
- docs/architecture/decisions/012-forked-substrate-design.md §2
- alkstore-contract-suite/src/properties.rs (`enqueue_opts_resolution`'s
deferral note)
## Notes
- **The 1-hour cap leg is not suite-pinned** (as pre-decided): reaching
capped attempts requires waiting out minute-scale delays. The cap
stays pinned engine-side — both engines' unit tests pin the curve
against the ADR text including the cap (SQLite's
`backoff_curve_lands_in_the_pinned_range` and the pg twin, verified
in the wave-3/4 rounds); the disposition is recorded in the row's
doc comment for the review gate.
- **Observation tolerance convention for the curve row**: the
computed delay is read back as `get_job`'s `run_at` minus a clock
read taken *before* the `retry(err, None)` call. That direction is
deliberate and race-free on the lower side: the retry's internal
clock read (SQLite's `unixepoch()` in-statement, pg's Rust-side
engine read) cannot precede the suite's, so the observed value
*over-reads* the delay, never under-reads — the pinned lower bound
is exact. The upper bound carries a one-second straddle tolerance
(retry commit and suite read may cross a wall second, and the
engines' stamps are integer seconds, ADR-010 §3's integerized
resolution). Asserted as a `(lower..=upper+1)` range membership; the
*identical* assertion on both engines is the equivalence pin
(ADR-012 §2's identical-outputs rule) — the row body is shared, so
the bounds are identical by construction.
- **Base 2 s kept the integer-second row resolution honest** per the
task text: ranges [1,2], [2,4], [4,8] across attempts 1–3 (the a=1
pin is inherently weak at one-second resolution — lower bound 1 with
upper ±1 — but the attempt-2/3 ranges are genuinely discriminating,
and the explicit-delay legs pin the exact-literal resolution).
- **Past-run_at leg stores the literal too**: the pin on the past leg
is the *claim semantics* (ready-now through the `run_at <= now`
predicate, bounded-wait claimable) and the stored literal (no
arithmetic on any form) — "resolves to ready now" is the claim-
predicate reading of the boundary-total rule (ADR-023 §2), not a
clamping of the stored value; both engines store verbatim
(`resolution.rs` twins verified).
- **Claim-polling observation posture**: both rows' ready-now waits
are bounded `claim_one` poll loops (100/50 ms cadence), deadline
asserts only — no timing-value assertions, single-store sequential
drive within the module doc's determinism posture.
- **One unreproducibility note on the helper**: the first draft made
`await_claimable` re-claim after the bounded wait, which found
nothing (the bounded wait consumed the claim); the helper returns
the claimed handle. Found on the first SQLite run, no engine-side
hazard.
- No ADR amendments needed; no divergences found (both engines'
arithmetic agreed out of the box — the equivalence pin held on the
first full run pairs).
## Summary
`enqueue_opts_resolution` extended in place with the wave-5
completion legs (its deferral note replaced by the completion
statement, ADR-023 §2 stamp accumulated): the `run_at`-alone literal
leg (future `run_at` = the row's ready time verbatim — a
deterministic equality, no clock read involved; past `run_at` stored
verbatim too and *claimable now* within a bounded-wait claim, the
run_at-ASC ordering making the observation unambiguous among the
row's other legs) and the neither-field leg (ready now at the
enqueue instant, `abs_diff(now) <= 5` tolerance-bounded proximity —
never a tight timing assert). New `backoff_curve_equivalence` row:
claim → `retry(err, None)` cycles on a `backoff_base_s = 2` queue
(ranges [1,2], [2,4], [4,8] per attempt, asserted as `(lower..=upper+1)`
range membership of `run_at − now_pre` with the race-free lower
bound and one-second straddle tolerance documented), reading each
computed delay back through `get_job`'s resolved `run_at`; the
explicit-delay override legs ride the same row (`Some(5)` honored
verbatim in [5, 6]; `Some(0)` resolving ready-now per the
boundary-total rule, claimed within a bounded wait). Stamped ADR-010
§3, ADR-020 §1, ADR-012 §2, ADR-023 §2. Both rows wired into both
engines' `contract_suite.rs` targets (SQLite `#[tokio::test]`, pg
`harness_row!`) — 25 rows per column, up from 24. Verified: SQLite
column green server-less (25/25 suite, 189 lib), pg column green vs
the harness server (postgres/poc@:15432 — 25/25 suite, 121 lib + 9
schema), 3 solo re-runs of each new/extended row per engine
(determinism), server-less pg column skips cleanly (25 "passed" via
the reachability gate), `cargo test -p alkstore-sqlite -p
alkstore-postgres` green, clippy `-D warnings`, fmt clean.