Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions docs/README-lanes.md
Original file line number Diff line number Diff line change
Expand Up @@ -1342,9 +1342,15 @@ still the lane**, which is the contract both readers of this output take, and
it is what makes a fourth and a fifth field safe to add at all.

`<lane>`, `<UTC>`, `<window>` — the window being the `window <s>:<i>` the
`/swap` recorded, which is where that lane was. **Exit 0** with rows, **8** with
none (and the reason on stderr, so stdout is only ever rows). A launcher takes
the first row's lane as its default and hands it to `lane-start --confirm`.
`/swap` recorded, which is where that lane was. **The lane is the register
row's spelling** (Amendment 15), as `window-lane`'s answer is, and not the
spelling of the lane's log file: a log written before that amendment is still
`lanes/log/openxfactory-4.md` beside the row `openXfactory-4`, and `swapped`
lists that lane as `openXfactory-4`, so a reader may hand the field straight to
`tmux rename-window` or to a read of the register. **Exit 0** with
rows, **8** with none (and the reason on stderr, so stdout is only ever rows). A
launcher takes the first row's lane as its default and hands it to
`lane-start --confirm`.

**The rows are in LANDING ORDER — most recently landed first — and not in UTC
order.** Amendment 7's file-order rule orders one lane's own lines and does not
Expand Down
29 changes: 26 additions & 3 deletions lanes-edit.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7949,6 +7949,16 @@ lane_next_free() { # <repo> ; rows on stdin
# swapped_lanes [<workstation>] — one row per swapped lane, tab-separated:
# <lane> <UTC> <window> <dir> <profile> <agent> <transcript>
#
# THE FIRST FIELD IS THE REGISTER ROW'S SPELLING OF THE LANE (Amendment 15), the
# way `window-lane`'s answer is. The record is read under the lane's LOG FILE
# name, and a log written before Amendment 15 is still `lanes/log/<lower>.md`
# beside a row that spells the lane in mixed case (`lanes/log/openxfactory-4.md`
# and `openXfactory-4`), so the raw name is the wrong one to print. A caller of
# this output hands that field to `tmux rename-window`, to `--name`, to
# `lane <name>` and to a read of the register, and each of them wants the row's
# spelling. The log's own spelling is kept for the two things that read the LOG
# — its path and the pickaxe key — and is never printed.
#
# THE LAST TWO ARE AMENDMENT 17(b)'s, and they are added at the END for the
# reason the fourth and fifth were: the FIRST FIELD BEFORE THE FIRST TAB is the
# contract every reader of this output takes (the launcher, the `handoff`
Expand Down Expand Up @@ -8049,8 +8059,15 @@ swapped_candidates() {
# written, up to and including its object, which is unique to it and
# which `git log -S` can find without a regex.
# `nm[l]` AND NEVER `l` (Amendment 15, `8345d2f`): the key is the lane
# folded to one case and `nm` is the spelling the register row carries,
# which is the one a caller of this output hands back to a read.
# folded to one case and `nm` is the lane as the event stream spells
# it, which is the base name of the lane LOG FILE (Amendment 16(c) keys
# every line to its file). That is NOT the register row spelling
# wherever the file does not carry it: a log written before Amendment 15
# is still `lanes/log/openxfactory-4.md` beside the row `openXfactory-4`.
# It stays the spelling of the log itself, for the pickaxe key below and for
# `log_path_for`; the row spelling is for `swapped_lanes` to print as
# the first field, and `window-lane` canonicalises its answer the same
# way. (No apostrophe in this comment: this awk program is single-quoted.)
printf "%s%c%s%c%s%c%s%c%s%c%s%c%s%c%s — lane %s, session %s@%s, %s, %s\n",
nm[l], 31, utc[l], 31, (w == "" ? "unknown" : w), 31,
(d == "" ? "" : d), 31, (pf == "" ? "" : pf), 31,
Expand All @@ -8065,6 +8082,12 @@ swapped_lanes() {
[ -n "$sw_rows" ] || return 0
while IFS="$US" read -r sw_l sw_u sw_w sw_d sw_p sw_a sw_t sw_key; do
[ -n "${sw_l:-}" ] || continue
# THE ROW'S SPELLING FOR THE FIRST FIELD, THE LOG'S FOR THE LOG (see above).
# `canon_lane` refuses a register holding the 15(d) pair and a table of
# former names it cannot read; this read keeps the log's own spelling then,
# for `window-lane`'s reason: it is informational and its contract is rows
# or 8, and the refusal belongs to the writer the lane leads to.
sw_can="$(canon_lane "$sw_l" 2>/dev/null || :)"
sw_rank=999999999
if have_remote_ref; then
sw_sha="$(git -C "$LANES_REPO" log -1 --format=%H -S"$sw_key" "origin/$LANES_BRANCH" -- "$(log_path_for "$sw_l")" 2>/dev/null || :)"
Expand All @@ -8073,7 +8096,7 @@ swapped_lanes() {
case "$sw_c" in ''|*[!0-9]*) : ;; *) sw_rank="$sw_c" ;; esac
fi
fi
printf '%09d%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n' "$sw_rank" "$US" "$sw_l" "$US" "$sw_u" "$US" "$sw_w" \
printf '%09d%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n' "$sw_rank" "$US" "${sw_can:-$sw_l}" "$US" "$sw_u" "$US" "$sw_w" \
"$US" "${sw_d:-}" "$US" "${sw_p:-}" "$US" "${sw_a:-}" "$US" "${sw_t:-}"
done <<EOF
$sw_rows
Expand Down
23 changes: 23 additions & 0 deletions tests/test_lane_helpers.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7518,6 +7518,13 @@ add_seed_row "| \`repoSwap-1\` | harness \`$DEAD_ID\` | Raven / test / brett | 2
printf 'PAUSED — lane reposwap-1, session %s@Raven, 2026-09-12T09:00:00Z, lane:reposwap-1 → swap; window swapwin:4; workstation Raven\n' "$DEAD_ID"
printf 'RESUMED — lane repoSwap-1, session %s@Raven, 2026-09-12T10:00:00Z, lane:repoSwap-1 → home opensoft/repoSwap\n' "$DEAD_ID"
} > "$LOGD/repoSwap-1.md"
# A SWAPPED LANE WHOSE ONLY LOG FILE IS LOWERCASE, which is every lane that
# predates Amendment 15: `lanes/log/openxfactory-4.md` beside the row
# `openXfactory-4`. `swapped` read the lane under the file's name and printed it.
add_seed_row "| \`repoSwLow-1\` | harness \`$DEAD_ID\` | Raven / test / brett | 2026-09-11T00:00Z | none | handoffs/repoSwLow/x.md | ACTIVE |"
{ printf '# lane reposwlow-1 — object log (lane-collision-protocol Amendment 7)\n'
printf 'PAUSED — lane reposwlow-1, session %s@Raven, 2026-09-12T09:30:00Z, lane:reposwlow-1 → swap; window lowwin:5; workstation Raven\n' "$DEAD_ID"
} > "$LOGD/reposwlow-1.md"
# THE PAIR THE AMENDMENT MAKES IMPOSSIBLE, seeded as it existed: two rows whose
# lane names differ only by case. Every writer refuses on it until 15(d)'s merge.
add_seed_row "| \`repoPair-1\` | harness \`$DEAD_ID\` | Eagle / test / brett | 2026-09-11T00:00Z | none | handoffs/repoPair/x.md | ACTIVE |"
Expand Down Expand Up @@ -7828,6 +7835,22 @@ is "…so column 10 is the line that binds it, which needs both halves at once
run "$E" window-lane Raven casewin:3
is "window-lane finds the lane from a record that spells it in another case" "$rc" 0
is "…and answers with the register row's spelling" "$out" "repoWin-1"
# `swapped` READS THE SAME RECORD AND HAS TO ANSWER WITH THE SAME SPELLING (#55).
# Its first field is what a caller hands to `tmux rename-window`, to `--name` and
# to a read of the register, so it is the ROW's spelling. The raw name the record
# is read under is the log FILE's base name (Amendment 16(c)), and a log written
# before Amendment 15 is lowercase beside a mixed-case row: `repoSwLow-1`, whose
# only log is `reposwlow-1.md`. Each lane is picked by its window, because Raven
# holds other swapped lanes too.
run "$E" swapped Raven
is "swapped lists the lanes a swap paused on that workstation" "$rc" 0
is "…naming a lane whose log FILE is lowercase by the register row's spelling" \
"$(printf '%s\n' "$out" | awk -F'\t' '$3 == "lowwin:5" { print $1 }')" "repoSwLow-1"
# THE `repoWin-1` ROW PASSES WITH OR WITHOUT THE FIX: its log file already
# carries the row's spelling, only its PAUSED line is lowercase, and every line
# is keyed to its file. It stays as the other shape of the same two spellings.
is "…and a lane whose log file carries the row's spelling by that spelling" \
"$(printf '%s\n' "$out" | awk -F'\t' '$3 == "casewin:3" { print $1 }')" "repoWin-1"

# `--all` CLEARS `--lane`, SO IT MUST NOT REFUSE FOR ONE EITHER. The register
# here holds the 15(d) pair; `--all` is the every-lane listing and a `--lane`
Expand Down
Loading