Skip to content

PR #83 Copilot rounds 12-13, filed under the two-round cap: lane-start launches past a failed set-row-state, request-handoff's self-window fence reads the @id alone, the liveness fixture outlives the wrapper's timeout #142

Closed

Description

@brettheap

Copilot reviewed #83 automatically on the finisher's two pushes (rounds 12 and 13, on a031b54 and 400d559, 2026-10-03), past the two-round cap Brett Heap ruled on 2026-09-16 (AGENTS.md, testing section, rule 2). All three findings are on code #83 introduced. None was a clean minimal fix, so per that rule they are filed here and #83 lands regardless.

1. lane-start launches after a failed set-row-state (round 12, high)

#83 (comment) (lane-start:3128 at 400d559)

Copilot's claim: a nonzero set-row-state is only a note, so the row keeps its old state (for example PAUSED) while the log records STARTED/RESUMED and the session launches. Once that process exits, the stale row can make the lane look available to a second holder. It asks for an abort before launch, as the add-row path does.

Why it was not taken: the non-fatal handling is a deliberate decision from #83's Copilot round 6 (9af86e1). Before it, the bare call under set -e killed the launch with the helper's exit 5 and no sentence. The rule cited there is Amendment 6(c): the row's stamp is the record of the act, not its licence. Under Amendment 18 the binding readers fence on is the log's STARTED/RESUMED (lane_binding_scan), not the row. The real gap is the case where the row write fails because the push failed, so the log line is not published either. Step 5b ("a lane that cannot write its log still starts") is Amendment 7 policy. Making either write fatal is a change to protocol text, which makes it a word for Brett Heap, not a fix to slip into a finisher round. If the ruling is "fail closed", the change is a die with the repair command in place of the note here and in 5b, and a rework of the suite case without --confirm nothing is asked, which is what round 6 measured coming back 5.

2. request-handoff's self-window fence compares only the @id (round 13, moderate)

#83 (comment) (lanes-edit.sh:11098, and Copilot names :11190)

Copilot's claim: binding_is_this_window compares only the recorded @id, and rh_here proves only host/container. If a stale binding's id has been reissued to the asker's own window (a tmux server replaced after a reboot, for example), request-handoff refuses with "binding IS this window". That refusal comes before the --force branch, so from that window the lane can be neither asked for nor forced.

Why it was not taken: the edge is real (the escape is to run from any other window), but Copilot's fix of gating on binding_window_state = live trades it for the reverse failure. A lane window that lane <name> moved into another session (Addendum 1 (i-2)) keeps its id but leaves the record naming the old session, so binding_window_state answers unknown by design (Copilot round 6). The gated fence would then let the bound session itself write a HANDOFF-REQUESTED against its own binding, which its own guard answers by typing /handoff --exit into its own pane. That is the stale-record-under-a-move gap already filed as #95. The two failures need one answer, and #95 is where it belongs. The :11190 site (guard_type into ${rh_win##* }) is already gated on rh_wstate = live, which is the id-AND-session agreement rule.

3. The liveness fixture outlives the wrapper's hard timeout (round 12, "previously missed", medium)

From the round-12 review body: #83 (review) (tests/test_lane_helpers.sh:665)

LIVE_SLEEP=$(( LIVE_BOUND + 600 )) deliberately outlives TIMEOUT_SECONDS (round 6, so the fixture never dies under a slow macOS run). But subprocess.run(..., timeout=TIMEOUT_SECONDS) in tests/test_lane_helpers_suite.py kills only the bash child. The suite's EXIT trap never runs on that path, so LIVE_PID and any later fixture sleeps are orphaned for up to 70 minutes. The impact is a stray sleep (no file, lock or register is touched), which is why this was filed rather than taken. The fix is in the wrapper: start the suite with start_new_session=True and, on TimeoutExpired, os.killpg the group before re-raising.

Lane: openRepoTools-3

Activity

  1. brettheap commented on Oct 11, 2026

    @brettheap
    ContributorAuthor

    CLAIMED — lane openRepoTools-4, session e545e636-93fd-4b80-81b1-48177346b887@Eagle, 2026-10-11T16:32:42Z, for #142

    Logged in lanes/log/openRepoTools-4.md at e66e970c7ae837878bbc3fdb7bac25160b4ddbc7.

    The three reads (lane-collision-protocol Rule 1):

    1. existing `CLAIMED —` comments on opensoft/openRepoTools#142:
       none
    2. `gh pr list --repo opensoft/openRepoTools --state all --search "#142"`, kept where the row or its body names `#142`:
       none
    3. `git ls-remote --heads git@github.com:opensoft/openRepoTools` branches naming `142` as a whole token:
       none
    
  2. brettheap commented on Oct 21, 2026

    @brettheap
    ContributorAuthor

    Closing on Brett Heap's ruling of 2026-10-21: "yes to all six rulings as recommended" (lane 4's R1 and R2).

    Nothing is left open here.

    Lane: openRepoTools-4

  3. brettheap commented on Oct 21, 2026

    @brettheap
    ContributorAuthor

    RELEASED — lane openRepoTools-4, session e545e636-93fd-4b80-81b1-48177346b887@Eagle, 2026-10-21T10:43:30Z, for #142 — item 3 fixed by #217 and items 1 and 2 kept on Brett Heap's rulings R1 and R2 of 2026-10-21; #142 is closed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions