review-004-fixes gate passed — all sixteen dispositions verified by code-read against the review's failure mechanisms (armor/state-machine/hardening/decision changes structurally match their tasks' Notes of record; every injected-panic/death/interleave test drives the real mechanism); no regressions among the review-004 inline fixes' pinned postures (tick drop-+-replenish, raw tx-form seed + mem has_offset_row, MAX_SLEEP_S caps, saturating claim stamp, register-failure unregisters, poison-recovery idiom, encode depth 127); records landed — review 004's recorded-findings items annotated with dispositions/task pointers (record reads closed), implementation.md gains the fix-batch review-rounds entry, task-file audit done with three minor hygiene defects fixed inline (stale placeholder lines incl. pre-existing ones in review-wave-3/release-readme, completed-AC checkboxes left unticked on five batch tasks, the gate description's fifteen→sixteen task count); gates green this session: build, server-less workspace tests, full live pg column vs harness pglo-poc (135+26+9), clippy -D warnings, fmt --check, fuzz corpus replay 6/6, wasm32 mem check, doc gate zero warnings, taskgraph validate (96); task -> completed
This commit is contained in:
1 parent
23cf0e7046
commit
609dc3b39c
12 files changed
+318
-58
No files matched your search
@@ -52,6 +52,11 @@ or distributed machinery whose repair exceeds a review fix, or are
|
||||
conscious postures to record. None blocks the release; each names its
|
||||
shape so a future session can decompose without re-deriving.
|
||||
|
||||
*(Dispositions, 2026-10-11: all sixteen items decomposed into the
|
||||
`review-004-fixes` fix batch — the sixteen `tasks/*` files below each
|
||||
carry the per-item decisions of record and verification — and the
|
||||
batch's gate audited them all landed. The record reads closed.)*
|
||||
|
||||
1. **sqlite seam panic-safety (defense-in-depth)** —
|
||||
`with_writer`/`with_reader`/`blocking_read` (`alkstore-sqlite/src/seam.rs`,
|
||||
`substrate/schema.rs`) release their slot/pool connection after the
|
||||
@@ -66,6 +71,9 @@ shape so a future session can decompose without re-deriving.
|
||||
needs abandonment plumbing on both `Writer` (drop + path-based
|
||||
replenish) and `Readers` (an outstanding decrement), which is a
|
||||
deliberate small design task, not an inline patch.
|
||||
*Disposition: landed via `sqlite-fix-seam-panic-safety` (RAII
|
||||
`WriterLease`/`ReaderLease` guards, drop-not-release, replenish/
|
||||
abandon dispositions; injected-panic tests in `store/seam_tests.rs`).*
|
||||
2. **sqlite post-watcher-death subscribe hang** — after the watcher
|
||||
thread exits (db-file replacement), `subscribe()` still enrolls new
|
||||
senders with no poller alive (`substrate/watcher.rs:391-396`): a
|
||||
@@ -74,6 +82,9 @@ shape so a future session can decompose without re-deriving.
|
||||
closes" posture (enforced only for pre-death subscribers). Needs a
|
||||
dead-store/dead-watcher sign that new subscription paths consult —
|
||||
a state-machine change across `store.rs`/`notify.rs`/`stream.rs`.
|
||||
*Disposition: landed via `sqlite-fix-watcher-death-subscribe` arm
|
||||
(a) — the dead sign set before the fatal exit, fallible `subscribe`
|
||||
failing closed under the senders lock.*
|
||||
3. **sqlite watcher initial-stat failure self-kill** — an
|
||||
identity-`stat` failure at watcher start seeds `(0, 0)`
|
||||
(`watcher.rs:164-170`); the first *successful* later stat mismatches
|
||||
@@ -81,6 +92,9 @@ shape so a future session can decompose without re-deriving.
|
||||
on recovery from a transient stat hiccup. Rare, but the fix (an
|
||||
identity-unknown state instead of a false identity) is another
|
||||
watcher-state change — bundle with item 2 if either is taken up.
|
||||
*Disposition: bundled with item 2 in `sqlite-fix-watcher-death-
|
||||
subscribe` arm (b) — the `Option<(u64, u64)>` identity-unknown
|
||||
baseline; the first successful stat captures without driving death.*
|
||||
4. **pg forwarder register/unregister TOCTOU** — the registry refcount
|
||||
and the LISTEN/UNLISTEN command emission are not one critical
|
||||
section (`forwarder.rs:131-176` vs `438-482`): interleaved
|
||||
@@ -90,6 +104,10 @@ shape so a future session can decompose without re-deriving.
|
||||
re-issue. The fix is a decide-and-queue restructure inside the
|
||||
forwarder — forwarder surgery that should ride its own session with
|
||||
the existing test-seam vocabulary.
|
||||
*Disposition: landed via `pg-fix-forwarder-hardening` (a) —
|
||||
`ChannelSet::enqueue_register`/`enqueue_unregister` make the
|
||||
refcount decision and the command enqueue one critical section
|
||||
under the registry guard; replay-proven both ways.*
|
||||
5. **pg server-side BIGINT overflow on consumer stamps** — the claim,
|
||||
heartbeat, retry-reschedule, and retention-sweep statements compute
|
||||
server-side sums over consumer-supplied i64 values
|
||||
@@ -102,6 +120,10 @@ shape so a future session can decompose without re-deriving.
|
||||
guard the server expressions) — but the *which side* question is
|
||||
contract-adjacent (ADR-023 §2's totality wording) and deserves its
|
||||
own decision, not an inline patch.
|
||||
*Disposition: `pg-decide-stamp-arithmetic-side` decided the server
|
||||
expression owns the guard (result-domain saturation, no input
|
||||
clamp); `pg-fix-bigint-stamp-overflow` landed it as
|
||||
`saturating_stamp_expr` at the six sites, pinned live.*
|
||||
6. **pg forwarder hang-shaped arms** — two narrow ones: a failed
|
||||
generation-verify/LISTEN batch is treated as connection death and
|
||||
parks on `poll_task.await` forever even though the session may be
|
||||
@@ -110,8 +132,13 @@ shape so a future session can decompose without re-deriving.
|
||||
awaiting a command on a black-holed connection (the `run_command`
|
||||
await sits outside the shutdown `select`, `forwarder.rs:781`, no
|
||||
timeout on this connection). Both want the same treatment family —
|
||||
timeouts/bounded waits on the listener path — bundle into the
|
||||
forwarder-hardening session (item 4).
|
||||
timeouts/bounded waits on the listener path — bundle into the
|
||||
forwarder-hardening session (item 4).
|
||||
*Disposition: both bundled into `pg-fix-forwarder-hardening` (b/c)
|
||||
— the `bounded_wait` primitive bounds every listener-path await
|
||||
(`LISTENER_QUERY_TIMEOUT` 5 s / `LISTEN_SETTLE_TIMEOUT` 2 s,
|
||||
shutdown-selected), the failed-verify settle aborts at the bound;
|
||||
the black-hole proxy harness test pins the close-time reclaim.*
|
||||
7. **pg forwarder diagnosability** — the reconnect arm's connect
|
||||
failures are swallowed with `.ok()` and the loop's exit discards the
|
||||
poll error (`forwarder.rs:825/855-869`): an operator sees nothing
|
||||
@@ -119,22 +146,36 @@ shape so a future session can decompose without re-deriving.
|
||||
log facade and 17 library-path `eprintln!` sites carry its
|
||||
diagnostics (verified secret-free — no DSN/password material ever
|
||||
printed). A `log`/`tracing` adoption decision is a family-level
|
||||
call; recorded rather than made here.
|
||||
call; recorded rather than made here.
|
||||
*Disposition: `decide-log-facade-adoption` adopted `tracing`
|
||||
(ADR-025, engine crates only, user sign-off 2026-10-11; all 19
|
||||
library-path `eprintln!` sites migrated, substrate sites riding
|
||||
delta D-41) and `pg-fix-forwarder-diagnosability` surfaced the two
|
||||
arms (`warn` on failed reconnect connects with attempt/backoff
|
||||
context, `error` on the poll-exit ending).*
|
||||
8. **sqlite listener-bridge asymmetry** — `listen()` parks one
|
||||
`spawn_blocking` thread per subscription (`notify.rs:98-104`, tokio
|
||||
blocking-pool ceiling ~512) while the stream bridge does the
|
||||
identical job on a dedicated `std::thread`
|
||||
(`stream.rs:368-379`); past ~500 concurrent listeners the *whole*
|
||||
engine's seams queue behind parked bridges. Aligning the two
|
||||
bridges (std-thread shape) is a small contained change deferred
|
||||
alongside item 2's subscription-path work.
|
||||
bridges (std-thread shape) is a small contained change deferred
|
||||
alongside item 2's subscription-path work.
|
||||
*Disposition: landed via `sqlite-fix-listener-bridge-alignment` —
|
||||
the listen bridge takes the stream bridge's named std-thread shape
|
||||
exactly (including the spawn-failure fail-closed arm).*
|
||||
9. **sqlite run_schedules error flattening** —
|
||||
`lease.renew(...).await.unwrap_or(false)` maps any renew failure
|
||||
(including the closed-store `Database` error) to `LeadershipLost`
|
||||
(`scheduler.rs:205-211`), misdirecting the documented respawn recipe
|
||||
at a dead store. Small, but the right arm set (closed vs lost vs
|
||||
storage failure) is a contract-adjacent error-classification change
|
||||
on a stable surface — record, don't rush.
|
||||
on a stable surface — record, don't rush.
|
||||
*Disposition: `sqlite-fix-scheduler-error-classification` landed the
|
||||
loss-vs-failure arm set (`Ok(false)` stays `LeadershipLost`; a
|
||||
failed renewal propagates its opaque classification) with the dated
|
||||
ADR-009 §1 annotation; the pg twin discovered mid-batch landed via
|
||||
`pg-fix-scheduler-error-classification`, implementing to match.*
|
||||
10. **mem growth postures (N-1 family)** — two perf/posture notes to
|
||||
carry into the mem spec's growth section when next touched: the
|
||||
subscribe path drains the full backlog into the receiver's pending
|
||||
@@ -143,20 +184,32 @@ shape so a future session can decompose without re-deriving.
|
||||
"drains to the tail then parks" shape, but unbounded on the
|
||||
consumer side); the claim path is an O(total-live-rows) scan with
|
||||
full-row clones per claim (`queue.rs:122-181`) — blessed economics
|
||||
for the ephemeral tier, worth one sentence in `engine-mem.md` if
|
||||
ever revisited.
|
||||
for the ephemeral tier, worth one sentence in `engine-mem.md` if
|
||||
ever revisited.
|
||||
*Disposition: landed via `mem-doc-growth-outbox-notes` arm (a) —
|
||||
the growth postures pinned in `engine-mem.md`'s new growth
|
||||
section, anchored to the sites.*
|
||||
11. **mem outbox outcome swallow** — `outbox run_once` drops the ack/
|
||||
retry row-refs' booleans and returns `Ok(true)` even when delivery
|
||||
outlived the visibility window and nothing landed
|
||||
(`outbox.rs:104-122`). Inherent to the no-heartbeat outbox design
|
||||
(at-least-once reclaim is the recovery), but a `debug_assert!` or
|
||||
doc sentence pinning the "processed means delivered-or-reclaimable"
|
||||
semantic would prevent future confusion.
|
||||
semantic would prevent future confusion.
|
||||
*Disposition: bundled into `mem-doc-growth-outbox-notes` arm (b)
|
||||
— the "processed means delivered-or-reclaimable" semantic pinned
|
||||
in `engine-mem.md`'s outbox section; the `debug_assert!` declined
|
||||
with the false-positive rationale recorded in the task.*
|
||||
12. **core `offset()` initial value** — `EventReceiver::offset()`
|
||||
pins the post-yield value only; the pre-yield return (the seeded
|
||||
checkpoint vs 0) is unpinned in the contract text. A doc-only fix
|
||||
once the three engines' pre-yield values are confirmed equal (not
|
||||
verified this session; left as a named gap).
|
||||
once the three engines' pre-yield values are confirmed equal (not
|
||||
verified this session; left as a named gap).
|
||||
*Disposition: landed via `core-pin-offset-initial-value` — the
|
||||
three engines verified equal (0 on every pre-yield arm, live on
|
||||
all three columns) and the doc-pin branch applied; pinned in
|
||||
core-contract.md, the trait doc, and the suite row
|
||||
`receiver_offset_pre_yield_is_zero`.*
|
||||
13. **pg identifier truncation cross-channel collision** —
|
||||
`LISTEN`/`UNLISTEN` interpolate the channel as a quoted identifier
|
||||
(truncated at 63 bytes server-side) while `pg_notify` carries it as
|
||||
@@ -166,12 +219,21 @@ shape so a future session can decompose without re-deriving.
|
||||
is deliberate). The honest cheap fix is a deployment-matrix/
|
||||
docs note ("names longer than the PG identifier limit may
|
||||
collide"); deferred here because the matrix was just finalized by
|
||||
the gate — fold it into whichever doc pass runs next (or into the
|
||||
publish session's reading).
|
||||
the gate — fold it into whichever doc pass runs next (or into the
|
||||
publish session's reading).
|
||||
*Disposition: landed via `docs-pg-identifier-truncation-note` —
|
||||
the note in deployment.md (dated) and engine-postgres.md, the
|
||||
mechanism sharpened (the server *rejects* ≥ 64-byte `pg_notify`
|
||||
channels; the collision is on the registration side), the no-cap
|
||||
verdict untouched.*
|
||||
14. **core error `Display` log-forging** — `InvalidName`/\
|
||||
`ReservedName` / `InvalidSpec` interpolate raw consumer strings
|
||||
into `Display`; control characters can forge log lines in naive
|
||||
consumers. Typical-idiom risk, low; recorded.
|
||||
consumers. Typical-idiom risk, low; recorded.
|
||||
*Disposition: landed via `core-fix-display-log-forging` — the
|
||||
`display_safe` escape helper in the three variants' `Display`
|
||||
arms (plus `Error::Codec`, the one same-class neighbor); taxonomy
|
||||
untouched.*
|
||||
15. **unsafe without `// SAFETY` in the substrate** — the eight
|
||||
`unsafe { ctx.get_connection() }` UDF blocks
|
||||
(`substrate/ops.rs:147-236`) carry no justification comments. The
|
||||
@@ -180,13 +242,20 @@ shape so a future session can decompose without re-deriving.
|
||||
a non-obvious safety constraint would otherwise be missed") says
|
||||
this is where they'd live. Not added this session: the substrate
|
||||
is lineage-port code under ADR-012 §3's diff-fidelity posture —
|
||||
comments must ride a PROVENANCE delta. Recorded for whenever the
|
||||
substrate is next touched.
|
||||
comments must ride a PROVENANCE delta. Recorded for whenever the
|
||||
substrate is next touched.
|
||||
*Disposition: landed via `sqlite-substrate-safety-comments` — all
|
||||
ten same-class sites (the eight + `schema.rs`'s notify
|
||||
registration + the test-module probe) carry concrete-invariant
|
||||
`// SAFETY` comments, registered as delta D-40.*
|
||||
16. **Cosmetic metadata asymmetry** — the three engines' dev-dep tokio
|
||||
features disagree (`rt-multi-thread+macros+time` / `test-util` /
|
||||
`rt+macros`); harmless (the contract suite carries the test
|
||||
runtime) but an easy-to-trip asymmetry when copying test code.
|
||||
Recorded, not normalized mid-release.
|
||||
runtime) but an easy-to-trip asymmetry when copying test code.
|
||||
Recorded, not normalized mid-release.
|
||||
*Disposition: landed via `normalize-tokio-dev-deps` — all three
|
||||
engines normalized to `rt-multi-thread + macros + time +
|
||||
test-util`, dev-dep metadata only.*
|
||||
|
||||
## False positives caught on verification (for the record)
|
||||
|
||||
|
||||
Reference in new issue
Block a user