decide the pg server-side stamp-arithmetic guard (review 004 item 5): the server expression owns it — the clamp domain is the arithmetic result, saturated to the i64 domain, no input clamped/validated at any seam; per-call args (heartbeat extend, retry override, lock ttl x2) have no enqueue to clamp at, QueueOpts verbatim-stamping is the review-002 posture, and the boundary row already pins argument totality — the annotation corrects the 'plain SQL integer add' form on pg (never total in the overflow domain), verified green against the Postgres 16 harness (both clamp edges, representable rides exact, now-MIN clamps to MAX); six sites of record (queue.rs:386/912/1000/715, lock.rs:92/217); window state verified open (no tag, no publish), dated class-1 annotation landed in ADR-023 §2; task -> completed

This commit is contained in:
glm-5.3-flash committed 2026-10-11 13:03:00 +00:00
1 parent 608104ab13
commit 60f7d02769
2 files changed
+138 -8

No files matched your search

@@ -170,7 +170,69 @@ offsets are total.** Each disposition answers to a decided principle:
checkpoint are the [ADR-019](019-mechanism-handle-surfaces.md) §6
monotone no-ops — rejections were never the behavior, so pinning
the duration row's shape here would have contradicted all three
engines.)*
engines.)
*(Annotation, 2026-10-11 — the pg stamp-arithmetic guard decision
([ADR-017](017-contract-versioning.md) §2 class 1, the window
verified open — no tag exists, no `cargo publish` has occurred; the
review-004 item-5 pre-fix precedent). Review 004's post-round finding:
pg's server-side stamp arithmetic — the claim's
`$2 + visibility_timeout_s` (claim deadline), the heartbeat's
`$3 + extend`, the retry-reschedule's `$2 + delay_s`, the retention
sweep's `$2 − dead_letter_retention_s`, and the lock stamp/renew's
`$3 + ttl` (`lock.rs:92/217`) — overflow-failed on plain bigint
("bigint out of range") and the failure is *sticky per row*, one
extreme-stamped row poisoning every later claim/heartbeat/sweep that
sums against it. The side question is here because the boundary row's
totality lives on the *argument* values these sums consume, and the
two candidate guards differ in what they touch: an enqueue-seam
clamp/validate owns the guard at the entry of the consumer-supplied
i64s; a server-expression guard clamps the arithmetic *result*.
**Decided: the server expression owns it — the clamp domain is the
sum's result, no input is clamped or validated at any seam.** The
enqueue seam cannot own the guard: four of the six arguments are
per-call (`heartbeat(extend)`, the `retry(err, Some(d))` override,
`try_lock`/`renew(ttl)` ×2) and have no enqueue to clamp at; and
where an enqueue does exist, a *result* saturation is what the
pinned posture already computes, not a new input rule — enqueue's
own stamps resolve in Rust `saturating_add` (`resolution.rs`, both
engines), the boundary row pins argument totality ("any i64 is
well-defined… no clamping, no rejection" — a caller's
`heartbeat(i64::MAX)` or `retry(err, Some(i64::MAX))` is a value,
not a violation), and `QueueOpts` stamps enter rows unvalidated
verbatim by the recorded review-002 disposition, so validating them
at entry would be a *posture change*, not a guard. The guard form,
precise: **every server-side stamp expression saturates its result
to the i64 domain** — `LEAST(GREATEST(<sum computed in numeric>,
-9223372036854775808), 9223372036854775807)::bigint`, subtraction
sites analogously — verified green against a Postgres 16 harness: an
overflowing sum clamps at either edge, a representable result rides
untouched (`1700000000 + i64::MIN` stays exact, matching Rust's
`saturating_add`), `now − i64::MIN` clamps to `i64::MAX` (matching
mem's retention `saturating_sub`). The extreme-stamped row's
observable semantics, per site: a row stamped
`visibility_timeout_s = i64::MAX` claims to the `i64::MAX` deadline
(the claim never lapses through expiry; effectively-never, the same
shape as sqlite's REAL-approximation and mem's saturation); a row
stamped `dead_letter_retention_s = i64::MIN` sweeps every dead row
(`sat(now − MIN) = i64::MAX`); `heartbeat(extend)` extremes renew to
the saturated edge (a past saturated deadline voids through the
validity predicate on the next op, the annotation above's negative
semantics preserved); `retry(err, Some(i64::MAX))` reschedules to
`i64::MAX` (ready ~never, the caller's value honored to the edge);
`ttl = i64::MAX` stamps an `i64::MAX` expiry. No contract text
changes: the table pins these dispositions already — what the
annotation completes is the *arithmetic form*, correcting the
"plain SQL integer add" parenthetical above: on pg the pinned
saturating arithmetic is realized as the server-side guard, not a
plain add, and the "bigint out of range" failure leaves the
reachable surface (no opaque-Err arm covers arithmetic overflow;
the duration row's rejection stays `ttl <= 0` only). Sites of
record: pg `queue.rs:386/912/1000/715`, `lock.rs:92/217`; enqueue
itself stays Rust-resolved (no SQL-side sum at enqueue). The
implementation rides `tasks/pg-fix-bigint-stamp-overflow.md` —
`cargo test -p alkstore-postgres` live-server legs pin the
sticky-poison retirement.)*
This is a **core-contract amendment** (doc text on `claim_batch`,
both `read` forms, `try_lock`/`renew`, and a shared domain-rule