- git row: a second exec on a served git channel answers channel_failure
inline — the serve rides on, no second serving path; race-free by
construction (advertisement drained, serve parked at the gated list_refs)
- tty rows: the pipe row (second exec) and the shell row (second shell
request) — the same inline decline shape, channel still usable
- the rows assert the decline event's exact request vocabulary (class
request, reason channel-not-held, route git/pipe/absent, debug level,
self-describing build) — the class's vocabulary coverage
- tests/common/event_capture.rs: the observe-suite's capture convention
shared across the mapping binaries
- test-only: no production change; the guard held its documented shape
in every featured build (verified default / git / session /
session,git / tunnel / sftp / --all-features)
Verified: cargo test (+ per-feature + --all-features) all green ·
cargo clippy --all-targets -- -D warnings ✓ · cargo clippy
--all-features --all-targets -- -D warnings ✓ · cargo fmt --check ✓ ·
cargo doc --no-deps 0 warnings · taskgraph validate ✓ (35 tasks)
The wave-3 gate's booked finding 1: the git row's exit-report order
was honored by scheduling, not by construction — into_stream()'s
ChannelCloseOnDrop spawned a CHANNEL_CLOSE send racing the
exit_status_request send for a queue position on russh's bounded
message queue (event_buffer_size, default 10); a full buffer at the
serve tail could silently no-op the report.
- the seam now rides a split-halves duplex built from russh 0.65's
public API (its ChannelRx/ChannelTx are private): the reader is
git_map's ChannelHalveReader (owned read half, the private rx's
observation semantics repinned, no Drop path ever messages the
wire) and the writer the write half's ChannelTx via
make_writer_ext (poll_shutdown still sends EOF; the Rust 2024
capture phantom erased through a trait object)
- the report's send is now the sole close-contracting sender,
ordered ahead of the explicit close by sequential awaited sends on
the one handle — saturated buffer or not
- new wire row backlogged_seam_tail_still_reports_exit_status_before_close:
a volume flood freezes the armed client loop (the new harness
DataGate + the client data hook russh awaits inline) so the server's
flush pends and the bounded message queue saturates at the serve
tail; the gate's release drives the tail through the unwinding
contention — the row pins exit-status(0) before close under the
saturation and falsifies the old shape deterministically (15/15 red
under a temporary into_stream() revert, 10/10 green with the fix)
- doubles gain a race-safe per-repo serve gate (install_gate, the
double-check pattern over list_refs); harness gains
drive_with_data_gate (the drive* bodies factored into
mount_and_connect, existing signatures unchanged)
- all existing git wire rows unchanged and green (wire order
identical when the race does not fire); spawn-and-return intact;
tty rows untouched; event_buffer_size stays russh's default
(pinned in the row)
Verification: cargo test (default), --all-features, and six mixed
per-feature builds green; clippy x2 -D warnings; fmt -check;
cargo doc --no-deps 0 warnings; taskgraph validate (35 tasks).
- dispatch: the full exec grammar replaces the wave-2 skeleton probe
(quoted/unquoted paths, the .git normalization decision, unknown-
service / service-only decline-with-reason class; the probe's unit
rows migrate with their pinned verdicts preserved)
- git_map: the git row dispatches serve_duplex_resolved over the
channel duplex (repo id validated, never resolved; the exit-status
mapping 0/1 decided per POC-3 §A.5; status before close from the
spawned task), with the resolved identity riding the seam
- handler: the store-and-take channel handoff (stored at the open,
taken in the spawned serving task, released at close) and the
max_exec_command_len pre-parse cap
- config course correction: GitSeam carries the assembly-supplied
alkgit Limits (the ADR-009 budget alkgit's contract assigns the
assembler)
- tests: tests/git_mapping.rs (byte-level process-mode advertisement,
ls-refs round + exit 0, the collapsed-denial byte-order + exit 1,
the identity-ride authorize-gate witness, the packless CAS push,
the grammar/cap decline rows, the sequential-serve store row, and
the real-tool git 2.43 clone smoke over a TCP mount with a
skip-with-reason posture); dispatch_core/observe rows updated to
the new decision set; tests/common/git_doubles.rs (the hand-rolled
recording alkgit quartet)
Verification: cargo test (default), --features session, --features
git, --all-features; clippy -D warnings ×2; fmt --check;
cargo doc --no-deps; taskgraph validate