#!/usr/bin/env bash
#
# lane-start — the FIRST act of a lane: name the tmux window after the lane,
# put the lane's row in the register, and launch the session under the same
# name. One command at the boundary, so the three things that must agree are
# set in one act and cannot drift apart.
#
# THE LANE RULE (Brett Heap, 2026-09-10)
#   lane = tmux window name = Claude session name, in the form
#   `<repo>-<position across, left to right>`. The working directory confers
#   NO lane — two lanes may share one; a window still called `claude` has no
#   lane at all; and whether a name is free is decided by whether the
#   register row's recorded session id is LIVE, never by whether a row exists.
#
# PROTOCOL  ~/.agents/protocols/lane-collision-protocol.md
#   Rule 4 + Amendment 2 — the window is NAMED for the lane BEFORE the row is
#     appended, and peers are addressed by that name.
#   Rule 9 + Amendment 5 — every register write is one commit, made by
#     lanes-edit.sh, in the person's workspace repository.
#   Rule 10 — every row names its workstation.
#   Amendment 7 (DRAFT 2026-09-11) — after the row is written, the lane's own
#     object log records that the lane is here. Every line has an object, and
#     a lane-kind line's object is the lane itself:
#       STARTED — lane X, session <uuid>@<ws>, <UTC>, lane:X → home owner/repo; estate <estate>
#     `RESUMED` for a session that is being resumed rather than started. The
#     home repo comes from `git remote get-url origin` of the lane's OWN
#     directory: `<repo>-<n>` is a label, not a scope, and this line is the
#     only thing that says where a lane actually lives. It is resolved through
#     `lanes/repos.tsv` before it is written (R20), because a home is inherited
#     by every `#n` that lane writes and a legacy org spelling would key those
#     against a repository nothing else can reconcile them with.
#   Amendment 6 (DRAFT 2026-09-11, awaiting Brett Heap's word) — A LANE IS
#     RESUMED BY THE SESSION ID ITS ROW RECORDS, NEVER BY ITS TITLE. Titles are
#     not unique: `claude --help` says `-r, --resume [value]` is "Resume a
#     conversation by session ID, or open interactive picker with optional
#     search term", so only a session id is an exact resume — a title merely
#     filters the picker. On 2026-09-11 four transcripts in one working
#     directory carried the title `codeXfactory-1` and eight more carried
#     `codeXfactory-1 (2)` / `(4)`, while the session Brett was actually
#     driving carried no title at all.
#   Rule 3 + Amendment 8 (DRAFT 2026-09-12) — THE HANDOFF IS STAMPED HERE TOO.
#     On a resume, the handoff the row points at gets Rule 3's line, in place,
#     as the line after its header block:
#       RESUMED by <uuid> (lane <name>) at <UTC> — lane-start on <ws>
#     committed on its own as `handoff(<lane>@<ws>): RESUMED by <uuid>`, with
#     an explicit pathspec and a `Lane:` trailer (Amendment 4(d)), then pulled
#     and pushed. It NEVER refuses the launch: a stamp that cannot be written
#     prints the command that writes it. Seven resumes of one lane needed that
#     line written by hand, and while it was owed the counts drifted 6/4/5
#     across the row, the object log and the handoff itself.
#
# USAGE
#   lane-start [options] <repo> <n>      # lane-start openRepoShape 2
#   lane-start [options] <repo>-<n>      # the full lane name works too
#   lane-start [options] <n>             # <repo> = basename of the cwd's git root
#   lane-start --dir <path> <lane>       # any lane name, when --dir says where
#   lane-start                           # no <repo> and no <n>: this is `lane`
#
# BARE, THIS IS `lane` (Amendment 18 Addendum 1 clause (i-4)): the lanes,
# numbered, and the one you pick is bound. It renders nothing of its own — it
# `exec`s that word, carrying `--dry-run` and `--dir`, which mean the same thing
# there, and REFUSING by name the options `lane` has nothing to apply them to
# rather than dropping them. On a workstation with no `lane` the old refusal is
# still the whole answer.
#
# <repo> is parsed out of the lane name only because it is what locates the
# lane's directory. With `--dir` there is nothing left to parse, so the name is
# taken VERBATIM — which is how a lane named before the `<repo>-<n>` rule
# (`browser-ui-repair`) is started.
#
# OPTIONS
#   --dir <path>     the lane's checkout            (default $PROJECTS_ROOT/<repo>)
#   --estate <name>  the handoff estate folder      (default <repo>)
#   --dry-run        print every step; rename nothing, write nothing, launch
#                    nothing
#   --no-launch      do everything except the launch, and print the claude
#                    command on stdout — for the launcher integration and the
#                    tests
#   --confirm        when this window's name is not the lane, print the three
#                    facts that disagree — the WINDOW, the SESSION live in it,
#                    the ROW — and ask before taking it. The launcher passes it
#                    when the lane came from the swap RECORD rather than from
#                    the window name or a flag (Amendment 8)
#   --yes            answer that question yes without asking, for a caller that
#                    has already asked
#   --request-handoff  a lane bound in ANOTHER place is never taken (Amendment
#                    18(b)). This is the `y` to the question this command asks
#                    on a terminal, for a caller that has none: the request is
#                    written to the lane's log and pushed, typed into the bound
#                    pane where it is on this tmux server, and waited on
#   --force <why>    clause (e)'s override: release that binding ON ITS BEHALF
#                    and bind here. A SECOND invocation, never automatic, and
#                    the <why> is written into an append-only log and is what
#                    the bound session reads when it refuses every prompt from
#                    then on
#   --wait <s>       how long to wait for the handoff (default 300, clause (c))
#   --agent <name>   WHICH AGENT resumes this lane (Amendment 17(c)). Default:
#                    the agent of the lane's last `PAUSED` record, else
#                    `claude`. `claude` with its transcript here resumes it by
#                    id exactly as Amendment 6 has always done; every other
#                    case launches the named agent with the handoff's TOP BLOCK
#                    as its first prompt. The table is `claude` and `codex`; a
#                    name it does not carry is a refusal naming the two, never a
#                    guessed argv
#   --fresh          A NEW SESSION of this lane's agent, primed by the handoff's
#                    top block, whatever transcript the row names — the
#                    fresh-session mode as an ARGUMENT rather than as an
#                    environment variable (openRepoTools#94). The lane's own
#                    pending restart intent outranks it; a conflicting one is a
#                    refusal and never a substitution
#   --operation <id> the restart operation this launch belongs to, passed by the
#                    pane supervisor. The intent named by it is the one this run
#                    reads; an id that is not the lane's current operation is a
#                    refusal
#   --bind <uuid>    THE NAME GUARD'S BINDING MODE, and nobody else's: the
#                    guard passes it on a person's choice `2` at its offer
#                    (Amendment 12(h) rule 2, openRepoTools#70). <uuid> is the
#                    transcript of the session live in THIS window. It is
#                    appended to the lane's session cell even where another row
#                    records it — that `2` is the person's yes (clause (h) rule
#                    4) — and the row's stamp, the lane's log line and the
#                    handoff's Rule 3 stamp all name it, never the id this run
#                    would otherwise have resumed. It binds or it refuses: only
#                    with --no-launch, never with --fresh or --agent, and a
#                    <uuid> that is not this window's live session, or a window
#                    named for another lane, is a refusal before anything is
#                    written
#   -h, --help
#   --               everything after it is passed through to claude
#
# WHAT IT DOES, in order
#   1. derives LANE=<repo>-<n> and the lane's directory (which must exist);
#   2. refuses unless it is already inside tmux: it renames the window it is
#      run in and never creates a session;
#   3. LIVENESS CHECK, before it takes the name. If the register already has a
#      row for LANE it reads the session id(s) out of THE PUBLISHED row's
#      session cell — `lanes-edit.sh register-row`, which fetches and reads
#      `origin/<branch>` — and looks for a LIVE record (pid alive, start time
#      still matching, a status that is not `ended`) in every profile's
#      `sessions/*.json`. A live holder in ANOTHER tmux window is a refusal. A
#      row whose recorded sessions are all dead is a lane you are RESUMING, and
#      that is allowed;
#   3b. the LIVE SESSION IN THIS WINDOW (Amendment 8), which is not the same
#      question as step 3's. The harness mints a new transcript uuid with
#      nobody acting — a `/clear` does it, and so did the 2026-09-12 usage
#      reset that carried this lane's conversation into `4a91f1dc…` while its
#      row still ended on `09dd34d1…`. That id is in NO row, so step 3 cannot
#      see it and answers "this lane is parked" about the conversation sitting
#      in the very window it was asked about. Keyed on the WINDOW instead
#      (`lanes-edit.sh window-session`), the record is found: its uuid is
#      appended to the session cell in step 5, BEFORE the stamp, and it is what
#      this run resumes and stamps. There is no flag for it and there could not
#      be one — the id does not exist until the session does, so the act is
#      `lane-start --no-launch <repo> <n>` run IN that window, which is what the
#      SessionStart hook's block tells the new session to do. (`--bind <uuid>`
#      is the one caller already INSIDE that session — the name guard — naming
#      it, and it is the guard's alone: see OPTIONS);
#   3c. `--confirm`, if it was passed and this window is not already named for
#      the lane: the triple in front of a person, and a question. Before the
#      rename and before any write, so a No costs nothing;
#   4. `tmux rename-window <LANE>` — which also turns automatic-rename OFF for
#      that window (tmux(1) rename-window), so the name survives the next
#      command the window runs. A NEW lane's name is read back, and where
#      another window carries it too the rename is undone and the run refuses;
#   5. the row: `lanes-edit.sh add-row` when there is none, otherwise
#      `set-row-state`. Never a hand edit and never a whole-file write.
#      THE STATE IS AMENDMENT 6(c)'s STAMP, written here rather than owed to
#      the session afterwards, and since Amendment 13(a) it is the WHOLE cell
#      (`<STATE> · <UTC> · <one line>`, the UTC stamped by the writer):
#        LIVE · <UTC> · RESUMED by <uuid> (lane <lane>) — lane-start on <ws>:
#        window renamed, launching <the command>; dir <dir>; window <ref>
#      The TAIL states what happened, so a `--no-launch` run ends `window
#      renamed, no launch` and never claims to have launched anything.
#      `STARTED` where a new session takes the name, and the uuid is the one
#      this run actually resumes or mints, read from the PUBLISHED row. A stamp
#      that is owed is a stamp that is missed, and under Amendment 6(b) a missed
#      stamp is not bookkeeping debt — it is a lost lane. A brand-new row needs
#      no stamp: it is created with that uuid already in its session cell;
#   6. the launch. It is DECIDED in step 5a, before the row is written, because
#      a brand-new session's id is minted there and step 5 must record it.
#      RESUME BEATS NEW throughout — a rename into a title that is still held
#      mints `<LANE> (2)` and the lane loses its address. Three cases, in order:
#        a. `exec claude --resume <id>`, where <id> is THE LAST session id in
#           the PUBLISHED row's session cell and
#           `<projects state>/<cwd key>/<id>.jsonl` exists. Exact: that
#           conversation and no other.
#        b. `exec claude --resume <LANE>` when no recorded id resolves but a
#           transcript here carries the custom title <LANE> — or `<LANE> (N)`,
#           which is the same lane: that suffix is what a rename into a title
#           something else still holds mints, and the liveness check has always
#           read it that way. THE FALLBACK, not the rule — it opens the picker
#           filtered by the title, and several transcripts can share one title.
#           A suffix found here is reported: it means a stale holder was live,
#           and the cure is to retire the holders, not to live with `(4)`.
#        c. `exec claude --name <LANE> --session-id <fresh uuid>` for a lane
#           with no history here. The uuid is minted so the row can carry it,
#           which is what makes (a) work on the next start.
#
# THE RESUME TARGET — WHY THE LAST ID, AND WHY THE PUBLISHED CELL
#   The session cell is a HISTORY, written left to right: a lane's row reads
#   `<first> → <after the first /clear> → <after the profile switch>`, oldest
#   first, because each succeeding session appends itself. So the LAST session
#   id in the cell is the lane's current one, and that is the only id this
#   script will resume. Earlier ids are the lane's past and are never resumed
#   (a stale lineage is precisely what went wrong on 2026-09-11).
#
#   AND THE CELL IS THE PUBLISHED ONE. `$LANES_FILE` is this checkout's working
#   tree, and a `git fetch` does not move a working tree: a uuid a peer stamped
#   from another clone and pushed is simply absent here until something pulls.
#   Read from there, a row published as `<U1> → <U2>` still reads `<U1>` — so
#   the operator lands in the lane's PREVIOUS conversation, the status appended
#   to the row names the wrong id, and the RESUMED line goes into
#   `lanes/log/<lane>.md` carrying a session uuid that is not the lane's
#   current one, in a file nothing ever rewrites. Every other state read in
#   this tooling goes through `origin/<branch>` after a fetch; this one does
#   too, through the same `register-row` this script already asks before it
#   adds a row. `live-holder`'s id set stays a UNION of both (R25) and is the
#   one exception, for the opposite reason: liveness fails CLOSED, so an id
#   only this checkout knows is one more reason to refuse a rename.
#
# KEEPING THE ROW CURRENT
#   Resuming by a recorded id only works if the row is current, so this script
#   makes it current where it can:
#     * case (c), NEW ROW — the row is created with the minted id already in
#       its session cell, instead of `pending — set by the session's first act`;
#     * case (c), EXISTING ROW — `lanes-edit.sh append-session-id` appends
#       `→ harness <minted id>` after the cell's last id, matching that id
#       INSIDE THE SESSION CELL: the 6(c) stamp writes the same uuid twice more
#       into the state cell, so a whole-row anchor (`replace-in-row`) refuses on
#       every row this tool has already stamped — three occurrences in this
#       estate's own `openRepoProject-1` row. When the cell has no
#       id to append to (some rows record only `session_…` footer ids, which
#       are not transcript ids), it prints the command and leaves the act to
#       the session — it never guesses at the cell's text;
#     * case (a) — nothing to do: the row already names the session being
#       resumed;
#     * case (b) — the id cannot be known before the picker runs, so the
#       session stamps its own row as its first act (Amendment 6(c)).
#   `--session-id` is set to LANE_START_SESSION_ID=0 to turn the minting off;
#   the row then reads `pending — set by the session's first act` as before.
#
# WHAT COUNTS AS A SESSION ID IN THE CELL
#   The TRANSCRIPT uuid — the name of the session's `<uuid>.jsonl` — and only
#   that, because it is the only id `--resume` takes and the only one the
#   liveness records key on. Some rows record a PR-FOOTER id (`session_01…`)
#   instead; those cannot be resumed or checked, so the script names them and
#   says the row needs the transcript uuid rather than treating the cell as
#   empty. Every RESUMED / handoff / takeover stamp writes the transcript uuid.
#
# OUTPUT  every step and every refusal goes to stderr; the ONLY thing written
#   to stdout is `--no-launch`'s command line, so `--no-launch` composes.
#
# EXIT
#   0  done
#   1  environment — not inside tmux, no tmux, a RECORDED directory that is
#      gone, no register, or `lanes-edit.sh live-holder` failed (which is NOT
#      the same as its answering 8, "no live session holds this lane")
#   2  refusal — an ARGUMENT ERROR, and one further case this amendment adds: a
#      name that is not a lane, a position that is not a position, a name a
#      window cannot take, a lane whose register holds two rows and so resolves
#      to none, a lane that is live in another window — and A LANE WHOSE
#      CHECKOUT IS NOT RECORDED AND CANNOT BE PROVED (Evidence 7).
#
#      THAT LAST ONE MOVED FROM 1 TO 2 AND THE MOVE IS THE POINT. Evidence 7:
#      a lane whose record predates clause (c) carries no `dir`, the default
#      `$PROJECTS_ROOT/<repo>` did not exist, and this script exited **1**
#      behind the launcher's `exec` — a pane that said `[exited]` with the
#      message scrolled past it. It is a REFUSAL a person fixes with one flag,
#      not an environment that failed, and `restart` already spends 2 on the
#      same fact (clause (i), `R-A11-20`: *"no such lane, no recorded
#      directory, no profile recorded yet"*). A directory the lane itself
#      RECORDED and which is now gone keeps 1: that is a path that was right
#      and moved, and nothing is searched for in its place.
#
#      A PERSON'S ANSWER IS NOT AN ARGUMENT ERROR. `--confirm` answered `N`, and
#      `--confirm` with no tty and no `--yes` — the same answer with nobody
#      there to give it — rename nothing, write nothing, print one notice and
#      `exec` Claude BARE with the pass-through arguments, exit 0. A launcher
#      that `exec`s this script would otherwise leave the operator in an exited
#      pane with no Claude in it. Under `--no-launch` the bare command is
#      printed on stdout, so a launcher can exec it itself.
#
# ENVIRONMENT
#   PROJECTS_ROOT        default ~/projects
#   LANES_FILE           default <the workspace repository>/lanes/LANES.md
#   LANES_EDIT           default lanes-edit.sh beside this command
#   AGENT_PROTOCOL_ROOT  dir holding workspace.yaml (default ~/.agents)
#   OPENREPOTOOLS_BIN_DIR  where `--install` put the commands (default
#                        ~/.local/bin) — searched for lanes-edit.sh
#   CLAUDE_CONFIG_DIR    the profile whose sessions/ and projects/ are read
#   CLAUDE_PROJECTS_DIR  default $CLAUDE_CONFIG_DIR/projects, else ~/.claude/projects
#   CLAUDE_BIN           the Claude Code to launch. Unset, it is the absolute
#                        path `claude-current --porcelain` answers, the one
#                        beside this command or in $OPENREPOTOOLS_BIN_DIR and
#                        never one on PATH: npm's published version, updated
#                        first when every copy is behind, and a stale one
#                        REFUSED with exit 2 before anything is written
#                        (opensoft/workBenches#119). `claude` from PATH only
#                        where no claude-current is installed. Set, it is a pin
#                        and launched as it is, unless it equals
#                        CLAUDE_RESOLVED_BIN with no CLAUDE_VERIFIED_VERSION:
#                        that is an earlier launch's answer inherited through a
#                        session's environment, and it is resolved again
#   CLAUDE_RESOLVED_BIN  the path a resolution chose, exported beside CLAUDE_BIN
#   CLAUDE_VERIFIED_VERSION  the version a launcher's own claude-current read
#                        for CLAUDE_BIN (equal to CLAUDE_RESOLVED_BIN): recorded
#                        as `claude <version>` on the log line, and removed
#                        before the launch so no session inherits it
#   CLAUDE_ALLOW_STALE=1 claude-current answers with a stale copy instead of
#                        refusing it; docs/README-claude-current.md has the rest
#   LANE_START_SESSION_ID  0 turns off minting a uuid for a new session (and
#                        therefore turns off writing it into the row)
#   LANE_START_HANDOFF_ANSWER  answers Amendment 18(c)'s question — *"ask it to
#                        hand off, then bind here?"* — without a terminal. The
#                        seam the tests drive it through, and its own variable
#                        rather than `LANE_START_ANSWER`'s because one run can
#                        ask both questions and a single seam would answer the
#                        wrong one. Set at all, it is the answer; anything but
#                        y/yes is No
#   LANE_START_ANSWER    answers `--confirm`'s question without a terminal —
#                        the seam the tests drive it through. Set at all, it is
#                        the answer; anything but y/yes is No
#   LANES_REPO           the checkout the register and the handoffs share
#                        (default: the workspace repository)
#   LANES_WORKSPACE_ROOT the workspace repository, overriding the `path:` in
#                        ${AGENT_PROTOCOL_ROOT:-~/.agents}/workspace.yaml — the
#                        test seam, and the only override there is
#   LANES_BRANCH         default main — the branch the handoff stamp is pushed on
#   LANES_GIT_TIMEOUT    seconds bounding each git call that touches the NETWORK
#                        (default 60; 0 or a non-number turns the bound off)
#   LANES_GIT            the git binary THOSE calls use, so a test can hand them
#                        a git that hangs without shadowing git for the script
#   LANES_NO_GIT=1       write the handoff's stamp but commit nothing
#   LANE_START_FRESH=1   a NEW session of this lane's agent, started with the
#                        top block of the handoff the row names as its first
#                        prompt — which is what a context clear IS. It was
#                        `/ctx`'s one seam under Amendment 17(f) and it still
#                        works; it is NO LONGER THE AUTHORITY (openRepoTools#94):
#                        the lane's own restart intent outranks it and `--fresh`
#                        stands beside it, because an environment variable does
#                        not survive the launcher's `tmux new-session` and this
#                        command was measured being reached without it
#
# It spells no absolute path of its own. Since Amendment 9(a) the register is
# found through `$AGENT_PROTOCOL_ROOT/workspace.yaml` rather than beside this
# file — this is an installed command now, and a command's own directory is
# evidence about the command, not about a person's data. Its WRITER is found
# beside it, because `--install` places the two together. Everything else hangs
# off $HOME.

set -euo pipefail

prog=lane-start

SELF="${BASH_SOURCE[0]}"
RESOLVED="$(readlink -f -- "$SELF" 2>/dev/null || printf '%s' "$SELF")"
SCRIPT_DIR="$(cd -- "$(dirname -- "$RESOLVED")" && pwd)"

# --- THE WORKSPACE REPOSITORY (lane-collision-protocol Amendment 9(a)) -------
#
# The person's data — the register `lanes/LANES.md`, the object logs
# `lanes/log/`, the handoffs, the manifests `park` writes, and a
# `lanes/repos.tsv` override — is found through
# `$AGENT_PROTOCOL_ROOT/workspace.yaml`, and NEVER from this file's own
# location. `resume:466` and `status:1673` already read that same file under
# that same name, and Amendment 9(a) mints no second one: a second way to find
# it is a second answer.
#
# Deriving it from here stopped being POSSIBLE the moment this became an
# installed regular file in `~/.local/bin` with no register anywhere near it,
# and it stopped being WANTED for a subtler reason: a file's location on disk
# is evidence about the file, not about a person's data.
#
# THESE FOUR FUNCTIONS ARE A DELIBERATE COPY, byte for byte, across
# `lanes-edit.sh`, `lane-start`, `lane-end` and `link-estates` — the same trade
# openRepoTools already makes for its own fetch shim (`openRepoTools:93-100`).
# A shared `lanes-common.sh` would be a TENTH file for `--install` to place and
# a broken helper the first time somebody copied only some of them. Each of
# these is one file a person has on PATH.
#
# FAILING TO FIND IT IS A REFUSAL, NEVER A GUESS. No file, no `path:`, no
# `repository:`, or a `path:` that is not the root of a checkout of the
# `repository:` named beside it → the caller refuses, exit 1 — the code
# `lanes-edit.sh` has always used for *registry not found* — with the fix
# named: `openRepoTools wip init`. Nothing here ever creates that file, writes
# a register, or falls back to a path derived from its own location. THE
# CHECKOUT TEST IS NEW: nothing validated it before this, so a `path:` pointing
# at some other repository used to be accepted and now is not.
#
# `LANES_WORKSPACE_ROOT` is the test seam and the only override — the seam
# `lane-start` already spelled for handoff resolution, widened to the whole
# question so `test_lane_helpers.sh` can point every helper at one sandbox.
# --- BEGIN shared workspace resolver (Amendment 9(a)) ----------------------
# BYTE-IDENTICAL IN ALL FOUR LANE HELPERS, and held there by
# `tests/test_repo_hygiene.py`. The estate commands carry the same discipline
# for their own estate resolver and for the same reason its guard gives: a
# drifted copy is TWO ANSWERS to one question, and "where is this person's
# workspace" is exactly the question Amendment 9(a) exists to give one answer
# to. Edit it in one file and the test names the other three.
LANES_WS_WHY=""

lanes_ws_yaml() { printf '%s\n' "${AGENT_PROTOCOL_ROOT:-$HOME/.agents}/workspace.yaml"; }

# `key: value` at the TOP LEVEL only, first occurrence, with an inline `#`
# comment and surrounding quotes stripped and a leading `~` expanded against
# $HOME (nothing expands a bare `~` inside a file). The anchored `^key:` never
# reaches into the INDENTED `orgs:` map, which Amendment 9(a) puts out of
# scope: these helpers read `repository:` and `path:` and nothing else, because
# one register in the first workspace repository is the whole rule — the
# register never follows that map. Two lines of sed, because a YAML parser is
# not a dependency any of these files will take for one scalar.
lanes_ws_field() {
  local v
  v="$(sed -n -e "s/^$1:[[:space:]]*//p" "$2" 2>/dev/null | head -n 1 |
    sed -e 's/[[:space:]]*#.*$//' -e 's/[[:space:]]*$//')"
  v="${v%\"}"; v="${v#\"}"
  v="${v%\'}"; v="${v#\'}"
  case "$v" in
  '~') v="$HOME" ;;
  '~/'*) v="$HOME/${v#'~/'}" ;;
  esac
  printf '%s\n' "$v"
}

# THE WORKSTATION'S NAME IS READ, NEVER INVENTED — AND NEVER `hostname` INSIDE A
# CONTAINER (lane-collision-protocol Amendment 11, ratified decision 8(d), as
# corrected by A11 Addendum 3's `R-A11-14`).
#
# WHAT WENT WRONG. `opensoft/brett-wip` `origin/main` carries SIX lines in
# `lanes/log/openRepoProject-1.md` whose workstation is a container id — five
# `@0e7d1a79a07e`, one `@55cceb3e5bc9` — in an append-only file, written by every
# writer inside that container and not only by Evidence 6's fork. A row on a
# workstation that does not exist is a row no reader can match, no crossing can
# detect and no `swapped <ws>` can answer for; and the log is never rewritten, so
# each one is wrong for ever.
#
# WHO OWNS THE VALUE. `R-A11-14`: the **workBenches launcher**, which runs on the
# host and exports `LANES_WORKSTATION=<the host's own hostname -s>` into every
# session AND every container it starts, beside the `CLAUDE_PROFILE_NAME` it
# already exports. These helpers READ it. They do not write it, they do not
# derive it from a second file, and THEY NEVER SUBSTITUTE A PLACEHOLDER: an
# `@unknown-workstation` is the same defect one field along from the `unknown`
# clause (e) refuses in the session field, and the rejected alternative — a
# `workstation:` key in `workspace.yaml` — is a SECOND PLACE FOR THE TRUTH TO BE
# WRONG beside the variable the launcher already sets.
#
# THE THREE ANSWERS, as `<name><TAB><source>`:
#
#   seam              `$LANES_WORKSTATION` is set. This is the ordinary case
#                     wherever the launcher started the session.
#   hostname          no seam, and this is NOT a container: `hostname -s`, which
#                     is what the seam has defaulted to since Amendment 6 and
#                     what every row written before this rung was written by.
#   container-unset   no seam, and this IS a container. The NAME still answers,
#                     because a read in front of every launch may not refuse —
#                     it will simply match nothing, which is the honest answer —
#                     but every WRITER refuses, exit 2, naming the variable and
#                     the launcher that sets it.
#
# IT ANSWERS AS A PAIR, AND THAT IS NOT A STYLE CHOICE. A caller reads the name
# with `$(lanes_workstation)`, which is a COMMAND SUBSTITUTION and therefore a
# subshell: a global the function set there dies with it. The source is on the
# same line as the name, which is the only way out of a subshell there is.
#
#   $LANES_IN_CONTAINER   1 or 0, forcing the probe. THE TEST SEAM, and nothing
#                         else sets it: the suite must be able to exercise both
#                         halves of this rule on one host, and the host it runs
#                         on is a container exactly when it is.
lanes_in_container() {
  case "${LANES_IN_CONTAINER:-}" in
  1) return 0 ;;
  0) return 1 ;;
  esac
  [ -e /.dockerenv ] || [ -e /run/.containerenv ]
}

lanes_workstation_pair() {
  local v
  if [ -n "${LANES_WORKSTATION:-}" ]; then
    printf '%s\t%s\n' "$LANES_WORKSTATION" seam
    return 0
  fi
  v="$(hostname -s 2>/dev/null || hostname 2>/dev/null || printf 'unknown')"
  if lanes_in_container; then
    printf '%s\t%s\n' "$v" container-unset
  else
    printf '%s\t%s\n' "$v" hostname
  fi
}

# THE NAME ALONE, which is what every writer of the workstation column wants.
lanes_workstation() { lanes_workstation_pair | cut -f1; }

# The ONE SENTENCE a writer refuses with, in one place, so the three writers
# cannot word it three ways. Empty on every other source, so
# `[ -n "$(lanes_workstation_why "$src")" ]` is the whole of the test.
lanes_workstation_why() {   # <source>
  [ "${1:-}" = container-unset ] || return 0
  printf '%s\n' "this is a container and \$LANES_WORKSTATION is not set, so there is no workstation name to write. This host's own \`hostname\` is the CONTAINER'S id, not a workstation, and a row on a workstation that does not exist is a row no reader can match — in a log nothing ever rewrites (Amendment 11, decision 8(d); R-A11-14). The value is the workBenches launcher's to export into every session and container it starts. Set it for this one and re-run: export LANES_WORKSTATION=<this host's name>"
}

# One of the spellings `git remote get-url origin` prints for one GitHub
# repository, reduced to a bare lowercased `<owner>/<name>` so it can be
# compared against workspace.yaml's own `<owner>/<name>`. A URL that is not
# GitHub's is compared as it stands, lowercased — which is what lets a sandbox
# name a bare local origin and still be checked.
lanes_ws_norm() {
  local u="${1%.git}"
  case "$u" in
  https://github.com/*) u="${u#https://github.com/}" ;;
  ssh://git@github.com/*) u="${u#ssh://git@github.com/}" ;;
  git@github.com:*) u="${u#git@github.com:}" ;;
  esac
  printf '%s' "$u" | tr '[:upper:]' '[:lower:]'
}

# Do these two name one repository? Equal after normalisation, OR the origin's
# path ENDS in the `<owner>/<name>` the pointer file spells — which is how a
# GitHub Enterprise host, an ssh alias and a local bare mirror laid out by
# owner and name all say the same thing as `https://github.com/<owner>/<name>`.
# The pointer file spells `<owner>/<name>` because that is what a person types;
# `git remote get-url` spells a URL because that is what git stores.
lanes_ws_same_repo() {
  local a b
  a="$(lanes_ws_norm "$1")"
  b="$(lanes_ws_norm "$2")"
  [ -n "$a" ] && [ -n "$b" ] || return 1
  [ "$a" = "$b" ] && return 0
  case "$a" in */"$b") return 0 ;; esac
  return 1
}

# Prints the workspace checkout's real root, or returns 1 having set
# $LANES_WS_WHY to the one sentence that says which of the five ways it failed.
# ROOT-NESS IS ITS OWN CHECK: `rev-parse --is-inside-work-tree` and
# `remote get-url origin` both succeed from any SUBDIRECTORY of a work tree, so
# a `path:` naming a subdirectory would otherwise be accepted and resolve
# `<path>/lanes/LANES.md` inside the wrong directory.
lanes_workspace_root() {
  local yaml repo path origin toplevel real
  LANES_WS_WHY=""
  if [ -n "${LANES_WORKSPACE_ROOT:-}" ]; then
    printf '%s\n' "$LANES_WORKSPACE_ROOT"
    return 0
  fi
  yaml="$(lanes_ws_yaml)"
  if [ ! -r "$yaml" ]; then
    LANES_WS_WHY="there is no $yaml"
    return 1
  fi
  repo="$(lanes_ws_field repository "$yaml")"
  path="$(lanes_ws_field path "$yaml")"
  if [ -z "$repo" ]; then
    LANES_WS_WHY="$yaml names no \`repository:\`"
    return 1
  fi
  if [ -z "$path" ]; then
    LANES_WS_WHY="$yaml names no \`path:\`"
    return 1
  fi
  if ! git -C "$path" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
    LANES_WS_WHY="$yaml names path: $path, which is not a git checkout"
    return 1
  fi
  origin="$(git -C "$path" remote get-url origin 2>/dev/null || :)"
  if ! lanes_ws_same_repo "$origin" "$repo"; then
    LANES_WS_WHY="$yaml names repository: $repo, but $path is a checkout of ${origin:-no origin at all}"
    return 1
  fi
  toplevel="$(git -C "$path" rev-parse --show-toplevel 2>/dev/null || :)"
  real="$(cd -- "$path" 2>/dev/null && pwd -P)" || real=""
  if [ -z "$real" ] || [ "$toplevel" != "$real" ]; then
    LANES_WS_WHY="$yaml names path: $path, which is not the ROOT of that checkout (${toplevel:-unknown} is)"
    return 1
  fi
  printf '%s\n' "$real"
}

# The refusal's body, so all four helpers say the same thing in the same words.
#
# THE REASON IS RE-DERIVED HERE, IN THE PARENT SHELL, and that is the whole
# point of this line. Every caller reaches the resolver through a command
# substitution — `LANES_WS_ROOT="$(lanes_workspace_root || :)"` — which runs it
# in a SUBSHELL, so the $LANES_WS_WHY it set died with that subshell and the
# parent still holds the empty string it started with. Six distinct diagnoses
# were being computed and all six were being thrown away; every one of the
# refusals Amendment 9(a) enumerates printed the same "no reason recorded".
# The resolver is read-only and cheap — two `sed`s and three `git` reads — and
# it is reached on the refusal path only, so running it again HERE is the one
# place its answer survives to be printed.
lanes_workspace_why() {
  [ -n "$LANES_WS_WHY" ] || lanes_workspace_root >/dev/null 2>&1 || :
  printf '%s' "the workspace repository could not be found — ${LANES_WS_WHY:-no reason recorded}.
    Amendment 9(a): every lane helper reads \`repository:\` and \`path:\` from
    $(lanes_ws_yaml), never from its own location. One command writes that
    file, creates or clones the repository and places the symlinks:
        openRepoTools wip init"
}
# --- END shared workspace resolver ------------------------------------------

# THE REGISTER AND ITS WRITER, after the move (Amendment 9(b)). The register is
# the workspace repository's `lanes/LANES.md`, found through the pointer file
# above. The writer is `lanes-edit.sh`, which `--install` places BESIDE this
# command — in `~/.local/bin` when installed, in the checkout when run from one
# — 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=""
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_edit_default() {
  local d
  [ -x "$SCRIPT_DIR/lanes-edit.sh" ] && { printf '%s\n' "$SCRIPT_DIR/lanes-edit.sh"; return 0; }
  d="${OPENREPOTOOLS_BIN_DIR:-$HOME/.local/bin}"
  [ -x "$d/lanes-edit.sh" ] && { printf '%s\n' "$d/lanes-edit.sh"; return 0; }
  command -v lanes-edit.sh 2>/dev/null && return 0
  printf '%s\n' "$SCRIPT_DIR/lanes-edit.sh"
}
LANES_EDIT="${LANES_EDIT:-$(lanes_edit_default)}"

PROJECTS_ROOT="${PROJECTS_ROOT:-$HOME/projects}"
CLAUDE_HOME="${CLAUDE_CONFIG_DIR:-$HOME/.claude}"
PROJECTS_STATE="${CLAUDE_PROJECTS_DIR:-$CLAUDE_HOME/projects}"

# WHICH CLAUDE CODE A LAUNCH STARTS (opensoft/workBenches#119, Brett Heap
# 2026-09-29, verbatim "for 2, we can run update on every start, this ensures
# we have the latest models"). Decided here, from the environment as it
# arrived, and acted on by `lane_claude_resolve_launch` below, once a launch
# is certain: before the binding handoff, and in the bare launch a `--confirm`
# answered No takes. Three shapes, and docs/README-claude-current.md has the
# contract:
#   * CLAUDE_BIN unset: resolve through `claude-current`, the one `--install`
#     places beside this command;
#   * CLAUDE_BIN equal to CLAUDE_RESOLVED_BIN with no CLAUDE_VERIFIED_VERSION:
#     an earlier launch's answer, inherited through a session's environment.
#     It is not an operator's pin, so it is resolved again;
#   * anything else is a pin and is launched as it is. A pin that a launcher's
#     own `claude-current` produced carries CLAUDE_VERIFIED_VERSION, which is
#     recorded on the log line as `claude <version>`.
# CLAUDE_VERIFIED_VERSION is read once and removed, so it never reaches the
# session: a launch from inside that session must resolve again.
lane_claude_version=""
lane_claude_resolve=0
lane_claude_checked=0
if [ -z "${CLAUDE_BIN:-}" ]; then
  lane_claude_resolve=1
elif [ "$CLAUDE_BIN" = "${CLAUDE_RESOLVED_BIN:-}" ]; then
  if [ -n "${CLAUDE_VERIFIED_VERSION:-}" ]; then
    lane_claude_version="$CLAUDE_VERIFIED_VERSION"
  else
    lane_claude_resolve=1
  fi
fi
unset CLAUDE_VERIFIED_VERSION
CLAUDE_BIN="${CLAUDE_BIN:-claude}"

# `claude-current` is looked for where `--install` puts it and NEVER on PATH:
# beside this command, else in $OPENREPOTOOLS_BIN_DIR. A sandbox that copies
# this command somewhere without it, as the lane suite does, then launches the
# `claude` its own PATH names, and no test reaches a real npm.
lane_claude_current() {
  local d
  [ -x "$SCRIPT_DIR/claude-current" ] && { printf '%s\n' "$SCRIPT_DIR/claude-current"; return 0; }
  d="${OPENREPOTOOLS_BIN_DIR:-$HOME/.local/bin}"
  [ -x "$d/claude-current" ] && { printf '%s\n' "$d/claude-current"; return 0; }
  return 1
}

# lane_claude_resolve_launch: for a run that is to resolve (above) and is about
# to launch, `claude-current --porcelain` names the Claude Code to start. It
# reads npm's published version, updates the user-writable install first when
# every copy is behind, and answers with an absolute path it has run
# `--version` on; CLAUDE_BIN becomes that path, exported with
# CLAUDE_RESOLVED_BIN. Its exit 2 is a refusal (every copy still behind npm)
# and ends this run with 2; any other failure (1, nothing runnable; 64, a
# malformed setting) ends it with 1, the environment status. Both callers come
# before a binding handoff, window rename or transcript move, and the bare
# launch a `--confirm` answered No
# takes. Its stderr is the operator's and goes straight through. Never under
# `--no-launch`, which launches nothing and is the first act INSIDE a running
# session, and never under `--dry-run`, which must not update anything. It
# resolves once: a second call does nothing.
lane_claude_resolve_launch() {
  local lcc_cmd lcc_out lcc_rc=0 lcc_line lcc_path="" lcc_version="" lcc_status=""
  (( lane_claude_resolve )) || return 0
  (( ! no_launch )) || return 0
  lane_claude_resolve=0
  if ! lcc_cmd="$(lane_claude_current)"; then
    note "no claude-current beside this command or in ${OPENREPOTOOLS_BIN_DIR:-$HOME/.local/bin}, so $CLAUDE_BIN is launched as it is (through PATH, where it is a bare name), unchecked against npm; openRepoTools --install places claude-current"
    return 0
  fi
  if (( dry_run )); then
    plan "$lcc_cmd --porcelain   (chooses the Claude Code to launch; not run under --dry-run, because it may update one)"
    return 0
  fi
  lcc_out="$("$lcc_cmd" --porcelain </dev/null)" || lcc_rc=$?
  case "$lcc_rc" in
    0) : ;;
    2) die "claude-current refused the launch (exit 2, its reason above): the newest Claude Code installed is behind the one npm publishes. Nothing was written. CLAUDE_ALLOW_STALE=1 $prog … launches it anyway, or CLAUDE_BIN=<path> pins one." 2 ;;
    *) die "claude-current named no Claude Code to launch (exit $lcc_rc, its reason above). Nothing was written." 1 ;;
  esac
  while IFS= read -r lcc_line; do
    case "$lcc_line" in
      path=*)    [ -n "$lcc_path" ]    || lcc_path="${lcc_line#path=}" ;;
      version=*) [ -n "$lcc_version" ] || lcc_version="${lcc_line#version=}" ;;
      status=*)  [ -n "$lcc_status" ]  || lcc_status="${lcc_line#status=}" ;;
    esac
  done <<LCC
$lcc_out
LCC
  case "$lcc_path" in
    /*) [ -f "$lcc_path" ] && [ -x "$lcc_path" ] ||
          die "claude-current answered '$lcc_path', which is not an executable file. Nothing was written." 1 ;;
    *) die "claude-current exited 0 without an absolute path= line (it printed '$lcc_out'). Nothing was written." 1 ;;
  esac
  CLAUDE_BIN="$lcc_path"
  CLAUDE_RESOLVED_BIN="$lcc_path"
  export CLAUDE_BIN CLAUDE_RESOLVED_BIN
  lane_claude_version="$lcc_version"
  lane_claude_checked=1
  step "launching claude ${lcc_version:-of an unknown version} (${lcc_status:-no status}) at $lcc_path, as claude-current chose"
}

LS_TMP=""
cleanup() { [ -n "${LS_TMP:-}" ] && rm -f -- "$LS_TMP"; return 0; }
trap cleanup EXIT INT TERM

note() { printf '%s: %s\n' "$prog" "$*" >&2; }
step() { printf '%s: %s\n' "$prog" "$*" >&2; }
plan() { printf '%s: PLAN %s\n' "$prog" "$*" >&2; }
die()  { printf '%s: %s\n' "$prog" "$1" >&2; exit "${2:-1}"; }
usage() { sed -n -e '1,2d' -e '/^#/!q' -e 's/^# \{0,1\}//' -e p "$RESOLVED"; }
# EVERY ARGUMENT AS ONE SHELL WORD, WITHOUT `printf %q` AND WITHOUT A PIPE —
# measured on the macOS job at `db206db` and `ac0c697`, where three cases of
# this branch's own went red and no other platform could see it. One line, two
# defects:
#
#   * `printf '%q '` RENDERS DIFFERENTLY UNDER BASH 3.2, which is what Apple
#     ships and what that job runs (`/bin/bash` 3.2.57). Bash 4.4 and later
#     give a multi-line argument back as `$'…\n…'` — one readable, runnable
#     word; 3.2 has no such form and escapes every space and every byte of
#     every multi-byte character with a backslash of its own. The one caller
#     that passes a multi-line argument is the `--no-launch` print of a launch
#     carrying the handoff's top block as its first prompt (Amendment 17(c)),
#     and it got back neither a readable line nor a runnable one.
#   * AND THE PIPE THROUGH `sed` MADE THAT FATAL RATHER THAN UGLY. Under
#     `set -o pipefail` this function's status IS the pipeline's, and BSD `sed`
#     in a UTF-8 locale (`LC_ALL=en_US.UTF-8` on that runner) refuses bytes
#     that are not a valid sequence — `RE error: illegal byte sequence` — which
#     is what 3.2's `%q` makes of the em dash every one of these documents is
#     written with. `quoted` is a BARE command in the `--no-launch` branch, so
#     `set -e` ended the command there: exit 1, and an empty stdout.
#
# So the quoting is this file's own, and it is the POSIX one every shell reads
# the same way: a word of safe characters bare, anything else in single quotes
# with its own single quotes spelled `'\''`. A newline inside single quotes IS
# a newline, so the line stays readable as well as runnable, on either bash.
quoted() {
  q_sep=""
  for q_a in "$@"; do
    case "$q_a" in
      '' | *[!A-Za-z0-9._/:=@%+,-]*)
        printf "%s'%s'" "$q_sep" "${q_a//\'/\'\\\'\'}" ;;
      *) printf '%s%s' "$q_sep" "$q_a" ;;
    esac
    q_sep=' '
  done
  return 0
}

# ------------------------------------------------------------------ arguments

dry_run=0; no_launch=0; estate=""; dir_override=""; confirm=0; take_yes=0
agent_flag=""; fresh_flag=0; op_flag=""
# THE NAME GUARD'S BINDING MODE (openRepoTools#70) — the transcript being bound.
bind_sid=""
# AMENDMENT 18(c)/(e) — the three words a second place has for a bound lane.
request_handoff=0; force_why=""; handoff_wait=300
positional=(); pass=()

while [ $# -gt 0 ]; do
  case "$1" in
    --dry-run)   dry_run=1; shift ;;
    --no-launch) no_launch=1; shift ;;
    --confirm)   confirm=1; shift ;;
    --yes)       take_yes=1; shift ;;
    # AMENDMENT 17(c) — RESUME THIS LANE FROM ANY AGENT THAT CAN READ IT. A
    # lane's state is model-neutral: the register row, the object log, the
    # handoff with its Rule 3 resume prompt, the worktrees and branches. The
    # transcript is ONE agent's convenience, and until this flag the only door
    # into a lane launched `claude` and nothing else. Both spellings refuse an
    # empty value, for the reason `--dir` states above.
    --agent)     agent_flag="${2-}"; [ -n "$agent_flag" ] || die "--agent needs a name" 2; shift 2 ;;
    --agent=*)   agent_flag="${1#--agent=}"; [ -n "$agent_flag" ] || die "--agent needs a name" 2; shift ;;
    # `--fresh` — THE FRESH-SESSION MODE AS AN ARGUMENT, and it exists because
    # the environment seam it stands beside cannot be relied on to arrive
    # (openRepoTools#94, measured on Eagle 2026-09-15T20:59Z). `/ctx` set
    # `LANE_START_FRESH=1` in the command it respawned the pane with, the
    # launcher re-created the child through `tmux new-session`, and tmux hands
    # a command the SERVER's environment and not the client's — so this
    # command was reached with the variable gone and resumed the very
    # transcript the context clear had just paused. An ARGUMENT survives an
    # `exec`; it does not survive a re-creation either, which is why the
    # DURABLE RESTART INTENT below outranks both. This flag is for the caller
    # that reaches this command directly.
    --fresh)     fresh_flag=1; shift ;;
    # THE OPERATION THIS LAUNCH BELONGS TO (openRepoTools#94). The supervisor
    # passes it so that this run reads the intent it was started for and no
    # other, and so that a launch arriving with a STALE operation refuses
    # rather than consuming a newer lane's intent.
    --operation)   op_flag="${2-}"; [ -n "$op_flag" ] || die "--operation needs an operation id" 2; shift 2 ;;
    --operation=*) op_flag="${1#--operation=}"; [ -n "$op_flag" ] || die "--operation needs an operation id" 2; shift ;;
    # THE NAME GUARD'S BINDING MODE (openRepoTools#70). The guard's choice `2`
    # passes the transcript it is running in, and this run stamps THAT id rather
    # than the one the row would have resumed. What it may be combined with is
    # decided below the loop, where every flag has been read.
    --bind)      bind_sid="${2-}"; [ -n "$bind_sid" ] || die "--bind needs the transcript uuid of the session being bound" 2; shift 2 ;;
    --bind=*)    bind_sid="${1#--bind=}"; [ -n "$bind_sid" ] || die "--bind needs the transcript uuid of the session being bound" 2; shift ;;
    # AMENDMENT 18(c) AND (e) — THE SECOND PLACE'S THREE WORDS, and each of
    # them is an ANSWER to a question this command would otherwise ask. A
    # caller with no terminal on stdin cannot be asked (an agent's is not one),
    # so `--request-handoff` is that `y` written down; `--force` is clause
    # (e)'s override, which is a SECOND invocation and never automatic and
    # which takes the WHY it writes into an append-only log; `--wait` is the
    # clause's own default of 300 seconds, named.
    --request-handoff) request_handoff=1; shift ;;
    --force)     force_why="${2-}"; [ -n "$force_why" ] || die "--force takes the WHY you are taking a lane another place is bound to: it is written into that lane's append-only log and it is the sentence the bound session reads when it refuses every prompt from then on (Amendment 18(e))" 2; shift 2 ;;
    --force=*)   force_why="${1#--force=}"; [ -n "$force_why" ] || die "--force takes the WHY you are taking a lane another place is bound to (Amendment 18(e))" 2; shift ;;
    --wait)      handoff_wait="${2-}"; [ -n "$handoff_wait" ] || die "--wait needs a number of seconds" 2; shift 2 ;;
    --wait=*)    handoff_wait="${1#--wait=}"; [ -n "$handoff_wait" ] || die "--wait needs a number of seconds" 2; shift ;;
    # THE TWO SPELLINGS OF ONE FLAG GIVE ONE ANSWER, and these two did not
    # (#26, the review of `c3ebcfe`, `lane-start:707`). `--dir ""` refuses;
    # `--dir=` set the variable to nothing and fell through as if the operator
    # had not named a directory at all — so the rungs below it ran, and one of
    # them is `$PROJECTS_ROOT/<repo>`: `lane-start --dir= <repo> <n>` started in
    # a checkout the operator had not asked for instead of refusing a path they
    # had not given. `restart:151` — the same flag, on the sibling command —
    # has carried the guard on both spellings all along, which is what makes
    # this a divergence rather than a decision. Held for every flag in this
    # estate by `test_the_two_spellings_of_a_flag_refuse_the_same_empty_value`,
    # derived from the arms themselves rather than from a list.
    --dir)       dir_override="${2-}"; [ -n "$dir_override" ] || die "--dir needs a path" 2; shift 2 ;;
    --dir=*)     dir_override="${1#--dir=}"; [ -n "$dir_override" ] || die "--dir needs a path" 2; shift ;;
    --estate)    estate="${2-}"; [ -n "$estate" ] || die "--estate needs a name" 2; shift 2 ;;
    --estate=*)  estate="${1#--estate=}"; [ -n "$estate" ] || die "--estate needs a name" 2; shift ;;
    -h|--help)   usage; exit 0 ;;
    --)          shift; pass=("$@"); break ;;
    -*)          die "unknown option '$1' — see $prog --help" 2 ;;
    *)           positional+=("$1"); shift ;;
  esac
done

repo=""; n=""; verbatim=""
case "$handoff_wait" in ''|*[!0-9]*) die "--wait takes a whole number of seconds; '$handoff_wait' is not one" 2 ;; esac
# TWO ANSWERS TO ONE QUESTION ARE NOT AN ANSWER. `--request-handoff` asks the
# bound place to release the lane and waits for it; `--force` releases it on
# that place's behalf without asking. Passing both says both, and which one a
# run took would be decided by the order of two arms rather than by the person.
[ "$request_handoff" = 1 ] && [ -n "$force_why" ] &&
  die "--request-handoff ASKS the place that holds this lane to hand it off and waits for it; --force takes it without asking and makes that place stop loudly (Amendment 18(e)). They are two different acts on somebody else's session — pick one." 2
# THE BINDING MODE BINDS A SESSION THAT IS ALREADY RUNNING, AND NOTHING ELSE
# (openRepoTools#70). Its whole reason to exist is that the guard's `yes` ran
# `--no-launch` and the row's resume path stamped `RESUMED by <the id the row
# already had>` — a conversation nobody was in. So every combination that could
# put a different id on that stamp is refused here, before anything is read or
# written: a launch (the session is running; there is nothing to start), a fresh
# session (a second answer to which session this lane is), and another agent
# (the session being bound is the Claude one the guard is running in). These are
# refusals, never quiet corrections: a caller that passes them has misread what
# the mode is for.
if [ -n "$bind_sid" ]; then
  [[ "$bind_sid" =~ ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$ ]] ||
    die "--bind takes the transcript uuid of the session live in this window (the name of its <uuid>.jsonl), and '$bind_sid' is not one" 2
  [ "$no_launch" = 1 ] ||
    die "--bind is the name guard's binding mode: it binds the session ALREADY running in this window and launches nothing, so it is given only with --no-launch (Amendment 12(h) rule 2, openRepoTools#70)" 2
  [ "$fresh_flag" = 0 ] ||
    die "--bind binds the session live in this window and --fresh starts a new one: two answers to which session this lane is. Pick one." 2
  [ -z "$agent_flag" ] ||
    die "--bind binds the Claude session live in this window, and --agent names an agent to launch; a run that launches nothing has no agent to name" 2
fi
case "${#positional[@]}" in
  2) repo="${positional[0]}"; n="${positional[1]}" ;;
  1)
    arg="${positional[0]}"
    if [[ "$arg" =~ ^[0-9]+[A-Za-z]?$ ]]; then
      n="$arg"
    elif [[ "$arg" == *-* ]] && [[ "${arg##*-}" =~ ^[0-9]+[A-Za-z]?$ ]]; then
      repo="${arg%-*}"; n="${arg##*-}"
    elif [ -n "$dir_override" ]; then
      verbatim="$arg"
    else
      # `lane-start <repo>` WITH NO POSITION LISTS AND SUGGESTS (Brett Heap,
      # 2026-09-13, interactive multi-choice, verbatim "Yes, list and suggest
      # (Recommended)"; A11 Addendum 4 ruling 6's third delta, tracked as
      # `opensoft/openRepoTools#28`). It used to refuse with a placeholder `<n>`
      # for the operator to translate, at the one moment they are trying to
      # start work and do not know which positions are taken.
      #
      # IT RENDERS NOTHING OF ITS OWN. `lanes --prefix <repo>` is that listing
      # and its next-free-position footer, installed beside this command by
      # `openRepoTools --install`; a second rendering here is a second thing to
      # drift. Where it is absent — an older workstation — the refusal below is
      # still the whole answer, so this is an improvement and never a dependency.
      # BESIDE THIS COMMAND FIRST, THEN PATH (Copilot round 1 on #45): the two
      # are placed in ONE directory by `openRepoTools --install`, and a
      # workstation carrying two copies must not render this listing out of a
      # different version from the one it is standing in. Same rule as the bare
      # form's `lane` below and as `lane`'s own `$LANES_EDIT`.
      if [ -x "$SCRIPT_DIR/lanes" ]; then ls_cmd="$SCRIPT_DIR/lanes"
      else ls_cmd="$(command -v lanes 2>/dev/null || :)"
      fi
      # AND THE REFUSAL PROMISES A LISTING ONLY WHERE ONE WAS MADE (#26, the
      # review of `c3ebcfe`, `lane-start:602`). `|| :` made every code of that
      # read the same code, and the sentence below then sent a person to "the
      # listing above" when what was above it was `lanes`'s own refusal. `0` and
      # `8` both PRINT one — 8 is the empty repository, whose listing is the
      # next free position and the line that takes it — `2` is a `lanes`
      # predating the read, which says so in its own words, and anything else is
      # a read that FAILED. Nothing of the listing is re-rendered here on any of
      # them: this command renders none of it (the paragraph above), the read's
      # own output and stderr have already gone to the terminal, and what
      # changes is only whether this refusal claims a listing it did not get.
      ls_listed=0
      if [ -n "$ls_cmd" ]; then
        note "'$arg' is a repository and not a lane. Its lanes, and the position that is free:"
        ls_rc=0
        LANES_NO_FETCH=1 "$ls_cmd" --prefix "$arg" >&2 || ls_rc=$?
        case "$ls_rc" in
          0 | 8) ls_listed=1 ;;
          2) : ;;
          *) note "that listing FAILED (exit $ls_rc) — which is not 'this repository has no lanes', so no position is offered from it" ;;
        esac
      fi
      # STILL EXIT 2, AND NOTHING IS LAUNCHED. A listing is what a person asked
      # for; a caller that scripted `lane-start <repo>` expecting a session must
      # not read 0 from a run that started none.
      from_listing=" with a position from the listing above"
      [ "$ls_listed" = 1 ] || from_listing=""
      die "'$arg' is not a lane: a lane is <repo>-<position>, e.g. $arg-1. Run: $prog $arg <n>$from_listing, or name the checkout yourself with --dir <path> to use '$arg' as the lane name" 2
    fi
    ;;
  0)
    # BARE `lane-start` IS `lane` (Amendment 18 Addendum 1 clause (i-4),
    # ratified 2026-09-14T14:05:54Z verbatim "ratify the addendum"): *"Bare
    # `lane-start` — no repository, no position — is an alias of `lane`, so
    # clause (i) as ruled still holds and there is one implementation."*
    #
    # IT RENDERS NOTHING OF ITS OWN, exactly as the `<repo>`-with-no-position
    # rung above renders nothing of its own: `lane` is the listing, the numbered
    # pick and the three branches, installed beside this command by
    # `openRepoTools --install`. Where it is ABSENT — an older workstation — the
    # refusal below is still the whole answer, so this is an improvement and
    # never a dependency.
    #
    # `exec`, NOT A CALL: this command is itself `exec`ed by the launcher, so a
    # pick that ends in a launch must replace this process rather than leave it
    # waiting on a child that has replaced itself.
    if [ -x "$SCRIPT_DIR/lane" ]; then lane_word="$SCRIPT_DIR/lane"
    else lane_word="$(command -v lane 2>/dev/null || :)"
    fi
    if [ -n "$lane_word" ]; then
      # THE OPTIONS ARE NOT DROPPED ON THE FLOOR (Copilot round 1 on #45,
      # `lane-start:661`). This command's parser has already taken them, and an
      # `exec` with none of them turns `--no-launch` — a flag whose whole
      # promise is that nothing starts — into an interactive pick that launches.
      # `--dry-run` and `--dir` mean the same thing in `lane` and go with it;
      # every other flag here is this command's own, has no meaning for a
      # listing that has not been answered yet, and is REFUSED BY NAME rather
      # than ignored.
      lane_argv=("$lane_word")
      [ "$dry_run" = 0 ] || lane_argv+=(--dry-run)
      [ -z "$dir_override" ] || lane_argv+=(--dir "$dir_override")
      # AMENDMENT 18(c)/(e)'s THREE GO WITH IT, for the reason `--dry-run` and
      # `--dir` do: they mean the same thing in `lane`, whose BOUND ELSEWHERE
      # branch is the other door to the same request, and a flag silently
      # dropped is a promise that was not kept.
      [ "$request_handoff" = 0 ] || lane_argv+=(--request-handoff)
      [ -z "$force_why" ] || lane_argv+=(--force "$force_why")
      [ "$handoff_wait" = 300 ] || lane_argv+=(--wait "$handoff_wait")
      ls_drop=""
      [ "$no_launch" = 0 ] || ls_drop="$ls_drop --no-launch"
      [ "$confirm" = 0 ]   || ls_drop="$ls_drop --confirm"
      [ "$take_yes" = 0 ]  || ls_drop="$ls_drop --yes"
      # AND THE VALUE GOES WITH THE FLAG THAT TOOK ONE (Copilot round 4 on #45,
      # `lane-start:690`). `--estate` and `--` are parsed WITH their operands,
      # and a suggested command carrying the flag and not the value is one
      # nobody can run: `lane-start --estate x --yes` printed `lane-start <repo>
      # <n> --estate --yes`, whose `--estate` swallows the `--yes` and names an
      # estate `--yes`. A line printed for a person to type is a line this
      # command has to be willing to have typed back at it.
      # AND EACH VALUE IS QUOTED THE WAY THE SHELL WILL READ IT BACK (Copilot
      # round 7 on #45, `lane-start:698`): `--estate 'team blue'` printed bare
      # is two words when it is typed again, which is a suggested command that
      # does something else. `quoted` is the same helper every other printed
      # command in this file goes through.
      [ -z "$estate" ]     || ls_drop="$ls_drop --estate $(quoted "$estate")"
      [ "${#pass[@]}" = 0 ] || ls_drop="$ls_drop -- $(quoted "${pass[@]}")"
      # AND THE LINE CARRIES THE OPTIONS THAT WERE *KEPT* TOO (Copilot round 8
      # on #45, `lane-start:706`). The remedy was built out of the refused flags
      # alone, so `lane-start --dir /work/repo --estate x` printed `lane-start
      # <repo> <n> --estate x` and the checkout the person had named was gone
      # from the line they were told to type. What is suggested is the WHOLE
      # command they meant, not the half this rung could not take.
      ls_keep=""
      [ "$dry_run" = 0 ]     || ls_keep="$ls_keep --dry-run"
      [ -z "$dir_override" ] || ls_keep="$ls_keep --dir $(quoted "$dir_override")"
      [ "$request_handoff" = 0 ] || ls_keep="$ls_keep --request-handoff"
      [ -z "$force_why" ]    || ls_keep="$ls_keep --force $(quoted "$force_why")"
      [ "$handoff_wait" = 300 ] || ls_keep="$ls_keep --wait $handoff_wait"
      if [ -n "$ls_drop" ]; then
        die "bare \`$prog\` is \`lane\` (Amendment 18 Addendum 1 clause (i-4)), which lists the
    lanes and binds the one you pick — and$ls_drop belongs to a lane that has
    already been named, so there is nothing here for it to apply to. It is
    refused rather than ignored: a flag that is silently dropped is a promise
    that was not kept.
      pick a lane:                    $prog
      that lane, with those options:  $prog <repo> <n>$ls_keep$ls_drop" 2
      fi
      note "no <repo> and no position: this is \`lane\`, which lists the lanes and binds the one you pick (Amendment 18 Addendum 1 clause (i-4))"
      exec "${lane_argv[@]}"
    fi
    usage >&2; die "a lane needs a position: $prog <repo> <n>" 2 ;;
  *) die "too many arguments: $prog <repo> <n>" 2 ;;
esac

[ -n "$verbatim" ] || [[ "$n" =~ ^[0-9]+[A-Za-z]?$ ]] || die "'$n' is not a position — the lane form is <repo>-<position across, left to right>, e.g. 2" 2

# No <repo> anywhere: the cwd's git root names it, and only its basename.
if [ -z "$repo" ] && [ -z "$verbatim" ]; then
  top="$(git rev-parse --show-toplevel 2>/dev/null || :)"
  [ -n "$top" ] || die "no <repo> given and this directory is not a git checkout — run it inside the lane's checkout, or: $prog <repo> $n" 1
  repo="$(basename -- "$top")"
fi

# ------------------------------------ AMENDMENT 15(a): `<repo>` IS A DIRECTORY
#
# **A lane name is one name under any case, and the register row's spelling is
# the one it carries** (ratified 2026-09-14T00:07:18Z). The `<repo>` half of a
# NEW lane's name has no row to take a spelling from, so it takes the CHECKOUT'S
# REAL DIRECTORY NAME — which is the only spelling on this workstation that is a
# fact rather than a habit, and the one every later reader of the lane's `dir`
# and `$PROJECTS_ROOT/<repo>` rung will meet.
#
# TWO DIRECTORIES DIFFERING ONLY BY CASE ARE A REFUSAL NAMING BOTH. On a
# case-insensitive filesystem — macOS — they cannot both exist and this never
# fires; on Linux they can, and choosing one of them is choosing which
# repository the lane is in.
#
# `ls` and ONE awk rather than a `tr` per entry: this sits in front of a launch,
# `$PROJECTS_ROOT` holds a few dozen directories, and the `[ -d ]` below runs
# only for the names that already matched. The `--` stays for the reason
# `lanes-edit.sh`'s twin scan carries in full (`log_files_named_ci`; Copilot
# round 3 on openRepoTools#41, declined with a measurement): BSD `ls` ends its
# options at `--` like every other POSIX utility, and the step line this
# function produces — `repo repocase → repoCase` — is asserted on the macOS job,
# where an `ls` that refused `--` would leave it silent.
projects_dir_matches() {   # <typed repo>
  ls -- "$PROJECTS_ROOT" 2>/dev/null |
    awk -v want="$1" 'BEGIN { w = tolower(want) } tolower($0) == w { print }' |
    while IFS= read -r pdm_m; do
      [ -d "$PROJECTS_ROOT/$pdm_m" ] && printf '%s\n' "$pdm_m"
    done
}
if [ -n "$repo" ] && [ -d "$PROJECTS_ROOT" ]; then
  repo_hits="$(projects_dir_matches "$repo" || :)"
  repo_hit_n=0
  if [ -n "$repo_hits" ]; then repo_hit_n="$(printf '%s\n' "$repo_hits" | grep -c . || :)"; fi
  # THE REFUSAL IS FOR A RUN THAT HAS NO OTHER ANSWER, AND `--dir` IS THE OTHER
  # ANSWER. Its own remedy names `--dir <path>`, so refusing a run that already
  # passed one is refusing the fix it printed: `lane-start --dir /chosen repotwin
  # 1` was rejected before the rung that honours the flag (Copilot round 1 on
  # openRepoTools#41). With the checkout named, the ambiguity that is left is
  # only about the lane-s NAME, which keeps the spelling that was typed and is
  # then overruled by the register row-s a few lines below — so this SAYS what
  # it did not resolve and carries on.
  if [ "$repo_hit_n" -gt 1 ] && [ -z "$dir_override" ]; then
    die "$PROJECTS_ROOT holds $repo_hit_n directories whose names differ only by case for '$repo': $(printf '%s\n' "$repo_hits" | tr '\n' ' ')— a lane name is ONE name under any case (Amendment 15(a)), so there is no spelling of '$repo' this can take without choosing which repository the lane is in. Name the checkout yourself with --dir <path>, or rename one of those directories." 2
  fi
  if [ "$repo_hit_n" -gt 1 ]; then
    note "$PROJECTS_ROOT holds $repo_hit_n directories whose names differ only by case for '$repo': $(printf '%s\n' "$repo_hits" | tr '\n' ' ')— --dir has named the checkout, so this run is not ambiguous about WHERE the lane is. Its NAME keeps the '$repo' you typed, and the register row's own spelling wins over that below (Amendment 15(a))."
  fi
  if [ "$repo_hit_n" = 1 ] && [ "$repo_hits" != "$repo" ]; then
    step "repo $repo → $repo_hits (Amendment 15(a): the checkout's real directory name under $PROJECTS_ROOT)"
    repo="$repo_hits"
  fi
fi

LANE="${verbatim:-$repo-$n}"
[[ "$LANE" =~ ^[A-Za-z0-9][A-Za-z0-9._-]*$ ]] || die "'$LANE' is not usable as a window and session name (allowed: letters, digits, . _ -)" 2

# The position after this one, for the refusal to name. `10#` because a lane
# may be `-08` and 08 is not a number in base 8.
if [[ "$n" =~ ^[0-9]+$ ]]; then next_n="$((10#$n + 1))"; else next_n="<the next free position>"; fi

if [ -z "${LANES_FILE:-}" ]; then die "$(lanes_workspace_why)" 1; fi
[ -f "$LANES_FILE" ] || die "no register at $LANES_FILE — the workspace repository $(lanes_ws_yaml) names carries no lanes/LANES.md. \`openRepoTools wip init\` seeds one (it is idempotent); or set LANES_FILE" 1
[ -x "$LANES_EDIT" ] || die "no register writer at $LANES_EDIT — \`lanes-edit.sh\` is installed beside this command by \`openRepoTools --install\`. Run that, or set LANES_EDIT" 1

# ------------------------- AMENDMENT 15: THE ROW'S SPELLING IS THE LANE'S NAME
#
# The row wins over the directory, and over what was typed: it is what the
# window is renamed to (step 4), what `--name`s every launch branch (step 5a),
# what the row stamp and the object log carry, and what the log file is called.
# `--verbatim` lanes come through here too — `browser-ui-repair` is a row like
# any other and a `lane-start Browser-UI-Repair` is that lane.
#
# ONE RESOLVER, SHARED. `lanes-edit.sh canon-lane` is the same read `lane-end`,
# `lanes` and `restart` make, for the reason clause (h) gives every other read
# in this toolset: an implementation of "which row is this name's" in each
# command is how they would come to disagree about it.
#
# 2 IS TWO ANSWERS AND THE REFUSAL IS THE ONE THAT MATTERS (Copilot round 4 on
# openRepoTools#41). It is the code a helper predating this amendment spends on
# an unknown subcommand — every workstation until adoption reaches it — and it is
# ALSO `canon-lane`'s own two-rows refusal. Carrying on from both was written
# here on the reading that the refusal is one this script makes again forty lines
# below out of its own read of the register; that read is `$LANES_FILE`, THE
# WORKING TREE, and the register this refusal is about is `origin/<branch>`. On a
# checkout that is behind, the pair is published and this file holds one row: the
# local scan passes, and what the operator gets is the stderr-suppressed
# `register-row` read below turning the SAME refusal into a generic exit 1 that
# names neither spelling. So the refusal is asked for by its own words — no old
# helper emits them from an unknown subcommand — and relayed, with the fallback
# for a genuinely old helper left exactly as it was.
cl_out=""; cl_rc=0
cl_out="$("$LANES_EDIT" canon-lane "$LANE" 2>/dev/null)" || cl_rc=$?
cl_why=""; cl_pair=0
case "$cl_rc" in 2 | 66) cl_why="$(LANES_NO_FETCH=1 "$LANES_EDIT" canon-lane "$LANE" 2>&1 >/dev/null || :)" ;; esac
case "$cl_why" in *"Amendment 15(d)"*) cl_pair=1 ;; esac
case "$cl_rc" in
  0)
    if [ -n "$cl_out" ] && [ "$cl_out" != "$LANE" ]; then
      step "lane $LANE → $cl_out (Amendment 15: the register row's spelling is canonical)"
      LANE="$cl_out"
    fi ;;
  2)
    if [ "$cl_pair" = 1 ]; then
      printf '%s\n' "$cl_why" >&2
      die "the PUBLISHED register spells lane $LANE two ways (above), so no read and no write under that name is unambiguous and nothing here picks one — Amendment 15(d): merge the newer row's session id(s) into the older row's session cell, in order, remove the newer row in the SAME commit naming both spellings, push, and re-run. Nothing was launched, renamed or written." 2
    fi ;;
  66)
    # AMENDMENT 16(e) — THE ALIAS TABLE COULD NOT BE READ, AND THAT IS NOT A
    # SPELLING QUESTION (Copilot round 4 on openRepoTools#81). `lanes/aliases.tsv`
    # is what makes a lane's OLD name resolve to its row, so a table nobody can
    # read makes a RENAMED lane look like a lane nobody has — and the next line
    # of this command is the one that decides whether to add a row. Carrying on
    # with the typed name there is a SECOND row for a lane that has been running
    # all day, which is the duplicate Amendment 15(a) exists to refuse.
    printf '%s\n' "$cl_why" >&2
    die "lane $LANE's name could not be resolved: ${LANES_EDIT##*/} could not read the lane alias table (above, exit 66). Amendment 16(e) makes a renamed lane's old name resolve through that file for ever, so a name it cannot answer for may be a lane that is already running under another one — and this command would add a second row for it. Fix the read and re-run. Nothing was launched, renamed or written." 2 ;;
  *) note "$LANES_EDIT canon-lane $LANE failed (exit $cl_rc) — carrying on with the name as typed, which the register may spell differently" ;;
esac

repo="${repo:-$LANE}"          # the verbatim form has no <repo> of its own
estate="${estate:-$repo}"

# ----------------------------------------- 1b. THE LANE'S DIRECTORY
#
# AMENDMENT 11 CLAUSE (c). A lane's checkout is known to every process that is
# IN it and to nothing that is about to start one, and Evidence 2 turned that
# into a restart that printed `[exited]`: `openXfactory-5`'s checkout is
# `~/projects/xFactory/openxFactory`, this script derived `$PROJECTS_ROOT/<repo>`
# and died here, and the launcher had no `--dir` to pass. Evidence 3 made it
# worse and quieter — a restart started from `/workspace` came up WITHOUT the
# repository's `CLAUDE.md` and without the lane's memory, because the harness
# keys a session to the directory it was started in, while `--resume <uuid>`
# went on continuing the transcript under the repository's own project folder.
# So the directory is READ FROM THE LANE'S OWN RECORD, and this script `cd`s
# into it before it launches (step 6).
#
# SIX RUNGS, FIRST ANSWER WINS, and clause (c) states them here rather than
# leaving them to an implementation because the launcher draft that read the
# first text of that clause invented one of its own:
#
#   1. `--dir <path>` — the operator's word. NOT tested for existence at this
#      rung: the refusal below names the path and the flag that fixes it, and a
#      script that silently dropped what it was told would hide that.
#   2. the SWAP RECORD's `dir` for this lane — `swapped`'s fourth tab-separated
#      field (clause (h)).
#   3. the LANE'S LOG — `lanes-edit.sh lane-dir <lane>`, the `dir ` sub-field of
#      its last lane-kind line carrying one.
#   4. `$PROJECTS_ROOT/<repo>` — the default, and ONLY the default for a lane
#      that has never been started under this amendment.
#   5. THE ESTATE'S `project.yaml` LEGS, and
#   6. A CHECKOUT NAMED FOR THE HOME'S REPOSITORY one or two levels under
#      `$PROJECTS_ROOT` — both added for Evidence 7, both PROVED by the
#      candidate's own `origin` against the lane's recorded home, and both
#      STATED IN FULL beside the code that implements them a hundred lines
#      below rather than a second time here.
#
# THEY WERE FOUR UNTIL EVIDENCE 7 AND THIS BLOCK WENT ON SAYING SO (#26, the
# review of `c3ebcfe`, `lane-start:780`). `708395e` added rungs 5 and 6 to this
# file; `2f44da0` corrected the MANUAL's count to six. The contract THE CODE
# CARRIES still said "FOUR RUNGS" and "THERE IS NO FIFTH RUNG" a hundred lines
# above the two rungs it had grown — which makes the code below look
# unreachable to its next reader, and the one act that reading invites is
# deleting it.
#
# WHAT THAT SENTENCE RULED OUT IS UNCHANGED, AND IT WAS NEVER A COUNT: THE
# CWD'S OWN CHECKOUT IS RULED OUT BY NAME. Deriving the directory from the
# directory the operator happens to be standing in is an inference, and this
# script writes the lane's HOME into its Amendment 7 `STARTED` line from that
# directory's `origin`, which every `#n` the lane afterwards writes inherits. An
# inference that can silently re-home a lane is not worth the refusal it saves;
# the refusal names `--dir`, and `--dir` is one word. Rungs 5 and 6 are not that
# inference and cannot decay into it: every candidate is PROVED by its own
# `origin` against the recorded home, one that fails the proof is passed over,
# and both are skipped entirely for a lane with no recorded home to prove it
# against.
#
# EVERY READ FAILS TO THE NEXT RUNG AND NEVER TO A REFUSAL. Amendment 7(d)'s
# fail-closed rule says a read that could not run must never be taken for
# "nothing to report"; it does not say the rungs below it stop answering. 8 is
# no answer, 2 is a helper predating Amendment 11 — expected and silent, told
# from a caller's bug by the helper's own words rather than by its status —
# and anything else is named once and then carried past.
# `owner/repo` out of a checkout's `origin`. DEFINED HERE rather than beside
# its first old caller, because Evidence 7's two rungs are the FIRST callers
# and they run four hundred lines earlier; a function defined after its call
# site is a function that is not there yet.
origin_nwo() {
  local url nwo
  url="$(git -C "$1" remote get-url origin 2>/dev/null || :)"
  [ -n "$url" ] || return 1
  nwo="$(printf '%s\n' "$url" | sed -E 's#\.git$##; s#^git@[^:]+:##; s#^ssh://[^/]+/##; s#^https?://[^/]+/##')"
  [[ "$nwo" =~ ^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$ ]] || return 1
  printf '%s\n' "$nwo"
}

# A CANDIDATE IS PROVED BY ITS OWN `origin`, NEVER BY ITS NAME. Both of the two
# rungs Evidence 7 adds hand every candidate through here, and a candidate whose
# origin is not the lane's recorded home is not taken — which is what keeps them
# rungs rather than the inference clause (c) rules out by name.
lane_dir_is_home() {   # <candidate dir> <owner/repo the record names>
  ldh_o="$(origin_nwo "$1" 2>/dev/null || :)"
  [ -n "$ldh_o" ] || return 1
  ldh_c="$("$LANES_EDIT" resolve-repo "$ldh_o" 2>/dev/null || :)"
  [ -n "$ldh_c" ] && ldh_o="$ldh_c"
  [ "$(printf '%s' "$ldh_o" | tr 'A-Z' 'a-z')" = "$(printf '%s' "$2" | tr 'A-Z' 'a-z')" ]
}

DIR=""; DIR_SOURCE=""; DIR_DEFAULT_TRIED=""
if [ -n "$dir_override" ]; then
  DIR="$dir_override"; DIR_SOURCE="--dir"
fi
if [ -z "$DIR" ]; then
  ld_out=""; ld_rc=0
  ld_out="$("$LANES_EDIT" swapped 2>/dev/null)" || ld_rc=$?
  case "$ld_rc" in
    0)
      ld_row="$(printf '%s\n' "$ld_out" | awk -F'\t' -v l="$LANE" 'tolower($1) == tolower(l) { print; exit }')"
      if [ -n "$ld_row" ]; then
        ld_cand="$(printf '%s' "$ld_row" | cut -f4)"
        case "$ld_cand" in
          /*) DIR="$ld_cand"; DIR_SOURCE="the swap record" ;;
        esac
      fi ;;
    8|2) : ;;
    *) note "$LANES_EDIT swapped failed (exit $ld_rc) — carrying on to the lane's log for its directory" ;;
  esac
fi
if [ -z "$DIR" ]; then
  ld_out=""; ld_rc=0
  ld_out="$("$LANES_EDIT" lane-dir "$LANE" 2>/dev/null)" || ld_rc=$?
  case "$ld_rc" in
    0) case "$ld_out" in /*) DIR="$ld_out"; DIR_SOURCE="the lane's log" ;; esac ;;
    8|2) : ;;
    *) note "$LANES_EDIT lane-dir $LANE failed (exit $ld_rc) — carrying on to the default for its directory" ;;
  esac
fi
# A DIRECTORY THAT WAS RECORDED AND IS GONE IS ITS OWN FAILURE, and it keeps
# its own code. Rungs 1 to 3 are the operator's word and the lane's own record:
# where one of them answered and the path is not there, the path is NAMED and
# `--dir` is named beside it, and nothing below this line runs — searching for a
# substitute for a directory the lane itself recorded is the silent re-home
# clause (c) rules out. Evidence 7's case is the OTHER one: no rung answered at
# all, `$DIR` is still empty here, and rungs 5 and 6 are what that case reaches.
if [ -n "$DIR" ] && [ ! -d "$DIR" ]; then
  die "no such directory: $DIR (from $DIR_SOURCE) — pass --dir <path> if this lane's checkout is somewhere else" 1
fi
if [ -z "$DIR" ]; then
  if [ -d "$PROJECTS_ROOT/$repo" ]; then
    DIR="$PROJECTS_ROOT/$repo"; DIR_SOURCE="the default \$PROJECTS_ROOT/<repo>"
  else
    DIR_DEFAULT_TRIED="$PROJECTS_ROOT/$repo"
  fi
fi

# ------------------------------------- EVIDENCE 7: THE LANE WHOSE CHECKOUT IS
#                                       NESTED, AND WHOSE RECORD PREDATES `dir`
#
# Measured 2026-09-13T23:01Z and reported by Brett Heap
# (`brettheap/new-workstation#20`, comment 5656793094). `pclaude team03m`
# auto-selected the saved lane `opsXfactory-5` from its swap record, the
# launcher handed a bare lane name to this script, rung 4 derived
# `~/projects/opsXfactory` — which does not exist — and this script **exited 1
# before Claude started**, leaving a pane that said `[exited]`. The lane's real
# checkout is `~/projects/xFactory/xFactories/OpsxFactory`. Its own record could
# not help: its `STARTED`/`RESUMED` lines carry `home opensoft/OpsxFactory;
# estate xFactory` and its `PAUSED` swap line carries `window …; workstation
# docker-desktop`, and **no `dir`** — the field this amendment adds, which
# nothing backfills (Amendment 7(i)).
#
# TWO RUNGS BEFORE THE REFUSAL, AND NEITHER IS AN INFERENCE. Rungs 5 and 6 are
# both proved by the candidate's own `origin` against the lane's RECORDED HOME,
# so what they find is the checkout of the lane's own repository and not "a
# directory that merely has the right name". That distinction is the whole of
# why clause (c) rules the cwd's checkout out by name: this script writes the
# lane's home from the directory's `origin`, and a wrong directory silently
# re-homes the lane. A directory whose origin IS the recorded home cannot.
#
#   5. THE ESTATE'S `project.yaml` LEGS. openRepoShape's manifest is a top-level
#      `legs:` list of `repository:` / `path:`, and Amendment 7 decision 3
#      treats legs as home. Where a manifest names the lane's home as a leg, the
#      leg's `path` resolved against that manifest's directory IS the checkout,
#      declared rather than searched for.
#   6. A CHECKOUT NAMED FOR THE HOME'S REPOSITORY, one or two levels under
#      `$PROJECTS_ROOT` — the two depths the estate actually uses and the same
#      two `same_project` globs for manifests. `opsXfactory` the lane label and
#      `OpsxFactory` the repository are not the same string, which is why the
#      NAME comes from the alias table's own canonical spelling
#      (`resolve-repo`) rather than from the lane's label.
#
# BOTH ARE SKIPPED ENTIRELY WHERE THE LANE HAS NO RECORDED HOME, because there
# is then nothing to prove a candidate against and a match would be a guess.
if [ -z "$DIR" ]; then
  ls_home=""; ls_rc=0
  ls_home="$("$LANES_EDIT" resolve-home "$LANE" 2>/dev/null)" || ls_rc=$?
  [ "$ls_rc" = 0 ] || ls_home=""
  case "$ls_home" in */*) : ;; *) ls_home="" ;; esac
fi
# Rung 5 — the legs.
if [ -z "$DIR" ] && [ -n "$ls_home" ]; then
  for ls_m in "$PROJECTS_ROOT"/*/project.yaml "$PROJECTS_ROOT"/*/*/project.yaml; do
    [ -f "$ls_m" ] || continue
    # ONLY `repository:` AND `path:`, and only as navigation: the manifest says
    # of itself that it CONFERS NOTHING, and `role:` is never read here. This is
    # the SECOND reader of `legs[]` in this toolset — `lanes-edit.sh`'s
    # `project_legs_file` is the first — and it exists because that one answers
    # with repositories alone and no read in clause (h)'s table carries a leg's
    # PATH. Naming the duplication is the honest half of it.
    ls_cand="$(awk -v want="$ls_home" '
      /^[A-Za-z_][A-Za-z0-9_]*:/ { inlegs = ($0 ~ /^legs:/); repo = ""; path = ""; next }
      !inlegs { next }
      /^[ \t]*-[ \t]/ { repo = ""; path = "" }
      /^[ \t]+repository:[ \t]*/ { v = $0; sub(/^[ \t]+repository:[ \t]*/, "", v)
        sub(/[ \t]+$/, "", v); gsub(/^"|"$/, "", v); gsub(/^'"'"'|'"'"'$/, "", v); repo = v }
      /^[ \t]+path:[ \t]*/ { v = $0; sub(/^[ \t]+path:[ \t]*/, "", v)
        sub(/[ \t]+$/, "", v); gsub(/^"|"$/, "", v); gsub(/^'"'"'|'"'"'$/, "", v); path = v }
      repo != "" && path != "" && tolower(repo) == tolower(want) { print path; exit }' "$ls_m" 2>/dev/null || :)"
    [ -n "$ls_cand" ] || continue
    ls_dir="$(dirname -- "$ls_m")"
    case "$ls_cand" in .) ls_try="$ls_dir" ;; /*) ls_try="$ls_cand" ;; *) ls_try="$ls_dir/$ls_cand" ;; esac
    [ -d "$ls_try" ] || continue
    lane_dir_is_home "$ls_try" "$ls_home" || continue
    DIR="$ls_try"; DIR_SOURCE="the legs of ${ls_m#$PROJECTS_ROOT/} (Evidence 7)"
    break
  done
fi
# Rung 6 — a checkout named for the repository, proved by its origin.
if [ -z "$DIR" ] && [ -n "$ls_home" ]; then
  ls_name="${ls_home#*/}"
  for ls_try in "$PROJECTS_ROOT/$ls_name" "$PROJECTS_ROOT"/*/"$ls_name" "$PROJECTS_ROOT"/*/*/"$ls_name"; do
    [ -d "$ls_try" ] || continue
    lane_dir_is_home "$ls_try" "$ls_home" || continue
    DIR="$ls_try"; DIR_SOURCE="the checkout of $ls_home under \$PROJECTS_ROOT (Evidence 7)"
    break
  done
fi

# THE REFUSAL IS A REFUSAL (exit 2) AND NOT AN ENVIRONMENT FAILURE (exit 1), and
# it is ONE LINE a person can type. Evidence 7's whole cost was that this was a
# `1` behind an `exec`: a pane that said `[exited]` and a message nobody read.
# `restart` already spends 2 on exactly this case — *"no such lane, no recorded
# directory, no profile recorded yet"* (clause (i), `R-A11-20`) — so after this
# the two commands answer the same way about the same fact.
if [ -z "$DIR" ]; then
  # EVERY PIECE OF THIS MESSAGE IS BUILT OUT HERE, and that is this file's own
  # rule rather than a style: an apostrophe inside a `${var:-…}` expansion is
  # parsed by bash as a QUOTE and not as prose, and the whole script then fails
  # to parse. `restart` carries the same warning over the same kind of hint.
  ls_where="$PROJECTS_ROOT/$repo"
  [ -z "$DIR_DEFAULT_TRIED" ] || ls_where="$DIR_DEFAULT_TRIED"
  ls_pos="${LANE##*-}"
  if [ -n "$ls_home" ]; then
    ls_tried="the default $ls_where, the project.yaml legs of $ls_home, and a checkout of $ls_home one or two levels under $PROJECTS_ROOT"
  else
    ls_tried="the default $ls_where. This lane has no home on record either, so there was nothing to prove a candidate against"
  fi
  die "lane $LANE has no recorded checkout and none could be PROVED, so nothing was started.
    Tried: $ls_tried.
    Name it once, and every later start reads it back out of the lane's own log:
      lane-start --dir <path> $repo $ls_pos
    Nothing here guesses. This script writes the lane HOME from the directory's
    origin, and a directory that merely has the right name would re-home the lane
    for every \`#n\` it writes afterwards (Amendment 11 clause (c); Evidence 7,
    brettheap/new-workstation#20 comment 5656793094)." 2
fi
DIR="$(cd -- "$DIR" && pwd)"
DIR_REAL="$(cd -- "$DIR" && pwd -P)"
[ "$DIR_SOURCE" = "--dir" ] || step "dir $DIR, from $DIR_SOURCE (Amendment 11 clause (c))"

# THE DIRECTORY THIS SCRIPT IS ABOUT TO RECORD MUST BE READABLE BACK OUT OF THE
# LINE THAT RECORDS IT (clause (c), and Amendment 8(b)'s same refusal for
# `window`). `, ` and ` — ` are what divide an event line into its fields and
# its free text, `; ` is what divides the payload's SUB-FIELDS from each other,
# and a `"` is what clause (c) uses to make a path with a space ONE ref under
# Amendment 7(b)'s grammar — so a path carrying any of the four is REFUSED,
# naming the path, rather than truncated, escaped or appended. A log whose own
# parser cannot read a line is a log that has lost the fact.
#
# `; ` WAS THE ONE THIS FENCE DID NOT HAVE, and clause (c) names it in the same
# breath as the other two: *"A value containing `, `, ` — ` or `; ` is refused,
# exit 2, naming it — not truncated, not escaped, and not appended."* The
# `/lane-swap` skill, the other writer the clause names, has refused all three
# since `68614bf`; this one refused two of them and the quoting does NOT cover
# the gap. `payload_subfield` splits on `; ` BEFORE it honours a quote
# (`lanes-edit.sh:payload_subfield`), so `dir "/p/a; b"` — quoted, because it
# carries a space — splits into `dir "/p/a` and `b"`, and `lane-dir` answers
# `"/p/a`: a path that is wrong, carries a quote mark, and was never written by
# anyone. That is Evidence 3's failure exactly, in a file nothing rewrites.
case "$DIR" in
  *', '*|*' — '*|*'; '*|*'"'*)
    die "this lane's directory is $DIR, and a \`dir\` sub-field may not contain ', ', ' — ', '; ' or '\"': those are what divide an event line into its fields, its sub-fields and its free text, and the log is append-only, so a line written wrong there is wrong for ever. Move the checkout, or start the lane with --dir <a path without them>" 2 ;;
esac

# THIS LANE'S OWN ARGUMENTS, so no hint this script prints ever hands a reader a
# `<repo> <n>` to translate while the script holds both (F-B6's rule, on this
# side of the seam). A lane named before the `<repo>-<position>` rule has no
# position to print and is started through `--dir`, exactly as it was here.
if [ -n "$n" ]; then self_args="$repo $n"; else self_args="--dir $DIR $LANE"; fi

step "lane $LANE · dir $DIR · estate $estate"

# ----------------------------------------------------------------- 2. in tmux

[ -n "${TMUX:-}" ] || die "run this inside the tmux window that will carry the lane — it renames that window and never creates a tmux session" 1
command -v tmux >/dev/null 2>&1 || die "tmux is not on PATH, but \$TMUX is set — this environment is inconsistent" 1
this_window="$(tmux display-message -p '#{session_name}:#{window_id}' 2>/dev/null || :)"
[ -n "$this_window" ] || die "tmux did not answer display-message — cannot tell which window this is" 1
this_window_name="$(tmux display-message -p '#W' 2>/dev/null || :)"
# AMENDMENT 11 CLAUSE (c) — THE WINDOW SUB-FIELD IS `<tmux session>:<window
# index> <@window id>`, TWO SPACE-SEPARATED REFS IN ONE SUB-FIELD, and neither
# of them is the `<session>:<@id>` above. That one is the harness's own `tmux`
# spelling and is what `window-session` matches a session record on; the
# record's refs are a person's `<session>:<index>` and tmux's own `<@id>`,
# which is what clause (b)'s precedence 3 and clause (h)'s `window-lane` match.
# Reading one for the other is how a record would name a window nothing can
# resolve, so both are captured here, from tmux, and neither is derived from
# the other.
this_window_ref="$(tmux display-message -p '#{session_name}:#{window_index}' 2>/dev/null || :)"
this_window_id="$(tmux display-message -p '#{window_id}' 2>/dev/null || :)"
record_window="$this_window_ref"
# THE ID IS WRITTEN WHERE ONE IS KNOWABLE AND THE SUB-FIELD IS THE REF ALONE
# WHERE IT IS NOT: a record with no id is COMPLETE, because the NAME is the key
# (clause (b)) and the id is information (ratified decision 5). A tmux server
# restart, a workstation reboot or a swap taken from a terminal that is then
# closed all leave a recorded id naming nothing, and a binding keyed on the id
# would lose the lane where one keyed on the name does not.
# AND AN ID IS `@<digits>` AND NOTHING ELSE (F-X13(a)). `@*` accepted anything
# that merely STARTED with an at-sign, and two things that are not ids do: a
# tmux too old to know `#{window_id}` PRINTS THE FORMAT BACK, and a shim on
# PATH may print anything at all. Either one recorded here is a lie in an
# append-only log — and worse than an absence, because the sub-field would then
# name a window `window-lane` can never resolve while looking complete.
# `claude-profile` makes exactly this check on exactly this value
# (`workBenches#71`'s `lane-swap` skill, `:239-240`: `[[ "$win_id" =~
# ^@[0-9]+$ ]]`), and two writers of one field with two standards is the drift
# this branch removes everywhere else.
#
# Written as a `case` rather than `[[ =~ ]]` to match this file's own style for
# this test: `@` alone is not an id, and `@` followed by any non-digit is not
# one either.
case "$this_window_id" in
  @) : ;;
  @*[!0-9]*) : ;;
  @*) record_window="$this_window_ref $this_window_id" ;;
esac
case "$record_window" in
  *', '*|*' — '*|*'"'*)
    die "this window's tmux refs are '$record_window', and a \`window\` sub-field may not contain ', ', ' — ' or '\"' (Amendment 8(b), extended by Amendment 11 clause (c) to \`dir\`): those are what divide an event line into its fields and its free text, and the log is append-only. Rename the tmux session" 2 ;;
esac
step "this window is $this_window, named '${this_window_name:-?}'"
step "  its record refs are $record_window"

# Active restarts refuse unowned callers before any binding repair or rename.
# Detailed prompt and launch-fact validation follows before transcript writes.
preparation_failure_identity=""
preparation_failure_snapshot() {   # validated restart-intent output
  printf '%s\n' "$1" | awk -F'\t' '
    {v[$1]=$2} END {printf "%s|%s|%s|%s|%s|%s", v["state"],v["mode"],v["attempt"],v["new_transcript"],v["operation"],v["generation"]}'
}
preparation_failure_resume_check() {   # validated restart-intent output
  pfr_identity="$(preparation_failure_snapshot "$1")"
  case "$pfr_identity" in failed\|preservation-only\|0\|none\|*) : ;;
    *) die "a failed supervised launch requires its same-operation supervisor; ordinary resume refuses. Nothing was launched." 2 ;;
  esac
  [ -z "$preparation_failure_identity" ] || [ "$pfr_identity" = "$preparation_failure_identity" ] ||
    die "the failed preparation changed during ordinary recovery. Nothing was launched." 2
  [ -z "${op_flag:-}${LANE_RESTART_OPERATION:-}${LANE_RESTART_ATTEMPT:-}" ] ||
    die "failed preparation permits only ordinary resume without restart operation or attempt tokens. Nothing was launched." 2
  [ "${fresh_flag:-0}" != 1 ] && [ "${LANE_START_FRESH:-0}" != 1 ] ||
    die "failed preparation permits only ordinary resume, not a fresh session. Nothing was launched." 2
  LANES_NO_FETCH=1 "$LANES_EDIT" legacy-restart-check "$LANE" ||
    die "managed or unknown ownership blocks failed-preparation recovery. Nothing was launched." 2
  pfr_holder_rc=0
  LANES_NO_FETCH=1 "$LANES_EDIT" lane-holders "$LANE" >/dev/null || pfr_holder_rc=$?
  [ "$pfr_holder_rc" = 8 ] ||
    die "ordinary recovery from failed preparation requires confirmed absence of every holder (lane-holders exited $pfr_holder_rc). Nothing was launched." 2
  preparation_failure_identity="$pfr_identity"
}
eri_rc=0
eri_out="$(LANES_NO_FETCH=1 "$LANES_EDIT" restart-intent "$LANE" --dir "$DIR" 2>/dev/null)" || eri_rc=$?
case "$eri_rc" in
  0)
    eri_state="$(printf '%s\n' "$eri_out" | awk -F'\t' '$1=="state" {print $2; exit}')"
    eri_op="$(printf '%s\n' "$eri_out" | awk -F'\t' '$1=="operation" {print $2; exit}')"
    case "$eri_state" in
      preparing) die "this restart is still preparing its preservation records. Nothing was changed." 2 ;;
      failed) preparation_failure_resume_check "$eri_out" ;;
      pending|starting)
        eri_token="${op_flag:-${LANE_RESTART_OPERATION:-}}"
        [ -n "$eri_token" ] || die "an active restart requires its supervisor operation token. Nothing was changed." 2
        [ "$eri_token" = "$eri_op" ] || die "operation $eri_token is not lane $LANE's current restart operation $eri_op. Nothing was changed." 2
        LANES_NO_FETCH=1 "$LANES_EDIT" legacy-restart-check "$LANE" || die "managed ownership blocks this legacy restart. Nothing was changed." 2
        # --no-launch is a read-only command preview for an active restart.
        (( ! no_launch )) || dry_run=1 ;;
      ready) : ;;
      INCOMPLETE) die "the restart intent is INCOMPLETE: its fenced fields cannot compare. Nothing was changed. Read it: lanes-edit.sh restart-intent $LANE" 2 ;;
      UNKNOWN-SCHEMA) die "the restart schema is unreadable (Amendment 7(d)). Resuming could open the transcript that /ctx PAUSED. Update this workstation's openRepoTools or reconcile the intent once no restart is active. Nothing was changed." 2 ;;
      *) die "the restart intent is malformed ($eri_state). Nothing was changed." 2 ;;
    esac ;;
  8|2) : ;;
  1) die "the restart intent could not be read. That is NOT 'no restart is in flight': ordinary resume could open the transcript that /ctx PAUSED. Set LANES_LANE_STATE_ROOT to a readable control root. Nothing was changed." 2 ;;
  *) die "the restart intent could not be read. Nothing was changed." 2 ;;
esac

# -------------------------------------------------------- 3. liveness check

# 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
# where ownership could not be established. ANY other status — a helper that
# predates the verb included — is UNKNOWN as well, and refused the same way:
# a fence that opens because its read failed is no fence (Amendment 7(d)).
seam_refuse() {   # <lane> <the act>
  sr_out=""; sr_rc=0
  sr_out="$("$LANES_EDIT" managed-projection "$1" 2>/dev/null)" || sr_rc=$?
  case "$sr_rc" in
  0) die "lane $1 is owned by the managed ledger (owner ${sr_out:-unnamed}), and $2 is a legacy lane act, refused here, before the binding is read, before a handoff is requested of anybody and before a byte is written: no row, no log line, no stamp, no window name, no launch. Brett Heap's ruling of 2026-10-04: \"managed ledger owns enrolled lanes; #97 owns legacy\". Act on this lane through the managed ledger." 2 ;;
  8) : ;;
  *) die "whether the managed ledger owns lane $1 is UNKNOWN (\`$LANES_EDIT managed-projection $1\` exited $sr_rc): its register row carries managed-owner vocabulary that does not parse, or the read failed. An ownership nobody could establish is never read as legacy (Amendment 7(d)), so $2 is refused here, before the binding is read, before a handoff is requested of anybody and before a byte is written: no row, no log line, no stamp, no window name, no launch. Read it: $LANES_EDIT managed-projection $1" 1 ;;
  esac
}
# AT THE TOP OF SECTION 3, and so BEFORE Amendment 18's binding gate and its
# `request-handoff`: asking a managed lane's place to hand off is itself a
# legacy act on that lane.
seam_refuse "$LANE" "a lane start"

# The row, READ (never written) with the same rule lanes-edit.sh uses to find
# one: the row's FIRST backticked token is the lane name.
# AMENDMENT 15 — `tolower` ON BOTH SIDES, exactly as `row_line` now compares.
# This read is what decides "is this lane new", and it was the byte-for-byte
# comparison that let `lane-start openxfactory 2` add a SECOND row for
# `openXfactory-2` at 2026-09-13T23:51:56Z. Case-insensitive, the lane is found,
# the branch below is the RESUME branch, and `add-row` is never reached.
rows_for_lane() {
  awk -v lane="$1" '
    substr($0,1,1) == "|" {
      p1 = index($0, "`"); if (p1 == 0) next
      rest = substr($0, p1 + 1); p2 = index(rest, "`"); if (p2 == 0) next
      if (tolower(substr(rest, 1, p2 - 1)) == tolower(lane)) print
    }' "$LANES_FILE"
}
# The names those rows carry — which under Amendment 15 may be two spellings of
# ONE name, and a refusal that could not say so would send a person looking for
# a duplicate that is not there to find.
row_names_for_lane() {
  awk -v lane="$1" '
    substr($0,1,1) == "|" {
      p1 = index($0, "`"); if (p1 == 0) next
      rest = substr($0, p1 + 1); p2 = index(rest, "`"); if (p2 == 0) next
      t = substr(rest, 1, p2 - 1)
      if (tolower(t) == tolower(lane)) print t
    }' "$LANES_FILE"
}

row="$(rows_for_lane "$LANE" || :)"
row_count=0
[ -n "$row" ] && row_count="$(printf '%s\n' "$row" | grep -c . || :)"

if [ "$row_count" -gt 1 ]; then
  rfl_names="$(row_names_for_lane "$LANE" | tr '\n' ' ')"
  rfl_distinct="$(row_names_for_lane "$LANE" | LC_ALL=C sort -u | grep -c . || :)"
  rfl_why="and lanes-edit.sh can edit neither"
  if [ "$rfl_distinct" -gt 1 ]; then
    # BRACED, AND THE BRACES ARE LOAD-BEARING (A9 Addendum 4, R-A9-11): bash
    # decides where a variable NAME ends with `isalnum()`, which is LOCALE-
    # DEPENDENT, and bash 3.2 on Darwin under the runner's `en_US.UTF-8` reads
    # the three bytes of `—` as name characters — so this looks up
    # `rfl_names—`, which `set -u` then kills the script over. Caught by
    # `test_no_shipped_bash_leaves_a_variable_name_to_bash_3_2s_locale`, which
    # is the rule this repository already learned once.
    rfl_why="spelled ${rfl_names}— a lane name is ONE name under any case (Amendment 15), so those are two rows for ONE lane, and lanes-edit.sh can edit neither"
  fi
  die "the register has $row_count rows for lane $LANE, $rfl_why. Merge them into one row by hand in $LANES_FILE (one line each) — Amendment 15(d): append the newer row's session id(s) to the older row's session cell, in order, and remove the newer row in the SAME commit, whose message names both spellings — then commit with 'LANES_LANE=$LANE lanes-edit.sh commit \"merged duplicate rows\"' and re-run" 2
fi

# AND EVERYTHING THIS SCRIPT DECIDES FROM THE ROW IS DECIDED AGAINST WHAT HAS
# LANDED, not against this checkout. `$LANES_FILE` is the working tree, and a
# `git fetch` does not move it: a row another workstation added and pushed, or a
# uuid it stamped on an existing row, is simply absent here until something
# pulls. Two decisions turn on that row and BOTH used to read the working tree.
#   "IS THIS LANE NEW" — reaching `add-row` on that reading appends a SECOND row
#     (`add-row` checks the working tree too, and `commit_push`'s rebase then
#     brings the peer's row in underneath it), and two rows for one lane is a
#     register no helper can edit at all, because `row_line` requires exactly one.
#   "WHICH SESSION IS THIS LANE'S" — the resume target, the id in the status
#     appended to the row, and the uuid stamped on the RESUMED / STARTED line
#     (see THE RESUME TARGET above).
# So: ask for the PUBLISHED row ONCE, here, for both. 0 and 8 are the answers;
# anything else is the helper failing, and this script decides nothing about a
# row on an answer it did not get. LANES_NO_FETCH=1 is honoured inside the
# helper, for an offline start.
pub_rc=0
pub_row="$("$LANES_EDIT" register-row "$LANE" 2>/dev/null)" || pub_rc=$?
if [ "$row_count" = 0 ]; then
  case "$pub_rc" in
    8) : ;;                        # no published row either: the lane really is new
    0)
      note "the register on origin/main ALREADY has a row for $LANE, and this checkout does not:"
      pub_row_first="${pub_row%%$'\n'*}"
      printf '  %s\n' "${pub_row_first:0:200}" >&2
      note "adding a row here would make two, and two rows for one lane is a register lanes-edit.sh cannot edit."
      note "RECOVERY — bring this checkout up to date, then re-run this command:"
      note "  git -C \"$(cd -- "$(dirname -- "$LANES_FILE")/.." && pwd)\" pull --rebase origin main"
      die "refusing to add a second row for $LANE" 2 ;;
    *)
      note "the helper's own output is above."
      die "$LANES_EDIT register-row $LANE failed (exit $pub_rc). That is NOT 'the register has no row for $LANE', and this script will not add a row on an answer it did not get — a duplicate row is a register no helper can edit. Fix the helper (or run it by hand: $LANES_EDIT register-row $LANE), then re-run." 1 ;;
  esac
else
  case "$pub_rc" in
    0) : ;;
    8)
      # A row HERE and none on `origin/main`: it is in a commit this checkout
      # has not pushed, or on another branch. There is then no published cell,
      # so there is no recorded session to resume — and this script does not
      # fall back to the working tree, because falling back is the fault. The
      # ids below are named as DIAGNOSTICS, never as a target: nothing outside
      # this checkout can see them. `lane-end`'s refusal reads `origin/<branch>`
      # for the same reason and cannot see an unpushed line either — what has
      # landed is what other lanes can see.
      note "this checkout has a row for $LANE and the register on origin/main has none — so there is no PUBLISHED session cell, and no recorded session to resume."
      unpub_ids="$(printf '%s\n' "$row" | awk -F'|' '{print $3}' | grep -oiE '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}' | tr 'A-F' 'a-f' | tr '\n' ' ' || :)"
      [ -n "$unpub_ids" ] && note "  the id(s) only this checkout's copy carries, which nothing else can see: ${unpub_ids% }"
      note "  RECOVERY — push the register from here, then re-run: git -C \"$(cd -- "$(dirname -- "$LANES_FILE")/.." && pwd)\" push origin main" ;;
    *)
      note "the helper's own output is above."
      die "$LANES_EDIT register-row $LANE failed (exit $pub_rc). That is NOT 'the register has no row for $LANE', and this script will not pick a resume target on an answer it did not get: resuming the working tree's id lands the operator in the lane's previous conversation and stamps that uuid on an append-only line. Fix the helper (or run it by hand: $LANES_EDIT register-row $LANE), then re-run." 1 ;;
  esac
fi

# Every field of a `| … |` row by position: 1 is empty (before the leading
# pipe), 2 the lane cell, 3 the session-id cell, NF-1 the state cell.
# OF THE PUBLISHED ROW. `$row` above is this checkout's, and it is read for
# exactly one thing: whether adding a row would make two. Every id this script
# acts on comes from `$pub_row`, which is empty when the published register has
# no row for the lane — the case the `8` branch above has already reported.
cell() { printf '%s\n' "$pub_row" | awk -F'|' -v i="$1" '{print $i}'; }

# Only the SESSION-ID CELL is read for ids. State cells quote other lanes'
# session ids all the time ("RESUMED by <id>", "handed off to <id>"), and a
# live one of those is not this lane's holder.
# Two readings of the same cell. The liveness check below wants the SET, so it
# sorts; the resume target wants the ORDER, because the cell is a history and
# its LAST id is the lane's current session (see THE RESUME TARGET above).
session_ids=""
session_ids_ordered=""
if [ "$row_count" = 1 ]; then
  session_ids_ordered="$(cell 3 | grep -oiE '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}' | tr 'A-F' 'a-f' || :)"
  [ -n "$session_ids_ordered" ] && session_ids="$(printf '%s\n' "$session_ids_ordered" | sort -u)"
  id_count=0; [ -n "$session_ids" ] && id_count="$(printf '%s\n' "$session_ids" | grep -c . || :)"
  step "the register already has a row for $LANE; its session cell on origin/main names $id_count session id(s)"
  # A row may record only `session_01…` FOOTER ids. Those are not transcript
  # ids: a transcript is `<uuid>.jsonl`, so a footer id can neither be checked
  # for liveness nor resumed. Name the gap rather than behave as if the cell
  # were empty — that silence is what made 2026-09-11 hard to diagnose.
  if [ "$id_count" = 0 ]; then
    footer_ids="$(cell 3 | grep -oE 'session_[A-Za-z0-9]{10,}' | sort -u || :)"
    if [ -n "$footer_ids" ]; then
      note "the cell records only PR-footer ids ($(printf '%s' "$footer_ids" | tr '\n' ' ')), which are not transcript ids — so this lane has no liveness check and no resume target. Its session must stamp its TRANSCRIPT uuid (the name of its <uuid>.jsonl) on the row."
    fi
  fi
else
  step "the register has no row for $LANE yet"
fi

# LIVENESS IS ONE IMPLEMENTATION, and it lives in `lanes-edit.sh`, because
# `who` asks exactly this question about exactly these rows and two copies
# would drift. It reads the row's session cell itself and tries EVERY
# transcript uuid recorded there, not merely the last one — a lane whose
# earlier lineage is still running is still held.
#
# It also carries the `nameSource` fix: a session record's `name` is evidence
# about some OTHER lane only when a person or a peer set it. `nameSource:
# derived` is the harness naming a window after its working directory, and
# treating that as a denial reported "no live session holds <lane>" for
# sessions that plainly did (2026-09-11, the orchestrator's own window).
# ONLY 0 AND 8 ARE ANSWERS: 0 is "this record holds the lane", 8 is "no live
# record does". Any other exit is the helper FAILING, and this script must not
# read a failure as "the name is free" — renaming a running session into a
# title something else still holds is exactly what mints `<lane> (2)` and costs
# the lane its address (AGENTS.md rule 7). The first version swallowed the
# helper's stderr and treated every non-zero exit as "no holder", so a helper
# that could not run at all produced a confident "no live session holds <lane>"
# about a session that was live in another window.
live_holder() { "$LANES_EDIT" live-holder "$LANE"; }

# AND IT IS ASKED UNCONDITIONALLY. This used to run only when the row THIS
# CHECKOUT has already named a session id, which is the wrong gate twice over:
# the ids came from the working tree, which no fetch moves, so a row (or a newly
# stamped uuid) that another workstation had already published was read as "no
# ids, nothing to check"; and a lane with no row here at all skipped the check
# entirely. Both skip exactly when the answer matters — the helper owns the row
# lookup, fetches first, and unions the published ids with this checkout's (R25),
# so asking it costs one fetch and can only ever ADD a reason to refuse.
holder_here=0
LS_TMP="$(mktemp)"
holder=""; lh_rc=0
holder="$(live_holder 2>"$LS_TMP")" || lh_rc=$?
[ -s "$LS_TMP" ] && cat -- "$LS_TMP" >&2
case "$lh_rc" in
  0)
    # WHOSE SESSION IT IS COMES FROM THE HELPER (Amendment 8, ruling (g)), not
    # from a string compare on the `tmux` column here. The first version made
    # that compare, and on 2026-09-12 it refused this lane the window it was
    # running in: the record it was handed was the harness's `kind: bg`
    # COMPANION, which carries the interactive session's own `sessionId` and no
    # `tmux` at all, so `"none" != "$this_window"` and the refusal read
    # "lane openRepoProject-1 is live in session c5701b54… (tmux none)" about
    # the session typing the command. A record with no target is not a record in
    # no window — the helper now answers with `here`, `elsewhere` or `orphan`,
    # having tested `$CLAUDE_CODE_SESSION_ID`, the window, and this pane's
    # process tree in that order.
    #
    # AN EMPTY FIFTH FIELD IS A REFUSAL, not a pass: an older `lanes-edit.sh`
    # that does not send one must not be read as saying "here".
    IFS=$'\037' read -r h_id h_target h_name h_pid h_where <<<"$holder"
    case "$h_where" in
      here)
        holder_here=1
        step "this window's own session $h_id (pid $h_pid, name '${h_name:-none}') already holds $LANE — carrying on" ;;
      orphan)
        # AMENDMENT 6(d), and not a refusal. A live record that names no window
        # and is in no pane's process tree is an idle background session still
        # holding the name — the thing 6(d) says to retire. It is not in this
        # window, so it is not this window's session; it is in no window, so it
        # is nobody's rival either. Say so, name the act, and carry on.
        note "lane $LANE is named by a live record that is in NO window and not in this pane's process tree: session $h_id, pid $h_pid, name '${h_name:-none}'. That is an orphaned holder, not a rival (Amendment 6(d)) — retire it: kill $h_pid. Carrying on."
        ;;
      *)
        note "lane $LANE is live in session $h_id (tmux ${h_target:-unknown}); take $repo-$next_n or resume that window"
        note "  $prog $repo $next_n"
        note "  tmux switch-client -t ${h_target%.*}     # or go to the window that holds it"
        exit 2 ;;
    esac ;;
  8)
    if [ "$row_count" = 1 ]; then
      step "no live session holds $LANE — this is a resume of a lane whose sessions have all ended"
    else
      step "no live session holds $LANE — the register records no session for it at all, here or on origin/main"
    fi ;;
  *)
    note "the helper's own output is above."
    die "$LANES_EDIT live-holder $LANE failed (exit $lh_rc). That is NOT 'no live session holds $LANE', and this script will not rename the window on an answer it did not get: a rename into a name something still holds is what mints '$LANE (2)'. Fix the helper (or run it by hand: $LANES_EDIT live-holder $LANE), then re-run." 1 ;;
esac

# ------------------------------ 3a. the orphaned holders (Amendment 8(f))
#
# R-A8-6. Step 3 asked whether the lane's CURRENT id is held. This asks who is
# still holding its EARLIER ones — Amendment 6(d)'s orphans, the live-but-idle
# sessions that are the whole reason the `/resume` picker offered this lane two
# transcripts of which neither was the lane.
#
# IT NAMES THEM AND IT NEVER KILLS. The retire act is `kill <pid>`, printed
# here with the session id and the profile beside it so a person can check
# before running it, and run by that person. Clause (f) rules it the operator's
# act — an idle background session is exactly the shape of thing that turns out
# to be somebody's long-running job — and it never blocks or delays the launch:
# a helper too old to know the read simply says nothing.
ih_out=""; ih_rc=0
ih_out="$("$LANES_EDIT" idle-holders "$LANE" 2>/dev/null)" || ih_rc=$?
if [ "$ih_rc" = 0 ] && [ -n "$ih_out" ]; then
  note "lane $LANE: this row's EARLIER session ids are still held by live but idle sessions (Amendment 6(d) orphans). They are history, not alternatives — retire them, and $prog never does it for you:"
  while IFS=$'\t' read -r o_sid o_pid o_kind o_prof; do
    [ -n "$o_sid" ] || continue
    note "  session $o_sid (kind ${o_kind:-none}, profile ${o_prof:-unknown}) — retire it: kill $o_pid"
  done <<<"$ih_out"
fi

# THE RESUME TARGET, from the PUBLISHED cell (R33): the LAST id in it. Read
# here rather than in 5a because step 3b may replace it with an id the cell does
# not carry yet, and 5a's launch decision has to see that.
row_sid=""
[ -n "$session_ids_ordered" ] && row_sid="$(printf '%s\n' "$session_ids_ordered" | tail -n1)"

# ------------------------------------- 3b. the live session in THIS window
#
# A DIFFERENT QUESTION FROM STEP 3's, and Amendment 8 exists for the gap between
# them. Step 3 asks "is any session the ROW names alive"; this asks "what is
# live in THIS WINDOW". The harness mints a new transcript uuid with nobody
# acting — a `/clear` does it (Amendment 6, fact 4), and so did the 2026-09-12
# usage reset that carried this lane's conversation into `4a91f1dc…` while its
# row still ended on `09dd34d1…`. An id in no row is an id `live-holder` cannot
# look up: it answers 8, "this lane is parked", about the conversation sitting
# in the window it was asked about, and this script would then resume the lane's
# PREVIOUS conversation and stamp that uuid on an append-only line.
#
# So the id is taken from the record itself, and step 5 appends it to the
# session cell BEFORE it stamps — which is what makes liveness and the next
# resume follow it. There is no flag for this and there could not be one: the id
# does not exist until the session does. The act is `lane-start --no-launch` run
# IN the window, which is what the SessionStart hook's block asks the new
# session to do, and what this lane did by hand at 2026-09-12T16:59Z.
#
# A FAILED READ IS A WARNING HERE, NOT A REFUSAL, and that is not R22 being
# waived. R22 is for a read whose empty answer PERMITS something: `live-holder`
# fails closed because a rename over a live name costs a lane its address. This
# read only ever ADDS an id to a cell, and it runs after `live-holder` has
# already read the same records and refused if it could not — so a failure here
# means the records went unreadable between two calls a second apart, and the
# honest response is to say so and carry on rather than to refuse a lane its
# start.
# ------------------- AMENDMENT 18(h): ONE LIVE PROCESS PER TRANSCRIPT
#
# *"`lane-start` — every launch branch and `--no-launch`'s window-binding step —
# counts the live records carrying the id it is about to resume or bind, across
# every profile's `sessions/`, and REFUSES when a process other than this
# window's holds it, naming the pid(s), their windows or `bg`, and the retire
# act; it never appends such an id to the row and never launches a second resume
# of it."* Ratified 2026-09-14T13:15:18Z as revision 4 of Amendment 18;
# opensoft/openRepoTools#39.
#
# MEASURED, AND THAT IS WHY IT IS A REFUSAL AND NOT A NOTE. On 2026-09-14 at
# 12:05Z the harness spawned `claude --session-id d1ac715c… --fork-session` under
# a `bg-pty-host`; at 12:07Z the launcher NAMED it as a defect; at 12:10Z a
# `lane-start --no-launch openRepoTools 3` in a new window bound THAT SAME
# transcript as the row's session, seeing nothing; at 12:25Z a second `pclaude`
# resumed it interactively. Three live processes, one transcript file, and the
# retire act could not see any of them BECAUSE the row now recorded the id.
# The count below is the read that was missing, and it is asked of the id this
# run is about to write down or resume — never of the lane.
#
# IT FAILS CLOSED, AND THE THREE CODES ARE THE CONTRACT: 0 with rows, 8 with
# none, 64 a usage error, anything else a read that did not happen. A 2 is a
# `lanes-edit.sh` that predates this read — the un-upgraded workstation — and
# THAT one falls through with a note, exactly as clause (h)'s other reads do,
# because refusing every lane start on every workstation that has not installed
# this yet is not a safety property.
#
# AND THE HARNESS HAS A FENCE OF ITS OWN ON THE SAME FILE, WHICH THIS RUN MUST
# ASK BEFORE IT EXECS RATHER THAN AFTER (measured on Eagle 2026-09-15 against
# `claude` 2.1.270, and reproduced live in a scratch config directory): a
# `claude --resume <id>` whose id is carried by a live session record whose
# `kind` is anything but `interactive` REFUSES AND EXITS 1 before it starts,
# with
#
#   Error: Session <id> is running as a background session. Run `claude agents`
#   to find its id, then `claude attach <id>` to open it, or `claude stop <id>`
#   first to resume it here. Add --fork-session to branch off a copy instead.
#
# — the harness's own `H5`/`zpe` pair, which takes the FIRST live record for the
# id whose `kind !== "interactive"` (a `--bg` job, a `bg-pty-host` child, the
# `bg` COMPANION of Amendment 8 ruling (g)) and stops there. A second live
# INTERACTIVE record does NOT stop it — the same measurement got past that check
# and failed later, on authentication — which is exactly why 18(h) is this
# tooling's to enforce and not the harness's.
#
# THE COST OF ASKING IT LATE IS A FALSE `RESUMED`. The row, the object log and
# the handoff stamp are all written BEFORE the `exec` at the foot of this
# command, so a launch the harness refuses leaves a lane recorded as RESUMED by
# a session that never started, and in a launcher-created window — `pclaude
# --lane <lane> <profile>`, whose pane's only command this is — tmux prints
# `[exited]` over the message and closes it (opensoft/workBenches#77's shape,
# one door along). So the `resume` rule below asks the harness's question in
# front of the launch and prints the harness's own remedy beside this estate's.
dup_check() {   # <session uuid> <what this run was about to do with it> [<rules>]
  # THE RULES, AND THE THIRD ARGUMENT IS WHICH OF THEM APPLY:
  #   bind         (the default) 18(h)'s duplicate count alone — the
  #                window-binding call, which opens no transcript;
  #   resume       both rules — the branch that is about to `--resume` this id
  #                with no record of it in this window;
  #   resume-here  the harness's fence alone — the same branch where the id IS
  #                this window's own live session, whose duplicate count the
  #                window-binding call above has already made.
  local dc_id="${1-}" dc_why="${2-}" dc_rules="${3-bind}" dc_rows="" dc_rc=0 dc_other="" dc_bg="" dc_att=""
  local dc_pid dc_kind dc_tgt dc_prof dc_where dc_verdict dc_file
  [ -n "$dc_id" ] || return 0
  : > "$LS_TMP"
  dc_rows="$("$LANES_EDIT" transcript-holders "$dc_id" 2>"$LS_TMP")" || dc_rc=$?
  case "$dc_rc" in
    0 | 8) : ;;
    2) [ -s "$LS_TMP" ] && cat -- "$LS_TMP" >&2
       note "this \`lanes-edit.sh\` has no \`transcript-holders\` (exit 2), so whether another live process already carries $dc_id is NOT known here. Install the one beside this script (\`openRepoTools --install\`); carrying on."
       return 0 ;;
    *) [ -s "$LS_TMP" ] && cat -- "$LS_TMP" >&2
       die "$LANES_EDIT transcript-holders $dc_id exited $dc_rc, so whether another live process already carries that transcript could NOT be read — and that is not 'no other process does'. A transcript is held by ONE live process (Amendment 18(h)); nothing has been renamed, written or launched." 1 ;;
  esac
  [ "$dc_rc" = 0 ] || return 0
  while IFS=$'\037' read -r dc_pid dc_kind dc_tgt dc_prof dc_where dc_verdict dc_file; do
    [ -n "${dc_pid:-}" ] || continue
    # `unrelated` BLOCKS HERE AND NOWHERE ELSE, and the difference is the
    # question being asked. `transcript_holders` answers "who holds this
    # transcript, and what is this window's relation to them", and its
    # `unrelated` means THIS WINDOW CARRIES NO RECORD OF IT AT ALL — kept
    # silent there so that a rule about a TRANSCRIPT cannot overturn
    # `live_holder`'s verdicts about a LANE, or `forks`, from a read that was
    # asked about neither. THE QUESTION HERE IS 18(h)'s OWN and is narrower:
    # *"the id it is about to resume or bind"*. The ROW-RESUME branch reaches
    # this call only when `row_sid != win_sid`, so this window has no record of
    # that id and EVERY live holder of it comes back `unrelated` — counting
    # only `duplicate` made that branch's check one that could never fire
    # (Copilot round 1 on opensoft/openRepoTools#52). At the window-binding call
    # the id IS this window's own session, so a `here` record exists and nothing
    # is `unrelated`; one rule, two call sites, no second definition of a
    # duplicate.
    #
    # AND IT DOES NOT DECIDE WHETHER THE LANE IS TAKEN. An ORPHAN — a live but
    # idle holder of the row's id — is still reported and never refused as a
    # rival (Amendment 8(f), through `live_holder`'s own verdict, printed above
    # this with 6(d)'s act), and a `bg` companion still holds no lane. What
    # 18(h) adds is about the FILE: this branch's next act is `claude --resume
    # <that id>`, and the clause says *"it never appends such an id to the row
    # and never launches a second resume of it"*. 8(f)'s own sentence does not
    # reach that state either — it rules on *"a row's EARLIER session ids …
    # still held by live but idle sessions"*, and this is the id the row ENDS
    # on, which is the one a resume opens.
    #
    # THE HARNESS'S OWN FENCE FIRST, because it decides whether the `exec` this
    # branch is about to make can start at all, and it reads the record's KIND
    # and not this read's verdict: the `bg` COMPANION of the session live in
    # THIS window is `companion` here — benign, one session seen twice — and it
    # is still a record whose kind is not `interactive`, so `claude --resume`
    # stops on it. A record with no `kind` at all is written down as
    # `interactive` by `transcript_holders` (an older harness wrote nothing
    # else), which is the same reading the harness makes.
    if [ "$dc_rules" != bind ] && [ -n "${dc_kind:-}" ] && [ "$dc_kind" != interactive ]; then
      dc_bg="${dc_bg:+$dc_bg, }pid $dc_pid ($dc_where, kind $dc_kind, profile $dc_prof)"
      if [ -z "$dc_att" ] && [ -n "${dc_tgt:-}" ] && [ "$dc_tgt" != none ]; then
        dc_att="${dc_tgt%.*}"
      fi
    fi
    # AND IT IS NOT A SECOND VERDICT, SO IT DOES NOT `continue` PAST 18(h)'s
    # COUNT: one record can be both — a `bg` duplicate in another profile is a
    # second process on the file AND the thing the harness will stop on — and a
    # refusal that named only the newer of the two reasons would drop the one
    # this suite has asserted since #52. `resume-here` is the exception and
    # states why: the id is this window's own session, whose duplicate count the
    # window-binding call above has already made.
    [ "$dc_rules" = resume-here ] && continue
    case "$dc_verdict" in
      duplicate | unrelated) : ;;
      *) continue ;;
    esac
    dc_other="${dc_other:+$dc_other, }pid $dc_pid ($dc_where, kind $dc_kind, profile $dc_prof)"
    if [ -z "$dc_att" ] && [ -n "${dc_tgt:-}" ] && [ "$dc_tgt" != none ]; then
      dc_att="${dc_tgt%.*}"
    fi
  done <<<"$dc_rows"
  [ -n "$dc_bg" ] || [ -n "$dc_other" ] || return 0
  if [ -n "$dc_other" ]; then
    note "another live process already carries transcript $dc_id: $dc_other"
    note "A transcript is held by ONE live process (Amendment 18(h)): two of them append to one file, each overwriting what the other wrote, and a row that records it has two processes answering for one lane. This run was about to $dc_why, and it has done NOTHING — no window renamed, no id appended, no session launched."
  fi
  if [ -n "$dc_bg" ]; then
    note "a live BACKGROUND session already carries transcript $dc_id: $dc_bg"
    note "\`$CLAUDE_BIN --resume $dc_id\` would REFUSE to start against it — \"Session $dc_id is running as a background session … Add --fork-session to branch off a copy instead\" — and exit 1 before anything ran (measured against claude 2.1.270, and reproduced in a scratch configuration directory). This run was about to $dc_why, and it has done NOTHING: no window renamed, no id appended, no session launched. A lane recorded RESUMED by a launch the harness refuses is a false transition in two append-only files, and in a window a launcher has just made — \`pclaude --lane <lane> <profile>\`, whose pane's only command this is — tmux prints \`[exited]\` over the message and closes it."
    note "open the one that is running rather than a second copy of it: \`claude agents\` names its id, \`claude attach <id>\` opens it, \`claude stop <id>\` ends it."
  fi
  # WHERE THAT PROCESS IS, WHEN ITS RECORD SAYS SO (Amendment 18 Addendum 1's
  # posture: the conversation that is already live is ATTACHED, never started a
  # second time). The line is printed beside the retire act and not instead of
  # it: which of the two this is — the lane running in another window, or a
  # duplicate to retire — is the person's to read, and only one of them is a
  # window to go to.
  [ -n "$dc_att" ] && note "that process is in ${dc_att}: tmux switch-client -t $dc_att   (from outside tmux: tmux attach -t ${dc_att%%:*})"
  die "retire the other one first — \`lane-end\` proves it is this lane's duplicate and prints Amendment 6(d)'s act for it, and it ends, writes and kills nothing:
    lane-end $LANE --retire <pid>" 1
}

win_sid=""; win_target=""; win_name=""; win_pid=""; win_profile=""
: > "$LS_TMP"
win_rec=""; ws_rc=0
win_rec="$("$LANES_EDIT" window-session "$this_window" 2>"$LS_TMP")" || ws_rc=$?
[ -s "$LS_TMP" ] && cat -- "$LS_TMP" >&2
case "$ws_rc" in
  0)
    IFS=$'\037' read -r win_sid win_target win_name win_pid win_profile <<<"$win_rec"
    step "this window's live session is $win_sid (name '${win_name:-none}', pid $win_pid, profile ${win_profile:-unknown})" ;;
  8) step "no live session record names this window ($this_window)" ;;
  *)
    note "$LANES_EDIT window-session $this_window failed (exit $ws_rc) — carrying on without it. This read only ever ADDS the harness's new transcript uuid to the cell, and live-holder has already read the same records; if the cell is behind, stamp it yourself." ;;
esac

# AMENDMENT 18(h), THE WINDOW-BINDING STEP. Asked BEFORE the vetoes and before
# anything is taken: an id a second live process already carries is one this run
# must neither append to a cell nor resume, whatever the vetoes below decide
# about whose it is.
[ -n "$win_sid" ] && dup_check "$win_sid" "bind $win_sid as lane $LANE's session"

# The id the cell does not carry. `$session_ids` is the PUBLISHED set (step 3),
# so an id only this checkout knows is not treated as recorded either.
#
# NOT WHEN STEP 3 ALREADY FOUND ITS HOLDER HERE: a row whose OWN id is live in
# this window is a cell that is current by definition, and there is nothing to
# append. And only a TRANSCRIPT UUID is ever appended — a cell records those and
# only those (Amendment 6(b)), and a record carrying anything else in its
# `sessionId` is not something `--resume` could take.
# ------------------ 3b(i). THE WINDOW-NAME VETO (Amendment 11, `R-A11-12`)
#
# STEP 3b'S FENCE IS TWO VETOES AND NO PERMISSION, and this is the second of
# them. `R-A11-1` was corrected twice before it reached this shape and both
# corrections are worth the reader's time, because each one broke the mechanism
# in the opposite direction:
#
#   * the FIRST fence added "and the row carries no transcript yet", which made
#     step 3b's cell-stamping DEAD in every case it exists for — the `/clear`,
#     the usage reset, the profile switch — and was withdrawn (RV-T1);
#   * the SECOND made the window's own NAME a CONDITION FOR TAKING, and that
#     fails for every session that came up bare in a window still called
#     `claude`, which was 8 of this workstation's 16 windows and this lane three
#     times in one day (CF-T10). Its second disjunct, `live-holder` answering
#     `here`, is unreachable at the site it governs: the branch below requires
#     `holder_here = 0`.
#
# So neither is a permission. The rule is: the live session is taken UNLESS one
# of two vetoes fires.
#
#   VETO 1 — THE REGISTER. A uuid that belongs to ANOTHER ROW is never taken,
#     read through `lanes-edit.sh session-lane <uuid>` and fail-closed: only 0
#     and 8 are answers. That veto is ADOPTION ACT 0'S (`opensoft/brett-wip#5`
#     @`3719d97`), ported into this copy by `openRepoTools#24` (Amendment 9's
#     adoption act 3, MERGED as `d4b5710`), and this branch
#     does not re-implement it. THE SHA IS THE MERGE COMMIT AND NOT THE DRAFT
#     HEAD: act 0 merged 2026-09-13T19:14:37Z, squashed, so `#5`'s pre-merge
#     head `95e7a4c` is NOT an ancestor of `origin/main` and citing it names
#     something that never landed (F-X18).
#
#   VETO 2 — THE WINDOW'S NAME, and it is this PR's second layer. A window NAMED
#     FOR ANOTHER LANE is never taken. It catches what the register veto cannot:
#     a session whose uuid is in NO row at all — the harness mints one on every
#     `/clear` — running in a window that plainly belongs to somebody else. That
#     is Evidence 2(b) exactly: `lane-start openXfactory-5` typed from a window
#     named `openRepoProject-1` took this lane's live uuid as that lane's resume
#     target and planned to stamp it on that lane's row.
#
# A NAME IS A VETO AND NEVER A PERMISSION, which is the whole of `R-A11-12`: a
# window called `claude` vetoes nothing and the taking goes ahead, which is
# exactly the case the first correction was made to preserve.
# AND IT FAILS CLOSED, EXACTLY AS THE REGISTER VETO BESIDE IT DOES (`R-A11-12`;
# clause (d) rule 1, ratified verbatim): *"Both reads fail closed: any answer but
# 0 naming another lane or 8 leaves the cell and the resume target alone, because
# here an empty answer is what PERMITS the take."* Only **8** — no row knows this
# window's name — is permission. Every other code is a read that did not answer
# the question, and this is the one place where not answering it would be read as
# "the session is free": the cost of vetoing is one printed act, and the cost of
# permitting is another lane's uuid on an append-only line.
#
# THE `2` IS NAMED RATHER THAN LEFT TO BE FOUND. `register-row` exits 2 where
# `check_lane_name` refuses the string — a window name carrying a space, a slash
# or a leading `-`, which no lane name may carry (`lanes-edit.sh:1210-1215`). Such
# a window is not provably ANOTHER lane's, but it is not provably free either, and
# the ruling's words admit no third answer: it vetoes, and the note says which
# code came back so the operator can rename the window or pass --dir. A window
# named `claude`, `zsh` or anything else lane-SHAPED that no row knows exits 8 and
# still permits the take, which is what keeps the /clear, the usage reset and the
# profile switch working in the windows this estate actually has.
win_veto=""; win_veto_why=""
if [ -n "$win_sid" ] && [ -n "$this_window_name" ] && [ "$this_window_name" != "$LANE" ]; then
  if [ "$(printf '%s' "$this_window_name" | tr 'A-Z' 'a-z')" != "$(printf '%s' "$LANE" | tr 'A-Z' 'a-z')" ]; then
    wnv_rc=0
    "$LANES_EDIT" register-row "$this_window_name" >/dev/null 2>&1 || wnv_rc=$?
    case "$wnv_rc" in
      0) win_veto="$this_window_name"
         win_veto_why="which is another lane the register has a row for" ;;
      8) : ;;
      *) win_veto="$this_window_name"
         win_veto_why="and whether that is another lane is NOT KNOWN — \`$LANES_EDIT register-row $this_window_name\` exited $wnv_rc, which is neither 0 (a row) nor 8 (no row), so this read fails closed (R-A11-12)" ;;
    esac
  fi
fi

harness_sid=""; cell_anchor=""
# ------------------- 3b(ii). THE BINDING MODE (`--bind`, openRepoTools#70)
#
# THE GUARD'S CHOICE `2` IS A PERSON SAYING "THIS SESSION IS THAT LANE NOW", and
# clause (h) rule 2 names the act it asks for: *"the row created or this uuid
# appended to its cell"*. Without this mode the take below refused that uuid —
# veto 1, because the row being LEFT still records it — so the row's ordinary
# resume path ran instead and stamped the row, the lane's log and the handoff
# with `RESUMED by <the id the row already had>`, under `--no-launch`, about a
# conversation nobody was in; and the guard then appended the uuid to the cell
# itself. The cell ended right and the append-only log said something else.
#
# SO THE MODE IS STEP 3b's OWN TAKE, WITH VETO 1 ANSWERED BY THE PERSON. Clause
# (h) rule 4's limit is that a uuid never moves between rows WITHOUT the
# person's yes, and `--bind` is that yes, carried by the one caller that asked
# for it. Everything else about the take is unchanged: the cell is extended
# first and the stamp second (Amendment 8), with the PUBLISHED last id as the
# anchor. One rule is added, and it is the guard's own former anchor rule moved
# here: a cell recording no uuid is anchored on either of the two texts such a
# cell carries instead.
#
# AND IT BINDS OR IT REFUSES. Every case where the take cannot happen — no live
# session in this window, a different one from the uuid named, a window named
# for ANOTHER lane (veto 2, which this mode does NOT lift) — is a refusal here,
# before the rename and before any write. Carrying on would reach the resume
# path, and that path stamping an id nobody is in is the defect this mode exists
# to end.
if [ -n "$bind_sid" ]; then
  bind_lc="$(printf '%s' "$bind_sid" | tr 'A-F' 'a-f')"
  [ -n "$win_sid" ] ||
    die "--bind $bind_sid: no live session record names this window ($this_window), so there is no session here to bind. Nothing has been renamed, written or launched." 2
  [ "$(printf '%s' "$win_sid" | tr 'A-F' 'a-f')" = "$bind_lc" ] ||
    die "--bind names $bind_sid, and the session live in this window is $win_sid. The binding mode binds THIS window's session and no other one, so nothing has been renamed, written or launched." 2
  [ -z "$win_veto" ] ||
    die "this window is named '$win_veto', $win_veto_why — so the session live in it ($win_sid) is NOT bound as $LANE's (Amendment 11 clause (d) rule 1, veto 2, which --bind does not lift). Rename the window to $LANE first. Nothing has been renamed, written or launched." 2
  if [ "$bind_lc" = "$row_sid" ]; then
    step "--bind: $win_sid is already the last id in $LANE's session cell — nothing to append"
  else
    harness_sid="$win_sid"
    cell_anchor="$row_sid"
    if [ -z "$cell_anchor" ]; then
      # THE TWO TEXTS A CELL CARRIES INSTEAD OF A UUID: `none recorded`, which a
      # person writes into a row by hand, and the `pending` line this file writes
      # into a row it creates with no uuid to put there (step 5, below). Both are
      # whole-cell texts, so they anchor exactly as an id does, and a cell
      # carrying anything else prints the act and is never guessed at.
      bind_cell="$(cell 3 | sed -e 's/^ *//' -e 's/ *$//')"
      case "$bind_cell" in
        "none recorded" | "pending — set by the session's first act") cell_anchor="$bind_cell" ;;
      esac
    fi
    row_sid="$harness_sid"
    note "--bind: the session live in THIS window is $harness_sid, and it is bound as $LANE's on the person's choice 2 at the name guard (Amendment 12(h) rule 2). Its uuid goes into the session cell before the row's status — even where another row records it, because that choice is the person's yes (clause (h) rule 4) — and every stamp this run writes names it."
  fi
elif [ -n "$win_veto" ]; then
  note "this window is named '$win_veto', $win_veto_why — so the session live in it ($win_sid) is NOT taken as $LANE's, and $LANE's row is not stamped with it (Amendment 11 clause (d) rule 1, veto 2; Evidence 2(b)). Run this from $LANE's own window, or pass --dir and let it start its own session."
elif [ -n "$win_sid" ] && [ "$holder_here" = 0 ]; then
  if ! [[ "$win_sid" =~ ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$ ]]; then
    note "the session live in this window has id '$win_sid', which is not a transcript uuid — leaving the cell alone"
  elif printf '%s\n' "$session_ids" | grep -qx -F -- "$win_sid"; then
    step "  its uuid is already in the row's session cell — nothing to append"
  else
    # R-A11-1 (corrected; A11 Addendum 2, ratified 2026-09-13T18:05:29Z "Ratify
    # all four") — OWNERSHIP DECIDES, AND A LIVE SESSION THAT BELONGS TO ANOTHER
    # ROW IS NEVER TAKEN. Until this test, the branch above fired on ANY live
    # session in the typing window, so `lane-start X` typed from lane Y's window
    # resumed Y's transcript and appended Y's uuid to X's row — cross-lane
    # contamination, reproduced as Evidence 2(b) on `brettheap/new-workstation#20`
    # (the same run planned to write this lane's uuid into `openXfactory-5`'s row).
    #
    # THE TEST IS THE REGISTER, NOT THE WINDOW'S NAME. The two legitimate cases
    # this step exists for — a `/clear`, a usage reset, a profile switch — all
    # happen in a window the launcher has just made and named `claude`, BEFORE
    # step 4 renames it, and their uuid is one the harness has just minted, so it
    # is in NO row at all. Fencing on the window's name instead would refuse
    # exactly those three and leave step 3b dead, which is the failure `RV-T1`
    # raised against the withdrawn "and the row carries no transcript yet"
    # conjunct. An id that some OTHER lane's row already names is the one thing
    # that is provably not this lane's, and that is the fence.
    #
    # IT FAILS CLOSED (R22). Only 0 (a lane) and 8 (no row names it) are answers;
    # any other code is a read that did not happen — an older `lanes-edit.sh` with
    # no `session-lane` exits 2 — and a read that could not be made must never be
    # read as "the session is free", because an empty answer is what PERMITS the
    # take here. The cost of refusing is one printed act; the cost of permitting
    # is another lane's uuid on an append-only line.
    win_owner=""; wo_rc=0
    win_owner="$("$LANES_EDIT" session-lane "$win_sid" 2>/dev/null)" || wo_rc=$?
    if [ "$wo_rc" != 0 ] && [ "$wo_rc" != 8 ]; then
      note "$LANES_EDIT session-lane $win_sid failed (exit $wo_rc), so whose session is live in this window is NOT known — leaving $LANE's session cell and resume target alone. A helper with no 'session-lane' exits 2; install the one beside this script."
    elif [ "$wo_rc" = 0 ] && [ -n "$win_owner" ] && [ "$win_owner" != "$LANE" ]; then
      note "the session live in THIS window is $win_sid, and the register says it is lane $win_owner's, not $LANE's. A live session that belongs to another row is NEVER taken (R-A11-1): $LANE's session cell and resume target are left exactly as they are. Start $LANE in its own window, or take $win_owner here."
    else
      harness_sid="$win_sid"
      cell_anchor="$row_sid"
      row_sid="$harness_sid"
      note "the session live in THIS window is $harness_sid and the PUBLISHED session cell does not name it: the harness minted a new transcript (a /clear, a usage reset, a profile switch). No other row names it either, so it is this lane's current session, and the cell is stamped with it before the row's status."
    fi
  fi
elif [ -n "$win_sid" ]; then
  step "  it is the session step 3 already found holding $LANE in this window — the cell is current"
fi

# ------------------------------------------------------------- 3c. --confirm
#
# A window whose name is not the lane is a window whose lane came from somewhere
# else — the swap RECORD, or a flag — and taking it renames the window and
# writes the register. `--confirm` puts the three facts that disagree in front
# of a person first: the WINDOW, the SESSION live in it, and the ROW.
#
# NO TERMINAL AND NO `--yes` IS A REFUSAL, exit 2, before the rename and before
# any write. A question nobody can answer is not a Yes, and a launcher that read
# it as one would rename a window somebody else's lane is working in.
if (( confirm )); then
  if [ "$this_window_name" = "$LANE" ]; then
    step "--confirm: this window is already named $LANE — nothing to confirm"
  else
    # AMENDMENT 15 — A WINDOW NAMED FOR THIS LANE IN ANOTHER CASE IS NOT "not
    # the lane". The rename still happens below, because the row's spelling is
    # what the window is named; what changes is the sentence the operator is
    # asked to answer. Told their own lane's window is not the lane, the
    # reasonable answer is N — and N abandons a resume that was legitimate.
    if [ "$(printf '%s' "$this_window_name" | tr 'A-Z' 'a-z')" = "$(printf '%s' "$LANE" | tr 'A-Z' 'a-z')" ]; then
      why="named '$this_window_name', which is THIS LANE under another case — a lane name is ONE name under any case (Amendment 15), and the rename below is to the register row's own spelling, $LANE"
    else
      case "$this_window_name" in
        ""|claude|bash|zsh|sh|node) why="auto-named '${this_window_name:-none}'" ;;
        *)                          why="named '$this_window_name', which is not the lane" ;;
      esac
    fi
    note "--confirm: this window is $why. The three facts, before anything is renamed or written:"
    note "  window   $this_window '${this_window_name:-none}'"
    if [ -n "$win_sid" ]; then
      note "  session  $win_sid '${win_name:-none}' (pid $win_pid, profile ${win_profile:-unknown})"
    else
      note "  session  none — no live session record names this window"
    fi
    if [ "$row_count" = 1 ]; then
      note "  row      ${row:0:200}"
    elif [ -n "$pub_row" ]; then
      pub_row_first="${pub_row%%$'\n'*}"
      note "  row      ${pub_row_first:0:200}"
    else
      note "  row      none — the register has no row for $LANE"
    fi
    answer=""; no_tty=0
    if (( take_yes )); then
      step "Take lane $LANE in this window? [y/N] y   (--yes)"
      answer=y
    elif [ -n "${LANE_START_ANSWER+set}" ]; then
      step "Take lane $LANE in this window? [y/N] ${LANE_START_ANSWER:-<empty>}   (LANE_START_ANSWER)"
      answer="$LANE_START_ANSWER"
    elif [ -t 0 ]; then
      printf '%s: Take lane %s in this window? [y/N] ' "$prog" "$LANE" >&2
      IFS= read -r answer || answer=""
    else
      answer=""
      no_tty=1
    fi
    case "$answer" in
      y|Y|yes|YES|Yes) step "taking lane $LANE in this window" ;;
      *)
        # AMENDMENT 8(c)/(d), R-A8-3 — EVERY ANSWER LEADS SOMEWHERE AND NO
        # ANSWER EXITS. `claude-profile` EXECS this script, so this script's
        # exit status IS the launcher's: a refusal here is an exited pane with
        # no Claude in it, which is the one failure the whole change exists to
        # prevent. `N` means NOT THIS LANE, not NOT AT ALL — and no tty with no
        # `--yes` is the same answer with nobody there to give it, which must
        # still not take a lane on an inference nobody confirmed. Both fall
        # through to Claude, bare: nothing renamed, nothing written, no lane,
        # ONE notice, exit 0. Exit 2 is left to argument errors alone.
        if (( no_tty )); then
          bare_why="--confirm was passed, there is no terminal to ask on, and --yes was not, so lane $LANE is NOT taken in a window $why"
        else
          bare_why="lane $LANE is NOT taken: the answer was '${answer:-<empty, which is N>}'"
        fi
        note "$bare_why. Nothing has been renamed and nothing has been written. Starting Claude with no lane — to take it later, run: $prog $self_args"
        lane_claude_resolve_launch
        bare=("$CLAUDE_BIN" ${pass[@]+"${pass[@]}"})
        if (( no_launch )); then
          # The launcher asked for a command to exec; it gets the bare one, on
          # stdout, exactly as it would have got the lane's.
          quoted "${bare[@]}"; printf '\n'
          step "--no-launch: the command above was printed, not run"
          exit 0
        fi
        if (( dry_run )); then
          plan "exec $(quoted "${bare[@]}")"
          step "--dry-run: nothing was renamed, written or launched"
          exit 0
        fi
        step "exec: $(quoted "${bare[@]}")"
        exec "${bare[@]}"
        ;;
    esac
  fi
fi

# Refuse known local conflicts before resolving or updating Claude, and
# before asking a holder to release its binding.
lane_check_local_fences() {
# Step 3 fetched the published register. Before changing a tmux name, prove
# this identity was not retired (including an unpushed local archive row).
retired_rc=0
retired_hits="$(LANES_NO_FETCH=1 "$LANES_EDIT" retired-identity "$LANE" 2>/dev/null)" || retired_rc=$?
case "$retired_rc" in
  8) : ;;
  0) die "lane $LANE is RETIRED (archive: $retired_hits). Nothing was renamed or written; choose a free position." 2 ;;
  *) die "the lane archive could not be checked for $LANE (exit $retired_rc). Nothing was renamed or written." 1 ;;
esac

# AND A RETIRED ROW THAT IS STILL IN THE REGISTER (opensoft/openRepoTools#138
# item 14). The archive holds a retired row only once `archive-rows` has moved
# it there; until then the row says so itself, and `retired-identity` answers 8
# about it. So the row is asked too — this checkout's copy and the published
# one, either of which may be ahead — and so is the lane's own log: a state
# word of RETIRED, or a last lane-kind line that is RETIRED, is a lane that is
# not coming back, and resuming it would append a STARTED or RESUMED after its
# retirement in a log nothing ever rewrites.
#
# RETIRED ONLY, AND NOT ENDED. `lane-end` is "the window is closing" and
# `--retire` is "the lane is not coming back" (docs/README-lanes.md); a binding
# is released by a PAUSED or an ENDED alike (Amendment 18(b)), `lane` sends a
# closed lane back here to be reopened, and an ENDED lane resumed by this
# command is in the real register. Making ENDED terminal is a ruling's to make.
for retired_row in "$row" "$pub_row"; do
  retired_word="$(printf '%s\n' "$retired_row" | awk -F'|' 'NF > 2 {
    split($(NF - 1), w, " "); if (w[1] == "RETIRED") { print w[1]; exit } }')"
  [ -z "$retired_word" ] ||
    die "lane $LANE's register row says RETIRED, though the archive does not hold it yet: a retired lane is not coming back (opensoft/openRepoTools#138 item 14). Nothing was renamed or written; choose a free position." 2
done
retired_last_rc=0
retired_last="$(LANES_NO_FETCH=1 "$LANES_EDIT" lane-last "$LANE" 2>/dev/null)" || retired_last_rc=$?
retired_verb="$(printf '%s\n' "$retired_last" | cut -f1)"
case "$retired_last_rc:$retired_verb" in
  0:RETIRED)
    die "lane $LANE's object log ends on its RETIRED line, though the archive does not hold it yet: a retired lane is not coming back (opensoft/openRepoTools#138 item 14). Nothing was renamed or written; choose a free position." 2 ;;
  0:* | 8:*) : ;;
  *) die "\`$LANES_EDIT lane-last $LANE\` exited $retired_last_rc, so whether lane $LANE's log ends on RETIRED could NOT be read — and that is not 'it does not' (Amendment 7(d)). Nothing was renamed or written." 1 ;;
esac

# A lane name is a tmux-window address. tmux itself allows two distinct
# windows to carry one name, so check the whole server before taking it. A
# linked window may appear in several sessions with the same @id; that is one
# window, not a collision.
#
# ASKED OF A NEW LANE ONLY — one with no row — because only there is every
# other window carrying the name certainly FOREIGN: nothing has bound that lane
# yet. An EXISTING lane's own binding is different since Amendment 18 (#83):
# a bench in another container shares this tmux server, its window keeps the
# lane's name until that session hands off, and a second place binding the
# lane after a release, or through `--request-handoff`, is the ratified flow.
# Asked of every lane, this fence refused exactly that takeover.
if [ "$row_count" = 0 ]; then
  window_named_lane ||
    die "tmux could not list window names, so whether $LANE is already in use is unknown. Nothing was renamed or written." 2
  [ -z "$WNL_ID" ] ||
    die "another tmux window ($WNL_ID) is already named $WNL_NAME, and $LANE is a NEW lane, so that window is not its own. Lane window names must be unique in this tmux server; nothing was renamed or written." 2

  # AND THIS WINDOW'S OWN NAME (opensoft/openRepoTools#138 item 16). The scan
  # above skips this window, so a NEW lane started from a stale or reused
  # window still named for ANOTHER registered lane would rename it and take
  # that lane's tmux address. Only a name no row carries is reusable: `claude`,
  # a shell, or a string `check_lane_name` refuses, which no row can carry.
  # Both copies of the register are asked, because a row this checkout has not
  # pushed already owns its window, and a read that fails refuses.
  case "$this_window_name" in
    "" | *[!A-Za-z0-9._-]* | .* | -*) : ;;
    *)
      if [ "$(printf '%s' "$this_window_name" | tr 'A-Z' 'a-z')" != "$(printf '%s' "$LANE" | tr 'A-Z' 'a-z')" ]; then
        for own_read in register-row register-row-local; do
          own_rc=0
          LANES_NO_FETCH=1 "$LANES_EDIT" "$own_read" "$this_window_name" >/dev/null 2>&1 || own_rc=$?
          case "$own_rc" in
            8) : ;;
            0) die "this window is named $this_window_name, which is another lane the register has a row for (\`$own_read\`), and $LANE is a NEW lane: renaming the window would take that lane's tmux address (opensoft/openRepoTools#138 item 16). Start $LANE in a window of its own. Nothing was renamed or written." 2 ;;
            *) die "\`$LANES_EDIT $own_read $this_window_name\` exited $own_rc, so whether this window is another lane's could NOT be read — and that is not 'it is not' (Amendment 7(d)). Nothing was renamed or written." 1 ;;
          esac
        done
      fi ;;
  esac
fi
}
# The first window OTHER than this one that this tmux server names $LANE, in
# any case, into WNL_ID and WNL_NAME (both empty where there is none); 1 where
# tmux could not list the windows. The fence above asks it before the rename,
# and step 4 asks it again after.
window_named_lane() {
  WNL_ID=""; WNL_NAME=""
  wnl_tab="$(printf '\t')"
  wnl_rows="$(tmux list-windows -a -F "#{window_id}${wnl_tab}#{window_name}" 2>/dev/null)" || return 1
  while IFS="$wnl_tab" read -r wnl_id wnl_name; do
    [ -n "$wnl_id" ] || continue
    if [ "$wnl_id" != "$this_window_id" ] &&
       [ "$(printf '%s' "$wnl_name" | tr 'A-Z' 'a-z')" = "$(printf '%s' "$LANE" | tr 'A-Z' 'a-z')" ]; then
      WNL_ID="$wnl_id"; WNL_NAME="$wnl_name"
      return 0
    fi
  done <<EOF
$wnl_rows
EOF
  return 0
}
lane_check_local_fences

# ------------- 3b(ii). AMENDMENT 18(b): ONE BINDING PER LANE, AND THIS PLACE
#
# *"A bound lane is started nowhere else — not a second window on the same host,
# not another container, not another host — until its binding is released by a
# `PAUSED` (its own, or one written under (e)) or ended. Liveness is pronounced
# only from INSIDE the binding's own `host` and `container`, where the pid
# namespace is the record's: from anywhere else a binding is UNKNOWN, never
# dead, whatever `kill -0` says."* Ratified 2026-09-14T13:15:18Z as revision 4;
# opensoft/openRepoTools#38.
#
# THIS IS A SECOND FENCE AND NOT A REPLACEMENT FOR STEP 3. Step 3 asks whether a
# session the ROW names is alive and answers out of THIS workstation's session
# records — which is exactly the read that cannot cross a container seam, and
# exactly why it said NOT LIVE about a lane cloudBench was writing. So where the
# binding IS this host's and this container's, step 3 has already pronounced and
# nothing changes; where it is NOT, this fence refuses whatever `kill -0` said,
# because the record it read is from another pid namespace.
#
# THE ONE EXCEPTION IS THE WINDOW, and the helper has already applied it: on one
# host the launcher mounts ONE tmux socket into every container it starts, so a
# binding whose `@id` no longer resolves there — matched by Amendment 11(h)'s
# agreement rule, the id TOGETHER with its session — is DEAD, and Amendment
# 6(d)'s retire act and opensoft/openRepoTools#30's takeover path apply as they
# stand. That is the `gone` the read answers with, and it is answered only where
# the HOST matches, because a window id from another machine resolving here
# would be a coincidence.
#
# A HELPER PREDATING THIS READ FALLS THROUGH WITH A NOTE, exactly as clause
# (h)'s other reads do: refusing every lane start on every workstation that has
# not taken the install yet is not a safety property. Every OTHER code is a read
# that did not happen, and this one fails CLOSED — a binding that could not be
# read is not a lane that is free, and the cost of guessing here is two sessions
# writing one append-only log.
bind_out=""; bind_rc=0; bind_recheck=0
: > "$LS_TMP"
bind_out="$("$LANES_EDIT" binding "$LANE" 2>"$LS_TMP")" || bind_rc=$?
case "$bind_rc" in
  0) [ -s "$LS_TMP" ] && cat -- "$LS_TMP" >&2 ;;
  8) [ -s "$LS_TMP" ] && cat -- "$LS_TMP" >&2
     step "no binding: lane $LANE's last lane-kind line released it, or it has none (Amendment 18(b)) — nothing to ask" ;;
  2) [ -s "$LS_TMP" ] && cat -- "$LS_TMP" >&2
     note "this \`lanes-edit.sh\` has no \`binding\` (exit 2), so whether lane $LANE is bound somewhere else is NOT known here. Install the one beside this script (\`openRepoTools --install\`); carrying on with step 3's liveness read alone, which cannot see another container." ;;
  *) [ -s "$LS_TMP" ] && cat -- "$LS_TMP" >&2
     die "$LANES_EDIT binding $LANE exited $bind_rc, so where this lane is bound could NOT be read — and that is not 'it is bound nowhere'. A lane has ONE binding (Amendment 18(b)); nothing has been renamed, written or launched." 1 ;;
esac
if [ "$bind_rc" = 0 ]; then
  IFS=$'\t' read -r b_host b_cont b_win b_utc b_sess b_os b_where b_wstate <<<"$bind_out"
  if [ "$b_where" = here ]; then
    step "binding: this host ($b_host) and container ($b_cont), window $b_win since $b_utc — liveness here is this place's to pronounce, and step 3 has (Amendment 18(b))"
  elif [ "$b_wstate" = gone ]; then
    note "lane $LANE's binding is window $b_win in container $b_cont on host $b_host (since $b_utc), and that window is GONE from this tmux server — the pane a session must live in does not exist. That is the ONE case in which a binding elsewhere reads DEAD (Amendment 18(b)), because one host's launcher mounts one tmux socket into every container it starts. Carrying on: this is Amendment 6(d)'s retire act and openRepoTools#30's takeover path, unchanged."
  else
    # ---- CLAUSE (c): THE SECOND PLACE ASKS, AND NEVER TAKES.
    ls_bind_facts="lane $LANE is bound to window ${b_win:-none} in container ${b_cont:-none} on host ${b_host:-unknown} (session ${b_sess:-unknown}, last line ${b_utc:-unknown}); this tmux server says that window is ${b_wstate:-unknown}"
    ls_ask=0
    if [ -n "$force_why" ]; then
      ls_ask=force
    elif (( request_handoff )); then
      ls_ask=yes
    elif [ -n "${LANE_START_HANDOFF_ANSWER+set}" ]; then
      step "$ls_bind_facts"
      step "ask it to hand off, then bind here? [y/N] ${LANE_START_HANDOFF_ANSWER:-<empty>}   (LANE_START_HANDOFF_ANSWER)"
      case "$LANE_START_HANDOFF_ANSWER" in y|Y|yes|YES|Yes) ls_ask=yes ;; *) ls_ask=no ;; esac
    elif [ -t 0 ]; then
      note "$ls_bind_facts"
      printf '%s: ask it to hand off, then bind here? [y/N] ' "$prog" >&2
      IFS= read -r ls_answer || ls_answer=""
      case "$ls_answer" in y|Y|yes|YES|Yes) ls_ask=yes ;; *) ls_ask=no ;; esac
    else
      ls_ask=no-terminal
    fi
    if [ "$ls_ask" = no ] || [ "$ls_ask" = no-terminal ]; then
      ls_flag="Ask it to hand off — the request is written to the lane's log, pushed, and typed into that pane where it is on this tmux server:
      $prog --request-handoff $self_args"
      [ "$ls_ask" = no-terminal ] || ls_flag="Ask it to hand off:
      $prog --request-handoff $self_args"
      ls_why="a lane has ONE binding, and this is not it (Amendment 18(b))"
      [ "$ls_ask" = no-terminal ] && ls_why="$ls_why. There is no terminal on stdin to ask on — an agent's stdin is not one — so the flag is the answer"
      die "$ls_bind_facts.
    $ls_why. Nothing has been renamed, written or launched. Liveness is
    pronounced only from inside that binding's own host and container, so from
    here it is UNKNOWN and never dead, whatever a \`kill -0\` of a pid in
    another namespace would say.
      $ls_flag
      or take it anyway, which is a SECOND invocation and never automatic, and
      which makes that place STOP loudly rather than silently:
      $prog --force \"<why you are taking it>\" $self_args" 2
    fi
    # Approval precedes any possible update; resolution precedes release.
    # With no explicit agent the holder's new PAUSED may name Claude, so
    # preflight that possible launch before asking it to give up the binding.
    # An explicit other agent never needs a Claude preflight.
    if [ -z "$agent_flag" ] || [ "$agent_flag" = claude ]; then
      lane_claude_resolve_launch
    fi
    ls_rh=("$LANES_EDIT" request-handoff "$LANE")
    [ -z "$win_sid" ] || ls_rh+=(--session "$win_sid")
    if [ "$ls_ask" = force ]; then
      ls_rh+=(--force "$force_why")
    else
      ls_rh+=(--wait "$handoff_wait")
    fi
    (( dry_run )) && ls_rh+=(--dry-run)
    step "$(quoted "${ls_rh[@]}")"
    ls_rh_rc=0
    "${ls_rh[@]}" || ls_rh_rc=$?
    case "$ls_rh_rc" in
      0) bind_recheck=1; step "lane $LANE is free — binding it here (Amendment 18(c))" ;;
      8) bind_recheck=1; step "lane $LANE was already free by the time the request was made — binding it here" ;;
      2) die "the handoff was not obtained (the helper's own facts and its \`--force\` line are above), so lane $LANE is still bound elsewhere and NOTHING here has been renamed, written or launched." 2 ;;
      *) die "$LANES_EDIT request-handoff $LANE exited $ls_rh_rc, which is neither 'the lane is free' nor the refusal that says it is not — nothing here has been renamed, written or launched." 1 ;;
    esac
  fi
fi

# The successful handoff may have published a different agent in its PAUSED
# record. Read that authoritative answer now, before rename or transcript movement.
AGENT=""; AGENT_EXPLICIT=0; AGENT_ID=""; RECORDED_AGENT=""; RECORDED_AGENT_READ=0
read_recorded_agent() {
  rra_out=""; rra_rc=0
  rra_out="$("$LANES_EDIT" lane-agent "$LANE" 2>/dev/null)" || rra_rc=$?
  RECORDED_AGENT_READ=1
  case "$rra_rc" in
    0) RECORDED_AGENT="$rra_out" ;;
    8|2) RECORDED_AGENT="" ;;
    # A READ THAT FAILED IS NOT "THIS LANE'S RECORD NAMES NO AGENT", and the
    # helper says so in its own refusal: *"a caller that read it that way would
    # launch the default agent over a lane another one paused"* (Amendment
    # 7(d), `lanes-edit.sh`'s `lane-agent` arm). This used to `note` and launch
    # `claude` anyway — the one act in this whole command that no later refusal
    # can undo — so it refuses, and names the flag that goes past it, which is
    # a person naming the agent rather than this command guessing at one.
    *) die "\`$LANES_EDIT lane-agent $LANE\` failed (exit $rra_rc), so which agent paused this lane is UNKNOWN — and launching the default over a lane another agent paused is what Amendment 7(d) has this read refuse rather than answer. Run it by hand to see what it says, or name the agent: $prog --agent <name> …" 2 ;;
  esac
  return 0
}
if [ -n "$bind_sid" ]; then
  # THE BINDING MODE BINDS THE CLAUDE SESSION THE GUARD IS RUNNING IN
  # (openRepoTools#70), whichever agent last paused this lane: the launcher
  # table below would otherwise stamp `<agent> pending` for a session that is
  # plainly here and plainly Claude.
  AGENT=claude
elif [ -n "$agent_flag" ]; then
  AGENT="$agent_flag"; AGENT_EXPLICIT=1
else
  read_recorded_agent
  if [ -n "$RECORDED_AGENT" ]; then AGENT="$RECORDED_AGENT"; fi
  [ -n "$AGENT" ] || AGENT=claude
  [ "$AGENT" = claude ] || AGENT_EXPLICIT=1
fi
case "$AGENT" in
  *[!A-Za-z0-9._-]*|'') die "--agent takes a manifest key — letters, digits, '.', '_', '-' — and '$AGENT' is not one (Amendment 17(b))" 2 ;;
esac
# THE AGENT THIS LANE IS RUNNING, IN THE ENVIRONMENT OF THE SESSION IT STARTS
# (Copilot round 2 on openRepoTools#47). `lane-handoff` derives the record's
# `agent` sub-field from `$LANES_AGENT`, else `claude` — so a `codex` session
# launched here would write `agent claude` at its own handoff and the next
# `lane-start` would resume it with the wrong launcher, one record along. The
# launch decides which agent this is; the launch is therefore what says so.
export LANES_AGENT="$AGENT"
if [ "$AGENT" = claude ]; then
  lane_claude_resolve_launch
fi

# ------------------------------------------------------- 4. name the window

# Resolver work can take time. Preserve the final read too, so a retirement
# or new window collision during that wait still refuses before rename.
lane_check_local_fences

# ---------------- 3d. AND THE BINDING IS READ AGAIN BEFORE THE FIRST ACT
#
# A HANDOFF THAT LANDED IS AN OBSERVATION AND NOT A RESERVATION (Copilot round 1
# on opensoft/openRepoTools#83). `request-handoff` returns 0 when it SEES the
# release; between that and the rename, the row status, the log line and the
# launch, another place waiting on the same release can bind the lane — and
# `commit_push` rebases both append-only writes rather than refusing the second,
# so the log would carry two bindings and no reader could say which is the
# lane's.
#
# NOTHING IN THE RATIFIED TEXT GIVES A LANE A RESERVATION, and inventing one
# here would be an unratified act on an in-force protocol — it is filed rather
# than smuggled in (opensoft/openRepoTools#84). What IS available is to make the
# read the LAST thing before the first act instead of the first thing in the
# run: the window between them is then one read wide rather than a question, a
# rename, two register writes and a launch wide, and a lane that moved in it is
# a refusal naming where it went rather than a second binding written over it.
#
# A RESOLVER MAY WAIT TOO: another start can bind while this one waits for
# the update lock or npm. Recheck after resolution, immediately before rename,
# including an initially free binding. An unchanged existing binding remains
# valid; an observed release or replacement is not this invocation's binding.
# AND A DRY RUN HAS NOTHING TO RE-READ, BECAUSE IT DID NOTHING (Copilot round 3
# on opensoft/openRepoTools#83). `request-handoff --dry-run` prints its plan and
# answers 0 WITHOUT releasing anything, so an unconditional re-read here sees the
# binding still standing and refuses — and `lane-start --dry-run
# --request-handoff`, whose whole job is to print the plan, could never print
# one. A plan is a statement about what WOULD happen; the fence that protects
# the first act belongs to the run that takes it.
bind_waited="$bind_recheck"
bind_expected_rc="$bind_rc"; bind_expected_out="$bind_out"
if [ "$bind_recheck" = 1 ]; then
  bind_expected_rc=8; bind_expected_out=""
fi
[ "$lane_claude_checked" = 0 ] || bind_recheck=1
if [ "$bind_recheck" = 1 ] && (( dry_run )); then
  plan "read the binding again before the rename, and refuse if the lane moved while this run was taking it"
  bind_recheck=0
fi
if [ "$bind_recheck" = 1 ]; then
  : > "$LS_TMP"
  bind_again=""; bind_again_rc=0
  bind_again="$("$LANES_EDIT" binding "$LANE" 2>"$LS_TMP")" || bind_again_rc=$?
  [ -s "$LS_TMP" ] && cat -- "$LS_TMP" >&2
  case "$bind_again_rc" in
    8) [ "$bind_expected_rc" = 8 ] ||
         die "lane $LANE's binding changed while Claude was resolved: it is now released. Nothing here was renamed or bound; retry against the current record." 2
       if [ "$bind_waited" = 1 ]; then
         step "binding: still free after the handoff — taking it"
       else
         step "binding: still free after Claude resolution — taking it"
       fi ;;
    0)
      if [ "$bind_expected_rc" = 0 ] && [ "$bind_again" = "$bind_expected_out" ]; then
        step "binding: unchanged after Claude resolution"
      else
        IFS=$'\t' read -r ba_host ba_cont ba_win ba_utc ba_sess ba_os ba_where ba_wstate <<<"$bind_again"
        # A NEW OR CHANGED BINDING IS THE RACE, INCLUDING ONE IN THIS WINDOW.
        # This invocation wrote no STARTED/RESUMED yet. An unchanged prior
        # binding was accepted above; this one appeared during the wait.
        die "lane $LANE was BOUND AGAIN or changed while this run was taking it: it is now window ${ba_win:-none} in container ${ba_cont:-none} on host ${ba_host:-unknown} (session ${ba_sess:-unknown}, ${ba_utc:-unknown}). This run observed a free or earlier binding before its wait, and another binding now stands before its first act. This run has written no binding of its own yet, so that one is not this invocation's: a binding at THIS window is a second invocation IN it, which is the same race one pane closer. Nothing has been renamed, written or launched. Ask again, or take it up with that place:
      $prog --request-handoff $self_args" 2
      fi ;;
    2) [ "$bind_expected_rc" = 2 ] ||
         die "the binding could not be rechecked after Claude resolution (exit 2). Nothing here was renamed or bound." 1
       note "this \`lanes-edit.sh\` has no \`binding\`, so whether the lane moved again while this run waited is not known here; carrying on." ;;
    *) die "$LANES_EDIT binding $LANE exited $bind_again_rc on the re-read before the rename, so whether this lane is still free could NOT be established — and that is not 'it is'. Nothing has been renamed, written or launched." 1 ;;
  esac
fi

if (( dry_run )); then
  plan "tmux rename-window $LANE   (also turns automatic-rename off for this window)"
else
  win_auto_was=""
  [ "$row_count" != 0 ] || win_auto_was="$(tmux show-options -w -v automatic-rename 2>/dev/null || :)"
  tmux rename-window "$LANE"
  step "window renamed to $LANE (automatic-rename is now off for it)"
fi

# AND A NEW LANE'S NAME IS READ BACK (opensoft/openRepoTools#138 item 3). The
# fence's scan and the rename above are two tmux commands with nothing reserving
# the name between them, so two NEW-lane starts in two windows could both find
# it free and both take it — and the register's lock, which comes after, cannot
# undo a rename. Nothing here invents a reservation (#84: that is a ruling's to
# make); the rename is checked instead. tmux runs one command at a time, so of
# two starts that each rename and then list, the later list always sees the
# earlier rename: at most one keeps the name, and both refusing is the
# fail-closed answer. A list that fails is not a name that is free. A refusal
# gives THIS window back its name and its automatic-rename, so nothing of this
# run is left behind it.
if (( ! dry_run )) && [ "$row_count" = 0 ]; then
  rb_why=""
  if ! window_named_lane; then
    rb_why="tmux could not list the windows after the rename, so whether another window took $LANE as well is unknown"
  elif [ -n "$WNL_ID" ]; then
    rb_why="after the rename another tmux window ($WNL_ID) is named $WNL_NAME too: a second start took this NEW lane's name between this run's check and its rename"
  fi
  if [ -n "$rb_why" ]; then
    # NO NAME TO GO BACK TO IS NO UNDO: where tmux answered `#W` with nothing,
    # nothing here can name this window back, and the refusal says so rather
    # than claiming an undo it did not make.
    rb_undo="This window's rename could NOT be undone, because its earlier name is not known — rename it yourself: tmux rename-window <its name>"
    if [ -n "$this_window_name" ]; then
      if tmux rename-window "$this_window_name" 2>/dev/null; then
        rb_undo="This window's rename is undone"
      else
        rb_undo="This window's rename could NOT be undone — rename it back yourself: tmux rename-window $this_window_name"
      fi
    fi
    case "$win_auto_was" in
      "") tmux set-option -w -u automatic-rename 2>/dev/null || : ;;
      on) tmux set-option -w automatic-rename on 2>/dev/null || : ;;
    esac
    die "$rb_why (opensoft/openRepoTools#138 item 3). $rb_undo, and nothing has been written or launched. Lane window names are unique in a tmux server; settle which window is $LANE and re-run there." 2
  fi
fi

# ------------------------------------------------- 5a. what will be launched
#
# Decided BEFORE the row is written: a brand-new session's id is minted here
# and step 5 has to record it.

# Claude keeps one transcript directory per working directory, named by that
# path with every non-alphanumeric character turned into '-'. A lane reached
# through a symlink has two spellings, so both are searched.
sanitize() { printf '%s' "$1" | tr -c 'A-Za-z0-9' '-'; }

transcript_dirs() {
  printf '%s\n' "$PROJECTS_STATE/$(sanitize "$DIR")"
  [ "$DIR_REAL" = "$DIR" ] || printf '%s\n' "$PROJECTS_STATE/$(sanitize "$DIR_REAL")"
}

# ===================== AMENDMENT 17, adoption act 6: THE TRANSCRIPT FOLLOWS
# ===================== THE LANE
#
# `transcript_dirs` above looks under THIS PROFILE's projects directory and
# nowhere else, so a lane restarted under a NEW PROFILE after a usage limit
# never resumed its conversation: it fell to the title fallback or to a new
# session primed by a handoff the stuck session never refreshed.
#
# MEASURED FIRST, AND THE FACT SHRANK THE ACT (opensoft/openRepoTools#36, the
# correction of 2026-09-14T12:35Z): on a launcher-configured workstation EVERY
# profile's `projects/` is ONE shared directory —
# `readlink -f ~/.claude-profiles/profiles/<org>/<team>/<any>/projects` →
# `~/.claude-profiles/state/opensoft/projects` — so a transcript needs NO MOVE
# to be resumed under another profile, and the whole act there is to SAY SO.
# The move is for the workstation without that layout, where the two
# directories are really two.
#
# WHY A MOVE AND NEVER A COPY: two live transcripts of one uuid diverge, and
# nothing merges them. The pointer left behind says where it went.
# THE PROFILE STORE'S ROOT IS THE DOCUMENTED ONE, NEVER `~/.claude-profiles`
# SPELLED AGAIN (Copilot round 1 on openRepoTools#47). `$CLAUDE_PROFILES_HOME`
# is in this repository's README table and is what `lanes-edit.sh`'s own profile
# walk reads (`lanes-edit.sh:4381`); a second spelling here is a second answer
# to "where are this person's profiles", and on a workstation that moved the
# store it is the WRONG one — every scan below would find nothing, and a lane
# resumed under another profile would start a new conversation beside a
# transcript that was there all along.
PROFILES_HOME="${CLAUDE_PROFILES_HOME:-$HOME/.claude-profiles}"

profile_projects_dirs() {
  # This profile's own first, then every other profile's. Team profiles sit two
  # levels down, which is the same shape `lanes-edit.sh`'s `session_files` walks
  # for the sessions beside them.
  printf '%s\n' "$PROJECTS_STATE"
  for ppd_d in "$PROFILES_HOME"/profiles/*/*/*/projects \
               "$PROFILES_HOME"/profiles/*/*/projects \
               "$PROFILES_HOME"/profiles/*/projects \
               "$CLAUDE_HOME"/projects; do
    [ -d "$ppd_d" ] && printf '%s\n' "$ppd_d"
  done
}

# THE PHYSICAL PATH, WITHOUT `readlink -f` — which is not in the stock macOS
# userland (Copilot round 1 on openRepoTools#47), where it exits 1 and a
# fallback hands the path back UNRESOLVED. Two spellings of ONE directory then
# compare as two directories, and the shared-`projects/` case below — which on
# a launcher-configured workstation is EVERY case — would move a transcript
# that never needed moving, on the platform this suite's own macOS job runs.
# `cd -P` + `pwd -P` is the shell's own answer and is in every shell that
# parses this file. A path that is not a directory comes back as it was given,
# which is what the `readlink -f` fallback did.
real_of() { ( CDPATH=''; cd -P -- "$1" 2>/dev/null && pwd -P ) || printf '%s\n' "$1"; }
# THE HANDOFF'S DIGEST, spelled exactly as `lanes-edit.sh` spells it, because
# the two are compared: this file is what the intent recorded and what a launch
# verifies, and two implementations of one digest is one implementation too
# many. `none` where the workstation has neither tool — an ANSWER, meaning *not
# checked here*, never *unchanged*.
handoff_digest_of() {   # <file>
  [ -r "${1-}" ] || { printf 'none\n'; return 0; }
  if command -v sha256sum >/dev/null 2>&1; then
    sha256sum -- "$1" 2>/dev/null | awk '{print $1; exit}'
  elif command -v shasum >/dev/null 2>&1; then
    shasum -a 256 -- "$1" 2>/dev/null | awk '{print $1; exit}'
  else
    printf 'none\n'
  fi
}

profile_of_projects_dir() {   # <…/<profile>/projects> -> the profile's name
  popd_d="${1%/projects}"; popd_n="${popd_d##*/}"
  case "$popd_n" in .claude|claude|"") printf 'default\n' ;; *) printf '%s\n' "$popd_n" ;; esac
}

# The transcript of one id under ONE projects directory, in either spelling of
# the lane's path (a lane reached through a symlink has two).
transcript_under() {   # <projects dir> <id>
  tu_d="$1"; tu_id="$2"
  for tu_s in "$(sanitize "$DIR")" "$(sanitize "$DIR_REAL")"; do
    [ -f "$tu_d/$tu_s/$tu_id.jsonl" ] && { printf '%s\n' "$tu_d/$tu_s/$tu_id.jsonl"; return 0; }
  done
  return 1
}

# EVERY LIVE HOLDER OF AN ID, ACROSS EVERY PROFILE'S `sessions/` (Amendment
# 18(h), in force 2026-09-14T13:15:18Z: *"A transcript (one session id) is held
# by ONE live process"*). WHO IS LIVE IS `lanes-edit.sh`'s ONE ANSWER AND NOT A
# SECOND ONE HERE (opensoft/openRepoTools#56). This function used to read the
# records itself and test the pid with `kill -0` ALONE — one of the three tests
# `record_is_live` makes, not three — so a record that had ENDED, or whose pid
# had been RECYCLED onto some other process, read as a live holder and refused a
# transcript's follow with *"a LIVE process there holds it"* and the retire act,
# about a process that is not that session. `lanes-edit.sh transcript-holders`
# (opensoft/openRepoTools#52) is that read, on `record_is_live` — status not
# ended, the pid answers, and `procStart` is still the one the record wrote down
# — across every profile through `session_files`, and `dup_check` above already
# asks it; this asks it the same way and reads its exits the same way.
#
# EVERY ROW IT PRINTS IS A HOLDER HERE, WHATEVER ITS VERDICT. The verdict says
# what THIS WINDOW's relation to the holder is, which is `dup_check`'s question;
# the question at this call is narrower and older — *is any live process holding
# the id this run is about to move out of another profile* — and the move is
# wrong for a `companion` or a `here` record just as it is for a `duplicate`.
# The row's format is the contract this reads (`pid US kind US tgt US profile US
# where US verdict US file`), and the verdict stays the helper's to change.
#
# IT SETS `LIVE_HOLDERS` — `<pid><TAB><tmux target, or bg><TAB><profile>` per
# holder, one to a line — AND PRINTS NOTHING, and it is never called inside
# `$( )`: a refusal is `FOLLOW_WHY`, and a subshell would keep it to itself (the
# reason `follow_transcript` states beside its own variables). Returns 0 with
# the holders read (none is an answer), 2 where they could not be.
LIVE_HOLDERS=""
live_holders_of_id() {   # <id>
  lho_id="$1"; LIVE_HOLDERS=""; lho_rc=0; lho_rows=""
  lho_tab=$'\t'; lho_nl='
'
  : > "$LS_TMP"
  lho_rows="$("$LANES_EDIT" transcript-holders "$lho_id" 2>"$LS_TMP")" || lho_rc=$?
  case "$lho_rc" in
    0) : ;;
    8) return 0 ;;
    2) [ -s "$LS_TMP" ] && cat -- "$LS_TMP" >&2
       note "this \`lanes-edit.sh\` has no \`transcript-holders\` (exit 2), so whether a live process already holds transcript $lho_id is NOT known here. Install the one beside this script (\`openRepoTools --install\`); carrying on."
       return 0 ;;
    *) [ -s "$LS_TMP" ] && cat -- "$LS_TMP" >&2
       FOLLOW_WHY="$LANES_EDIT transcript-holders $lho_id exited $lho_rc, so whether a live process holds that transcript could NOT be read — and that is not 'none does'. A transcript is held by ONE live process (Amendment 18(h)): nothing was moved and nothing was launched."
       return 2 ;;
  esac
  while IFS=$'\037' read -r lho_pid lho_kind lho_tgt lho_prof lho_where lho_verdict lho_file; do
    [ -n "${lho_pid:-}" ] || continue
    # The raw tmux target, and `bg` where the record names none (`transcript-holders`
    # writes `none`) — what this said before it asked the helper.
    case "${lho_tgt:-none}" in none) lho_tgt=bg ;; esac
    LIVE_HOLDERS="${LIVE_HOLDERS:+$LIVE_HOLDERS$lho_nl}$lho_pid$lho_tab$lho_tgt$lho_tab${lho_prof:-}"
  done <<<"$lho_rows"
  return 0
}

# PUTTING THE MOVE BACK. The transaction below is three writes, and the two
# after the first each undo what came before them rather than leave a
# transcript split across two profiles. It reads `follow_transcript`'s own
# `ft_*` variables — one act, one set of names — and PRINTS what it could not
# undo rather than returning a code, because a rollback that itself failed is
# the one state nobody can infer from the outside and the refusal has to say it.
ft_rollback() {
  ftr_out=""
  if [ "${ft_moved_sib:-0}" = 1 ]; then
    mv -- "$ft_dest_dir/$ft_id" "$ft_sib" 2>/dev/null ||
      ftr_out="the sibling directory is at $ft_dest_dir/$ft_id and could not be put back to $ft_sib"
  fi
  mv -- "$ft_dest_dir/$ft_id.jsonl" "$ft_f" 2>/dev/null ||
    ftr_out="${ftr_out:+$ftr_out; }the transcript is at $ft_dest_dir/$ft_id.jsonl and could not be put back to $ft_f"
  printf '%s' "$ftr_out"
  return 0
}

# THE SEARCH, THE SAY AND THE MOVE. Sets `FOLLOW_FILE` (the transcript's path
# HERE, after any move) and `FOLLOW_WHY` (a refusal), and returns 0 found, 8
# nowhere, 2 refused. IT NEVER `die`s: a refusal inside `$( )` kills only the
# substitution's subshell, and the caller would carry on with an empty answer —
# which here would mean starting a second process on a transcript another live
# one holds.
FOLLOW_FILE=""; FOLLOW_WHY=""
follow_transcript() {   # <id>
  ft_id="$1"; FOLLOW_FILE=""; FOLLOW_WHY=""
  ft_here_real="$(real_of "$PROJECTS_STATE")"
  ft_shared=""
  while IFS= read -r ft_d; do
    [ -n "$ft_d" ] || continue
    [ "$ft_d" = "$PROJECTS_STATE" ] && continue
    ft_real="$(real_of "$ft_d")"
    if [ "$ft_real" = "$ft_here_real" ]; then
      # THE SHARED-DIRECTORY CASE, which on a launcher-configured workstation is
      # every case: the other profile's `projects/` IS this one, so the
      # transcript is already here and nothing is moved.
      ft_shared="${ft_shared:+$ft_shared }$(profile_of_projects_dir "$ft_d")"
      continue
    fi
    ft_f="$(transcript_under "$ft_d" "$ft_id" 2>/dev/null || :)"
    [ -n "$ft_f" ] || continue
    ft_prof="$(profile_of_projects_dir "$ft_d")"
    # A UUID WHOSE HOLDER IS LIVE THERE IS A REFUSAL, NEVER A MOVE (Amendment
    # 18(h)): moving the file out from under a running process, and then
    # resuming the same id here, is two live processes on one transcript — the
    # state measured on this lane on 2026-09-14 and the reason that clause
    # exists.
    # NOT `$( )`: `live_holders_of_id` sets `FOLLOW_WHY` when the holders cannot
    # be read, and a subshell would keep the refusal to itself.
    ft_hrc=0
    live_holders_of_id "$ft_id" || ft_hrc=$?
    [ "$ft_hrc" = 0 ] || return "$ft_hrc"
    ft_holders="$LIVE_HOLDERS"
    if [ -n "$ft_holders" ]; then
      FOLLOW_WHY="transcript $ft_id is in profile $ft_prof's projects directory ($ft_d) and a LIVE process there holds it:
$(printf '%s\n' "$ft_holders" | sed 's/^/      pid /; s/\t/ in /; s/\t/ under profile /')
    A transcript is held by ONE live process (Amendment 18(h)): moving it here and resuming the id would make a second. Nothing was moved and nothing was launched.
    End that process, or retire it: lane-end $LANE --retire <pid>"
      return 2
    fi
    # THE MOVE: the `<uuid>.jsonl` and its sibling `<uuid>/` directory, into the
    # SAME slug under this profile, with a pointer left where it was.
    ft_dest_dir="$PROJECTS_STATE/$(basename -- "$(dirname -- "$ft_f")")"
    ft_sib="${ft_f%.jsonl}"
    # `--dry-run` MOVES NOTHING (Copilot round 1 on openRepoTools#47). This
    # function runs long before the dry-run exit at the foot of the script, and
    # a command whose last line is *nothing was renamed, written or launched*
    # must not have moved a person's transcript out of another profile to get
    # there. The plan is printed with both paths instead, and the caller says
    # what it would have followed.
    if (( dry_run )); then
      plan "mv $ft_f $ft_dest_dir/$ft_id.jsonl (with its sibling $ft_id/, and a pointer left where it was)"
      FOLLOW_WHY="dry-run:transcript $ft_id is in profile $ft_prof's projects directory ($ft_d) and WOULD be moved into $ft_dest_dir"
      return 8
    fi
    mkdir -p -- "$ft_dest_dir" 2>/dev/null || {
      FOLLOW_WHY="could not create $ft_dest_dir to move transcript $ft_id into"; return 2; }
    # AN OCCUPIED DESTINATION IS REFUSED BEFORE ANYTHING MOVES (Copilot round 3
    # on openRepoTools#47). `mv <dir> <existing dir>` does not fail — it moves
    # the source INSIDE it — so a `<uuid>/` already sitting here would take the
    # other profile's sidecar as `<uuid>/<uuid>/`, mark the sibling moved, and
    # resume with the transcript's state split from the transcript. Nothing this
    # command writes is worth guessing which of two `<uuid>` directories is the
    # lane's, so it names what is there and stops. A name that is NOT a
    # directory is left to the transaction below, where `mv` really does fail
    # and the rollback puts the transcript back.
    if [ -d "$ft_dest_dir/$ft_id" ] || [ -e "$ft_dest_dir/$ft_id.jsonl" ]; then
      FOLLOW_WHY="transcript $ft_id is in profile $ft_prof's projects directory ($ft_d), and something ALREADY SITS where it would go: $ft_dest_dir/$ft_id$( [ -e "$ft_dest_dir/$ft_id.jsonl" ] && printf '.jsonl' ). Nothing was moved — a move onto an occupied name puts one transcript inside another, and which of the two is this lane's is not this command's to guess. Move that aside, or end the lane that owns it."
      return 2
    fi
    if ! mv -- "$ft_f" "$ft_dest_dir/$ft_id.jsonl" 2>/dev/null; then
      FOLLOW_WHY="could not move $ft_f into $ft_dest_dir (the transcript stays where it is, and this lane will not resume an id it cannot read)"
      return 2
    fi
    # THE THREE WRITES ARE ONE TRANSACTION (Copilot round 1 on
    # openRepoTools#47). The `.jsonl`, its sibling `<uuid>/` state directory and
    # the pointer left behind are one act, and a HALF-DONE one is worse than
    # none: a sibling orphaned in the other profile is state the resumed session
    # silently loses, and a transcript gone from where a person will look for it
    # with no pointer has had its only recovery trail deleted. So each of the
    # two below is CHECKED, and a step that cannot complete puts back what the
    # steps before it moved and refuses — naming the parts it could not put
    # back, because a rollback that itself failed is the one state nobody can
    # infer from the outside.
    ft_moved_sib=0
    if [ -d "$ft_sib" ]; then
      if mv -- "$ft_sib" "$ft_dest_dir/$ft_id" 2>/dev/null; then
        ft_moved_sib=1
      else
        ft_undone="$(ft_rollback)"
        FOLLOW_WHY="transcript $ft_id moved into $ft_dest_dir, but its sibling state directory $ft_sib could NOT follow it — half a transcript is not one, so the move was put back. Nothing was launched.${ft_undone:+
    WHAT COULD NOT BE PUT BACK: $ft_undone}"
        return 2
      fi
    fi
    # THE POINTER, WHERE THE FILE WAS: `<uuid>.jsonl.moved-to-<profile>-<UTC>`.
    # A person looking for a transcript that is not where they left it is owed
    # the sentence, in the directory they are standing in — so a pointer that
    # cannot be written (a source directory that is read-only, say) undoes the
    # move rather than completing it untraceably.
    ft_to="${CLAUDE_PROFILE_NAME:-}"
    [ -n "$ft_to" ] || ft_to="$(profile_of_projects_dir "$PROJECTS_STATE")"
    ft_ptr="$ft_f.moved-to-$ft_to-$(date -u +%Y-%m-%dT%H%M%SZ)"
    if ! printf 'moved to %s by %s at %s\n' "$ft_dest_dir" "$prog" "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
         > "$ft_ptr" 2>/dev/null; then
      rm -f -- "$ft_ptr" 2>/dev/null || :
      ft_undone="$(ft_rollback)"
      FOLLOW_WHY="transcript $ft_id could not be given its pointer at $ft_ptr, which is the only trail back to where it was — so the move was put back rather than left untraceable. Nothing was launched.${ft_undone:+
    WHAT COULD NOT BE PUT BACK: $ft_undone}"
      return 2
    fi
    step "transcript $ft_id was in profile $ft_prof's projects directory ($ft_d), which is NOT this profile's — moved into $ft_dest_dir, with a pointer left where it was (a copy would leave two live transcripts of one uuid diverge)"
    FOLLOW_FILE="$ft_dest_dir/$ft_id.jsonl"
    return 0
  done <<EOF
$(profile_projects_dirs)
EOF
  [ -z "$ft_shared" ] || FOLLOW_WHY="shared:$ft_shared"
  return 8
}

# The transcript of ONE recorded session id, in this directory.
recorded_transcript() {
  local id="$1" d
  [ -n "$id" ] || return 1
  while IFS= read -r d; do
    if [ -f "$d/$id.jsonl" ]; then printf '%s\n' "$d/$id.jsonl"; return 0; fi
  done < <(transcript_dirs)
  return 1
}

# A `/rename` is a `{"type":"custom-title",…}` record inside the transcript,
# and the LAST one wins — a session renamed away from this lane must not be
# resumed by it. Several transcripts can still carry one title; that is why
# this is only the fallback.
# `<LANE> (2)` is the SAME lane: that suffix is exactly what a rename into a
# title something else still holds mints, and live_holder() already reads it
# that way. A matcher that insisted on the bare string would hide a lane from
# itself — this orchestrator's own title on 2026-09-11 was `codeXfactory-1 (4)`.
# AMENDMENT 15 — THE TITLE IS MATCHED CASE-INSENSITIVELY, because the SESSION
# NAME is one of the lookups the rule names and because this is the branch that
# decides RESUME versus MINT A NEW ONE. `openXfactory-2`'s own transcript is
# titled `openxfactory-2` — the launcher named it that on 2026-09-13, and the
# row says `openXfactory-2` since the 15(d) merge — so a byte-for-byte matcher
# would find NO transcript for that lane and start a second conversation on it,
# which is the incident this amendment exists to stop, one branch along.
# `live_holder` and `fork_map` have matched titles case-insensitively all along;
# this was the one that did not.
#
# THE LANE IS LOWER-CASED ONCE, outside the loop, and only the candidate's own
# `base` per file — which is two processes this loop already spends on `grep`
# and `sed` for every file it looks at.
titled_transcript() {
  local d f last title base tt_lane_lc
  tt_lane_lc="$(printf '%s' "$LANE" | tr 'A-Z' 'a-z')"
  while IFS= read -r d; do
    [ -d "$d" ] || continue
    for f in "$d"/*.jsonl; do
      [ -e "$f" ] || continue
      last="$(grep -e '^{"type":"custom-title"' "$f" 2>/dev/null | tail -n1 || :)"
      [ -n "$last" ] || continue
      title="$(printf '%s' "$last" | sed 's/.*"customTitle":"//; s/".*//')"
      base="${title% (*)}"
      if [ "$(printf '%s' "$base" | tr 'A-Z' 'a-z')" = "$tt_lane_lc" ]; then printf '%s\t%s\n' "$f" "$title"; return 0; fi
    done
  done < <(transcript_dirs)
  return 1
}

new_uuid() {
  if [ -r /proc/sys/kernel/random/uuid ]; then cat /proc/sys/kernel/random/uuid
  elif command -v uuidgen >/dev/null 2>&1; then uuidgen | tr 'A-F' 'a-f'
  else return 1
  fi
}

# Amendment 7's lane verb follows the LAUNCH decision, which is the honest
# reading of it: a resume is a RESUMED and a new session is a STARTED.
lane_verb=STARTED
lane_sid=""

# ================= AMENDMENT 17(c): WHICH AGENT, AND WHAT IT IS LAUNCHED WITH
#
# *"`lane-start <repo> <n>` reads the row and the last `PAUSED`. Where the agent
# asked for is the one that paused, and its transcript is here, it resumes
# exactly as today (Amendment 6's case (a)). Otherwise — a different agent, or
# no transcript here — it launches the named agent with THE HANDOFF'S TOP BLOCK
# AS ITS FIRST PROMPT … With no `--agent` the default is the agent that paused;
# with no `PAUSED` the default is `claude`."*
#
# THE DEFAULT COMES FROM THE RECORD, THROUGH THE ONE READ THAT ANSWERS FOR IT
# (`lane-agent`, this amendment's sibling of `lane-dir`). 8 is "no record of
# this amendment yet" — every lane until its own next handoff — and it is not a
# failure: `claude` is what this command has always launched.
# THE AGENT'S OWN RESUMABLE ID, where the record carries one. For `claude` that
# is the transcript uuid the session cell already records and this script
# already resumes; for another agent it is the one id a launch has in hand, and
# it is what the row's session cell is appended with in that agent's spelling
# (`Codex <id>`). `none` is an ANSWER — the agent has no resumable id — and is
# not carried into the cell as if it were one.
#
# AND ONLY WHERE THE RECORD IS THAT AGENT'S (Copilot round 2 on
# openRepoTools#47). `lane-transcript` answers for the LANE — its last `PAUSED`,
# whichever agent wrote it — so a lane paused by `claude` and resumed with
# `--agent codex` would take the CLAUDE uuid and append it to the row's session
# cell spelled `Codex <uuid>`: an id no `codex` can resume, attributing this
# lane's history to a conversation that is not it, in a cell nothing rewrites.
if [ "$AGENT" != claude ]; then
  [ "$RECORDED_AGENT_READ" = 1 ] || read_recorded_agent
  if [ -n "$RECORDED_AGENT" ] && [ "$RECORDED_AGENT" != "$AGENT" ]; then
    note "the lane's last handoff names agent $RECORDED_AGENT and this launch is $AGENT, so the recorded transcript is NOT carried into the row's session cell — that id is $RECORDED_AGENT's and $AGENT cannot resume it. This launch is recorded without an id of its own; the session's first act stamps the row with the one it gets."
  else
    at_out=""; at_rc=0
    at_out="$("$LANES_EDIT" lane-transcript "$LANE" 2>/dev/null)" || at_rc=$?
    case "$at_rc" in
      0) [ "$at_out" = none ] || AGENT_ID="$at_out" ;;
      8|2) : ;;
      *) note "$LANES_EDIT lane-transcript $LANE failed (exit $at_rc) — the row's session cell will record this launch without the agent's own id" ;;
    esac
  fi
fi
# ------------- THE FRESH SESSION, AND WHICH OF ITS THREE SOURCES IS AUTHORITY
#
# A CONTEXT CLEAR IS ONE SENTENCE — *a NEW session of this lane's agent,
# started with the top block of the handoff the row names as its first prompt* —
# and it is why `/ctx` does not simply resume the transcript it has just paused.
# What changed on 2026-09-15 is not the sentence but WHO SAYS IT.
#
# `LANE_START_FRESH=1` WAS THE SEAM AND IS NO LONGER THE AUTHORITY
# (openRepoTools#94, measured on Eagle 2026-09-15T20:59Z). `/ctx` respawned the
# lane's own pane with the variable set, and this command was reached WITHOUT
# it: `claude-profile` re-creates the child through tmux, and its own code says
# the rule — *"`tmux new-session` hands the command the SERVER's environment,
# not this client's, so a variable the operator exported in their own shell
# reaches the child only if it is written into the command string"*. It threads
# six values explicitly and this was never one of them. The gates below were
# correct and were simply never reached with `fresh` set; the lane resumed the
# uuid it had just paused, and the record said an act had happened that had not.
#
# SO THE AUTHORITY IS A FILE, and the three sources are read in this order:
#
#   1. THE LANE'S OWN RESTART INTENT — `lanes-edit.sh restart-intent <lane>`,
#      written under the lane's control root BEFORE the old process was killed
#      and read back here whatever the environment did. It is the only channel
#      that crosses a boundary another repository owns, because it is on disk
#      rather than in an environment. Only `pending` and `starting` authorise a
#      launch: a `ready` intent is HISTORY (which is what makes an ordinary
#      `lane <name>` after a successful `/ctx` an ordinary resume), and a
#      failed launch is the supervisor's to retry, moving it back to `starting`.
#      Failed preparation authorizes only guarded ordinary resume with unchanged
#      intent history; it has no supervised launch authority.
#   2. `--fresh`, for the caller that reaches this command directly and has no
#      launcher between it and here.
#   3. `LANE_START_FRESH=1`, kept exactly as it was so that nothing written
#      about it stops working, and no longer trusted to arrive.
#
# AND AN INTENT THAT DISAGREES WITH THIS RUN IS A REFUSAL, NEVER A SUBSTITUTION
# (spec: *the operation launch refuses without substituting the conflicting
# value*). An intent naming another directory is an intent for a lane in
# another checkout, and launching this one in it is Evidence 3's silent loss of
# the repository's CLAUDE.md and the lane's memory; an `--operation` that is not
# the lane's current one is a supervisor acting for an operation that has been
# superseded.
fresh=0
fresh_why=""
hs_workspace_root() { lanes_workspace_root; }

# The file the row's handoff cell names. Three spellings, first hit wins, and
# every one of them is a READ:
#   (a) a path the cell already spells — absolute, or `~`-rooted, which is
#       Amendment 4(e)'s estate spelling reaching the same file through the
#       `~/projects/<estate>/handoffs` symlink;
#   (b) `<the register's own checkout>/<cell>` — the repository-relative
#       spelling every row this script writes carries, and the one the register
#       and the handoffs share;
#   (c) `<the workspace repository>/<cell>`, for a register reached from
#       somewhere else.
# A cell that spells a path of its own is answered by (a) alone: joining an
# absolute path on to a root gives a path nothing has.
hs_resolve() {
  local cell="$1" cand root
  [ -n "$cell" ] || return 1
  case "$cell" in
    '~/'*) cand="$HOME/${cell#'~/'}" ;;
    /*)    cand="$cell" ;;
    *)     cand="" ;;
  esac
  if [ -n "$cand" ]; then
    [ -f "$cand" ] || return 1
    printf '%s\n' "$cand"; return 0
  fi
  if [ -n "${LANES_REPO:-}" ] && [ -f "$LANES_REPO/$cell" ]; then
    printf '%s\n' "$LANES_REPO/$cell"; return 0
  fi
  root="$(hs_workspace_root 2>/dev/null || :)"
  if [ -n "$root" ] && [ -f "$root/$cell" ]; then
    printf '%s\n' "$root/$cell"; return 0
  fi
  return 1
}

first_prompt=0
ri_state=""; ri_op=""; ri_gen=""; ri_mode=""; ri_dir=""; ri_hf=""; ri_dig=""; ri_rc=0; ri_expected_digest=""; ri_prompt=""; ri_active=0; ri_attempt=""; ri_prepared=""; ri_agent=""; ri_profile=""
ri_out="$(LANES_NO_FETCH=1 "$LANES_EDIT" restart-intent "$LANE" --dir "$DIR" 2>/dev/null)" || ri_rc=$?
case "$ri_rc" in
  0)
    ri_state="$(printf '%s\n' "$ri_out" | awk -F'\t' '$1 == "state" { print $2; exit }')"
    ri_op="$(printf '%s\n'    "$ri_out" | awk -F'\t' '$1 == "operation" { print $2; exit }')"
    ri_gen="$(printf '%s\n'   "$ri_out" | awk -F'\t' '$1 == "generation" { print $2; exit }')"
    ri_mode="$(printf '%s\n'  "$ri_out" | awk -F'\t' '$1 == "mode" { print $2; exit }')"
    ri_dir="$(printf '%s\n'   "$ri_out" | awk -F'\t' '$1 == "dir" { print $2; exit }')"
    ri_hf="$(printf '%s\n'    "$ri_out" | awk -F'\t' '$1 == "handoff" { print $2; exit }')"
    ri_dig="$(printf '%s\n'   "$ri_out" | awk -F'\t' '$1 == "digest" { print $2; exit }')"
    ri_pane="$(printf '%s\n' "$ri_out" | awk -F'\t' '$1 == "pane" {print $2; exit}')"
    ri_attempt="$(printf '%s\n' "$ri_out" | awk -F'\t' '$1 == "attempt" {print $2; exit}')"
    ri_prepared="$(printf '%s\n' "$ri_out" | awk -F'\t' '$1 == "prepared_digest" {print $2; exit}')"
    ri_agent="$(printf '%s\n' "$ri_out" | awk -F'\t' '$1 == "agent" {print $2; exit}')"
    ri_profile="$(printf '%s\n' "$ri_out" | awk -F'\t' '$1 == "profile" {print $2; exit}')" ;;
  # 8 IS AN ANSWER — this lane has no restart in flight, which is every
  # ordinary launch — and 2 IS A HELPER THAT PREDATES THIS READ: an installed
  # `lanes-edit.sh` from before openRepoTools#94 answers 2 from its
  # unknown-subcommand arm, and on that workstation no `/ctx` could have
  # written an intent at all. The estate's fence is one sentence and
  # `lane-handoff` spells it out at its own register reads — *"`0` an answer,
  # `8` NO ANSWER and `2` a helper predating the read — both of those fall to
  # the next rung"*. Both fall to the next rung here too, and neither is worth
  # a note printed on every launch of every lane.
  8|2) : ;;
  # AND 1 IS NOT ONE OF THEM (Copilot round 2 on openRepoTools#121). `1` is
  # *the control root could not be derived*, which is a READ THAT COULD NOT BE
  # MADE and never *there is no restart in flight* — and the two are opposite
  # facts at this one gate. The sidecar `/ctx` wrote sits under a root resolved
  # from the lane's recorded directory or `$PROJECTS_ROOT`, and the pane this
  # launch runs in is a NEW one whose environment is not the one that wrote it;
  # a root that resolved then and does not now leaves this command reading
  # nothing and calling it nothing-in-flight. What it would then do is resolve
  # an ordinary resume source — and for a lane whose `/ctx` has just killed its
  # pane, that is the transcript the `/ctx` PAUSED. That is openRepoTools#94,
  # recreated by the very command written to prevent it.
  #
  # SO IT REFUSES, and so does any code this fence does not classify. The old
  # line said *refusing every launch on a helper that could not answer is not a
  # safety property* — which is true of a lane with no restart in flight and
  # false of the one gate whose wrong answer resumes a paused transcript. The
  # refusal names what to run to see the failure and both ways out of it,
  # because a refusal a person cannot act on is not better than the defect.
  1)
    die "lane $LANE's restart intent could not be read: it has no lifecycle control root here (\`$LANES_EDIT restart-intent $LANE\` exits 1 — its record names no directory and \$PROJECTS_ROOT is not a directory in this environment). That is NOT 'no restart is in flight': the sidecar a /ctx writes lives under that root, and launching without reading it would resolve an ordinary resume source — which for a lane whose pane a /ctx has just replaced is the transcript that /ctx PAUSED (openRepoTools#94). Nothing was renamed, written or started. Give this run a root it can resolve: set \$LANES_LANE_STATE_ROOT, or make \$PROJECTS_ROOT (default \$HOME/projects) a directory — the lane's own record names its checkout once it has been started with one, and resolves on that." 2 ;;
  *)
    die "lane $LANE's restart intent read FAILED (\`$LANES_EDIT restart-intent $LANE\` exited $ri_rc), and a read that failed is never an answer (Amendment 7(d)). Nothing was renamed, written or started: this is the one launch gate whose wrong answer resumes the transcript a /ctx just paused (openRepoTools#94), so it refuses rather than falling through to an ordinary resume source. Run that command yourself to see what it says, then launch again." 1 ;;
esac
if [ -n "$preparation_failure_identity" ]; then
  pfr_current="$(preparation_failure_snapshot "$ri_out")"
  [ "$pfr_current" = "$preparation_failure_identity" ] ||
    die "the failed preparation changed during ordinary recovery. Nothing was launched." 2
fi
if [ -n "${LANE_RESTART_OPERATION:-}" ]; then
  [ -z "$op_flag" ] || [ "$op_flag" = "$LANE_RESTART_OPERATION" ] ||
    die "the explicit restart operation disagrees with the supervisor token. Nothing was started." 2
  op_flag="${op_flag:-$LANE_RESTART_OPERATION}"
fi
# AN `--operation` NAMES THE INTENT IT BELONGS TO, AND ONLY THAT ONE.
if [ -n "$op_flag" ]; then
  [ -n "$ri_state" ] ||
    die "--operation $op_flag was given and lane $LANE has no restart intent to match it against (the read above says what answered). A supervised launch is made for ONE operation and this one cannot be found: nothing was renamed, nothing was written and no session was started. Read it with:  lanes-edit.sh restart-intent $LANE" 2
  [ "$op_flag" = "$ri_op" ] ||
    die "--operation $op_flag is not lane $LANE's current restart operation, which is ${ri_op:-none} (state ${ri_state:-none}, generation ${ri_gen:-0}). A stale supervisor must never launch against a newer operation — nothing was renamed, written or started. Read it with:  lanes-edit.sh restart-intent $LANE" 2
fi
case "$ri_state" in
  # AN INTENT THIS READER CANNOT UNDERSTAND REFUSES THE LAUNCH, AND DOES NOT
  # QUIETLY RESUME (Copilot round 1 on openRepoTools#121). `lanes-edit.sh`
  # answers `UNKNOWN-SCHEMA` where a newer tooling wrote the record, and that
  # answer used to fall through this `case` to the ordinary resume-source
  # resolution below — which is the SAFE half of the decision (it authorises no
  # fresh session) sitting on top of the UNSAFE one: the lane whose intent that
  # is has just had its pane killed by a `/ctx`, and the resume source waiting
  # there is the transcript that `/ctx` PAUSED. Falling through would resume it.
  # That is openRepoTools#94 exactly, reached down a second road.
  #
  # So it is a refusal, in the one shape Amendment 7(d) gives: a read that could
  # not be made is never an answer. It costs a person the lane until the
  # workstation's `lanes-edit.sh` is new enough to read the file — and the
  # message says both ways out, which is what makes that recoverable rather than
  # a wall.
  INCOMPLETE)
    die "lane $LANE has a restart intent that is missing facts a launch is fenced on (\`lanes-edit.sh restart-intent $LANE\` answers INCOMPLETE and names them). Its writer records every field on every transition, so a record missing one was not written by this tooling — and launching from it would skip the very checks those fields exist for: the pane comparison and the handoff digest both treat an absent value as *cannot compare*. Nothing was renamed, written or started. Read it, and remove it once you know no restart is in flight:  lanes-edit.sh restart-intent $LANE" 2 ;;
  UNKNOWN-STATE)
    die "lane $LANE has a malformed restart state. Nothing was started. Read it: lanes-edit.sh restart-intent $LANE" 2 ;;
  UNKNOWN-SCHEMA)
    die "lane $LANE has a restart intent this \`lanes-edit.sh\` cannot read: its schema is one this version does not know (\`lanes-edit.sh restart-intent $LANE\` answers UNKNOWN-SCHEMA). That is NOT 'no restart is in flight' — a read that could not be made is never an answer (Amendment 7(d)) — and starting anyway would resolve an ordinary resume source, which for a lane whose /ctx just killed its pane is the transcript that /ctx PAUSED. Nothing was renamed, written or started. Update this workstation's openRepoTools so it can read that record, or remove the intent once you know no restart is in flight:  lanes-edit.sh restart-intent $LANE" 2 ;;
  failed)
    [ -n "$preparation_failure_identity" ] ||
      die "a failed restart appeared during ordinary launch. Recheck it before recovery. Nothing was launched." 2
    preparation_failure_resume_check "$ri_out" ;;

  preparing)
    die "this restart is still preparing its preservation records. No launch is authorized. Read it: lanes-edit.sh restart-intent $LANE" 2 ;;
  pending|starting)
    ri_active=1
    [ "$AGENT" = claude ] && [ "$ri_agent" = claude ] || die "legacy supervised restart requires the recorded Claude agent. Nothing was started." 2
    if [ -n "${CLAUDE_PROFILE_NAME:-}" ] && [ "$ri_profile" != none ]; then
      [ "$CLAUDE_PROFILE_NAME" = "$ri_profile" ] || die "the launcher profile disagrees with the restart intent. Nothing was started." 2
    fi
    if [ -n "${LANE_RESTART_ATTEMPT:-}" ]; then
      [ "$LANE_RESTART_ATTEMPT" = "$ri_attempt" ] || die "this child belongs to a superseded restart attempt. Nothing was started." 2
    fi
    [ -n "$op_flag" ] || die "an active restart requires its supervisor operation token. Ordinary lane launch cannot consume it. Retry with lane-handoff --supervise --lane $LANE --operation $ri_op." 2
    LANES_NO_FETCH=1 "$LANES_EDIT" legacy-restart-check "$LANE" ||
      die "managed or unknown ownership blocks this legacy restart. Nothing was started." 2
    if [ -n "$ri_pane" ] && [ "$ri_pane" != none ] && [ -n "${TMUX_PANE:-}" ]; then
      case "$ri_pane" in *.%*) ri_pane_id="${ri_pane##*.}" ;; %*) ri_pane_id="$ri_pane" ;; *) ri_pane_id="" ;; esac
      [ -z "$ri_pane_id" ] || [ "$ri_pane_id" = "$TMUX_PANE" ] || die "the restart intent names another pane. Nothing was started." 2
    fi
    [ "$ri_mode" = fresh-from-handoff ] || die "this restart has not completed preservation; its mode is $ri_mode. Nothing was started." 2
    [ -n "$ri_dig" ] && [ "$ri_dig" != none ] || die "the supervised restart has no complete handoff checksum. Nothing was started." 2
    if [ "$ri_mode" = fresh-from-handoff ]; then
      # THE DIRECTORY IS COMPARED BEFORE ANYTHING IS TAKEN. `real_of` is this
      # file's own resolver, so a symlinked projects root does not read as a
      # disagreement it is not.
      if [ -n "$ri_dir" ] && [ "$ri_dir" != none ] && [ "$(real_of "$ri_dir")" != "$(real_of "$DIR")" ]; then
        die "lane $LANE's restart intent (operation ${ri_op:-none}, state $ri_state) names checkout $ri_dir and this launch stands in $DIR. That is a conflict and not a preference: a launch that lands in the right transcript and the wrong directory loses the repository's CLAUDE.md and the lane's memory, silently (Evidence 3). Nothing was renamed, written or started. Launch it where the intent says, or read the intent:  lanes-edit.sh restart-intent $LANE" 2
      fi
      # THE HANDOFF'S DIGEST IS VERIFIED ON EVERY LAUNCH (spec: *a changed or
      # missing handoff blocks launch and retry*), because the top block of
      # that file is literally this launch's first prompt and a file that has
      # moved under the intent is a different instruction. A `none` digest is
      # *not checked here* — a workstation with neither `sha256sum` nor
      # `shasum` — and says so rather than passing silently.
      if [ -n "$ri_hf" ] && [ "$ri_hf" != none ] && [ -n "$ri_dig" ] && [ "$ri_dig" != none ]; then
        ri_now="$(handoff_digest_of "$ri_hf")"
        if [ "$ri_now" != "$ri_dig" ] && [ "$ri_now" != "${ri_prepared:-none}" ]; then
          die "lane $LANE's handoff has changed since its restart intent was written: the intent records digest $ri_dig for $ri_hf and that file now digests $ri_now. The top block of that file is this launch's FIRST PROMPT, so launching now would hand the new session the block of a handoff the /ctx did not write. Nothing was renamed, written or started (operation ${ri_op:-none}). Take the handoff again:  lane-handoff --restart" 2
        fi
      fi
      # The digest and the actual prompt must refer to the same row-bound file.
      ri_cell="$(cell 7 | sed 's/^[[:space:]]*//; s/[[:space:]]*$//')"
      ri_row_hf="$(hs_resolve "$ri_cell")" || die "the restart handoff the row names is missing. Nothing was started." 2
      [ -n "$ri_hf" ] && [ "$ri_hf" != none ] && [ -s "$ri_hf" ] &&
        [ "$ri_hf" -ef "$ri_row_hf" ] ||
        die "the restart intent and register name different handoffs. Nothing was started." 2
      ri_expected_digest="$(handoff_digest_of "$ri_hf")"
      fresh=1
      fresh_why=" (restart intent ${ri_op:-none}, state $ri_state: the /ctx respawn)"
    else
      note "lane $LANE has a restart intent in state $ri_state whose mode is '${ri_mode:-none}' and not 'fresh-from-handoff', so it authorises no fresh session here; this launch resolves its own resume source."
    fi ;;
esac
if (( ! fresh )) && [ "$fresh_flag" = 1 ]; then
  fresh=1
  fresh_why=" (--fresh)"
fi
if (( ! fresh )) && [ "${LANE_START_FRESH:-0}" = 1 ]; then
  fresh=1
  fresh_why=" (LANE_START_FRESH=1: the /ctx respawn)"
fi

# AMENDMENT 11, EVIDENCE 4 — `--name "$LANE"` IS ON EVERY LAUNCH BRANCH, NOT
# ONLY THE NEW-SESSION ONE. The session NAME is the lane's messaging address
# (Amendment 2): `ListAgents`, `SendMessage`, `@<lane>` and the statusline all
# read the harness record's name, and a resume that passes no `--name` gets a
# DERIVED one. Measured on this lane 2026-09-13: the transcript carried
# `customTitle: openRepoProject-1`, set once by `/rename`, while every process
# that resumed it that day carried `openrepoproject-b9`, `-1e`, `-27`, `-45` —
# four derived names for one lane, because only the new-session branch below
# passed the flag. A resume is a launch; a launch names its window's session
# after the lane, or the lane loses its address for the life of that session,
# and there is no API to rename a running one from inside.
new_sid=""
# ACT 6 — WHERE THE TRANSCRIPT IS, SAID RATHER THAN ASSUMED, and followed where
# it is in another profile's directory. This runs BEFORE the branch below, so
# `recorded_transcript` answers for a transcript this run has just moved here.
rec_file=""
resume_sid="$row_sid"
restored_sid=""
# NOT IN THE BINDING MODE (openRepoTools#70): the id there is a session that is
# RUNNING in this window, its launch decision does not read where its transcript
# is, and a transcript a live process holds is one this act refuses to move.
if [ -n "$row_sid" ] && [ "$AGENT" = claude ] && (( ! fresh )) && [ -z "$bind_sid" ]; then
  rec_file="$(recorded_transcript "$row_sid" 2>/dev/null || :)"
  if [ -n "$rec_file" ]; then
    # WHICH DIRECTORY IT WAS FOUND IN, and whether that directory is SHARED —
    # `readlink -f` equal across profiles is what makes a profile switch need no
    # move at all, and a person swapping accounts is owed that sentence rather
    # than a silent success they cannot reason about.
    shared_with=""
    here_real="$(real_of "$PROJECTS_STATE")"
    while IFS= read -r ppd; do
      [ -n "$ppd" ] && [ "$ppd" != "$PROJECTS_STATE" ] || continue
      [ "$(real_of "$ppd")" = "$here_real" ] || continue
      shared_with="${shared_with:+$shared_with }$(profile_of_projects_dir "$ppd")"
    done <<EOF
$(profile_projects_dirs)
EOF
    step "transcript $row_sid found in this profile's projects directory ($PROJECTS_STATE)${shared_with:+, which IS the directory profile(s) $shared_with read too (one shared directory: a profile switch resumes this lane by id and moves nothing)}"
  else
    # `|| ft_rc=$?` AND NOT `; ft_rc=$?`: this script runs under `set -e`, so a
    # function returning 8 as a bare command ENDS IT — with 8, which is this
    # estate's code for "no record" and which a caller would read as a lane-start
    # that found nothing rather than one that was never asked.
    ft_rc=0
    follow_transcript "$row_sid" || ft_rc=$?
    case "$ft_rc" in
      0) rec_file="$FOLLOW_FILE" ;;
      2) die "$FOLLOW_WHY" 2 ;;
      *) case "$FOLLOW_WHY" in
           shared:*) note "no transcript for $row_sid under this directory in any profile's projects directory (profiles ${FOLLOW_WHY#shared:} share this one)" ;;
           # `--dry-run` FOUND IT AND MOVED NOTHING. The run carries on as a
           # lane whose transcript is not here — which is what it would be
           # WITHOUT the move — because a dry run must not report a launch that
           # depends on a write it did not make.
           dry-run:*) note "--dry-run: ${FOLLOW_WHY#dry-run:}. Nothing was moved; the branch below is the one a lane with no transcript here takes" ;;
         esac ;;
    esac
  fi
fi

# AMENDMENT 17(c) MAKES THE PAUSED RECORD A RESUME SOURCE, NOT MERELY A LABEL.
# The row normally wins because its last transcript is the current one. A
# harness restart can, however, append the process/session id it minted while
# continuing an older Claude transcript. That id is then a perfectly readable
# row entry but has no `<id>.jsonl`; falling through to `--resume <LANE>` opens
# Claude's title picker and can immediately exit a launcher-created pane. The
# last PAUSED record already carries the exact agent transcript for this case.
# Where it names this same agent and that transcript exists, resume the exact id
# and put it back at the end of the cell below. A live session being bound in
# this window still wins: step 3b has first-hand evidence and must never be
# replaced by an older handoff.
#
# AND "BEING BOUND" IS TWO VARIABLES, NOT ONE (Copilot round 2 on
# openRepoTools#87). `$harness_sid` is set only where step 3b TAKES a session
# the row does not name; where the window's live session IS the row's, step 3
# has already said so with `holder_here` and `$harness_sid` stays empty — so
# that test alone let this fallback fire on the one state it was written to
# stand off: the lane live in THIS window, its transcript not under this
# directory (the harness has been seen to keep one under another `cwd` key),
# and an older PAUSED record beside it. It would have `--resume`d the older
# conversation over the person's own, in the window they are sitting in. Both
# halves of the evidence are asked for now — and `--bind` is that evidence
# named outright (openRepoTools#70).
if [ -z "$rec_file" ] && [ -z "$harness_sid" ] && [ -z "$bind_sid" ] && (( ! holder_here )) \
   && [ "$AGENT" = claude ] \
   && [ "$RECORDED_AGENT" = claude ] && (( ! fresh )); then
  paused_sid=""; paused_rc=0
  paused_sid="$("$LANES_EDIT" lane-transcript "$LANE" 2>/dev/null)" || paused_rc=$?
  case "$paused_rc" in
    0)
      if [[ "$paused_sid" =~ ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$ ]] \
         && [ "$paused_sid" != "$row_sid" ]; then
        paused_file="$(recorded_transcript "$paused_sid" 2>/dev/null || :)"
        if [ -z "$paused_file" ]; then
          paused_follow_rc=0
          follow_transcript "$paused_sid" || paused_follow_rc=$?
          case "$paused_follow_rc" in
            0) paused_file="$FOLLOW_FILE" ;;
            2) die "$FOLLOW_WHY" 2 ;;
            *) case "$FOLLOW_WHY" in
                 dry-run:*) note "--dry-run: ${FOLLOW_WHY#dry-run:}. Nothing was moved; the title/new-session branch below remains the dry-run result" ;;
               esac ;;
          esac
        fi
        if [ -n "$paused_file" ]; then
          resume_sid="$paused_sid"
          rec_file="$paused_file"
          restored_sid="$paused_sid"
          step "the row's last session id $row_sid has no transcript here, but this same agent's last PAUSED record names transcript $paused_sid and it is here ($(basename -- "$rec_file")) — resuming that exact id"
        fi
      fi ;;
    8|2) : ;;
    *) note "$LANES_EDIT lane-transcript $LANE failed (exit $paused_rc) — carrying on without the last PAUSED record's exact resume id" ;;
  esac
fi

# ---- THE LAUNCHER TABLE (Amendment 17(c)) -------------------------------
#
# ONE BRANCH PER AGENT, and a name this table does not carry is a REFUSAL that
# names the ones it does — never a guess at an argv nobody has tested. The
# table is deliberately short: `claude`, whose three cases are Amendment 6's
# and are unchanged below, and `codex`, which takes its first prompt
# positionally as `claude` does. A third agent is a row here and a test beside
# it, and nothing else.
if [ "$AGENT" != claude ]; then
  case "$AGENT" in
    codex)
      # THE LAUNCHER IS ON PATH, OR NOTHING IS WRITTEN (Copilot round 3 on
      # openRepoTools#47). The row, the object log and the Rule 3 stamp are all
      # written BEFORE the `exec` at the foot of this command, so a `codex` this
      # workstation does not have records the lane as RESUMED and then exits
      # 127 — a false transition in two append-only files that a person has to
      # repair by hand. The check is here, in 5a, which is before every write.
      command -v "$AGENT" >/dev/null 2>&1 ||
        die "this command's launcher table knows '$AGENT', and this workstation has no '$AGENT' on PATH. Nothing was written: the row, the object log and the handoff's Rule 3 stamp are all written before the launch, and a lane recorded as RESUMED by a launch that exits 127 is a false transition in two append-only files. Install it, or name an agent this workstation has: $prog --agent <name> …" 2
      # `codex` KEEPS NO ID THIS COMMAND CAN PASS: it prints its own resumable
      # id where it has one, so the lane's record carries whatever the last
      # handoff wrote (`transcript <id>`) and the session's own first act
      # corrects it. The top block is delivered positionally, which is the one
      # thing both agents in this table have in common.
      step "agent $AGENT — launching it with this lane's handoff top block as its first prompt (Amendment 17(c))"
      cmd=("$AGENT")
      lane_verb=RESUMED; lane_sid=unknown; first_prompt=1 ;;
    *)
      die "this command has no launcher for the agent '$AGENT'. It knows: claude (resume by id where its transcript is here, else a named new session with the handoff's top block as its first prompt) and codex (the top block as its first prompt). A lane is resumed by an agent whose launch this command has been taught and tested — never by a guessed argv (Amendment 17(c))." 2 ;;
  esac
elif [ -n "$bind_sid" ]; then
  # THE BINDING MODE STAMPS THE ID BEING BOUND (openRepoTools#70), and it is
  # decided FIRST, ahead of every branch that reads where a transcript is: the
  # session is running in this window, so which directory holds its file is not
  # a question this run has to answer, and the title and new-session branches
  # would stamp `unknown` or a minted id for a conversation that is plainly
  # here. Step 3b has already put this uuid at the end of the cell (or found it
  # there), and the 18(h) count for it was made at the window-binding call. The
  # command is the exact resume of that id — printed, never run, since --bind
  # comes only with --no-launch — which is what the next `lane-start` resumes.
  step "--bind: lane $LANE is bound to $win_sid, the session live in this window — the row's stamp, the lane's log line and the handoff's Rule 3 stamp name it"
  cmd=("$CLAUDE_BIN" --name "$LANE" --resume "$win_sid")
  lane_verb=RESUMED; lane_sid="$win_sid"
elif [ -n "$resume_sid" ] && [ -n "$rec_file" ]; then
  # AMENDMENT 18(h), AND THIS IS THE ONLY LAUNCH BRANCH WITH AN ID TO COUNT
  # (`main`, #52). The clause is *"the id it is about to resume or bind"*: this
  # branch is the one that resumes an id, and the count is asked INSIDE it
  # rather than above, because above it the row's id is merely a candidate —
  # act 6's search on the lines above is what decides whether anything resumes
  # it at all, and counting the holders of a transcript nobody is about to open
  # would refuse a lane for a fact about a conversation it is not going to
  # touch. The title-fallback branch resumes through the PICKER, whose
  # transcript is not knowable here, and the new-session branch MINTS a fresh
  # uuid; neither has an id, which is stated rather than left to be noticed.
  # AND THE HARNESS'S OWN FENCE IS ASKED ON BOTH SIDES OF THAT TEST, because it
  # is the one rule that still bites when the id IS this window's session: the
  # `bg` companion of a live session carries its id, and `claude --resume` stops
  # on a companion. `resume-here` asks that and nothing else — the duplicate
  # count for this id was already made at the window-binding call above.
  #
  # ONLY WHERE AN `exec` IS ABOUT TO HAPPEN. `--no-launch` and `--dry-run` open
  # no transcript and hand the harness nothing, so the harness's refusal is not
  # theirs to inherit — and AMENDMENT 8 RULING (g) IS EXPLICIT about the shape
  # that would otherwise break: a `bg` companion is one session seen twice and
  # NEVER refuses the lane to the window its own session is running in, which is
  # exactly what a `--no-launch` binding act in that window is. 18(h)'s count is
  # asked in both, unchanged, because an id a second process holds is one this
  # run must not WRITE DOWN either.
  ls_rules=bind
  if (( ! no_launch )) && (( ! dry_run )); then ls_rules=resume; fi
  if [ "$resume_sid" != "$win_sid" ]; then
    dup_check "$resume_sid" "resume transcript $resume_sid as lane $LANE" "$ls_rules"
  elif [ "$ls_rules" = resume ]; then
    dup_check "$resume_sid" "resume transcript $resume_sid as lane $LANE" resume-here
  fi
  if [ -n "$restored_sid" ]; then
    step "the recovered resume session is $resume_sid and its transcript is here ($(basename -- "$rec_file")) — resuming it by id"
  else
    step "the row's current session is $resume_sid and its transcript is here ($(basename -- "$rec_file")) — resuming it by id"
  fi
  (( holder_here )) && step "  (it is the session live in this window; --resume attaches to the same conversation)"
  cmd=("$CLAUDE_BIN" --name "$LANE" --resume "$resume_sid")
  lane_verb=RESUMED; lane_sid="$resume_sid"
elif (( fresh )) || (( AGENT_EXPLICIT )); then
  # `--agent claude` WITH NO TRANSCRIPT HERE, and the `/ctx` respawn: a NAMED
  # NEW SESSION, with the handoff's top block as its first prompt. It skips the
  # title fallback deliberately — a caller that named an agent, or a context
  # clear that has just written a fresh top block, is asking for a new session
  # of this lane and not for a picker filtered by a title.
  step "agent claude — a new session named for the lane, with this lane's handoff top block as its first prompt$fresh_why"
  cmd=("$CLAUDE_BIN" --name "$LANE")
  lane_verb=RESUMED; lane_sid=unknown; first_prompt=1
  if [ -n "$harness_sid" ]; then
    note "the live session in this window ($harness_sid) is not resumed by this launch: a first prompt is delivered to a session that has none. The cell still records the session that is in the window."
  elif [ "${LANE_START_SESSION_ID:-1}" != 0 ]; then
    if new_sid="$(new_uuid)"; then
      while recorded_transcript "$new_sid" >/dev/null 2>&1; do new_sid="$(new_uuid)"; done
      cmd+=(--session-id "$new_sid")
      lane_sid="$new_sid"
      step "minted session id $new_sid — the row will carry it, so the next $prog resumes it by id"
    else
      new_sid=""
      note "no uuid source (/proc/sys/kernel/random/uuid, uuidgen): the new session's own first act must stamp its id on the row"
    fi
  fi
elif titled="$(titled_transcript)"; then
  transcript="${titled%%$'\t'*}"; found_title="${titled#*$'\t'}"
  [ -n "$row_sid" ] && note "the row's last session id $row_sid has no transcript for this directory — falling back to the title"
  step "a transcript here carries the title '$found_title' ($(basename -- "$transcript")) — resume beats new"
  # THREE ANSWERS, NOT TWO (Amendment 15). A title that is not the lane's own
  # spelling is now one of two different facts, and they have different cures: a
  # dedupe suffix means ANOTHER holder was live when this one was renamed, and a
  # title differing only by CASE means this is the lane's own transcript under
  # the spelling it was launched with before the row's became canonical. Telling
  # a person to retire stale holders for the second would send them hunting a
  # collision that never happened.
  if [ "$found_title" != "$LANE" ]; then
    if [ "$(printf '%s' "$found_title" | tr 'A-Z' 'a-z')" = "$(printf '%s' "$LANE" | tr 'A-Z' 'a-z')" ]; then
      note "  that title spells this lane in another case, which is the SAME lane (Amendment 15): the window and the launch take the register row's spelling, $LANE"
    else
      note "  that title carries a dedupe suffix, so another holder of '$LANE' was live when it was renamed: retire the stale holders (lane-end --retire, or retitle them '<lane> · retired <date>') and end idle background sessions still holding the name"
    fi
  fi
  note "  '--resume $LANE' FILTERS THE PICKER, it does not resume exactly: pick the lane's own session, then put its id in the row's session cell"
  (( holder_here )) && step "  (that session is the one live in this window; --resume attaches to the same conversation)"
  cmd=("$CLAUDE_BIN" --name "$LANE" --resume "$LANE")
  # The picker decides which transcript this is, so the id is NOT KNOWABLE
  # here — and the line says so rather than naming the row's last id, which is
  # an id whose transcript this directory does not even have (that is why this
  # branch was reached). Writing it would put a session uuid on a RESUMED that
  # belongs to a different conversation, in a file nothing rewrites. `unknown`
  # is the grammar's own word for an id nobody has; the session stamps the row
  # with its real one as its first act (Amendment 6(c)).
  lane_verb=RESUMED; lane_sid=unknown
else
  step "nothing here to resume for $LANE — a new session takes the name"
  cmd=("$CLAUDE_BIN" --name "$LANE")
  # A NEW SESSION IS NEVER ATTRIBUTED TO THE OLD ONE. With minting turned off
  # (LANE_START_SESSION_ID=0), or with no uuid source at all, there is no id to
  # write — and an empty LANES_SESSION makes the helper fall back to the LAST id
  # in the row's cell, which is the session that has ENDED. The row itself is
  # left reading `pending — set by the session's first act` in that case, so the
  # log said one thing and the row another about the same act.
  lane_sid=unknown
  if [ -n "$harness_sid" ]; then
    # Nothing is minted: the row is about to name the session that is really in
    # this window, and minting a second id beside it would give the lane two
    # answers to "which session is this". The launch still takes a new session —
    # this branch was reached because the live one has no transcript in this
    # directory and cannot be resumed by id — and it is not attributed to the
    # other one, which is what `unknown` says.
    note "the live session in this window ($harness_sid) has no transcript in this directory, so it cannot be resumed by id. A new session takes the name and nothing is minted; the cell still records the session that is in the window."
  elif [ "${LANE_START_SESSION_ID:-1}" != 0 ]; then
    if new_sid="$(new_uuid)"; then
      while recorded_transcript "$new_sid" >/dev/null 2>&1; do new_sid="$(new_uuid)"; done
      cmd+=(--session-id "$new_sid")
      lane_sid="$new_sid"
      step "minted session id $new_sid — the row will carry it, so the next $prog resumes it by id"
    else
      new_sid=""
      note "no uuid source (/proc/sys/kernel/random/uuid, uuidgen): the new session's own first act must stamp its id on the row"
    fi
  fi
fi
cmd+=(${pass[@]+"${pass[@]}"})

# THE CLAUDE CODE TO START (opensoft/workBenches#119), once the agent and the
# launch are known. Resolution already ran before the binding handoff and
# first stateful act; use that selected path when building the final command.
if [ "$AGENT" = claude ]; then
  cmd[0]="$CLAUDE_BIN"
fi

# A LANE WITH NO ROW IS A `STARTED`, WHATEVER BRANCH LAUNCHED IT (Copilot round
# 1 on openRepoTools#47). Two branches above set the verb to RESUMED because
# they are resuming a lane that PAUSED — `--agent <name>` and the `/ctx` seam —
# and both are reachable for a lane the register has never carried, where
# `add-row` is about to write the first row and the object log has no line at
# all. A `RESUMED` opening that log is a line no reader can pair with a start,
# in a file nothing rewrites.
if [ "$row_count" = 0 ] && [ "$lane_verb" = RESUMED ]; then
  lane_verb=STARTED
  step "this lane has no row yet, so the record of this launch is a STARTED (there is nothing to have resumed)"
fi

# IS THERE A TRANSCRIPT UUID TO NAME AT ALL? (Amendment 8(d), R-A8-2.) Computed
# HERE, with the launch decision that produced `lane_sid`, because three later
# sections read it: the row's stamp (5), the object-log line (5b) and the
# handoff's Rule 3 stamp (5c). It used to be computed between the first two,
# which left the first reading a variable the last two shared.
# Reserve this attempt's transcript before row, log or handoff mutation.
if [ "$ri_active" = 1 ] && (( ! no_launch )) && (( ! dry_run )); then
  [ -n "$lane_sid" ] && [ "$lane_sid" != unknown ] || die "the restart has no prepared transcript. Nothing was written." 2
  LANES_NO_FETCH=1 "$LANES_EDIT" set-restart-intent "$LANE" starting \
    --expect 'pending|starting' --expect-operation "$ri_op" \
    --expect-generation "$ri_gen" --expect-attempt "$ri_attempt" \
    --expect-new-transcript none --new-transcript "$lane_sid" --reason 'transcript reserved before preservation writes' >/dev/null ||
      die "this restart attempt lost ownership before preservation writes. Nothing was launched." 2
fi

lane_sid_known=0
[[ "$lane_sid" =~ ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$ ]] && lane_sid_known=1

# WHO THE TWO STAMPS NAME (Amendment 17(c)). For `claude` it is the uuid and
# nothing else — `RESUMED by <uuid>`, the line Amendment 6(c), Amendment 8(d),
# this file's own header and the manual all quote. For another agent it is
# `<agent> <id>`, and `pending` where that agent's id is not knowable until it
# prints one: the STATE cell and the handoff are histories of acts, and an act
# that happened with an id nobody has yet is still an act that happened.
stamp_who="${lane_sid:-unknown}"
stamp_ok="$lane_sid_known"
if [ "$AGENT" != claude ]; then
  stamp_who="$AGENT ${AGENT_ID:-pending}"
  stamp_ok=1
fi

# ------------- 4a. what the last session left (opensoft/openRepoTools#91)
#
# THE RECONCILIATION IS PRINTED BEFORE ANYTHING IS WRITTEN, and it REFUSES
# NOTHING. A lane recorded `RUNNING` with no live holder stopped ungracefully —
# nothing was polled, refreshed or recorded — and one recorded `SWAPPING` with
# no live holder was interrupted MID-HANDOFF, where some of the three writes
# may have landed and some may not. Either way there may be worktrees carrying
# dirty or unpushed work, and the one thing this command must not do is start a
# session that writes over them in ignorance.
#
# IT IS HERE, ABOVE SECTION 5, because the `STARTED`/`RESUMED` line this run is
# about to write takes the lane to `RUNNING` — so a report printed after it
# would describe this launch rather than the crash it is recovering from.
#
# IT IS A REPORT AND NOT A GATE. `resume` RESETS NOTHING and `park` CREATES
# NOTHING (AGENTS.md rule 1); this prints what differs and names the act, and
# every refusal this command makes is the one it already made. A helper that
# predates the read (exit 2) and a lane with no snapshot (exit 8) are both
# silent — Amendment 7(i)'s cutover rule: nothing is backfilled.
if (( ! dry_run )); then
  lrec_out=""; lrec_rc=0
  lrec_out="$(LANES_NO_FETCH=1 "$LANES_EDIT" lane-reconcile "$LANE" 2>/dev/null)" || lrec_rc=$?
  case "$lrec_rc" in
    0)
      lrec_verdict="$(printf '%s\n' "$lrec_out" | awk -F'\037' '$1 == "VERDICT" { print $2 " — " $3; exit }')" || lrec_verdict=""
      # A RESUMABLE LANE IS QUIET ONLY WHEN ITS TREES ARE (Codex on ec9847e,
      # PR #97): `resumable` says the swap completed, not that every tree it
      # left is clean, published and where it was. So a resumable lane whose
      # TREES line counts anything dirty or unpushed, needing recovery, or
      # unmanaged or stale is reported like any other verdict.
      lrec_attn="$(printf '%s\n' "$lrec_out" | awk -F'\037' '$1 == "TREES" { split($3, a, " "); split($4, b, " "); split($5, c, " "); print a[1] + b[1] + c[1]; exit }')" || lrec_attn=""
      lrec_quiet=0
      case "$lrec_verdict" in
        running*|closed*|'') lrec_quiet=1 ;;
        resumable*)
          if [ "${lrec_attn:-0}" = 0 ]; then lrec_quiet=1
          else lrec_verdict="$lrec_verdict — and its trees below need reading before a writer is relaunched"
          fi ;;
      esac
      if [ "$lrec_quiet" = 0 ]; then
          note "LANE RECOVERY: $lrec_verdict"
          printf '%s\n' "$lrec_out" | awk -F'\037' '
            $1 == "STATE" { printf "  state    %s (%s, %s)\n", $2, $3, $4 }
            $1 == "HOLDER" { printf "  holder   %s %s\n", $2, $3 }
            $1 == "BINDING" && $2 != "here" && $2 != "free" { printf "  binding  %s %s\n", $2, $3 }
            $1 == "TREE" && $3 != "ok" { printf "  tree     %-18s %s\n", $3, $5 }
            $1 == "TREES" { printf "  trees    %s, %s, %s, %s\n", $2, $3, $4, $5 }' >&2 || :
          note "Nothing here was reset, recreated or deleted. Read it in full with: $LANES_EDIT lane-reconcile $LANE"
      fi ;;
    2 | 8) : ;;
    *) note "the lane recovery read failed (\`$LANES_EDIT lane-reconcile $LANE\` exited $lrec_rc). That is NOT 'this lane stopped cleanly' — a read that failed is never an answer (Amendment 7(d)). This launch goes on; run it by hand to see what it says." ;;
  esac
fi

# ------------------------------------------------------------- 5. the row

utc="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
started="$(date -u +%Y-%m-%dT%H:%MZ)"
today="$(date -u +%Y-%m-%d)"
# THE WORKSTATION COLUMN HAS ONE READER, AND NOW ONE SPELLING (A9 Addendum 4,
# R-A9-13). `lanes-edit.sh:438` computes this very cell as
# `${LANES_WORKSTATION:-$(hostname -s)}` and has since Amendment 6; this file
# computed it as a bare `hostname`, which honours no seam and, on any host
# whose `hostname` is a FQDN, writes `eagle.local` into a column every reader
# compares against `eagle`. Two spellings of one column are two answers. The
# seam is also what makes the moved suite runnable anywhere: its 55 seed rows
# spell the column `Eagle`, so before this it was green on a workstation
# literally named Eagle and on no other machine, GitHub's runners included.
ws_pair="$(lanes_workstation_pair)"
ws="${ws_pair%%	*}"
ws_why="$(lanes_workstation_why "${ws_pair##*	}")"
# A CONTAINER WITH NO CONFIGURED WORKSTATION WRITES NOTHING (Amendment 11,
# decision 8(d), `R-A11-14`). `$ws` goes into the row's workstation column, into
# the row's stamp and into the `session <uuid>@<ws>` of every event line this
# run writes — and `opensoft/brett-wip` `origin/main` already carries six log
# lines naming a container id, in a file nothing rewrites. The refusal is here,
# BEFORE the row and before the log, rather than at each of the three writes.
[ -z "$ws_why" ] || die "$ws_why" 2
env_name="$(basename -- "$CLAUDE_HOME")"
case "$env_name" in .claude|claude) env_name=default ;; esac
# THE AGENT'S OWN SPELLING IN THE ROW'S SESSION CELL (Amendment 17(c)): *"the
# row's session cell keeps its history as Amendment 6 has it; its entries
# already carry the agent's kind (`harness <uuid>`, `Codex <id>`)"*. The
# register has spelled Codex sessions that way since 2026-09-05, so the table
# is the register's own and not a new convention.
# --- BEGIN shared one-line cut (lane-collision-protocol Amendment 13(a)) ---
# BYTE-IDENTICAL IN `lane-start`, `lane-end` AND `lane-handoff`, the three
# commands that write a row's state cell — the same trade the four lane helpers
# already make for their workspace resolver, and for the same reason: a drifted
# copy is TWO ANSWERS to one question, and "what may this line contain, and
# where may it be cut" is one question.
#
# FOUR THINGS THE CELL'S LINE MAY NOT CARRY, and `set-row-state` REFUSES all
# four — which would cost the row its stamp or its closing write, so they are
# fixed here rather than met there:
#
#   ` · `  the phrase's own separator. A second one reads back as a fourth part
#          of `<STATE> · <UTC> · <one line>`; it is spelled `; `.
#   `|`    a cell boundary in a Markdown table row. A launch command or a
#          directory may legitimately hold one — `claude --flag 'a|b'`, a path
#          with a pipe in it — and the row is where it would forge a column
#          (Copilot round 1 on openRepoTools#82). It is spelled `¦`, the broken
#          bar, which is not a separator anywhere here; the object log's own
#          line keeps the character itself.
#   CR/LF  a row is ONE LINE of a table, so a newline in this text would split
#          it in two and every row after it would be read as a lane. Spelled
#          `; ` for the same reason the separator is (Copilot round 2).
#   >240   ratified decision O1's cap. Cut at 230 with the last partial WORD
#          dropped, which is what makes the cut safe: `${s:0:n}` counts BYTES
#          wherever the locale is not a UTF-8 one, and a byte offset can land
#          inside the very characters above. 230 and not 240, so the ` ...`
#          marker fits inside the cap however the two count.
cut_to_line() {   # <line> — the row's one line, safe to hand to set-row-state
  ctl="${1//$'\r'/ }"
  ctl="${ctl//$'\n'/; }"
  ctl="${ctl// · /; }"
  ctl="${ctl//|/¦}"
  [ "${#ctl}" -gt 230 ] || { printf '%s' "$ctl"; return 0; }
  ctl="${ctl:0:230}"
  case "$ctl" in *' '*) ctl="${ctl% *}" ;; esac
  printf '%s ...' "$ctl"
}
# --- END shared one-line cut ---

AGENT_WORD="$AGENT"
case "$AGENT" in
  claude) AGENT_WORD=harness ;;
  codex)  AGENT_WORD=Codex ;;
esac
user="$(id -un)"
handoff="handoffs/$estate/session-handoff-$today-lane-$LANE.md"

# The session cell of a NEW row names the session that is about to run,
# whenever one was minted — that is the whole point of minting it. And where a
# session is ALREADY live in this window (step 3b) the cell names THAT one: a
# lane bound to a running window mid-session is the ordinary shape of
# `--no-launch`, and a row minting a fresh uuid beside a conversation that is
# already there would name a session nobody will ever be in.
harness_cell="harness $harness_sid (transcript uuid; profile ${win_profile:-unknown})"
if [ -n "$harness_sid" ]; then
  session_cell="$harness_cell — live in this window, recorded by $prog $utc"
elif [ -n "$new_sid" ]; then
  session_cell="harness \`$new_sid\` (minted by $prog, $utc)"
else
  session_cell="pending — set by the session's first act"
fi

if [ "$row_count" = 0 ]; then
  # AMENDMENT 13(a) — A NEW ROW IS BORN IN THE PHRASE. The state cell opened
  # with the bare word `STARTING` for as long as the cell was a diary; it is one
  # phrase now — `<STATE> · <UTC> · <one line>` — and a row created outside that
  # shape is a row the first `set-row-state` would be the only thing to fix.
  # `LIVE` is the state, because this row is written by the act that takes the
  # lane live in this window, and the line says which act and on which
  # workstation.
  new_line="$lane_verb by $stamp_who (lane $LANE) — lane-start on $ws: row created"
  new_state="LIVE · $utc · $(cut_to_line "$new_line")"
  new_row="| \`$LANE\` | $session_cell | $ws / $env_name / $user | $started | none | $handoff | $new_state |"
  if (( dry_run )); then
    plan "lanes-edit.sh add-row"
    plan "  $new_row"
  else
    # THE SAME RULE AS THE STAMP ONE SCREEN DOWN, and the opposite ANSWER. A
    # bare command under `set -e` dies with the helper's own code and no
    # sentence of its own; this one is read. But a lane with no ROW is not a
    # lane with an unwritten stamp — every other lane's liveness read, every
    # crossing check and the next `lane-start` all key on that row — so this is
    # a refusal that says so, before the window is anything but renamed.
    ar_rc=0
    LANES_LANE="$LANE" "$LANES_EDIT" add-row "$new_row" || ar_rc=$?
    if [ "$ar_rc" = 0 ]; then
      step "row added"
    else
      die "the register row for $LANE was NOT added ($LANES_EDIT add-row exited $ar_rc; its own words are above). This window has been renamed and NOTHING else has been written — no session cell, no object log, no launch: a lane with no row is a lane no other lane's liveness read, crossing check or \`lane-start\` can see. Settle that refusal and re-run, or add it by hand:
    LANES_LANE=$LANE $LANES_EDIT add-row '$new_row'" "$ar_rc"
    fi
  fi
else
  # AMENDMENT 8 — THE CELL FIRST, THEN THE STAMP. The harness minted a
  # transcript uuid the published cell does not carry (step 3b), and the stamp
  # below is about to name that uuid: writing the stamp first would leave, for
  # as long as the two commits are apart, a row whose status names a session its
  # own session cell does not — and if the append then refused, for ever. So the
  # cell is extended first, with the same `replace-in-row` and the same anchor
  # discipline the minted case uses below: the anchor is the PUBLISHED last id,
  # which refuses exactly when this checkout's copy of the row is older than the
  # one that landed, and a refusal prints the act rather than corrupting a cell.
  if [ -n "$harness_sid" ]; then
    harness_hint="LANES_LANE=$LANE $LANES_EDIT append-session-id $LANE \"<the session cell's last id>\" \"→ $harness_cell\""
    # THE COMMIT SAYS WHICH ACT THIS WAS: under `--bind` nothing was minted, a
    # person moved a running session here (openRepoTools#70).
    harness_why="session cell: the harness minted $harness_sid for this window"
    [ -z "$bind_sid" ] || harness_why="session cell: bound $harness_sid on the person's choice 2 at the name guard (Amendment 12(h) rule 2)"
    if [ -z "$cell_anchor" ]; then
      note "the row's session cell records no transcript uuid to append to (some rows carry only \`session_…\` footer ids, which are not transcript ids). STAMP IT AS THIS SESSION'S FIRST ACT:"
      note "  $harness_hint"
    elif (( dry_run )); then
      plan "lanes-edit.sh append-session-id $LANE '$cell_anchor' '→ $harness_cell'"
    elif LANES_LANE="$LANE" "$LANES_EDIT" append-session-id "$LANE" "$cell_anchor" "→ $harness_cell" "$harness_why"; then
      step "session cell updated: $cell_anchor → $harness_sid (the transcript live in this window)"
    else
      note "the session cell was NOT extended with $harness_sid (this checkout's copy of the row does not carry $cell_anchor exactly once IN ITS SESSION CELL — it may be older than the published one). STAMP IT AS THIS SESSION'S FIRST ACT:"
      note "  $harness_hint"
    fi
  fi

  # The row is the next launch's first source, so make the exact transcript
  # recovered from the lane's PAUSED record its final entry again. Without
  # this, every subsequent launch would rediscover the same dead row id and
  # need the fallback. This is written before the RESUMED status for the same
  # ordering guarantee as the harness-minted append immediately above.
  if [ -n "$restored_sid" ]; then
    restored_cell="harness \`$restored_sid\` (transcript uuid; restored from the lane's last PAUSED record)"
    restored_hint="LANES_LANE=$LANE $LANES_EDIT append-session-id $LANE \"<the session cell's last id>\" \"→ $restored_cell\""
    if [ -z "$row_sid" ]; then
      note "the row's session cell records no transcript uuid to append the recovered id to. STAMP IT AS THIS SESSION'S FIRST ACT:"
      note "  $restored_hint"
    elif (( dry_run )); then
      plan "lanes-edit.sh append-session-id $LANE '$row_sid' '→ $restored_cell'"
    elif LANES_LANE="$LANE" "$LANES_EDIT" append-session-id "$LANE" "$row_sid" "→ $restored_cell" "session cell: restored $restored_sid from the lane's last PAUSED record"; then
      step "session cell updated: $row_sid → $restored_sid (the exact transcript from the lane's last PAUSED record)"
    else
      note "the session cell was NOT extended with recovered transcript $restored_sid (this checkout's copy of the row may be older than the published one). The launch is unaffected and so is the NEXT one: this recovery reads the lane's last PAUSED record and not the cell, so it finds the same transcript again and prints this same act — the row keeps naming an id no transcript answers to until somebody runs it. STAMP IT AS THIS SESSION'S FIRST ACT:"
      note "  $restored_hint"
    fi
  fi

  # AMENDMENT 8's RULE, FOLLOWED HERE TOO: THE CELL FIRST, THEN THE STAMP
  # (Copilot round 5 on openRepoTools#82). The harness path above says it in
  # those words — the stamp names a uuid, so the cell that carries the uuid is
  # written first — and this path did the opposite: it stamped the minted id and
  # THEN tried to append it, so a refused append left the row's state naming a
  # session its own session cell does not carry. The resume target is the
  # SESSION CELL and nothing else (Amendment 6(b)), so that never resumed the
  # wrong conversation — it resumed the id the register knew — but the row said
  # two things a reader has to reconcile. Written in this order the common path
  # says one thing, and a refused append still prints the act that cures it.
  # An EXISTING row that is about to run a NEW session: append the minted id
  # after the cell's last id, so the next start resumes by id instead of by
  # title. The append is `replace-in-row`, which refuses unless its anchor
  # occurs exactly once in the row — so a failure here is a refusal, never a
  # corruption, and it never fails the launch.
  #
  # THE ANCHOR IS THE PUBLISHED ID AND THE FILE IS THIS CHECKOUT'S, which is a
  # refusal exactly when the two disagree — a stale copy of the row, the case
  # the read above exists for. That is the right way round: appending after the
  # id THIS copy ends on would write a cell that no longer matches the one that
  # landed, and `commit_push`'s rebase would then conflict on the same line. The
  # refusal prints the act instead, and the launch is unaffected.
  if [ -n "$new_sid" ]; then
    stamp_hint="LANES_LANE=$LANE $LANES_EDIT append-session-id $LANE \"<the session cell's last id>\" \"→ harness \\\`$new_sid\\\`\""
    if [ -z "$row_sid" ]; then
      note "the row's session cell records no session id this script can read (some rows carry only \`session_…\` footer ids). STAMP IT AS THIS SESSION'S FIRST ACT:"
      note "  $stamp_hint"
    elif (( dry_run )); then
      plan "lanes-edit.sh append-session-id $LANE '$row_sid' '→ harness \`$new_sid\`'"
    elif LANES_LANE="$LANE" "$LANES_EDIT" append-session-id "$LANE" "$row_sid" "→ harness \`$new_sid\`" "session cell: $prog minted $new_sid for this window"; then
      step "session cell updated: $row_sid → $new_sid"
    else
      note "the session cell was NOT stamped (this checkout's copy of the row does not carry $row_sid exactly once IN ITS SESSION CELL — it may be older than the published one). STAMP IT AS THIS SESSION'S FIRST ACT:"
      note "  $stamp_hint"
    fi
  fi

  # AMENDMENT 6(c)'s STAMP, WRITTEN HERE. The row's first act after a resume is
  # `RESUMED by <transcript uuid>`, and under Amendment 6(b) that stamp is
  # load-bearing: it is what the NEXT lane-start resumes, so a missed one is not
  # bookkeeping debt, it is a lost lane. It used to be owed to the session that
  # lane-start had just exec'd — which is a stamp nobody writes when the session
  # dies at a usage reset before its first act, the shape this estate hits daily.
  # The verb follows the launch decision, exactly as the object-log line does: a
  # resume is RESUMED and a new session is STARTED, and the uuid is the one this
  # run actually resumes or mints, read from the PUBLISHED row (R33) or from the
  # record live in this window (step 3b).
  # THE TAIL STATES WHAT HAPPENED (Amendment 8(d), F-B5). The old line said
  # `launching <cmd>` unconditionally, so a `--no-launch` run stamped the row
  # with a launch that by definition did not happen — and `--no-launch` is now
  # the PRESCRIBED act twice over in clause (d) (the harness-mint append, and
  # the deferred writes of the title-fallback path), so the defect would have
  # become the common case rather than an edge. The head of the stamp — the
  # part Amendment 6(b) and clause (d) quote, up to and including `lane-start on
  # <ws>:` — is unchanged.
  # AMENDMENT 13(a) — WHAT HAPPENED FIRST, AND THE PLACE IT HAPPENED AFTER IT.
  # The tail used to read `window renamed, dir <dir>, window <ref>, launching
  # <cmd>`, and under a 240-character cap (ratified decision O1) that order puts
  # the ONE FACT THAT IS NOWHERE ELSE — the exact command this run launched —
  # behind two that are recorded twice over: clause (c) writes `dir` and
  # `window` into the lane's own log as sub-fields of this very act's
  # `STARTED`/`RESUMED` line, and Amendment 11's listing prints both as columns.
  # So the launch clause comes first and the two sub-fields follow it, and a
  # line long enough to be cut loses what a reader can look up rather than what
  # they cannot.
  if (( no_launch )); then
    did="window renamed, no launch"
  else
    did="window renamed, launching $(quoted "${cmd[@]}")"
  fi
  did="$did; dir $DIR${record_window:+; window $record_window}"
  # `$stamp_who` is computed with the launch decision above: the uuid for
  # Claude, `<agent> <id>` for any other agent (Amendment 17(c)).
  # AMENDMENT 13(a) — THE STAMP IS THE CELL NOW, not another entry appended to
  # it. The `state` column holds ONE PHRASE, `<STATE> · <UTC> · <one line>`, and
  # `set-row-state` stamps the UTC itself — so this builds the line alone, and
  # the `$utc` this run computed stays where it is still needed (the handoff's
  # Rule 3 stamp and the log line).
  #
  # THE STATE IS `LIVE` EITHER WAY. A launch takes the lane live in this window;
  # `--no-launch` is the recording act of a session that is already in it
  # (Amendment 6(c)), so the lane is live in both branches and the tail says
  # which one happened.
  #
  # AND THE LINE KEEPS `<verb> by <uuid>` WORD FOR WORD, because
  # `row_stamp_is_unknown` reads exactly that pair out of this cell — Amendment
  # 8(e)'s "first cure carries one condition", which tells a wrong lineage from
  # the title fallback. A ` · ` inside the line would read back as a fourth part
  # of the phrase, so it is spelled `; ` here rather than refused at the writer,
  # and a line over the cap is cut rather than costing the row its whole stamp:
  # what will not fit is in the object log, one line along.
  state_line="$lane_verb by $stamp_who (lane $LANE) — lane-start on $ws: $did"
  state_line="$(cut_to_line "$state_line")"
  # AND ITS STATUS IS READ, BECAUSE THIS FILE RUNS UNDER `set -e`. A bare
  # command here is a launch that DIES on the helper's refusal — exit 5, "an
  # edit moved more than one line", straight out of the shell with no sentence
  # of its own and the pane gone before anybody can read the helper's. Measured
  # in this suite: `without --confirm nothing is asked` came back 5, from a row
  # write nobody had asked to be fatal.
  #
  # AND IT IS A NOTE, NEVER A REFUSAL. The row's stamp is the RECORD of a resume
  # and not its licence — the same rule Amendment 6(c) and the handoff's Rule 3
  # stamp already take here — so a stamp that could not be written prints the
  # act that writes it and the lane still starts.
  if (( dry_run )); then
    plan "lanes-edit.sh set-row-state $LANE \"LIVE · $state_line\""
  else
    srs_rc=0
    LANES_LANE="$LANE" "$LANES_EDIT" set-row-state "$LANE" "LIVE · $state_line" || srs_rc=$?
    if [ "$srs_rc" = 0 ]; then
      step "row state set: LIVE · $lane_verb by ${lane_sid:-unknown}"
    else
      note "the row's state cell was NOT set (exit $srs_rc — the helper's own words are above), and the launch is not refused for it: the stamp is the record of this act, not its licence. Set it by hand:"
      note "  LANES_LANE=$LANE $LANES_EDIT set-row-state $LANE \"LIVE · $state_line\""
    fi
  fi

  # AMENDMENT 17(c) — THE CELL, IN THE AGENT'S OWN SPELLING. A launch of an
  # agent that is not Claude mints no transcript uuid and resumes none: the one
  # id it has in hand is the `transcript <id>` the lane's own last handoff
  # recorded (Amendment 17(b)), and the cell is appended with it as the register
  # has spelled such entries since 2026-09-05 — `Codex <id>`.
  #
  # AND NOTHING IS APPENDED WHERE THERE IS NO ID. `pending` in the session cell
  # would be the same defect clause (e) refuses in the session field of a log
  # line: the cell is what Amendment 6(b) resumes from, and a placeholder there
  # is a resume target nobody has. The row's STATE cell still records the act
  # (`RESUMED by codex pending`), because that cell is a history of acts.
  if [ "$AGENT" != claude ] && [ -n "$AGENT_ID" ]; then
    agent_cell="$AGENT_WORD \`$AGENT_ID\`"
    # THE ANCHOR IS THE PUBLISHED ROW'S LAST ID, which is the same anchor the
    # minted-uuid append below uses and for the same reason: `append-session-id`
    # refuses unless it occurs exactly once IN THE SESSION CELL, so a stale copy
    # of the row is a refusal that prints the act rather than a corruption.
    # `$cell_anchor` is NOT it — that variable is set only where a session is
    # live in this window whose uuid the cell lacks (step 3b), which is never
    # the case for a launch of an agent that is not Claude.
    if [ -z "$row_sid" ]; then
      note "the row's session cell records no id to append to, so this launch's $AGENT_WORD id is not in it. STAMP IT AS THIS SESSION'S FIRST ACT:"
      note "  LANES_LANE=$LANE $LANES_EDIT append-session-id $LANE \"<the session cell's last id>\" \"→ $agent_cell\""
    elif (( dry_run )); then
      plan "lanes-edit.sh append-session-id $LANE '$row_sid' '→ $agent_cell'"
    elif LANES_LANE="$LANE" "$LANES_EDIT" append-session-id "$LANE" "$row_sid" "→ $agent_cell" "session cell: $prog launched $AGENT for this lane"; then
      step "session cell updated: $row_sid → $agent_cell"
    else
      note "the session cell was NOT extended with $agent_cell (this checkout's copy of the row may be older than the published one). STAMP IT AS THIS SESSION'S FIRST ACT:"
      note "  LANES_LANE=$LANE $LANES_EDIT append-session-id $LANE \"<the session cell's last id>\" \"→ $agent_cell\""
    fi
  fi
fi

# ------------------------------------------- 5b. the lane's own object log
#
# Amendment 7. AFTER the row, because the row is what `who` reads the lane's
# liveness and handoff path out of, and a log line that named a lane with no
# row would point at nothing. It never fails the launch: a lane that cannot
# write its log still starts, and says that it could not.

# `owner/repo` out of the lane's own origin. Every URL form the estate uses:
# `git@github.com:owner/repo.git`, `https://github.com/owner/repo`, `ssh://…`.
# It CHECKS its own answer. A remote that is a local path, a mirror or any
# non-GitHub URL does not reduce to `owner/repo`, and recording one as the
# lane's home would be inherited by every `#n` that lane ever writes — and a
# home containing a space writes an event line the log's own parser cannot
# read back. `unknown` is the honest answer and the helper already refuses to
# expand `#n` against it.

origin_url="$(git -C "$DIR" remote get-url origin 2>/dev/null || :)"
home_nwo="$(origin_nwo "$DIR" || :)"
if [ -z "$home_nwo" ]; then
  home_nwo=unknown
  if [ -z "$origin_url" ]; then
    note "$DIR has no 'origin' remote, so the lane's home repo is recorded as 'unknown' — its cross-repo checks will not run until it is known"
  else
    note "$DIR's origin ('$origin_url') does not resolve to a GitHub owner/repo, so the lane's home repo is recorded as 'unknown' rather than as something every '#n' in this lane would inherit"
  fi
else
  # THE HOME IS CANONICAL (Amendment 7, R20). A checkout keeps whatever spelling
  # its `origin` had on the day it was cloned, and this estate has moved a
  # repository between orgs while the register was live: a lane homed on
  # `opensoft/codexFactory` wrote `#5` as an object key that could never collide
  # with another lane's `codeXfactory/codexFactory#5`, so two lanes held one
  # GitHub issue and nothing detected it. `lanes/repos.tsv` is what says the two
  # spellings are one repository, and every OTHER spelling in the tooling goes
  # through it — so this one does too, BEFORE the STARTED line is written, since
  # a home is inherited by every `#n` that lane ever writes.
  home_canon=""; hr_rc=0
  home_canon="$("$LANES_EDIT" resolve-repo "$home_nwo" 2>/dev/null)" || hr_rc=$?
  case "$hr_rc" in
    0)
      if [ -n "$home_canon" ] && [ "$home_canon" != "$home_nwo" ]; then
        step "home $home_nwo resolves through lanes/repos.tsv to $home_canon — recording the canonical spelling"
        home_nwo="$home_canon"
      fi ;;
    8)
      note "lanes/repos.tsv has no row for '$home_nwo', so the lane's home is recorded exactly as its origin spells it. If this repository has ever moved org or is spelled more than one way in the register, add a row to lanes/repos.tsv so every lane keys the same object the same way." ;;
    *)
      note "$LANES_EDIT resolve-repo '$home_nwo' failed (exit $hr_rc) — recording the spelling derived from origin" ;;
  esac
fi
# AMENDMENT 11 CLAUSE (c) — THE LANE'S DIRECTORY, PROFILE AND WINDOW, WRITTEN
# HERE BECAUSE THIS IS THE MOMENT THEY ARE ALL CERTAINLY KNOWN.
#
# `dir` closes Amendment 6's oldest open item by the record rather than by a
# symlink, an environment variable or a manifest: a lane's checkout is known to
# every process that is IN it and to nothing about to start one, so the one
# process that is certainly in it writes it down. `profile` is the second, and
# it is taken from `$CLAUDE_PROFILE_NAME`, which the launcher exports into
# every session it starts (`claude-profile:658`) — today a lane's profile is
# recoverable only from the tmux session name `claude-<profile>-<ts>-<pid>`,
# which act 1's window reuse and any rename destroy and which no record
# carries, so a restart typed anywhere but in the lane's surviving window
# cannot name the profile the launcher needs. `window` is Amendment 8(b)'s,
# gaining its `<@id>` ref.
#
# A LINE WRITTEN BEFORE THIS CLAUSE CARRIES NONE OF THEM, AND A READER THAT
# FINDS NONE SAYS SO RATHER THAN ASSUMING ONE — Amendment 7(i)'s cutover rule.
# So each sub-field is appended only where its value is actually in hand: no
# `$CLAUDE_PROFILE_NAME` is a lane started outside the launcher, and inventing
# `unknown` for it would be the same defect clause (e) refuses in the session
# field.
#
# A SPACE IS THE ONE CHARACTER THAT NEEDS A RULE RATHER THAN A REFUSAL, AND THE
# RULE IS QUOTING. Amendment 7(b) makes the space the separator between several
# refs inside one sub-field — which is exactly what `window`'s two refs rely on
# — so an unquoted `dir $HOME/my projects/x` (unquoted) parses as TWO refs and `lane-dir`
# hands back a truncated path that this script then refuses as "no such
# directory". The writer quotes it; `lane-dir` and every other reader take a
# value opening with `"` as running to its closing `"`, and strip both.
quote_subfield() {
  case "$1" in
    *' '*) printf '"%s"' "$1" ;;
    *)     printf '%s' "$1" ;;
  esac
}
lane_profile="${CLAUDE_PROFILE_NAME:-}"
case "$lane_profile" in
  *', '*|*' — '*|*'; '*|*'"'*)
    note "\$CLAUDE_PROFILE_NAME is '$lane_profile', which contains ', ', ' — ', '; ' or '\"' — the lane's \`profile\` sub-field is left out rather than written unreadable"
    lane_profile="" ;;
esac
lane_payload="home $home_nwo; estate $estate; dir $(quote_subfield "$DIR")"
[ -n "$lane_profile" ] && lane_payload="$lane_payload; profile $(quote_subfield "$lane_profile")"
[ -n "$record_window" ] && lane_payload="$lane_payload; window $record_window"
# `claude <version>`: the Claude Code this launch starts, as claude-current read
# it here or as a launcher's own claude-current handed it on
# (opensoft/workBenches#119). In hand only then, so appended only then, for
# the reason given above; and a version is digits, dots and a tag, so a value
# that is not one is left out rather than written into a line nothing rewrites.
lane_claude_version_re='^[0-9]+\.[0-9]+\.[0-9]+([-+][0-9A-Za-z.+-]+)?$'
if [ "$AGENT" = claude ] && [ -n "$lane_claude_version" ]; then
  if [[ "$lane_claude_version" =~ $lane_claude_version_re ]]; then
    lane_payload="$lane_payload; claude $lane_claude_version"
  else
    note "the Claude Code version '$lane_claude_version' is not x.y.z, so the lane's log line carries no \`claude\` sub-field"
  fi
fi

# AMENDMENT 8(d), R-A8-2 — `unknown` NEVER REACHES THE OBJECT LOG, AND THE RULE
# IS THE CONDITION RATHER THAN THE PATH. Amendment 7(b): the `session` field is
# the transcript uuid and only that. `lane_sid` is the literal `unknown`
# wherever this run has no uuid to name — the title fallback, where the picker
# has not run when the stamps would be written; a session already live in this
# window whose transcript is not in this directory; a run with no uuid source at
# all; `LANE_START_SESSION_ID=0`. The log is APPEND-ONLY, so a line written
# wrong there is wrong for ever, and the grammar's own writer does not write a
# line it cannot fill in. It is not a narrowing of Amendment 7 either: A8
# narrows A7 in exactly one place, clause (b)'s `PAUSED` payload, and not here.
#
# THE ROW'S STAMP STILL CARRIES `unknown`, and that is deliberate: the state
# cell is a history of ACTS, the act happened, and a placeholder there is a
# thing a reader can see. `unknown` never enters the SESSION cell, which is what
# Amendment 6(b) resumes from, and so is never replaced in it.
#
# BOTH DEFERRED RECORDS ARE WRITTEN BY THE FIRST ACT THAT KNOWS THE UUID — the
# session's own `lane-start --no-launch`, which clause (e)'s hook prompts by
# name. That run reads the live record whose tmux target is this window, APPENDS
# that uuid to the session cell through the cell-scoped edit, and only then
# writes this line and the handoff's stamp, both carrying the real uuid.
# (`lane_sid_known` is computed with the launch decision above, which is where
# `lane_sid` is decided and where the row's own stamp first reads it.)
#
# AND THE COMMAND IT PRINTS CARRIES THE AGENT THIS RUN WAS GIVEN
# (opensoft/openRepoTools#72 item 5). `$self_args` is the lane and nothing
# else, so a lane started `--agent codex` — which never has a uuid here, so it
# ALWAYS reaches this line — was handed a first act that dropped the flag, and
# the person who ran it had `lane-agent` choose instead: the agent of the lane's
# last PAUSED, which is whichever agent paused it and not the one now running
# it. `AGENT_EXPLICIT` is 1 for an agent named on the command line and for one
# the record named that is not the default; either way the run that settles
# this one is the same agent's, so it is written down, quoted like every other
# command this file prints. It goes AFTER the lane's own arguments, so the
# `--no-launch <repo> <n>` a reader looks for is still one run of words.
ls_defer_agent=""
if (( AGENT_EXPLICIT )); then ls_defer_agent=" $(quoted --agent "$AGENT")"; fi
if (( ! lane_sid_known )); then
  note "no transcript uuid is knowable at this instant (the row's stamp says '${lane_sid:-unknown}'), so the lane's $lane_verb log line is NOT written: Amendment 7(b) makes that field a transcript uuid and only that, and the log is append-only. Nor is the handoff's Rule 3 stamp. BOTH are written by the first act that knows the uuid, which is this session's own:"
  note "  $prog --no-launch $self_args$ls_defer_agent"
elif (( dry_run )); then
  plan "lanes-edit.sh log $lane_verb lane:$LANE → \"$lane_payload\""
else
  if LANES_LANE="$LANE" LANES_SESSION="$lane_sid" "$LANES_EDIT" log "$lane_verb" "lane:$LANE" '→' "$lane_payload"; then
    step "object log: $lane_verb lane:$LANE, home $home_nwo"
  else
    note "the lane's object log was NOT written ($lane_verb, home $home_nwo). Write it as this session's first act:"
    note "  LANES_LANE=$LANE $LANES_EDIT log $lane_verb lane:$LANE '→' \"$lane_payload\""
  fi
fi

# ------------------------------------------- 5c. the handoff's Rule 3 stamp
#
# AMENDMENT 8 — LANE-START WRITES THE RULE 3 STAMP. Rule 3 makes the FIRST act
# of a lane resuming from a handoff a stamp on that handoff, in place, before
# it reads any further and before any other act. It was the SESSION's to write,
# and it was missed every time: seven resumes of this lane needed it written by
# hand afterwards, and while it was owed the three records of the same day
# disagreed about how many resumes there had been — the row said six, the
# object log four, the handoff five, about ONE lane on ONE day. Amendment 6(c)
# found exactly this about the row's own stamp and cured it the same way: the
# boundary act that KNOWS the resume writes the record of it, because a stamp
# that is owed is a stamp that is missed.
#
# ON A RESUME OF AN EXISTING ROW, AND NOTHING ELSE. The verb is `$lane_verb` —
# the very one 5a decided for the row's status and 5b's object line — so the
# three can never disagree about whether this was a resume. A brand-new row is
# not a resume of anything: the file its handoff cell names does not exist yet,
# and the session that will write it has not run.
#
# THE INSERT POINT IS RULED: the line immediately after the first blank line
# that follows line 1 — line 1 being the lane header (Rule 4) and the blank the
# end of the header block. That puts THIS resume at the top of the block of
# stamps, above the ones before it.
#
# AFTER 5b, so that every `lanes-edit.sh` write this run makes is already
# committed before this one touches the checkout at all. The register and the
# handoffs share one checkout, and the helper REFUSES a checkout carrying an
# uncommitted change to a tracked file it is not itself writing (Amendment 5,
# `dirty_elsewhere`). Stamp the handoff first and let its commit fail, and the
# edit made for the row is the reason the row cannot be written.
#
# AND IT IS NEVER A REASON TO REFUSE THE LAUNCH. A handoff that has moved, a
# checkout with no git, a rebase conflict, a push that hangs — each one prints
# the command that finishes the act, and the lane still starts. Rule 3's stamp
# is the RECORD of a resume, not the licence for one, and refusing the session
# would lose the conversation the stamp is about. (Rule 3 also says a lane that
# finds an existing stamp stops and reports. That is addressed to the session
# reading the resume prompt, not to the act that records the resume: the file
# already carries one line per resume and gains one more.)

# Ruling (h)'s bound, in this script's own few lines rather than reached for in
# the helper's: every git call that touches the NETWORK runs under
# `LANES_GIT_TIMEOUT` seconds (default 60; `0` or a non-number turns the bound
# off), so a hung remote costs the launch a minute and never the session. No
# `timeout` on PATH is not a reason to skip the call — it is a reason to make
# it unbounded, which is what this did before the bound existed.
HS_TIMED_OUT=0
hs_git_net() {
  local rc=0 budget="${LANES_GIT_TIMEOUT:-60}"
  HS_TIMED_OUT=0
  case "$budget" in
    ''|0|*[!0-9]*) "${LANES_GIT:-git}" "$@" || rc=$? ;;
    *)
      if command -v timeout >/dev/null 2>&1; then
        timeout -k 5 "$budget" "${LANES_GIT:-git}" "$@" || rc=$?
        case "$rc" in 124|137) HS_TIMED_OUT=1 ;; esac
      else
        "${LANES_GIT:-git}" "$@" || rc=$?
      fi ;;
  esac
  return "$rc"
}

# F-B7 — WHICH CASE THE READER IS IN, said rather than assumed. A stamp that is
# committed here and not pushed is carried out by the next `lanes-edit.sh` write
# ONLY where the handoff lives in the register's own checkout: that write pushes
# the BRANCH, so it takes the orphaned commit with it. `hs_resolve` also accepts
# an absolute path and a workspace root, either of which can land outside
# `$LANES_REPO` — and nothing ever pushes a commit made there, because no
# `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
    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.)"
  fi
  return 0
}

# The workspace repository, which is where handoffs live (Amendment 4(a)) and,
# since Amendment 9(a), where the register lives too. THIS USED TO BE A SECOND
# READER of the same file with a looser rule — it took any `path:` at any
# indentation and checked nothing — and Amendment 9(a) is explicit that a
# second way to find one thing is a second answer. It now defers to the one
# resolver above, which is the same in all four helpers.

# The handoff path is field 7 of the PUBLISHED row: the register's header is
# `| lane | session id | workstation / env / user | started (UTC) | objects
# owned | handoff path | state |`, and awk's field 1 is the empty string before
# the leading pipe. A row carrying an EXTRA cell after its state — there are
# such rows — does not move field 7; counting back from NF would.
# AND IT STAMPS ONLY WITH A REAL UUID (R-A8-2). A stamp naming `unknown` is a
# Rule 3 record that answers nothing about who resumed, in the one document this
# protocol cannot afford to rewrite; the note above names the act that writes it
# together with the deferred log line, at the first instant either can be right.
# AND THE STAMP NAMES THE AGENT WHERE ONE WAS NAMED (Amendment 17(c)): *"the
# Rule 3 resume prompt … single-use, and stamped `RESUMED by …` before anything
# else, as Rule 3 requires"*. `$stamp_ok` is `$lane_sid_known` for Claude — the
# rule R-A8-2 gives — and 1 for an agent whose id is its own kind of id, because
# refusing that stamp would leave Rule 3 unstamped for every launch this
# amendment exists to make.
if [ "$lane_verb" = RESUMED ] && [ "$row_count" = 1 ] && (( stamp_ok )); then
  hs_cell="$(cell 7 | sed 's/^[[:space:]]*//; s/[[:space:]]*$//' || :)"
  hs_stamp="RESUMED by $stamp_who (lane $LANE) at $utc — lane-start on $ws"
  hs_subject="handoff($LANE@$ws): RESUMED by $stamp_who"
  hs_trailer="Lane: $LANE ($ws)"
  hs_file=""
  if [ -z "$hs_cell" ]; then
    step "the row names no handoff path, so there is no Rule 3 stamp to write"
  elif ! hs_file="$(hs_resolve "$hs_cell")"; then
    hs_ws_root="$(hs_workspace_root 2>/dev/null || :)"
    note "the handoff the row points at was NOT found, so Rule 3's stamp is not written: '$hs_cell'"
    note "  looked under ${LANES_REPO:-<this checkout has no git root>} and ${hs_ws_root:-<no readable path: in ${AGENT_PROTOCOL_ROOT:-$HOME/.agents}/workspace.yaml>}"
    note "  STAMP IT AS THIS SESSION'S FIRST ACT — this line under the handoff's header block:"
    note "    $hs_stamp"
    note "  then: git -C <the workspace repo> commit -m \"$hs_subject\" -m \"$hs_trailer\" -- <the file>"
  else
    # A handoff may be reached through the estate's `handoffs` symlink, so the
    # path git is given is the REAL one: a pathspec that leaves the repository
    # lexically is a pathspec git refuses, however plainly it is inside it.
    # `cd -P` AND NOT `readlink -f`, for the reason `real_of` gives above and
    # `lane-handoff` gives one file over (Copilot round 3 on openRepoTools#47):
    # an unresolved path here is a `hs_rel` git refuses as a pathspec, and the
    # stamp is then written and never committed.
    hs_dirreal="$( CDPATH=''; cd -P -- "$(dirname -- "$hs_file")" 2>/dev/null && pwd -P )" ||
      hs_dirreal="$(dirname -- "$hs_file")"
    hs_real="$hs_dirreal/$(basename -- "$hs_file")"
    # Resolve a final-component symlink too; atomic publication replaces its
    # real target and leaves the estate link intact.
    hs_links=0
    while [ -L "$hs_real" ]; do
      hs_links=$((hs_links + 1))
      [ "$hs_links" -lt 40 ] || die "the handoff symlink chain cannot be resolved. Nothing was launched." 2
      hs_link="$(readlink "$hs_real")" || die "the handoff symlink could not be read." 2
      case "$hs_link" in /*) hs_real="$hs_link" ;; *) hs_real="$(dirname -- "$hs_real")/$hs_link" ;; esac
      hs_dirreal="$( CDPATH=''; cd -P -- "$(dirname -- "$hs_real")" && pwd -P )" || die "the handoff target directory is missing." 2
      hs_real="$hs_dirreal/$(basename -- "$hs_real")"
    done
    hs_repo="$(git -C "$(dirname -- "$hs_real")" rev-parse --show-toplevel 2>/dev/null || :)"
    hs_rel="$hs_real"
    [ -n "$hs_repo" ] && hs_rel="${hs_real#"$hs_repo"/}"
    hs_fix="git -C ${hs_repo:-<the workspace repo>} commit -m \"$hs_subject\" -m \"$hs_trailer\" -- $hs_rel"
    hs_at=""
    if [ -r "$hs_real" ] && [ -s "$hs_real" ]; then
      hs_at="$(awk 'NR > 1 && /^[[:space:]]*$/ { print NR; exit }' "$hs_real" || :)"
      if [ -z "$hs_at" ]; then
        hs_at=1
        note "$hs_rel has no blank line after line 1, so it has no header block to stamp under — the stamp goes directly under line 1"
      fi
    fi
    if [ -z "$hs_at" ]; then
      note "the handoff the row points at is empty or unreadable, so Rule 3's stamp is not written: $hs_file"
      note "  STAMP IT AS THIS SESSION'S FIRST ACT — this line under the handoff's header block:"
      note "    $hs_stamp"
      note "  then: $hs_fix"
    elif (( dry_run )); then
      plan "stamp $hs_rel at line $((hs_at + 1)): $hs_stamp"
      plan "$hs_fix"
      plan "  then git -C ${hs_repo:-<the workspace repo>} pull --rebase origin ${LANES_BRANCH:-main} && … push origin ${LANES_BRANCH:-main}"
    else
      # THE FILE IS SPLICED, NEVER REWRITTEN. A handoff is the one document in
      # this protocol whose whole purpose is to be read by a later session, and
      # the act that deleted two lanes' rows on 2026-09-08 was a file written
      # whole from what somebody remembered of it. So: read it, put ONE line
      # in, write the rest back unchanged — and prove it before it lands. The
      # added line must be exactly the stamp, at exactly the ruled position,
      # and taking that line back out again must give the original file byte
      # for byte. If it does not, nothing is written at all: that is also what
      # catches a file whose last line has no newline, where `head` would glue
      # the stamp on to the end of it.
      hs_tmpd="$(mktemp -d)"
      hs_pre="$hs_tmpd/pre"; hs_out="$hs_tmpd/out"
      if ! cat -- "$hs_real" > "$hs_pre" 2>/dev/null; then
        note "the handoff the row points at could not be read, so Rule 3's stamp is not written: $hs_file"
        note "  STAMP IT AS THIS SESSION'S FIRST ACT — this line under the handoff's header block:"
        note "    $hs_stamp"
        note "  then: $hs_fix"
      else
        if [ "$ri_active" = 1 ] && [ "$ri_expected_digest" != none ] &&
           [ "$(handoff_digest_of "$hs_pre")" != "$ri_expected_digest" ]; then
          rm -rf -- "$hs_tmpd"
          die "the restart handoff changed before its owned resume stamp. Nothing was launched." 2
        fi
        { head -n "$hs_at" -- "$hs_pre"
          printf '%s\n' "$hs_stamp"
          tail -n "+$((hs_at + 1))" -- "$hs_pre"
        } > "$hs_out"
        if [ "$(sed -n -e "$((hs_at + 1))p" "$hs_out")" = "$hs_stamp" ] &&
           { head -n "$hs_at" -- "$hs_out"; tail -n "+$((hs_at + 2))" -- "$hs_out"; } | cmp -s - "$hs_pre"
        then
          if [ "$ri_active" = 1 ]; then
            ri_post_digest="$(handoff_digest_of "$hs_out")"
            # Persist both sides of this exact, verified stamp splice before
            # publishing bytes. Interruption on either side remains retryable.
            if ! LANES_NO_FETCH=1 "$LANES_EDIT" set-restart-intent "$LANE" starting \
              --expect starting --expect-operation "$ri_op" \
              --expect-generation "$ri_gen" --expect-attempt "$ri_attempt" \
              --expect-new-transcript "$lane_sid" --digest "$ri_expected_digest" --prepared-digest "$ri_post_digest" \
              --reason 'owned handoff stamp prepared' >/dev/null; then
              rm -rf -- "$hs_tmpd"
              die "this attempt could not reserve its handoff stamp. Nothing was launched." 2
            fi
            ri_expected_digest="$ri_post_digest"
          fi
          hs_publish_args=(publish-handoff "$LANE" "$hs_real" "$hs_out" --expect-digest "$(handoff_digest_of "$hs_pre")")
          if [ "$ri_active" = 1 ]; then
            hs_publish_args+=(--operation "$ri_op" --generation "$ri_gen" --attempt "$ri_attempt" --state starting --transcript "$lane_sid")
          fi
          if ! LANES_NO_FETCH=1 "$LANES_EDIT" "${hs_publish_args[@]}" >/dev/null; then
            rm -rf -- "$hs_tmpd"
            die "the handoff stamp could not be published atomically under its writer lock. Nothing was launched." 2
          fi
          step "handoff stamped at line $((hs_at + 1)) of $hs_rel: $hs_stamp"
          if [ "${LANES_NO_GIT:-0}" = 1 ]; then
            note "LANES_NO_GIT=1 — the stamp is written and NOT committed:"
            note "  $hs_fix"
          elif [ -z "$hs_repo" ]; then
            note "$hs_real is not inside a git checkout, so the stamp cannot be committed from here — it is written, and nothing outside this machine knows it."
          else
            # AMENDMENT 4(d) — one commit per write, an EXPLICIT pathspec, and
            # the `Lane:` trailer. Never `git add -A` and never a bare `git
            # commit`: this checkout is shared with every other lane on this
            # workstation, and a write left uncommitted is captured by the next
            # lane's commit with its attribution lost.
            hs_rc=0
            "${LANES_GIT:-git}" -C "$hs_repo" add -- "$hs_rel" 1>&2 || hs_rc=$?
            if [ "$hs_rc" = 0 ]; then
              "${LANES_GIT:-git}" -C "$hs_repo" commit -q -m "$hs_subject" -m "$hs_trailer" -- "$hs_rel" 1>&2 || hs_rc=$?
            fi
            if [ "$hs_rc" != 0 ]; then
              note "the stamp is written but NOT committed (git exit $hs_rc) — an uncommitted write is captured by the next lane's commit and its attribution is lost (Amendment 4(d)). Commit it yourself:"
              note "  $hs_fix"
            else
              step "handoff stamp committed: $hs_subject"
              hs_branch="${LANES_BRANCH:-main}"
              if ! hs_git_net -C "$hs_repo" pull --rebase -q origin "$hs_branch" 1>&2; then
                "${LANES_GIT:-git}" -C "$hs_repo" rebase --abort >/dev/null 2>&1 || :
                if [ "$HS_TIMED_OUT" = 1 ]; then
                  note "the pull before the push TIMED OUT after ${LANES_GIT_TIMEOUT:-60}s (ruling (h): the launch does not wait on a hung remote) — the stamp is a local commit here and was not pushed."
                else
                  note "the pull before the push did not apply (a conflict, or no reachable origin) — the rebase is aborted, the checkout is clean, and the stamp is a local commit here that was not pushed."
                fi
                # RV-B3 — LOOK FIRST, because an aborted pull does NOT mean the
                # commit stayed here. Observed live 2026-09-12T23:04Z: this
                # lane's handoff commit hit an abort on a peer lane's untracked
                # log file, and the peer's own helper then rebased and pushed —
                # carrying this lane's local commit `59a2576` out to origin
                # underneath its own `f053245`. A reader who ran the re-push
                # blind at that point lands the same stamp twice, in the one
                # document this protocol cannot afford to rewrite. The
                # push-rejected branch below has always said to look; this one
                # promised a recovery that is sometimes already done.
                note "  git -C $hs_repo fetch origin $hs_branch && git -C $hs_repo log --oneline origin/$hs_branch -3   # a peer's push may already carry it"
                note "  git -C $hs_repo pull --rebase origin $hs_branch && git -C $hs_repo push origin $hs_branch      # only if it is not there"
                hs_carry_note
              elif ! hs_git_net -C "$hs_repo" push -q origin "$hs_branch" 1>&2; then
                if [ "$HS_TIMED_OUT" = 1 ]; then
                  note "the push TIMED OUT after ${LANES_GIT_TIMEOUT:-60}s (ruling (h)) — a hung push often LANDED and the connection did not close, so look before pushing again."
                else
                  note "the push was rejected — the stamp is a local commit here and other workstations cannot see it yet."
                fi
                note "  git -C $hs_repo fetch origin $hs_branch && git -C $hs_repo log --oneline origin/$hs_branch -3"
                note "  git -C $hs_repo push origin $hs_branch      # only if it is not there"
                hs_carry_note
              else
                step "handoff stamp pushed to origin/$hs_branch"
              fi
            fi
          fi
        else
          note "the splice of Rule 3's stamp into $hs_rel did not prove out (one line added, none changed), so NOTHING was written to it. Add this line under its header block yourself:"
          note "    $hs_stamp"
          note "  then: $hs_fix"
        fi
      fi
      rm -rf -- "$hs_tmpd"
    fi
  fi
fi

# ------------------------- 5d. the first prompt (Amendment 17(c) and (f))
#
# *"it launches the named agent with THE HANDOFF'S TOP BLOCK AS ITS FIRST
# PROMPT (the Rule 3 resume prompt, read from the file the row names)"*.
#
# AFTER 5c, AND THAT ORDER IS THE WHOLE OF RULE 3. The block handed to the new
# session is read AFTER this run has stamped `RESUMED by …` into the file, so
# the session reads a prompt that already carries the record of its own resume —
# and a `/ctx` respawn hands over the block `lane-handoff` wrote one step
# earlier, which is the same bytes from the same file rather than a second copy
# of them.
#
# THE TOP BLOCK IS THE HEAD OF THE FILE DOWN TO THE FIRST `---` RULE, which is
# the marker every refresh writes between the fresh block and the history below
# it, and 200 lines at the outside for a handoff that has none. A first prompt
# is a prompt, not a document: the session reads the rest of the file itself,
# and that is what "older sections below are history" means.
handoff_top_block() {   # <file>
  awk 'NR > 1 && $0 ~ /^---[ \t]*$/ { exit } { print } NR >= 200 { exit }' "$1"
}

if (( first_prompt )); then
  fp_cell=""
  if [ "$row_count" = 1 ]; then
    fp_cell="$(cell 7 | sed 's/^[[:space:]]*//; s/[[:space:]]*$//' || :)"
  else
    fp_cell="$handoff"
  fi
  fp_file=""
  [ -n "$fp_cell" ] && fp_file="$(hs_resolve "$fp_cell" 2>/dev/null || :)"
  if [ "$ri_active" = 1 ] && (( fresh )); then
    [ -n "$fp_file" ] && [ "$fp_file" -ef "$ri_hf" ] ||
      die "the delivered restart prompt is not the intent-bound handoff. Nothing was launched." 2
    [ "$ri_expected_digest" = none ] || [ "$(handoff_digest_of "$fp_file")" = "$ri_expected_digest" ] ||
      die "the restart handoff changed after preparation. Nothing was launched." 2
  fi
  if [ -n "$fp_file" ] && [ -s "$fp_file" ]; then
    fp_text="$(handoff_top_block "$fp_file")"
    if [ "$ri_active" = 1 ] && (( fresh )); then
      [ -n "$fp_text" ] || die "the supervised handoff has no first prompt. Nothing was launched." 2
      [ "$ri_expected_digest" = none ] || [ "$(handoff_digest_of "$fp_file")" = "$ri_expected_digest" ] ||
        die "the restart handoff changed while reading its prompt. Nothing was launched." 2
    fi
    if [ -n "$fp_text" ]; then
      cmd+=("$fp_text")
      step "first prompt: the top block of $fp_cell ($(printf '%s\n' "$fp_text" | grep -c .) lines), delivered to $AGENT as its opening prompt"
    else
      note "the handoff the row names is empty at its head, so $AGENT is launched with no first prompt: $fp_file"
    fi
  else
    # NEVER A REASON TO REFUSE THE LAUNCH, for the same reason a handoff that
    # cannot be stamped is not: Rule 3's block is the RECORD a session resumes
    # from, and a session with no prompt can still read the file itself.
    note "the handoff the row names was not found${fp_cell:+ ('$fp_cell')}, so $AGENT is launched with no first prompt. Its first act is to read that file and stamp it (Rule 3)."
  fi
fi

# --------- 5c. the transcript this launch is about to make, INTO THE INTENT
#
# THE SUPERVISOR CANNOT CONFIRM WHAT IT WAS NEVER TOLD (openRepoTools#94). Its
# readiness predicate asks whether the EXPECTED new transcript exists and is
# bound to this lane; the only process that knows which uuid that is, is this
# one, and only after 5a minted it. So it is written back into the intent
# before the `exec` — the last act this command takes that the supervisor can
# read — and the state goes with it: `starting` is *a launch was prepared for
# this operation*, and the legacy intent stays starting
# until readiness is CONFIRMED.
#
# THE WRITE IS FENCED ON THE OPERATION AND ON NOTHING ELSE. A launch that has
# been superseded between 5a and here writes nothing, and says so: the exit 7
# is the intent telling this run that a newer operation owns the lane.
#
# A FAILED FENCE OR WRITE REFUSES THE LAUNCH. An observer declining to mark
# readiness cannot undo the effects of a stale process that was already execed.
if (( fresh )) && [ "$ri_active" = 1 ] && (( ! no_launch )) && (( ! dry_run )); then
  ri_new="$lane_sid"
  [ -n "$ri_new" ] && [ "$ri_new" != unknown ] || ri_new="${new_sid:-}"
  ri_wrc=0
  # FENCED ON THE GENERATION AS WELL AS THE OPERATION (Copilot round 2 on
  # openRepoTools#121), which is what every write the supervisor makes of this
  # same intent carries. `$ri_gen` is the generation this run READ at the top,
  # before anything was renamed or written, and the supervisor's claim keeps it
  # — so a legacy operation advanced between the two has a launch here that
  # writes nothing and says so, rather than stamping its expected transcript
  # onto a newer generation's record.
  ri_fence=()
  case "${ri_gen:-}" in '' | *[!0-9]*) : ;; *) ri_fence=(--expect-generation "$ri_gen" --expect-attempt "$ri_attempt") ;; esac
  LANES_NO_FETCH=1 "$LANES_EDIT" legacy-restart-check "$LANE" ||
    die "managed ownership blocks the prepared legacy launch. Nothing was launched." 2
  LANES_NO_FETCH=1 "$LANES_EDIT" set-restart-intent "$LANE" starting \
    --expect 'pending|starting' --expect-operation "$ri_op" \
    ${ri_fence[@]+"${ri_fence[@]}"} \
    ${ri_new:+--new-transcript "$ri_new"} \
    --expect-new-transcript "$ri_new" --digest "$ri_expected_digest" --prepared-digest none \
    --reason "lane-start prepared the launch" >/dev/null 2>&1 || ri_wrc=$?
  case "$ri_wrc" in
    0) step "restart intent $ri_op: starting${ri_new:+, expected transcript $ri_new}" ;;
    7) die "the restart intent moved under this launch: another operation owns lane $LANE now. This stale launch was refused before exec. Re-read it: lanes-edit.sh restart-intent $LANE" 2 ;;
    *) die "the prepared transcript could not be recorded (set-restart-intent exited $ri_wrc). This supervised launch was refused before exec because readiness cannot verify its identity." 1 ;;
  esac
fi

# ------------- 5e. the estate's daily report (opensoft/openRepoTools#162)
#
# ONCE A DAY PER WORKSTATION, DETACHED, AND NEVER A REASON A START WAITS OR
# FAILS. `lane-worktrees sweep --all --dry-run --report` is the net under every
# actor that never runs `lane-end`: what is FOREIGN, orphaned, unpublished,
# aging or past retention across the estate, as one table, written to the state
# directory. It changes nothing. The first start of the day takes the stamp -
# `set -C` makes taking it one atomic create, so two starts at once run one
# report - and starts it with stdin, stdout and stderr closed, in a subshell
# that exits at once, so the report is no child of the session this command is
# about to exec. Every step of this either works or is skipped in silence:
# a report that could not start is tomorrow's start's to run.
# `LANE_WORKTREES_REPORT=off` is the switch, and both suites set it.
lane_daily_report() {
  [ "${LANE_WORKTREES_REPORT:-on}" = off ] && return 0
  ldr_bin=""
  if [ -x "$SCRIPT_DIR/lane-worktrees" ]; then
    ldr_bin="$SCRIPT_DIR/lane-worktrees"
  else
    ldr_bin="$(command -v lane-worktrees 2>/dev/null || :)"
  fi
  [ -n "$ldr_bin" ] || return 0
  ldr_state="${XDG_STATE_HOME:-$HOME/.local/state}/openRepoTools"
  ldr_day="$(date -u +%Y%m%d 2>/dev/null || :)"
  [ -n "$ldr_day" ] || return 0
  # THE REPORT IS PRIVATE (#170 item 11): it names every path, branch and lane
  # of the estate. Its directories are 0700, and it is written under umask 077.
  # A directory that could not be made 0700 - one that already existed wider,
  # on a file system or under an owner that refuses the chmod - runs NO report
  # (#179, Copilot round 1): the stamp is not taken, so tomorrow's start tries
  # again, and a report never lands where every local account could read it.
  ( umask 077; mkdir -p -- "$ldr_state/reports" ) 2>/dev/null || return 0
  chmod 700 "$ldr_state" "$ldr_state/reports" 2>/dev/null || return 0
  ( set -C; : > "$ldr_state/report-$ldr_day.stamp" ) 2>/dev/null || return 0
  for ldr_old in "$ldr_state"/report-*.stamp; do
    [ "$ldr_old" = "$ldr_state/report-$ldr_day.stamp" ] || rm -f -- "$ldr_old" 2>/dev/null || :
  done
  ldr_out="$ldr_state/reports/$(date -u +%Y%m%dT%H%M%SZ).md"
  # THE ESTATE THIS START READS: `$PROJECTS_ROOT` as resolved above, named to
  # the report rather than left for it to find again.
  ldr_estate=""
  [ -d "$PROJECTS_ROOT" ] && ldr_estate="$PROJECTS_ROOT"
  # A PANE KILLED AFTER THE STAMP WAS TAKEN DOES NOT TAKE THE REPORT WITH IT
  # (#170 E8): the report ignores the hangup (`nohup`, everywhere), and where
  # there is a `setsid` (Linux; macOS has none) it is in a session of its own,
  # which no terminal's hangup reaches at all. Otherwise today's stamp would
  # name a report that never finished, and none would run until tomorrow.
  ldr_detach=""
  command -v setsid >/dev/null 2>&1 && ldr_detach="setsid"
  ( umask 077
    $ldr_detach nohup "$ldr_bin" sweep --all --dry-run --report --post "$ldr_out" \
      ${ldr_estate:+--estate "$ldr_estate"} </dev/null >/dev/null 2>&1 & ) 2>/dev/null || :
  step "the estate's daily report is running, detached: $ldr_out"
  return 0
}
(( dry_run )) || lane_daily_report || :

# ---------------------------------------------------------------- 6. launch
#
# `cmd` was decided in 5a, before the row was written.

if (( no_launch )); then
  quoted "${cmd[@]}"; printf '\n'
  step "--no-launch: the command above was printed, not run (its cwd would be $DIR)"
  exit 0
fi

if (( dry_run )); then
  plan "cd $DIR"
  plan "exec $(quoted "${cmd[@]}")"
  step "--dry-run: nothing was renamed, written or launched"
  exit 0
fi

if [ -n "$preparation_failure_identity" ]; then
  pfr_final="$(LANES_NO_FETCH=1 "$LANES_EDIT" restart-intent "$LANE" --dir "$DIR")" ||
    die "the failed preparation could not be rechecked before ordinary launch. Nothing was launched." 2
  preparation_failure_resume_check "$pfr_final"
fi

cd -- "$DIR"
step "exec: $(quoted "${cmd[@]}")"
exec "${cmd[@]}"
