MEM-025: first_name slice dangles into compacted advert buffer (keeper/WIRECLI.c)

wcli_match_advert captures first_name as a pointer-pair slice into the advert buf, then holds it across the rest of the drain loop; wcli_read_pkt compacts the same buffer when IDLE runs out (u8bUsed+u8bShift memmove of surviving DATA to buf[0], then FILEDrain overwrites), so first_name's bytes are relocated/clobbered. The legacy first-ref fallback then does a_dup(u8c, fn, first_name) (a pointer copy, not a byte copy) and records the stale/overwritten region as a corrupt ref name. The slice stays within the BASS-carved buf, so this is a stale-memory read (corrupt name), not OOB. The goal is to snapshot the first ref name into stable storage at capture time.

Issues

A captured slice aliases a buffer that later compacts under it.

Blockers

None.

WIP

Re-verified 2026-07-07: flaw intact, sites shifted — capture keeper/WIRECLI.c:617 u8csMv(first_name, name) in wcli_match_advert (:551), compaction wcli_read_pkt :97-111 (u8bShift(buf, 0) at :111), stale use :669 a_dup(u8c, fn, first_name), WCLI_BUF 64KiB at :48. The new second-pass rescan (:645-666) only reads the compacted tail, so the legacy first-ref fallback (:667-671) still consumes the dangled slice.

TODOs

- Snapshot the first ref name into a stable buffer (small a_pad/u8bFeed copy, like WCLI_RECORD_NAME→name_out) at first sight (:615-619); use that copy in the :669 fallback. - Or fold the legacy first-ref pick into the WCLI_RECORD_NAME path during the main loop so no buf-aliasing slice is held across compacting reads. - Repro first: feed an advert > WCLI_BUF (forcing compaction) with empty want_branch and no refs/heads/main; assert the recorded first-ref name matches the real first ref, not garbage.

Blockers and bummers

None.