Row-first gate: consumer-inventory.md gains an engine-tier section — the mem-engine need recorded operator-authority, dated 2026-10-10 (wasm32 sandboxing across the alk protocol family + downstream ffi/napi/python-adapter economics; rusqlite/tokio-postgres structurally out on wasm, so mem is the only triad member the sandbox can carry). ADR-024 (decisions/024-mem-engine.md) pins the decision set: (1) separate `alkstore-mem` crate — discharges and amends ADR-001 §4 (superseded in part: full contract-v1 engine, not an "implementation convenience"; annotation on ADR-001 §4 + Status, class-1 window still open); (2) honest-ephemeral posture — no durability, single-process, ephemeral by design, never fleet-valid (ADR-010 §3's shared-pool predicate fails structurally), riding ADR-016's carriers unchanged (identity + docs + matrix); (3) full contract v1 tier with the asymmetry classification — `PayloadTooLarge` never produced (SQLite arm), no reconnection concept (reconnect-wake/watcher rows absent from mem's per-engine column), receiver close at engine drop, wake coalescing N/A; (4) `MemStore::new()` engine-native constructor — the one documented exception to the open-prose, core-contract.md Store concept amended; shared-instance (two opens → one engine) rejected with the ADR-016 §4-style re-entry gate (consumer-inventory row), register stays closed; (5) wasm32 — compile-clean for wasm32-unknown-unknown plus the suite's mem column green on host under a current-thread runtime flavor are wave-6 acceptance items; on-target suite execution scoped out with a named collapse condition (wasm-bindgen-test adapter crate) — a scope decision, not a pending-client hedge; (6) mem is not a core dev-dependency — core's doc examples stay mock-based, ADR-001 §4's doctest posture declines. engine-mem.md (draft): the in-process mapping — guarded per-mechanism state (no pool, no schema bootstrap, no forwarder, no spawn_blocking seam), the tx overlay (staged *_tx effects merged atomically at commit; read-your-own-writes easy, drop-=-rollback trivial; wake-at-commit structural — the seam pg needed pg-fix-tx-wake for, mem pins from birth via the existing tx-commit-atomicity rows), ADR-012 §2 third owner of the curve/opts/@every arithmetic (three-way equivalence, ADR-022's StoreFactory reused verbatim — born pinned). deployment.md: host-semantics row (single-process, ephemeral, never fleet-valid, wasm32-clean), mem connection-budget subsection (none — nothing to budget), durability-knobs row (the honest row is the absence), toolchain row (wasm32 subset + current-thread-clean, acceptance-cited). README/overview: engine-mem.md row, ADR-024 row, family table entry (alkstore-mem, no driver deps), current-state updated to the implementation phase with engine specs' stable statuses reflected. implementation.md: wave table gains wave 6 (mem engine, depends waves 1 + 5) and renumbers release readiness to wave 7 (fuzzing decision — the one remaining decided-at-implementation deferral — rides wave 7); wave-6 section records the born-pinned posture, acceptance items, the one suite-harness pre-task (past_stamp_sleep blocking sleep → async sleep, review 003's properties.rs:1683 note), and the window riders (review 003 Finding 1: the pg transient-fault seam, MEDIUM, rides wave 6; Findings 2–3 follow their park into wave 7's pre-release); wave-6 review gate defined; Decided points updated (mem discharged, fuzzing renumbered); stale wave-6 references swept across review docs and the landed tasks' notes (release-readiness items renumbered or annotated). Docs-only change; verified by cross-reference audit (all ADR/OQ/anchor references resolve, residual wave-6 mentions are correct under the new numbering or carry dated annotations).
362 lines
20 KiB
Markdown
362 lines
20 KiB
Markdown
---
|
||
id: review-wave-4
|
||
name: Review gate — wave 4 (Postgres engine)
|
||
status: completed
|
||
depends_on: [pg-engine-integration]
|
||
scope: moderate
|
||
risk: low
|
||
impact: phase
|
||
level: review
|
||
tags: [wave-4, review]
|
||
---
|
||
|
||
## Description
|
||
|
||
Review the Postgres engine before wave 5 decomposes. Primary lens per
|
||
the plan's review gates: **engine-vs-contract conformance** — the same
|
||
discipline as the wave-3 gate, now against the second engine, with
|
||
the pg-specific machinery added. Wave 5 (the contract suite) pins
|
||
*cross-engine equivalence*; this gate checks the pg implementation
|
||
against the pinned contract text line by line.
|
||
|
||
Check:
|
||
|
||
- **Contract conformance**: every trait method's behavior against
|
||
core-contract.md's per-mechanism text — validation at entry points
|
||
(auto-commit AND tx paths), error arms (`Database`-only receivers,
|
||
`Codec` at payload seams, `LeadershipLost` vs clean stop), value
|
||
shapes (`Job`/`StreamEvent` field-for-field), the no-work-is-a-value
|
||
vocabulary (`None`/`false`/empty-`Vec` where pinned, never errors).
|
||
- **ADR-023 follow-through**: extent guards at trait-impl entry
|
||
(claims + all four stream reads); duration guards on both lock call
|
||
sites; `encode_payload` consumed fallibly at every call site.
|
||
- **ADR-016 §5**: the 8000-byte check is client-side, typed, before
|
||
any round trip, on both `notify` and `notify_tx`; the limit constant
|
||
has one owner.
|
||
- **Forwarder integrity** (the pg engine's own high-risk machinery —
|
||
the analogue of the wave-3 gate's seam-integrity lens): the two
|
||
POC-pinned deadlock pitfalls structurally excluded (poll loop
|
||
before first query; `Client` alive for the listener's lifetime);
|
||
reconnect backoff + re-LISTEN from the live channel set; the
|
||
synthetic reconnect-wake on the reserved string broadcast to every
|
||
subscriber; lag surfaced, not silent; receiver close semantics
|
||
exactly the pg arm (open across reconnects, close at shutdown
|
||
only, terminal, never reopens).
|
||
- **Seam integrity**: drop = rollback under panic; failed
|
||
COMMIT/ROLLBACK arms discard (not re-pool) the object — pool
|
||
accounting exact under error paths (deployment.md's ADR-021 note);
|
||
ops-after-consume fail closed; no `spawn_blocking` anywhere (the
|
||
natively-async posture — a stray bridge would be a finding).
|
||
- **Backoff curve + boundary math**: the engine-side formulas match
|
||
ADR-010 §3's pinned range/cap and ADR-009 §4's boundary guarantee
|
||
exactly (wave 5 pins cross-engine equivalence; this gate checks
|
||
this implementation against the text).
|
||
- **Schema posture**: one engine-owned schema; payload columns
|
||
`bytea` (exact bytes — no JSONB normalization); no per-queue
|
||
tables; bootstrap idempotent.
|
||
- **Backlog column**: the engine's suite rows present, stamped, green
|
||
against the pg factory; the `PayloadTooLarge` pg arm row present.
|
||
- **Family standards**: no panics, no unwrap/expect outside tests, no
|
||
inline comments (doc comments fine), module-per-file.
|
||
- **Gates**: full workspace build/test/clippy/fmt; the pg suite green
|
||
against the harness server.
|
||
|
||
## Acceptance Criteria
|
||
|
||
- [ ] Contract conformance spot-checked against the spec text (not
|
||
just the tests)
|
||
- [ ] ADR-023's numeric-domain + typed-encoding follow-through
|
||
verified at their sites
|
||
- [ ] Forwarder + seam integrity verified (code-read, not
|
||
test-name-trust)
|
||
- [ ] Backoff curve + scheduler boundary math match the pinned ADR
|
||
text
|
||
- [ ] Backlog column present, stamped, green against the pg factory
|
||
- [ ] All gates green (incl. against the harness server)
|
||
- [ ] Findings recorded; wave 5 decomposition may proceed
|
||
|
||
## References
|
||
|
||
- docs/plans/implementation.md (Review gates)
|
||
- docs/architecture/core-contract.md
|
||
- docs/architecture/engine-postgres.md
|
||
- docs/architecture/decisions/004-postgres-driver.md
|
||
- docs/architecture/decisions/016-deployment-honesty.md §5
|
||
- docs/architecture/decisions/023-fourth-review-round.md
|
||
- tasks/review-wave-3.md (the gate discipline's precedent)
|
||
|
||
## Notes
|
||
|
||
Review performed 2026-10-08 (opencode, glm-5.3-flash) — full code-read of
|
||
`alkstore-postgres/src` (all 13 machinery files + 9 test modules, ~4.4k
|
||
lib lines) against core-contract.md, engine-postgres.md, ADR-004/007/
|
||
008/009/010/015/016/019/020/021. **Zero conformance findings needing a
|
||
code change.** Two flake investigations and four recorded observations
|
||
(all documentation/coverage-shaped, deferred to wave 5's natural homes)
|
||
below.
|
||
|
||
Gate checklist record (code-read against the spec text, per the
|
||
acceptance criteria — not test-name-trust):
|
||
|
||
- **Contract conformance**: entry-point validation on every name-bearing
|
||
method, auto-commit AND tx paths, before any round trip
|
||
(`store.rs` wiring + all eleven `*_tx` in tx.rs; `InvalidName` for
|
||
empty/whitespace-only, `ReservedName` for prefixed, via core's
|
||
`validate_shared_name`/`validate_local_name`; stream-consumer/
|
||
owner/worker ids as local names). `Database`-only receivers
|
||
(`recv`/`save_offset` Err arms — `database_only` remap in stream.rs);
|
||
`Codec` at every payload/decode seam (encode + row decodes, no silent
|
||
fallback); `LeadershipLost` vs clean stop arms (acquire-refusal and
|
||
renewal-loss both return before any tick); `Closed` on consumed tx
|
||
shells and pool-checkout paths. Value shapes decoded through core's
|
||
`#[doc(hidden)]` constructors (18-column `Job` shape, `StreamEvent`
|
||
field-for-field, dead-visible `get_job` carrying `last_error`/
|
||
`died_at`). No-work vocabulary held (`Ok(None)`/`Ok(false)`/empty
|
||
`Vec` where pinned). Queue scoping (`WHERE queue = $2`) verified on
|
||
`get_job_tx`/`get_job`/`ack_batch`/`cancel`; the live-then-dead
|
||
select order matches the SQLite arm.
|
||
- **ADR-023 follow-through**: extent guards at trait-impl entry on
|
||
`claim_batch` (`n <= 0` → empty `Vec`), both auto-commit stream
|
||
reads, both tx stream reads, and `EventReceiver::read_since` — pg's
|
||
negative-`LIMIT`-is-a-server-error artifact unreachable. Duration
|
||
guards on both lock call sites (`try_lock`, `Lock::renew` —
|
||
`ttl <= 0` → opaque `Database`, detail in the source chain).
|
||
Boundary args total (negative `trim_to` deletes nothing, unguarded —
|
||
verified `id <= -7` matches no rows). `encode_payload` consumed
|
||
fallibly at all 8 call sites through the one `encode_payload_bytes`
|
||
alias; no silent fallback.
|
||
- **ADR-016 §5**: the 8000-byte check is client-side, typed
|
||
(`PayloadTooLarge { limit: NOTIFY_PAYLOAD_LIMIT }`), before any round
|
||
trip, on **both** `notify` and `notify_tx`; one owner of the limit
|
||
constant (`tx::NOTIFY_PAYLOAD_LIMIT`); predicate `len >= limit` (the
|
||
NUL-inclusive wire budget, probe-pinned in tx_tests); measured on the
|
||
serde_json serialization (the stored-bytes form).
|
||
- **Forwarder integrity**: pitfall 1 structurally excluded (the poll
|
||
task owns the `Connection` and is spawned before any client query
|
||
every generation; the command select keeps co-residency permanent);
|
||
pitfall 2 excluded (the loop owns the `Client` for the generation's
|
||
lifetime; drop only at shutdown or post-session-death). Reconnect:
|
||
50 ms → 2 s cap exponential, re-LISTEN from the live channel-set
|
||
snapshot (registry-write-first ordering so a registration is never
|
||
lost), synthetic reconnect-wake on the reserved string broadcast to
|
||
every subscriber (verified: it rides the raw fanout, and the
|
||
wake-per-receiver bridge passes it through with the channel filter's
|
||
explicit reserved-string arm). No-replay honesty pinned (the gap
|
||
test asserts the committed-during-gap notify is *not* delivered).
|
||
Lag surfaced not silent (`Lagged(n)` logged-and-skipped at both the
|
||
bridge loop and the stream subscriber). Receiver close semantics
|
||
exactly the pg arm: the broadcast subscription + bridge outlive
|
||
connection generations (close is shutdown-only — the fanout sender
|
||
take in `Forwarder::shutdown` plus the loop's clone at exit); a
|
||
backend kill delivers the reconnect-wake, not `None`; terminal; the
|
||
pinned tests assert never-reopens.
|
||
- **Seam integrity**: drop = rollback via the captured
|
||
`Handle::spawn` detached teardown (no current-context resolve —
|
||
panic-safe; the runtime-gone arm closes the session server-side and
|
||
the server aborts the open tx, so no ghost survives it); failed
|
||
COMMIT/ROLLBACK/BEGIN arms discard via `Object::take` (never
|
||
re-pool an unknowable-state client) — pool accounting exact under
|
||
error paths (the deferred-FK COMMIT-failure test pins it);
|
||
ops-after-consume fail closed (`Error::Closed`); `with_tx` derives
|
||
from the trait's provided method over `begin_tx`/commit/drop — no
|
||
engine override to audit. `grep spawn_blocking` over
|
||
`alkstore-postgres/src` matches only doc text; every op is a straight
|
||
`.await` through the held object (the natively-async posture holds —
|
||
no stray bridge). The one sync-signature bridge
|
||
(`EventReceiver::save_offset` → `drive_sync` on the dedicated idle
|
||
wake runtime) is documented at the site with its probed-arms
|
||
rationale — the honest sync→async seam, not a `spawn_blocking`
|
||
re-entrancy trick, and it carries no engine state.
|
||
- **Backoff curve + boundary math**: `backoff_delay_s` is
|
||
line-identical reasoning to the text — equal-jitter
|
||
`[base·2^(a−1)/2, base·2^(a−1)]` integerized inclusive, 3600 s cap,
|
||
attempt index = the post-claim row count, exponent clamp at 30
|
||
(saturating, never overflowing); statistical range pins at 400 draws
|
||
per tuple + the 1800..=3600 cap band + end-to-end row assertions.
|
||
Scheduler: `@every` parser matches the pinned grammar (`@every
|
||
<n><unit>`, s|m|h|d, positive n, checked_mul — cron/floats/zero/
|
||
unknown-units reject `InvalidSpec` pre-storage); first-fire =
|
||
`now + interval` (strictly after now); the one-firer-per-boundary
|
||
machinery is exactly ADR-009 §4's two layers — (a) leadership via
|
||
the engine's own lock machinery on `__alkstore_scheduler` (per-
|
||
instance owner token; loss returns `Err(LeadershipLost)` before any
|
||
tick, both at acquire and mid-run), (b) the row-locked `SELECT …
|
||
FOR UPDATE` tick in one pool tx with fire-enqueues + boundary
|
||
advance + soonest read committing together (crash mid-tick
|
||
refires); 64-cap catch-up with skip-forward strictly past now
|
||
(`(gap/interval + 1)·interval` in 128-bit, clamped at `i64::MAX`).
|
||
Resolved-stamps sets (plain 300/3/5/none, outbox 60/5/5, one
|
||
`max_attempts` override, delay-over-`run_at`, relative-`expires`,
|
||
one clock read per enqueue) match ADR-010 §3a / ADR-020 line for
|
||
line; the outbox derivation `__alkstore_outbox:{name}` is reserved
|
||
and unreachable by `enqueue_tx`/`queue()`.
|
||
- **Seam error mappings**: all four helper shapes map into the opaque
|
||
`Database` with the source chain preserved; no engine-specific
|
||
variants minted anywhere.
|
||
- **Schema posture**: one engine-owned schema (default `alkstore`,
|
||
`PgOpts`-parametrized), `bytea` payload columns asserted per-table
|
||
(schema_tests), bigserial offsets monotone-never-renumbered (gap
|
||
test), no per-queue tables (queues are rows), idempotent bootstrap
|
||
(triple-run converges), schema-prefixed index names (the co-tenant
|
||
silent-skip hazard documented and answered), identifiers quoted
|
||
through the one `quote_identifier` boundary (schema name is the only
|
||
consumer-supplied interpolation; injection-safe).
|
||
- **Backlog column**: 10 rows green against the pg factory (twice this
|
||
session): the exemplar name-validation row, the three ADR-023 rows
|
||
verified as the same suite functions the SQLite column runs (not
|
||
rewritten — `extent_clamp_semantics`,
|
||
`duration_refusal_on_non_positive_ttl`,
|
||
`payload_round_trip_stores_exact_encoding`),
|
||
`payload_too_large_produced_on_pg` (the pg arm of the asymmetry row,
|
||
stamped ADR-008 §5/ADR-016 §5/ADR-020 §4 — the SQLite task's
|
||
deferred adoption discharged), drop-rollback, in-tx-RYOW,
|
||
enqueue-opts-resolution, receiver-close-and-save-arms, plus the
|
||
factory-shape row. All carry `Contract stamp:` doc stamps per the
|
||
ADR-022 convention (`grep`-audited).
|
||
- **Family standards**: no panics in library code (the only `expect`s
|
||
outside `#[cfg(test)]` are the five Mutex-poisoned guards in
|
||
forwarder.rs and the wake-runtime build — documented, unwrap-free
|
||
elsewhere; one wake-runtime `expect` is a fixed-shape builder that
|
||
cannot fail, module-doc'd). No inline comments beyond the
|
||
correctness-constraint sites AGENTS.md's exception names (wake
|
||
postures, unknowable-state arms, the loss-decision owner,
|
||
predicate conjuncts — all non-obvious-behavior notes). Module-per-
|
||
file holds; `#[non_exhaustive]` policy respected (none on `PgOpts`);
|
||
core has no driver deps; `eprintln!` diagnostics at the five
|
||
swallowed-wake/lag sites match the SQLite twin's posture (the
|
||
logging story is a wave-7 item (release readiness), not a wave-4 defect).
|
||
- **Gates**: `cargo build`, `cargo test` server-less (25 core + 188
|
||
sqlite + 111 pg-skip + 10 + 10 suite + 3 + 9 harness), clippy
|
||
`-D warnings`, fmt — all green; the pg lib suite 111/111 green
|
||
against the harness server (two consecutive full runs, 2×47 s, plus
|
||
stream-module and suite-target re-runs).
|
||
|
||
**Flake investigation** (the two task agents' `tx_publishes_compose_with_the_handle`
|
||
report — see Summary below for the disposition): reproduced once in 53
|
||
solo runs and once in the first full-suite run of this session; wake
|
||
path code-read clean; the stand-alone binary probe that mirrors the
|
||
test's beats (64 runs) never missed (delivery latency ~20–210 ms).
|
||
Root cause unresolved at gate time — resolved engine-side by the
|
||
general review (see F-1's updates below).
|
||
|
||
Deferred (documented, not fixed — each needs its own small task or a
|
||
wave-5/6 decision; none is a consumer-visible defect):
|
||
|
||
- **F-1 — the `tx_publishes_compose_with_the_handle` flake is
|
||
open** (contradicting the streams/locks agents' "unrelated, wait for
|
||
wave 5" read: reproduced twice this session — once in a
|
||
first-of-session full lib run, once in a solo run; ~2/106 runs
|
||
total, all at the same site). **Update (2026-10-09): root cause
|
||
found by the wave-4 general review
|
||
(`docs/reviews/002-wave-4-general-review.md`, Finding 2) — the tx
|
||
enqueue/publish paths issue no `pg_notify` wake at all; the
|
||
subscriber's pre-commit drain parks on a wake that never comes. Fix
|
||
is engine-side (one `pg_notify` in `publish_with_key_tx`), not the
|
||
suite-hardening candidates below, which become
|
||
defense-in-depth.** **Update 2 (2026-10-09): retired —
|
||
`pg-fix-tx-wake` landed the engine-side fix.** The tx producer
|
||
paths (`publish_with_key_tx`, `enqueue_tx`, `outbox_enqueue_tx`)
|
||
now issue their `pg_notify` wakes commit-atomically inside the
|
||
caller's tx (stream name / queue name / derived backing queue as
|
||
the channel; rollback drops the row with its wake), pinned by
|
||
tests; `tx_publishes_compose_with_the_handle` is deterministic
|
||
(20 consecutive solo runs green). The suite-hardening candidates
|
||
below remain valid as defense-in-depth but are **no longer
|
||
load-bearing** for this flake. Correction to the facts below: the
|
||
"engine's wake path is honest — the tx INSERT's commit *is* the
|
||
NOTIFY carrier" conclusion was wrong (nothing on that path ever
|
||
sent a NOTIFY); the 64-run probe simply sampled the lucky
|
||
attach-read/drain-vs-commit ordering every time.
|
||
Failure signature: `must_recv_event`'s 15 s
|
||
deadline exhausts — the bridge's re-drain never fires after a
|
||
committed `publish_tx`. Facts established: the engine's wake path is
|
||
honest (the tx INSERT's commit *is* the NOTIFY carrier — verified by
|
||
the 64-run probe mirroring the test's beats, which never missed and
|
||
never even saw >210 ms; and by 6 whole-stream-module suite runs and
|
||
30 full-suite 8-thread runs, all clean); the delivery pipeline
|
||
introduces no artificial delay (no debounce/sleep — wake → re-drain
|
||
straight-line); the two test beats (the post-commit `try_recv`
|
||
drains and the two 200 ms sleeps) are all before the wait and only
|
||
make the test *late-poll*, not miss; and the deadline miss cannot be
|
||
a slow delivery (a 210 ms probe ceiling vs a 15 s deadline). The
|
||
residual suspicion therefore sits in the wake *subscription* path —
|
||
a `Lagged`/command-race interaction between the fresh receiver's
|
||
bridge and the forwarder under load — but no mechanism was proved,
|
||
and nothing in the code contradicts the contract. Recorded for wave
|
||
5's suite hardening (or a wave-5-adjacent test-infra task): the
|
||
candidate dispositions are (a) harden `must_recv_event`'s deadline
|
||
(a parked `recv().await` with a timeout wrapper instead of the
|
||
20 ms polling loop — the deadline assert then still bounds the
|
||
property), (b) a `LOG_LAGGED`-style diagnostic counter on the bridge
|
||
to discriminate "wake never arrived" from "wake arrived, re-drain
|
||
missed", and (c) leave the skip-posture deadline as-is and re-triage
|
||
on recurrence. Not decomposed now: the flake is test-infra, not
|
||
engine code, and (b)+(c) are the cheap first steps.
|
||
- **F-2 — `bridge_loop`'s filter drops non-subscriber channel
|
||
notifications *before* the reserved-string check is reachable in the
|
||
`&&`'s false path** — cosmetic only: the code is correct (the
|
||
reserved-wake arm matches), the observation is that the condition's
|
||
order matters and is load-bearing; a `//` note at the site would
|
||
help future readers. Not fixed: AGENTS.md's comment policy says
|
||
no inline comments unless load-bearing — this one arguably is, and
|
||
the site already carries a doc-comment explaining the mapping; left
|
||
as-is to avoid comment churn.
|
||
- **F-3 — `spawn_bridge`'s `spawned.is_finished() → abort()` guard**
|
||
(stream.rs:599): detects a bridge task that finished before the
|
||
receiver was even boxed (runtime-gone class) but the boxed receiver
|
||
would surface after the bridge died — honest, but it's a
|
||
probabilistic check (a task could finish between the check and the
|
||
return, an unavoidable race the guard narrows). The task's failure
|
||
arm (the mpsc disconnect) still delivers the terminal `None` — no
|
||
lie is surfaced either way. Noted for the wave-5 close-arm rows'
|
||
fidelity; no action.
|
||
- **F-4 — wake-channel naming is now realized in code but no doc
|
||
section states it for streams**: the plan's Wave 4 section (lines
|
||
174–182) records the decision, and `stream.rs`/`queue.rs` doc
|
||
comments name it ("the mechanism-name-is-the-channel realization"),
|
||
but `core-contract.md`'s streams/notify sections don't mention the
|
||
channel naming (they don't need to — it's engine-internal), while
|
||
the reserved reconnect string *is* a contract string. No action —
|
||
recorded here so wave 7's docs pass notices where the naming live.
|
||
|
||
Wave 5 decomposition may proceed.
|
||
|
||
## Summary
|
||
|
||
**Review gate passed: 0 conformance findings; 1 open flake recorded
|
||
(F-1) + 3 documentation/coverage-shaped notes (F-2..F-4, no action);
|
||
all gates green.**
|
||
|
||
The gate's primary lens (engine-vs-contract conformance, line-by-line
|
||
against core-contract.md and the ADRs) came back clean across every
|
||
checklist item: entry-point validation (both paths), error arms, value
|
||
shapes, no-work vocabulary, the ADR-023 guards at their pinned sites,
|
||
the ADR-016 §5 client-side typed 8000-byte check with one limit owner,
|
||
the forwarder's structural exclusions + reconnect + re-LISTEN +
|
||
reserved-string reconnect-wake + no-replay honesty + the pg close arm,
|
||
seam integrity incl. the unknowable-state discard arms and pool
|
||
accounting, the natively-async posture (no `spawn_blocking` anywhere),
|
||
the backoff curve and scheduler boundary math matching the ADR text
|
||
exactly, the one-schema/`bytea`/no-per-queue-tables posture, the
|
||
10-row backlog column (stamped, green against the pg factory, twice),
|
||
and family standards.
|
||
|
||
Gates at review time: `cargo build` / `cargo test` /
|
||
`cargo clippy --all-targets -- -D warnings` / `cargo fmt --check` all
|
||
green; the pg lib suite 111/111 green against the harness server
|
||
(2×47 s full runs + stream-module and suite-target re-runs).
|
||
|
||
The one thing this gate cannot close: the flagged
|
||
`tx_publishes_compose_with_the_handle` flake was **reproduced twice**
|
||
(~2/106 runs) and root-caused to neither engine code nor the test's
|
||
beat ordering — the engine's wake path is verified honest (64-run
|
||
stand-alone probe, whole-module and 30× full-suite runs clean); the
|
||
miss is a still-unexplained wake-subscription interaction under load.
|
||
Recorded as F-1 for wave 5's suite hardening (candidate dispositions
|
||
in Notes); the task agents' "wait for wave 5 if it recurs" posture is
|
||
adopted — it recurred, wave 5 gets the record. (Superseded
|
||
2026-10-09: the wake-path-honesty conclusion was wrong — the general
|
||
review root-caused the flake engine-side — and `pg-fix-tx-wake`
|
||
retired F-1; see F-1's updates in Notes.)
|
||
|
||
Wave 5 decomposition may proceed. |