Eight implementation tasks + the gate under tasks/implementation/, folding the wave-3 gate's four booked findings in as dedicated tasks (the gate's own disposition — wave-4 material, not wave-3 backports). Hardening set (server-side, independent of the client chain, scheduled first as cheap remediation): - w4-git-exit-close: booked item 1 — the git row's status-before-close by construction (the seam/shape decided + recorded in-task; the saturated-buffer scenario pinned on the wire) - w4-channel-not-held-rows: booked item 2 — the guard's wire rows on git/tty pipe/shell, per build (test-only) - w4-tty-coverage: booked item 3 — the channel_close-fired cancel path + the Closed/Break no-exit-chunk rows + the write_all no-deadline known-limit record - w4-router-collision: booked item 4 — the ListenRouter token-collision fail-closed pre-check Client chain (sequential logistically — one client Handler impl): - w4-dial: the russh client stack + the connection handle + the client Handler skeleton at fail-closed defaults, over an in-process fake-sshd server double - w4-op-rows: exec/pty, direct-tcpip, git exec over the shared grammar, the sftp client-side decline — the POC-3 §D.3 mechanics - w4-reverse-listen: the -R leg — forward requests + the acceptor registry + late-install (the wave's highest-risk task) - w4-lifecycle: the OQ-12 primitives (cancellable handles, clean disconnect, no reconnect policy) review-wave-4 depends on all eight. The gate's item 5 (upstream asks) stays booked with its owners — no task. Plan wave-4 section carries the decomposition record + four flagged interpretations; wave table status updated. Verification: taskgraph validate ✓ (35 tasks)
3.3 KiB
id, name, status, depends_on, scope, risk, impact, level
| id | name | status | depends_on | scope | risk | impact | level | |
|---|---|---|---|---|---|---|---|---|
| w4-git-exit-close | Wave 4 — git row hardening (status-before-close by construction — wave-3 gate booked item 1) | pending |
|
narrow | medium | component | implementation |
Description
Close the wave-3 gate's only structural booked finding
(review-wave-3 §Booked findings item 1): the git row's
status-before-close is honored by scheduling, not by construction.
Today serve_duplex_resolved splits the channel stream internally and
its session halves drop when the serve returns — russh's
ChannelCloseOnDrop rx-half emits a server→client CHANNEL_CLOSE
inside the seam call, before serve_git_row's explicit
exit_status_request. The ordering currently holds (the task's
continuation queues the report in the same poll, ahead of the drop's
send) and every wire row passes, but a full Sender<Msg> buffer at
the serve tail could order the implicit close first and silently drop
the report (russh no-ops exit_status_request for an already-closed
channel) — a silent exit-report loss on a published row.
The fix wants a seam/shape change — decide + record which:
- split the channel halves in
serve_git_rowand pass them into the seam (the report then rides a half the seam never closes), or - queue the exit report while the stream is alive (the report's send ordered before any close-contracting drop by construction), or
- another shape that makes the ordering structural rather than scheduler-luck — the gate's reasoning and the two named options are the starting points, not the bounds.
Constraints: every existing git wire row stays green (no behavior
change on the happy path — this is ordering hardening, not semantics
change); the spawn-and-return constraint (ADR-006 decision 4) holds —
the reporting still rides the spawned task; the tty rows are NOT in
this class (their report precedes any close-contracting drop in one
task — the gate verified; don't touch them). New wire row(s) pinning
the construction: a saturated Sender<Msg> buffer at the serve tail
(the failure scenario made real) still delivers the exit report —
the by-construction property proven on the wire, not by reasoning.
Acceptance Criteria
- The shape decided + recorded (module docs carry the reasoning); the git row's status-before-close holds by construction, not scheduling
- Every existing git wire row green (no happy-path behavior change); the spawn-and-return constraint intact
- New wire row(s): the saturated-buffer scenario delivers the exit report (the by-construction property pinned)
cargo test(+ per-feature +--all-features), clippy ×2 (-D warnings), fmt,cargo doc --no-depspass
References
- tasks/implementation/review-wave-3.md §Booked findings item 1 (the full finding + the two named fix shapes)
- docs/architecture/mapping.md (the git exec row — exit-status both directions), docs/architecture/decisions/006-mapping-bridge-and-dispatch.md (decision 4 — spawn-and-return)
- src/git_map.rs, src/serve.rs (
report_exit_status_then_close— the wave-2 reporting mechanics this hardening composes with), alkgit 0.1.0serve_duplex_resolved(the seam whose half-ownership is the question)
Notes
To be filled by implementation agent
Summary
To be filled on completion