Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
fc0f999
docs: the triad split's lane-tooling side, surface by surface (T006, …
brettheap Oct 9, 2026
138b8b5
WIP (untested): T018 worktree visibility for triad legs — the legs re…
brettheap Oct 9, 2026
17d8431
T018 (a): the triad guidance for the sweep and lane-end's gate — READ…
brettheap Oct 9, 2026
8d28a3f
WIP (untested): T018 (a) tests — tests/test_triad_lane_tooling.py and…
brettheap Oct 9, 2026
09b8d4a
WIP (untested): T010 docs — the §4.14 CI sketch exits 4 under #190's …
brettheap Oct 9, 2026
cc4d248
T018 (c): the daily report counts each leg of an assembly as a checko…
brettheap Oct 9, 2026
3f3f4f3
T018 (d): lane-worktrees add records the leg it made a tree from, and…
brettheap Oct 9, 2026
b00fbc4
T018 (b): lane-handoff sees a triad's legs — the paired trees polled,…
brettheap Oct 9, 2026
834f536
T018 (b): lane-reconcile reads a triad's legs — each leg's worktree r…
brettheap Oct 11, 2026
8ac1e58
Merge feat/triad-lane-tooling-handoff (T018 (b), writer 2): lane-hand…
brettheap Oct 11, 2026
c5d9adb
WIP (untested): T018 (b) guidance — README-lanes says what lane-hando…
brettheap Oct 11, 2026
72ee697
WIP (untested): T018 (d) — add's refusal on an unreadable manifest is…
brettheap Oct 11, 2026
85f28c7
Merge main f87fd5a into feat/triad-lane-tooling (T018): test the bran…
brettheap Oct 11, 2026
adf63c8
WIP: checkpoint before account swap; done: #194 proving test written,…
brettheap Oct 11, 2026
c7a3bd1
commit_push publishes the local commits a write with nothing staged f…
Oct 13, 2026
0eb57d1
T018 docs: a parked paired tree is not the lane's to the sweep (§7 it…
Oct 13, 2026
b59e36e
T018 (b), pre-PR review M1 option (a): lane-handoff polls the paired …
Oct 13, 2026
43cfe91
test_commit_push_published_edit_194: the refusal case names a transcr…
Oct 13, 2026
97469c9
T018 docs: README-lanes and the analysis say what M1 (a), S1 and S2 c…
Oct 13, 2026
89d5f62
#214 review: only `commit` publishes the commits a write with nothing…
Oct 13, 2026
2a368d5
test_commit_push_published_edit_194: the no-op case asserts its behav…
Oct 13, 2026
a132530
Merge main aaa7bc8 into feat/triad-lane-tooling (T018): test the bran…
Oct 17, 2026
86cb75b
WIP (untested): T018: lane-reconcile reports a leg whose .git git can…
Oct 17, 2026
d0da540
WIP (untested): T018: lane-handoff counts a leg git cannot read as un…
Oct 17, 2026
5efc593
#214 adversarial check: `commit` reads the queue on the branch it pus…
Oct 17, 2026
e502a29
Merge main 2732d59 into feat/triad-lane-tooling (T018)
Oct 17, 2026
8e3a4f9
T018: lane-handoff withholds only a tree that could be an unreadable …
Oct 17, 2026
9968c51
T018 docs: record lane 1's rulings of comment 6240800023 in the analy…
Oct 17, 2026
002b27f
Exit-code tables: say the #194 refusal pushes none of them, not "noth…
Oct 17, 2026
84f330b
Merge main 83d2690 into feat/triad-lane-tooling (T018)
Oct 18, 2026
76e939e
#214 reviews (openRepoShape-2 6242165339, openRepoTools-3 6242725522)…
Oct 18, 2026
9227b62
Say what the publish fence checks: register and handoff writes by pat…
Oct 18, 2026
4e01756
Merge main f595e44 into feat/triad-lane-tooling (T018)
Oct 18, 2026
3b82a84
T018: the daily report lists a leg that is also a canonical clone onc…
Oct 18, 2026
3bc4f26
T018 docs: the analysis spells bench paths ~/projects/..., as the hyg…
Oct 18, 2026
06c5d13
Merge main f5c3bcd into feat/triad-lane-tooling (T018)
Oct 18, 2026
1ebc1ea
#194: a publish the pull empties exits 0 and says so; pin the fence's…
Oct 18, 2026
097f0b2
T018: verify 88ee9d9: 224 passed, 1 failed (test_the_lane_helper_suit…
Oct 18, 2026
a700ef3
T018 tests: the unreadable-leg tests ask the git under test what it s…
Oct 18, 2026
75702bc
Merge openRepoTools-4's #214 head 656b1914 as the stacked base of act…
Oct 18, 2026
d598c64
Merge openRepoTools-1's #246 head ea4db0d1 as the stacked base of act…
Oct 18, 2026
53e6989
Merge openRepoTools main 586dea25 (#247, #237) into act 2's slice 1a …
Oct 18, 2026
d7b8c6a
WIP: every register write goes through its lane's own checkout <W>-la…
Oct 18, 2026
6467cce
Re-run CI on main fe58808: refs/pull/246/merge was stale on 14239b9
Oct 18, 2026
0aa7c8d
Merge openRepoTools main fe588082 (#204, #206, #208, #218, #220, #221…
Oct 18, 2026
2c35ea1
Merge branch 'main' into fix/commit-push-publish-committed-edit
brettheap Oct 18, 2026
9e1d14e
lane-start and lane-end read a lane's row in its own register checkou…
Oct 18, 2026
871b27a
The shell suite's #67 cases (from main's #221, issue #67) name their …
Oct 18, 2026
d1b65b1
Merge branch 'main' into fix/commit-push-publish-committed-edit
brettheap Oct 18, 2026
a280513
Merge #214's final head eff9107b (its refresh over main 08e7550) into…
Oct 19, 2026
af59298
Merge #214's squash 9b94a597 into act 2's slice 1a with -s ours: its …
Oct 19, 2026
4e02fa6
tests/test_lanes_index.py: its Estate names its old W by the explicit…
Oct 19, 2026
027c345
Merge openRepoTools main b707bd70 into act 2's slice 1a (#198)
Oct 19, 2026
3f326e0
Merge #246's final head 5dd0df07 into act 2's slice 1a (#198)
Oct 19, 2026
281be58
Merge #246's squash 55aae16 into act 2's slice 1a with -s ours: the b…
Oct 19, 2026
0beb37d
Merge openRepoTools main f18b818 (#252, #264, #266, #283, #262, #267-…
Oct 20, 2026
a4e4462
Fix round 1 of #282 (lane 3's review): routing is opt-in until slice …
Oct 20, 2026
7eb779a
Fix round 1's surviving mutants are killed: 12 cases pin the opt-in g…
Oct 20, 2026
d22c8a2
Fix round 2 of #282 (lane 3's re-review): without the opt-in a lock i…
Oct 20, 2026
cb05cfc
Fix round 3 of #282 (lane 3's re-check of eead86d): without the opt-i…
Oct 20, 2026
4d6bc14
SC2093: mark 1a's routing exec as deliberate, as lane openRepoTools-3…
Oct 22, 2026
903d751
Merge openRepoTools-code main 577110e (the cutover's own commits and …
Nov 8, 2026
f0d363a
Merge openRepoTools-code main e393958 (code PR 15, openRepoShape v1.1…
Nov 8, 2026
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
55 changes: 54 additions & 1 deletion lane-end
Original file line number Diff line number Diff line change
Expand Up @@ -523,11 +523,18 @@ lanes_workspace_why() {
# — so `$SCRIPT_DIR` answers both without a second rule. `$OPENREPOTOOLS_BIN_DIR`
# and `$PATH` are the fallbacks for a command copied somewhere on its own.
LANES_WS_ROOT=""
# AMENDMENT 23 (act 2, slice 1a). With neither variable set, every write of a
# lane goes through that lane's own register checkout, and the register this
# command READS follows it there once the lane's name is known
# (`lane_register_follow`, below). A caller's `LANES_REPO` without `LANES_FILE`
# is the checkout the helper now writes in, so its own register is the one read.
LANES_REG_DEFAULT=0
[ -n "${LANES_FILE:-}" ] || [ -n "${LANES_REPO:-}" ] || LANES_REG_DEFAULT=1
if [ -z "${LANES_FILE:-}" ] || [ -z "${LANES_REPO:-}" ]; then
LANES_WS_ROOT="$(lanes_workspace_root || :)"
fi
: "${LANES_REPO:=$LANES_WS_ROOT}"
LANES_FILE="${LANES_FILE:-${LANES_WS_ROOT:+$LANES_WS_ROOT/lanes/LANES.md}}"
LANES_FILE="${LANES_FILE:-${LANES_REPO:+$LANES_REPO/lanes/LANES.md}}"

lanes_edit_default() {
local d
Expand Down Expand Up @@ -940,6 +947,52 @@ if [ "$cl_rc" = 0 ] && [ -n "$cl_out" ] && [ "$cl_out" != "$LANE" ]; then
LANE="$cl_out"
fi

# AMENDMENT 23 S1, S2 — THE REGISTER THIS COMMAND READS IS THE ONE ITS WRITES GO
# THROUGH. Under `LANES_ROUTE_WRITES=1` (opt-in until slice 1b, the review of
# #282's MUST 2) and the default resolution, every write of this lane goes
# through its own checkout, `<W>-lanes/<lane>/`, and W, the readers' copy, moves
# only by `lanes-edit.sh refresh-workspace`. So W's working tree does not carry the
# lane's own rows once they are written: a lane started through its checkout
# read as a lane with no row, and a second start refused to add a duplicate
# that W could not see. The row this command counts and acts on is therefore
# read from that checkout. The helper makes the checkout here if it is not
# there yet, exactly as this command's first write would; a dry run makes
# nothing and reads W where there is no checkout. ONLY THE READ MOVES: the
# handoff this command publishes is still W's until Amendment 23's later slices.
# A helper that predates the verb writes W itself, so W is what is read. A
# checkout that could not be made (2) or whose creation lock is held (4) is
# SAID, and W is read (SHOULD 2): Amendment 8(d) — a launch is never refused for
# a register act it can do without, and the writes after it say their own.
lane_register_follow() {
[ "${LANES_ROUTE_WRITES:-}" = 1 ] || return 0
[ "$LANES_REG_DEFAULT" = 1 ] && [ -n "${LANE:-}" ] || return 0
case "$prog" in lane-end) lrf_none="Nothing was written." ;; *) lrf_none="Nothing was launched, renamed or written." ;; esac
lrf_args=(lane-checkout "$LANE")
[ "${dry_run:-0}" = 1 ] || lrf_args+=(--create)
lrf_errf="$(mktemp "${TMPDIR:-/tmp}/${prog}-register.XXXXXX" 2>/dev/null || printf '')"
lrf_out=""; lrf_rc=0
lrf_out="$("$LANES_EDIT" "${lrf_args[@]}" 2>"${lrf_errf:-/dev/null}")" || lrf_rc=$?
lrf_err=""
if [ -n "$lrf_errf" ]; then lrf_err="$(cat -- "$lrf_errf" 2>/dev/null || :)"; rm -f -- "$lrf_errf"; fi
case "$lrf_rc" in
0)
[ -z "$lrf_err" ] || printf '%s\n' "$lrf_err" >&2
[ -f "$lrf_out/lanes/LANES.md" ] ||
die "lane $LANE's register checkout $lrf_out carries no lanes/LANES.md, so the lane's row cannot be read (Amendment 23 S1). $lrf_none" 1
LANES_FILE="$lrf_out/lanes/LANES.md" ;;
8) : ;; # a dry run, and no checkout yet: W is what there is
2 | 4)
case "$lrf_err" in *"unknown subcommand 'lane-checkout'"*) return 0 ;; esac
[ -z "$lrf_err" ] || printf '%s\n' "$lrf_err" >&2
note "lane $LANE's own register checkout could not be made (\`$LANES_EDIT lane-checkout $LANE --create\` exited $lrf_rc, above), so this command reads W's register, which may not show what this lane's earlier writes put there (Amendment 23 S1, 8(d)). Each write below says for itself whether it went through." ;;
*)
[ -z "$lrf_err" ] || printf '%s\n' "$lrf_err" >&2
die "lane $LANE's own register checkout could not be read (\`$LANES_EDIT lane-checkout $LANE\` exited $lrf_rc, above), so the row this command acts on cannot be read where its writes go (Amendment 23 S1). $lrf_none" 1 ;;
esac
return 0
}
lane_register_follow

# THE SEAM (ruling 2026-10-04): A MANAGED-OWNED LANE IS NOT THIS COMMAND'S.
# `lanes-edit.sh managed-projection` answers 0 with the owner where the lane's
# register row carries the managed ledger's marker, 8 for a legacy lane, and 1
Expand Down
63 changes: 61 additions & 2 deletions lane-start
Original file line number Diff line number Diff line change
Expand Up @@ -605,11 +605,18 @@ lanes_workspace_why() {
# — so `$SCRIPT_DIR` answers both without a second rule. `$OPENREPOTOOLS_BIN_DIR`
# and `$PATH` are the fallbacks for a command copied somewhere on its own.
LANES_WS_ROOT=""
# AMENDMENT 23 (act 2, slice 1a). With neither variable set, every write of a
# lane goes through that lane's own register checkout, and the register this
# command READS follows it there once the lane's name is known
# (`lane_register_follow`, below). A caller's `LANES_REPO` without `LANES_FILE`
# is the checkout the helper now writes in, so its own register is the one read.
LANES_REG_DEFAULT=0
[ -n "${LANES_FILE:-}" ] || [ -n "${LANES_REPO:-}" ] || LANES_REG_DEFAULT=1
if [ -z "${LANES_FILE:-}" ] || [ -z "${LANES_REPO:-}" ]; then
LANES_WS_ROOT="$(lanes_workspace_root || :)"
fi
: "${LANES_REPO:=$LANES_WS_ROOT}"
LANES_FILE="${LANES_FILE:-${LANES_WS_ROOT:+$LANES_WS_ROOT/lanes/LANES.md}}"
LANES_FILE="${LANES_FILE:-${LANES_REPO:+$LANES_REPO/lanes/LANES.md}}"

lanes_edit_default() {
local d
Expand Down Expand Up @@ -1157,6 +1164,52 @@ esac
repo="${repo:-$LANE}" # the verbatim form has no <repo> of its own
estate="${estate:-$repo}"

# AMENDMENT 23 S1, S2 — THE REGISTER THIS COMMAND READS IS THE ONE ITS WRITES GO
# THROUGH. Under `LANES_ROUTE_WRITES=1` (opt-in until slice 1b, the review of
# #282's MUST 2) and the default resolution, every write of this lane goes
# through its own checkout, `<W>-lanes/<lane>/`, and W, the readers' copy, moves
# only by `lanes-edit.sh refresh-workspace`. So W's working tree does not carry the
# lane's own rows once they are written: a lane started through its checkout
# read as a lane with no row, and a second start refused to add a duplicate
# that W could not see. The row this command counts and acts on is therefore
# read from that checkout. The helper makes the checkout here if it is not
# there yet, exactly as this command's first write would; a dry run makes
# nothing and reads W where there is no checkout. ONLY THE READ MOVES: the
# handoff this command publishes is still W's until Amendment 23's later slices.
# A helper that predates the verb writes W itself, so W is what is read. A
# checkout that could not be made (2) or whose creation lock is held (4) is
# SAID, and W is read (SHOULD 2): Amendment 8(d) — a launch is never refused for
# a register act it can do without, and the writes after it say their own.
lane_register_follow() {
[ "${LANES_ROUTE_WRITES:-}" = 1 ] || return 0
[ "$LANES_REG_DEFAULT" = 1 ] && [ -n "${LANE:-}" ] || return 0
case "$prog" in lane-end) lrf_none="Nothing was written." ;; *) lrf_none="Nothing was launched, renamed or written." ;; esac
lrf_args=(lane-checkout "$LANE")
[ "${dry_run:-0}" = 1 ] || lrf_args+=(--create)
lrf_errf="$(mktemp "${TMPDIR:-/tmp}/${prog}-register.XXXXXX" 2>/dev/null || printf '')"
lrf_out=""; lrf_rc=0
lrf_out="$("$LANES_EDIT" "${lrf_args[@]}" 2>"${lrf_errf:-/dev/null}")" || lrf_rc=$?
lrf_err=""
if [ -n "$lrf_errf" ]; then lrf_err="$(cat -- "$lrf_errf" 2>/dev/null || :)"; rm -f -- "$lrf_errf"; fi
case "$lrf_rc" in
0)
[ -z "$lrf_err" ] || printf '%s\n' "$lrf_err" >&2
[ -f "$lrf_out/lanes/LANES.md" ] ||
die "lane $LANE's register checkout $lrf_out carries no lanes/LANES.md, so the lane's row cannot be read (Amendment 23 S1). $lrf_none" 1
LANES_FILE="$lrf_out/lanes/LANES.md" ;;
8) : ;; # a dry run, and no checkout yet: W is what there is
2 | 4)
case "$lrf_err" in *"unknown subcommand 'lane-checkout'"*) return 0 ;; esac
[ -z "$lrf_err" ] || printf '%s\n' "$lrf_err" >&2
note "lane $LANE's own register checkout could not be made (\`$LANES_EDIT lane-checkout $LANE --create\` exited $lrf_rc, above), so this command reads W's register, which may not show what this lane's earlier writes put there (Amendment 23 S1, 8(d)). Each write below says for itself whether it went through." ;;
*)
[ -z "$lrf_err" ] || printf '%s\n' "$lrf_err" >&2
die "lane $LANE's own register checkout could not be read (\`$LANES_EDIT lane-checkout $LANE\` exited $lrf_rc, above), so the row this command acts on cannot be read where its writes go (Amendment 23 S1). $lrf_none" 1 ;;
esac
return 0
}
lane_register_follow

# ----------------------------------------- 1b. THE LANE'S DIRECTORY
#
# AMENDMENT 11 CLAUSE (c). A lane's checkout is known to every process that is
Expand Down Expand Up @@ -4255,7 +4308,13 @@ hs_git_net() {
# `lanes-edit.sh` write goes out of it. Promising a carry that will not happen
# is worse than printing the command, so the note says which it is.
hs_carry_note() {
if [ -n "${LANES_REPO:-}" ] && [ "$hs_repo" = "$LANES_REPO" ]; then
# UNDER `LANES_ROUTE_WRITES=1` NO WRITE GOES OUT OF W (Amendment 23 S2; the
# review of #282, SHOULD 6): with the default resolution each one goes through
# its lane's own checkout, so none will ever push a commit made here.
if [ "${LANES_ROUTE_WRITES:-}" = 1 ] && [ "$LANES_REG_DEFAULT" = 1 ] &&
[ -n "${LANES_REPO:-}" ] && [ "$hs_repo" = "$LANES_REPO" ]; then
note " (this handoff is in W ($hs_repo), and under LANES_ROUTE_WRITES=1 every lanes-edit.sh write goes through its lane's own checkout instead, so none will push this commit: the command above is the whole of the recovery.)"
elif [ -n "${LANES_REPO:-}" ] && [ "$hs_repo" = "$LANES_REPO" ]; then
note " (this handoff is in the register's own checkout, so the next lanes-edit.sh write out of it pushes the branch and carries this commit with it.)"
else
note " (this handoff is NOT in the register's checkout ($hs_repo), so no lanes-edit.sh write will ever push it: the command above is the whole of the recovery.)"
Expand Down
35 changes: 35 additions & 0 deletions lane-worktrees
Original file line number Diff line number Diff line change
Expand Up @@ -5519,7 +5519,24 @@ class Report:

def _foreign(self, clones: list, canonical: list) -> None:
rows = []
# AMENDMENT 23 S1 - A LANE'S REGISTER CHECKOUT IS NOT A STRAY CLONE (the
# review of opensoft/openRepoTools#282, SHOULD 5). `<W>-lanes/<lane>/` is
# a clone of the register's origin beside W, made on purpose and holding
# that lane's writes; listing it here told a person to dispose of it.
wroot = self.helper.workspace_root() if self.helper.path else ""
lanes_home = real(wroot) + "-lanes" if wroot else ""
# AND A W THAT IS ITSELF A LANE CHECKOUT (the re-review of #282, SHOULD
# 5): Eagle's lane windows resolve W to their own `<X>-lanes/<lane>/`,
# and lane-start runs this report from there. Its lanes home is then its
# parent, as lanes-edit.sh's `lanes_home_check` reads a `*-lanes` one.
home = os.path.dirname(real(wroot)) if wroot else ""
if len(os.path.basename(home)) > len("-lanes") and home.endswith("-lanes"):
lanes_home = home
registers = []
for c in clones:
if lanes_home and os.path.dirname(real(c)) == lanes_home:
registers.append(c)
continue
container = _under_container(c, self.root)
why = ""
if container:
Expand All @@ -5541,6 +5558,24 @@ class Report:
("LOAD-BEARING: " + _lean_text(lean)) if lean else ""])
self.add("FOREIGN repositories", rows, "none: every clone is the estate's own checkout",
"A lane creates worktrees, never clones. Each is a person's to dispose of.")
if registers:
self._register_checkouts(registers)

def _register_checkouts(self, registers: list) -> None:
"""Amendment 23 S1: each lane's own checkout of the register, reported
with what it holds that origin lacks, and never offered for disposal."""
rows = []
for c in registers:
last = git_out(c, "log", "-1", "--date=short", "--format=%cd") or "?"
ahead = git_out(c, "rev-list", "--count", "origin/main..HEAD")
held = ("its HEAD could not be compared with origin/main" if ahead is None else
f"{ahead} commit(s) origin/main lacks" if ahead != "0" else "")
rows.append([c, f"lane {os.path.basename(c)}", human_size(dir_size(c)), last, held])
self.add("Register checkouts (Amendment 23 S1)", rows, "none",
"Each is one lane's own checkout of the register, where its writes go, and "
"not a stray clone: lane-end's sweep retires one (Amendment 23 S6), and a "
"person moves one aside only once `git -C <path> cherry -v origin/main` "
"shows nothing.")

def _closed_lanes(self) -> dict:
"""{lane: why} for every lane whose snapshot is CLOSED or whose log's
Expand Down
Loading
Loading