A jab post //host push opens the remote's git-receive-pack TWICE: first in relate.relate→wire.advertRefs, only to read the old tip for the FF gate, and closed with a BARE io.close (no flush) so git-receive-pack dies fatal: the remote end hung up unexpectedly on EVERY push, even a successful one; then AGAIN in wire.push, which RE-drains the identical advert before sending the pack. One push, two connections, one gratuitous scary line. Reuse ONE session: advertise once, keep the child alive, run the LOCAL FF verdict + build the pack from that advert's haves, send updates+pack on the SAME fds; on the advert-only / non-FF refusal path send a flush-pkt (0000) before close so receive-pack exits clean. Respect GIT-016's graph-only relate spine — make its advert INJECTABLE, do not fuse wire transfer into the verdict. JS only (be/, via jab). Method: work; siblings GIT-013/GIT-016; cuts BE-006 stacked-error noise.
verbs/post/post.js pushRemote (~line 283) runs advert #1 + FF verdict (relate.relate, line 290) → wire.buildPushPack (local, line 309) → wire.push (advert #2 + send, line 310); the advert is drained twice against the same peer.shared/relate.js relate (line 42) calls wire.advertRefs(remoteUri, "receive-pack") internally (line 47) — it OWNS the advert; a caller holding one already cannot feed it in.shared/wire.js advertRefs (line 567) spawns git-receive-pack, drains the advert, then finally does a bare io.close(wfd) (line 583) — NO flush-pkt — so git-receive-pack hits EOF where it expects a command and prints fatal: the remote end hung up unexpectedly; fires on the post FF-gate, the non-FF refusal, AND pull verbs (head/get).shared/wire.js push (line 596) spawns a SECOND git-receive-pack, RE-drains the advert (line 604) via drainRecvAdvert, then buildPushBody (flush at line 552, clean close) writes the pack — the second advert is pure round-trip waste.jab post ssh://localhost/src/journal/beagle?main prints fatal: the remote end hung up unexpectedly then POSTNOFF … — the hangup is advert-only session #1 closing without a flush, NOT a push failure.old sha + a LOCAL dag.isAncestor walk (GIT-016, no content) — so it can run on the push session's own advert before any pack is sent.advertRefs (and any advert-only close) sends a flush-pkt 0000 before closing so git-receive-pack exits cleanly — kills the remote end hung up line on the post FF-gate, the non-FF refusal, and pull verbs.relate stays verdict-only; make its advert INJECTABLE so pushRemote feeds the session's already-drained advert instead of forcing a second advertRefs.old sent + parseReportStatus non-FF guard), same remote-tracking-ref save — only the wire choreography changes.be/, run via jab. Do NOT run native be; do NOT open beagle/.wire.advertRefs/push/buildPushPack/buildPushBody/classify, pkt.flushPkt, relate.relate/resolveRef, dag.isAncestor. No new deps, no new protocol code.old in the update command and keep parseReportStatus's non-fast-forward throw — the client verdict AUGMENTS, never replaces, it.GIT-019 comments, greppable, ticket-coded ≤64-char commit.push-ssh (FF), push-nonff (honest refusal), the http push path, or the pull verbs' advert (head/get).wire.js: open receive-pack once, expose { adv, send(updates, pack), close() }; send writes buildPushBody on the live wfd, close flush-closes. advertRefs becomes the "open + drain + flush-close" degenerate case sharing the same helpers.advertRefs finally: write pkt.flushPkt() to wfd BEFORE io.close(wfd) — one line, kills the hangup, no behaviour change (git-receive-pack treats zero-command + flush as a clean no-op exit).relate advert injection: add an optional adv param (skip the internal advertRefs when supplied) so pushRemote passes the session advert; pull verbs keep the internal advertise. Mirrors GIT-016's already-optional remoteIx.pushRemote reflow: open the push session → verdict via relate(…, adv) → on non-FF, session.close() (flush) + throw POSTNOFF → on FF, buildPushPack(serve, tip, haves-from-adv) + session.send(…) on the SAME connection → saveRemoteRef.relate injection.remote end hung up on stderr (counting ssh shim). — test/wire/push-1conn.advertRefs flush-close before io.close(wfd) so an advert-only session exits clean (pull verbs incl.). — landed 3610b643 (wire.js ~566).wire.js open-once push session (advert drained once, send on the same fds), drain+body helpers shared with advertRefs/push. — landed 3610b643 (wire.js §GIT-019 ~574).relate advert-injectable (adv param, relate.js ~42); pushRemote advertises once, verdict off that advert, send or flush-close+refuse on the same session (post.js ~301). — landed 3610b643.push-ssh FF, push-nonff honest refusal, put force twin, head/get advert; wire + post buckets. — green at land.relate verdict-only and INJECT the advert, do not move pack-building into the spine.advertRefs used by head/get/post/put — verify against ALL four, not just post.jab get file:/home/gritzko/.be?/beagle-ext; NEVER cp -a (the PUT-005 .be-redirect artifact).3610b643 ("reuse the same git connection for all phases", be/ trunk): one receive-pack session per ssh/local push (advert once → relate verdict → send on the same fds), advertRefs flush-closes so advert-only sessions exit clean (no remote end hung up on push gates or pull verbs), relate advert injectable. Test test/wire/push-1conn.