SIGN IN SIGN UP

fix(rustd): measure the live half of every tracing field, and give both binaries one clock

The last commit named an uninstalled subscriber as the biggest cause of lines
reading as unreachable. That was true and it was not sufficient: thirteen lines
stayed at zero with the subscriber installed and the code demonstrably running.

**`tracing`'s `log` feature makes every field expression compile twice.**
sqlx-core and sqlx-postgres request it, Cargo unifies features across the
workspace, so it is on for afd_redis too — a crate that never asked for it. The
macros then emit each field once for the event and once for a `log` record that
never runs when a subscriber is installed, and llvm-cov maps both copies to the
same source line and reports the DEAD one. `warn!(x = y.z(), ...)` therefore
read as uncovered however many times it ran.

Established, not inferred. `lock.rs`'s contention `warn!` showed its opening
line at 5 and its own `retry_ms` field at 0 — impossible if the callsite were
disabled, and a probe showed it enabled. Replacing the field with a
side-effecting expression printed three times in one test while the report still
said 0. A standalone crate with the same code and the same `tracing` 0.1.44 /
`tracing-core` 0.1.36 reported 5; adding `features = ["log"]` and changing
nothing else reported 0. `llvm-cov export --skip-expansions` does not restore
it.

The fix is a hoist, not an exemption: nineteen call-bearing field expressions
move to a `let` above their macro and enter as bare names. The rationale lives
once, beside the `tracing` dependency that causes it. Worth stating plainly —
**the 100% floor was unreachable through tests alone**, and no amount of test
writing would have closed those thirteen lines.

**One clock, because the port had already grown two answers.** afd_db carried a
private `now_millis` mapping a pre-epoch host to `0`; `clock.zig` returns the
negative reading and says why — a silent epoch-0 return corrupts UUIDv7 ordering
— so the two binaries answered the same broken host differently while writing
the same `audit.schema_migrations` table. §4's JWKS cache would have been the
third copy. `afd_core::clock` is now the single reading: `UnixMillis`, a pure
`millis_at` beside the clock-reading `now`, and `Clock`/`SystemClock`/
`FixedClock` shaped like the existing `EnvSource`/`ProcessEnv`/`MapEnv`.

No date crate — not chrono, not time, not jiff. Every timestamp column is
BIGINT, every wire field is i64, and a UUIDv7 carries a 48-bit millisecond field
in its own layout, so epoch-milliseconds is already the type three contracts are
written in; sqlx maps BIGINT to i64 with no feature flag, so nothing calendar
enters the graph. No monotonic reading is exposed either: elapsed time is
`Instant` and a deadline is `tokio::time::timeout` (Invariant 4), and omitting
the reading is what makes wall-versus-elapsed mixing unwritable. The one Zig
caller of the monotonic clock is a deadline loop, which is that shape already.

That surfaced a second divergence: the hub's reconnect `jitter()` read the WALL
clock for spread. A backward step — an operator correcting drift, an NTP
correction — replays the same sub-second nanoseconds and hands two redials the
same jitter, reproducing the lockstep the jitter exists to break, at exactly the
moment a cluster is most likely to be reconnecting at once. It reads a
process-owned `Instant` now.

The remaining gap-closing is ordinary work, not measurement: scanner boundaries
(a literal at offset zero, `""` inside a quoted identifier, a comment inside a
statement, an unclosed `$tag` at end of input), URLs sqlx parses but rejects told
apart from wrong schemes, `Migration::for_test` and `Migrator::default` called at
runtime, both client construction paths refusing a broken URL by role, the real
`ProcessEnv`, and the captured-backtrace rendering on all three error types by
the child-process shape afd_core already used.

94.57% → 98.12% lines, 354 tests across both tiers. afd_core and afd_wire join
afd_crypto at 100%; afd_redis 94.98% → 97.08%. The forty lines left all need
failure injection — a socket that accepts then drops, a killed backend, a
server that lies — and each is named in the spec with its route. No number moved.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
K
Kishore Kumar committed
872977d2f3f3e3d17651b62c1cbef139e8b9ef4b
Parent: 168998d