Repository navigation
Pin openRepoShape at 39d5c98 — the standard's docs and templates name $AGENT_PROTOCOL_ROOT (opensoft/openRepoShape#161); digest recomputed, gitlink and pin in one commit - #46
Merged
Conversation
…rogress) Compare check: gh api repos/opensoft/openRepoShape/compare/main...39d5c986fcfac1a160474bfe91c5f1c37fccc72c --jq .status -> identical. Independently confirmed: opensoft/openRepoShape PR #161's merge commit is this same sha (39d5c986fcfac1a160474bfe91c5f1c37fccc72c), on that repository's main. Bump command run exactly as contracts/openreposhape-pin.yaml states: git -C upstream/openRepoShape fetch origin git -C upstream/openRepoShape checkout 39d5c986fcfac1a160474bfe91c5f1c37fccc72c python3 -c "import sys; sys.path.insert(0, 'upstream/openRepoShape/scripts'); \ from repo_shape import tree_digest; print(tree_digest('upstream/openRepoShape', 'HEAD'))" Old commit: ba14e1d9308cb912e32f5d20e097bec89d9455a7 Old tree_sha256: 26a314f34239dd314c0cb7eab2da2915fc2d4bd27ae9c81349052fc4e6b4355e New commit: 39d5c986fcfac1a160474bfe91c5f1c37fccc72c New tree_sha256: a44c0165beb9d3b6ddfce46925bf04b8d19934d5327b5a304b5f3f11af699b02 `python3 -m pytest tests -q` was still running under the shared pytest lock (five sibling worktrees build concurrently) when this WIP commit was pushed ahead of a context swap. Suite counts to follow once it completes; this commit/PR is not to be merged until the run is confirmed green. Lane: openrepotools-3 (openRepoTools-3) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Reviewer's guide (collapsed on small PRs)Reviewer's GuidePins upstream/openRepoShape to the verified 39d5c986fcfac1a160474bfe91c5f1c37fccc72c main tip, updates its recomputed tree digest, and validates the synchronized pin with the full 571-test suite. Flow diagram for verified openRepoShape pin updateflowchart LR
OldPin["Old commit ba14e1d"] --> Fetch["Fetch and checkout verified main tip"]
Fetch --> NewPin["New commit 39d5c98"]
NewPin --> Digest["Recompute tree_sha256"]
Digest --> Contract["Update contracts/openreposhape-pin.yaml"]
NewPin --> Gitlink["Move upstream/openRepoShape gitlink"]
Contract --> Tests["Run tests/test_upstream_pin.py and full test suite"]
Gitlink --> Tests
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
There was a problem hiding this comment.
🟢 Approval recommended
The verified pin and digest updates are synchronized and the full test suite passes.
Pull request overview
Updates the pinned openRepoShape standard to commit 39d5c98 and refreshes its tree digest.
Changes:
- Advances the upstream submodule pin.
- Recomputes the recorded tree digest.
- Keeps the manifest and gitlink synchronized.
File summaries
| File | Summary |
|---|---|
contracts/openreposhape-pin.yaml |
Records the updated commit and tree digest. |
Review details
- Files reviewed: 2/2 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
brettheap
added a commit
that referenced
this pull request
Sep 14, 2026
…back `git add -A` while resolving the merge staged the submodule at the commit this worktree happened to have checked out (`ba14e1d`, this branch's base), which reverted `main`'s own pin bump to `39d5c98` (#46) in the gitlink while `contracts/openreposhape-pin.yaml` carried main's. The pin file and the gitlink move in ONE commit and never apart — AGENTS.md rule 3 of the pinned standard — so the gitlink is put back where main has it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019UFwD7bCS73jaUMJ2vuo5m
brettheap
added a commit
that referenced
this pull request
Sep 14, 2026
…d) into the Amendment 12 branch — three conflicts, all of them the two rounds writing about the same `--install`, and the macOS job's three red lines taken with them MERGE AND NEVER A REBASE: this branch is pushed and reviewed. THE THREE CONFLICTS, and each resolution keeps BOTH sides rather than picking: 1. `openRepoTools`'s `jq`-missing refusal. This branch made it name the PAIR of entries and print both blocks; `main` added a REGULAR-FILE check for `~/.claude/settings.json` immediately under it (#44 round 1: `chmod` follows a symlink and `mv -f` swallows one). Both are kept, and that check's own refusal is respelled for the pair — it merges two entries, not one. 2. `openRepoTools`'s `present` arm. This branch split it in two, one line per entry, and made the WRITE conditional on either being absent, so a person's settings never pass through a state carrying one of the pair; `main` gave the arm a `chmod 600` for the mode a `present` run never applied (#40 finding 3). Both: the `SessionStart` arm keeps `main`'s mode restoration verbatim — its test asserts the sentence — the guard arm says what it found and does NOT chmod a second time (the mode belongs to the FILE, not to either entry), and the one write follows them. 3. `README.md`'s install paragraph and the cap that counts it. Both rounds rewrote the same sentences: two merged entries with the name guard's own description (here) and the regular-file rule with the modes `--install` stamps (`main`). The merged paragraph carries both, which is longer than either half, so the cap is the count of WHAT MERGED — 417 and 428 -> 436 — with both dated entries kept and a third naming the merge, which is the rule the 2026-09-13 entry states in its own words. AND THREE COUNTS `main` STATES THAT THE SECOND HOOK ENTRY MOVES: "eleven of the eighteen artifacts", "seventeen of the eighteen artifacts", and the comment calling `settings.json` "the eighteenth artifact" — it carries the eighteenth AND the nineteenth since adoption act 3. `HOOK_ENTRIES = 2` already derives the total in `tests/test_openrepotools_command.py`; these are the prose beside it. THE macOS JOB'S THREE RED LINES AT `6cf5359`, WHICH ARE THIS BRANCH'S AND NOT THE MERGE'S. `tests-macos` failed where every other job passed, on the one case round 2 added for the lock's pane fallback: the fixture made the live record's pid a CHILD of the fake pane's, and `pid_under` climbs `/proc` to answer that — which macOS does not have. The record was "here" on Linux and nowhere on the macOS runner, so the guard refused with "no live session record in THIS window carries this session id" and the lock never ran. The fixture now gives the pane the record's OWN pid, which `pid_under` answers at its first step with no walk at all, and the case says why in its own comment. THE BEHAVIOUR WAS NEVER PLATFORM-SPECIFIC: `guard_type`'s fallback asks tmux for `#{pane_id}`, and the same is true on both. The submodule is checked out at the pin `main` brought (`39d5c98`). Lane: openrepotools-3 (openRepoTools-3) Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019UFwD7bCS73jaUMJ2vuo5m
brettheap
added a commit
that referenced
this pull request
Sep 15, 2026
…ndoff` on PATH, `/handoff` with `/swap`, `/lane-swap` and `/ctx`, the record naming the agent and its transcript, and `lane-start --agent` resuming a lane from any agent the table carries (#47) * WIP (swap-imminent commit, pushed unverified): a handoff is the swap under one name — `lane-handoff` on PATH, `/handoff` with `/swap` and `/lane-swap` as aliases, `/ctx` = `/handoff --restart`, the record naming the agent and its transcript, and `lane-start --agent` resuming the lane from any agent the launcher table carries WIP, AND THE WORD IS IN THE SUBJECT BECAUSE THE PROOF IS NOT IN YET. Every file parses (`bash -n` on the four commands and the suite, `py_compile` on the three pytest files) and the bash suite was green through every pre-existing section on the run before this one; the Amendment 17 section this commit adds had NOT yet been reached when the swap was called, and `python3 -m pytest tests -q` has not been run at all. Nothing here is merged on that basis: the next session re-runs both suites and takes what they say. lane-collision-protocol **Amendment 17** (ratified 2026-09-14T09:45:33Z, revision 2 with clause (f)), **Amendment 18(d)** and **Addendum 2**; #36, acts 1-8. THE ACT HAS ONE NAME AND THREE DOORS. `lane-handoff` on PATH (new file, `INSTALLABLES` 11 -> 12) is the `/lane-swap` skill's steps as one command: the identity triple fixed through `lanes-edit.sh`, the handoff file refreshed with a fresh Rule 3 top block, every running writer polled — `git status --short` and `git log @{u}..` of every worktree under the lane's checkout `.claude/worktrees/` and `<projects>/.lane-worktrees/<lane>/` — `PAUSED` written with Amendment 11(c)'s payload plus Amendment 17(b)'s `agent <name>; transcript <id|none>`, and the one restart line printed. The top block's template gains a WRITERS section (worktree, branch, brief, last commit, dirty and unpushed counts) and the first line *"relaunch every writer below from where it stands"*; it is PREPENDED and the file is never rewritten, so what was there stays below a `---` rule as history. `skills/handoff/SKILL.md` carries the steps with their history (a rename, so `git log --follow` reads straight through); `skills/lane-swap/SKILL.md` and `commands/swap.md` name it and add nothing, and `commands/handoff.md` and `commands/ctx.md` are new. `--exit` (Amendment 18(d)) types `/exit` into the lane's own pane — the pane from the LIVE record's own `tmux` field — because a handoff to another place is a handoff and not a restart. `--restart` is `/ctx` (clause (f)): `tmux respawn-pane -k` on that same pane through the launcher, with `LANE_START_FRESH=1 pclaude --lane <lane> <profile>` — never `restart <lane>`, which Addendum 2 takes off the person's PATH. BOTH REFUSE BEFORE THEY TOUCH THE PANE where the record could not be written: *"a pane is never respawned over an unrecorded lane"*. `lanes-edit.sh`, ADDITIVELY, because #41 is landing in the same file: `pause_subfields_check` validates the two sub-fields in the WRITER (`write_event`, from any caller) and reads them with `all` so that `agent not a key` is refused rather than read as `not`; `swapped` gains a sixth and a seventh field, EMPTY for every record written before the amendment; `window_lane`'s reader names that row's fields in full so a short list cannot swallow them; four new reads (`lane-agent`, `lane-transcript`, `lane-last`, `workspace-root`); and `log … --utc <UTC>` dates the late record by its own field. `lane-start --agent <name>` (clause (c)): the default is the agent of the last `PAUSED`, else `claude`. `claude` with its transcript here resumes by id exactly as Amendment 6 has always done; otherwise a launcher table — `claude` takes a named new session with the handoff's TOP BLOCK as its first prompt, `codex` takes the top block positionally, and a name the table does not carry is a refusal naming the two it knows. The Rule 3 stamp and the row's session cell are written BEFORE the launch, the stamp naming the agent (`RESUMED by codex <id>`) and the cell in that agent's own spelling (`Codex <id>`). ACT 6, the transcript follows the lane, shrunk to what the measurement of 2026-09-14T12:35Z left of it: `lane-start` SAYS which projects directory it found the transcript in and whether that directory is SHARED (`readlink -f` equal across profiles), and MOVES the `<uuid>.jsonl` and its sibling `<uuid>/` only where another profile's `projects/` really is another directory, leaving the pointer `<uuid>.jsonl.moved-to-<profile>-<UTC>` where they were. A uuid whose holder is LIVE in another profile is a refusal naming the pid, its window or `bg`, the profile and the retire act (Amendment 18(h)) — never a move, because a copy leaves two live transcripts of one uuid to diverge. ACT 7, `--late`, AND THE RULE IT IS BUILT ON. A lane's state is its log's last lane-kind line IN FILE ORDER and the log is append-only, so a late `PAUSED` appended after the relaunch's `RESUMED` would make a lane that is RUNNING read as paused. The simplest rule that keeps every `binding` and state read correct is to refuse to write a line that can no longer be last: `--late` REQUIRES `--at <UTC>` — a late line is dated by its own field — and is written only where the lane's last lane-kind line is a `STARTED` or `RESUMED` older than that instant. Every other case is a refusal that writes nothing, made BEFORE the writers are polled and before the handoff is refreshed, so a refused `--late` leaves the lane exactly as it found it. Stated in the code, in the skill and in the manual. Docs: `docs/README-lanes.md` gains "The handoff (Amendment 17)" — the act under its three names, the two sub-fields and the reads that answer for them, the launcher table, `/ctx`, `--late` with its rule, and the transcript rule; `README.md`'s install section moves to twelve files, three skills, three command files and twenty-five artifacts, with the cap raised in a dated entry. Lane: openrepotools-3 (openRepoTools-3) Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * WIP (second swap-imminent commit, unverified): the anchor `lane-start` appends a non-Claude agent's id to is the PUBLISHED row's last id, and four Amendment 17 cases in the suite ask what they say they ask WIP FOR THE SAME REASON THE FIRST ONE IS: this is the predecessor's working tree at the moment the swap was called, committed so that nothing is lost and so that the next run's diff is against a tree that parses. The Amendment 17 section had not been through a green run when these lines were written; the suites decide what survives. `lane-start`: the id `append-session-id` is anchored on for an agent that is not Claude is `$row_sid`, the LAST id of the published session cell, which is the same anchor the minted-uuid append uses and for the same reason — `append-session-id` refuses unless its anchor occurs exactly once in that cell, so a stale copy of the row is a refusal that prints the act rather than a corruption. `$cell_anchor` is not that id: it is set only where a session is live in this window whose uuid the cell lacks, which is never the case for the launch of an agent that is not Claude, so the branch as written took the empty-anchor door every time. The suite, four cases that were asking something other than what they read: `lane-handoff`'s stdout is kept in `hf1_out` because a `swapped` read stands between the run and the assertions that quote it; the unwritable-record `/ctx` case is asked from a window NO live record names, so that there is no transcript uuid anywhere and `write_event` really does refuse (Amendment 11(e)) rather than being handed one by the window read; the shared-`projects/` case gets its own lane `repoSH-1`, because `repoFR-1`'s cell has since gained the uuid the `LANE_START_FRESH=1` run minted and that one has no transcript at all — the other branch; and the live-holder record is named for ANOTHER lane, which is the shape Amendment 18(h) is written about: a second process on one transcript that the lane's own liveness read does not see. Lane: openrepotools-3 (openRepoTools-3) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * `lane-handoff` is a command in the index and not only after `--install` chmods it: the executable bit, the macOS parse step and the mode of every placed file are each derived from a list the next file joins by existing THE PROOF THE TWO WIP COMMITS SAID WAS NOT IN YET. `bash tests/test_lane_helpers.sh` is **1630 passed, 0 failed, 0 skipped, 0 pending**, with the 129 cases of `== Amendment 17: the handoff is the swap ==` among them — the section that had not been reached when the swap was called. Nothing in the amendment's own code needed changing for that; what this commit carries is what reading the file alongside the suite found. `lane-handoff` WAS COMMITTED 100644. Every other file `--install` places is 100755 in the index and `repos.tsv`, which is data, is not. The installed copy runs anyway — `--install` stamps 755 on everything it places — so the defect has no symptom there; what it costs is `./lane-handoff` from a clone, and the `cp -p` this suite copies it with, which takes the mode git recorded. The suite's own case did not see it because the fixture ran `chmod 755` on the copy. That line is gone: the case now reads back the mode THE REPOSITORY carries, which is the only mode anyone else gets. AND THE THREE LISTS IT WAS MISSING FROM, each closed so that the next file joins by existing rather than by being remembered: * `ALL_BASH` gains it through a new `HELPER_BASH`, with the reason it is in neither list beside it stated where the other two state theirs — not `SHIPPED_BASH`, because `R-A11-11` (*a swap is never left unwritten*) is why it does not `set -e`; not `LANE_BASH`, because it carries no copy of Amendment 9(a)'s workspace resolver, resolving no workspace and reading the one path it needs back from `lanes-edit.sh workspace-root`. So 837 lines of shipped bash now take the parse gate, the LF index, the flag-spelling rule and the four bash-3.2 text rules; it passes all of them as written. * the macOS job's `/bin/bash -n` step, which is a HAND-WRITTEN LIST and the only place the README's bash-3.2 claim is asked of bash 3.2. `lane-handoff` was not in it and nothing said so: the job goes green and proves one file less than it claims. `test_the_macos_job_parses_every_bash_file_this_repository_ships` reads that step and holds it against `ALL_BASH`, per name, because `bash -n a b` parses `a` and hands `b` to it as `$1`. * the index mode, read out of the installer's OWN `INSTALLABLES=( … )` rather than a list in the suite — 755 for a command, 644 for the `.tsv` that is read and never run. That is the test that would have caught this the moment `lane-handoff` joined the installer's list, with nobody coming here first. THE COUNTS THAT STATE THEMSELVES, finished: `AGENTS.md` and `docs/README-lanes.md` still said eleven files, two skills and eighteen artifacts — twelve, three, three and twenty-five — and four docstrings in the installer's tests counted the same way. `README.md`, the installer's prose and every derived count moved with the first WIP commit; these are the ones that state rather than derive. lane-collision-protocol **Amendment 17** (in force 2026-09-14T09:45:33Z), **Amendment 18(d)** and **Addendum 2**; #36. Lane: openrepotools-3 (openRepoTools-3) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * The `/ctx` respawn types the word Amendment 18 Addendum 2 gives it — `lane <lane>` where that word is on PATH, the launcher where it is not, and never a `lane` this estate did not place Addendum 2 clause (i-8), in force 2026-09-14T16:50:32Z, says the respawn after `/ctx` *"relaunches the lane's own pane with `lane <name>` (its parked branch is exactly Amendment 11(i)'s act), or through the launcher directly"*, and its adoption line names this issue: *"#36 (`/ctx`) respawns with `lane <name>`"*. What this branch had was the second half of that sentence and never the first: every respawn was `pclaude --lane <lane> <profile>`. So `lane-handoff --restart` now asks PATH for the word and types it — `LANE_START_FRESH=1 lane <lane>`, with NO profile argument, because `lane <name>`'s parked branch reads the record this command has just written for the lane's directory and profile and asks nothing. The launcher line stays as the door the same clause leaves open, for the workstation where `lane` is not installed yet: it arrives with #43 and this act ships first, and a respawn is the one act no later refusal can undo — the pane's process is already dead when the new command fails — so the word is used only where this command can SEE it. AND NOT EVERY `lane` ON A PATH. `pclaude` is nobody else's name; `lane` is an ordinary English word, and a pane respawned over somebody else's `lane` is a pane the person cannot get back. The file is read for the string every bash file this toolset ships carries (`lane-collision-protocol`, in all six of them), and one that carries none is passed over for the launcher with a line saying which file was passed over — the safe side of the two, because it still starts the lane. The skill and the manual say the same thing in the same order, and the skill's snippet is now the choice the command makes in code rather than one branch of it. TESTS, in `tests/test_lane_helpers.sh` § "Amendment 17", all three on a PATH THIS FILE BUILDS: `a17_path_without_lane` drops every directory holding a `lane` from the section's PATH, so the cases ask their own question on a workstation that has the word (#43 places it in `~/.local/bin`) and on one that does not. `repoHF-8`, with a fake `lane` carrying the marker, asserts the respawn line is that file and `repoHF-8`, with the FRESH seam still on it, with no profile argument, and never the launcher; `repoHF-9`, with a fake `lane` carrying none, asserts the launcher line and the sentence naming what was passed over; `repoHF-5`, on a PATH with no `lane` at all, keeps every assertion it had. VERIFIED HERE: `bash -n lane-handoff`, `bash -n tests/test_lane_helpers.sh`. Suite before this commit, at e25b54c: 1630 passed, 0 failed, 0 skipped. THE RUN OF THE SUITE WITH THESE CASES IN IT FOLLOWS THIS COMMIT — it is pushed now because a context clear of the driving session is imminent and an unpushed change is a change the next session cannot see. Lane: openrepotools-3 (openRepoTools-3) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * The `/ctx` respawn reads the `lane` it found through a redirect, because the job that runs this suite under BSD `head` is the macOS one and a portability question is not one to answer inside the act that kills a pane `lane-handoff --restart` reads the head of the `lane` it found on `PATH` for the string every bash file this toolset ships carries, and read it as `head -c 8192 -- "$lane_word_path"`. The macOS job runs `python3 -m pytest tests -q` — which is this shell suite, through `tests/test_lane_helpers_suite.py` — under BSD `head`, whose option handling is its own; `head -c 8192 < "$file"` hands the file to the utility as a file descriptor and asks nothing of its argument parsing. Same bytes, same guard, one fewer question. Parsed: `bash -n lane-handoff`. The suite at f8a4ce6, with the three PATH cases this guard exists for, was 1821 passed, 0 failed, 0 skipped; the run over this line follows. Lane: openrepotools-3 (openRepoTools-3) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * A handoff names the KIND of clear it was written for, because an in-process clear does not kill this lane's writers — the top block runs `ListAgents` first and relaunches only what it does not name; and the two stale tests CI found in the same breath THE MEASURED FACT, in this lane on 2026-09-14: a harness `/clear` mints a NEW TRANSCRIPT ID IN THE SAME PROCESS. Every subagent the lane has running survives it — only the tool calls they had in flight die, a `Bash` killed that way exiting 137 — and the handoff written before that clear said *"every agent dies with this context; relaunch every writer"*, which was FALSE. A next session that believed it would have put a SECOND writer on a worktree the first one still held, and two writers on one worktree is how the work in it is lost. Only a NEW PROCESS takes the writers with it: the pane respawned (`--restart`, which is what `/ctx` does here), the session ended (`--exit`), or the launcher run after a plain handoff. So the act now records WHICH IT WAS and the top block tells the next session what to do about it: * `lane-handoff --in-process` — the clear that keeps this process. Refused with `--restart` and `--exit`, because each of those replaces the process every writer is a child of. Default, and every other form: `respawn`. * the `PAUSED` payload carries `kind <in-process|respawn>` after `agent` and `transcript`, on the same argument those two were added on: a reader written before the field stops at the sub-field it knows. It is in the RECORD and not only in the handoff because the record is what a later reader and a launcher have. * the top block's act (3) is now, in both kinds: **RUN `ListAgents` FIRST. A WRITER STILL LISTED IS ALIVE AND OWNS ITS WORKTREE: DO NOT RELAUNCH IT. Relaunch only writers `ListAgents` does NOT name, and only after `git status --short` and `git log @{u}..` in that worktree say where it stood.** The `WRITERS` section repeats the rule where the list is, and the kind adds its own sentence — *expect `ListAgents` to name none of them* for a respawn, *expect it to name every one, and relaunch NONE* for an in-process clear. The skill, `commands/ctx.md` and the manual say the same in the same order, and the skill carries the table of the two kinds so that a session writing the block by hand writes the same two texts. AND THE TWO TESTS CI FOUND, both of which were green here for the wrong reason: * `test_the_swap_skill_snippet_and_its_prose_spell_the_same_command` read `skills/lane-swap/SKILL.md`, which Amendment 17(a) turned into an ALIAS that restates no step — so it was asserting over an emptiness. It now reads the installer's own `SKILL_NAME`, which is where the canonical skill is declared once, and every assertion it makes lands on the file that carries the act (2 `restart_cmd=` branches, no `pclaude run` unexplained, `--lane` leading). * `test_no_committed_file_names_a_host_absolute_path` caught three `/home/b/` spellings in the manual's examples. They are `~/projects/repoHF` and `~/.claude/projects` now, which is what every other example in that file uses. AND ONE SUITE AT A TIME, in `AGENTS.md` where an agent is sent to read it: six lanes build in sibling worktrees of this checkout and FOUR SUITES RAN AT ONCE under the guard they had been given — `pgrep -af 'python3 -m pytest' | grep -v pgrep >/dev/null` never waits where `grep` is the harness's own shell function (status 1 when its stdout is `/dev/null`), and its unanchored pattern matches the guard's own command line. The working form is an anchored `pgrep -fc` with its pattern split so it cannot match itself, then `flock` so the waiters cannot all start together. The cap entry for those nineteen lines is in the test that holds it. SUITE: `bash tests/test_lane_helpers.sh` — 1821 passed, 0 failed, 0 skipped at `f8a4ce6` (the merge of Amendment 15); **1844 passed, 0 failed, 0 skipped** with the `kind` cases of this commit (+23: the record's kind, the block's ListAgents rule and its two texts, the `--in-process` record and block, the pane untouched, and both refusals). `bash -n` on `lane-handoff` and the suite. The pytest run that would have covered the two test files above is NOT started: this workstation has three suites running under other lanes and this lane is shutting down on Brett Heap's word; CI on #47 is the authority and has already run these two tests red on their pre-fix bytes. Lane: openrepotools-3 (openRepoTools-3) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * A pane is never respawned over a record that is only part written, a transcript never half-moves between profiles, and the launch line is quoted by something bash 3.2 and BSD `sed` both read — Copilot rounds 1 and 2, Amendment 17 Addendum 1, and the suite's own lock THE macOS JOB'S THREE RED CASES WERE THIS BRANCH'S OWN, and the defect is one line that has been in `lane-start` since before this amendment: quoted() { printf '%q ' "$@" | sed 's/ $//'; } Two defects in it, and only their combination is fatal. `printf '%q '` renders differently under BASH 3.2 — what Apple ships, and what `tests-macos` runs (`/bin/bash` 3.2.57 on macOS 26.6.2): bash 4.4 and later give a multi-line argument back as `$'…\n…'`, one readable and runnable word, while 3.2 has no such form and escapes every space and every byte of every multi-byte character with a backslash of its own. And the PIPE made that fatal rather than ugly: under `set -o pipefail` the function's status is the pipeline's, and BSD `sed` in a UTF-8 locale (`LC_ALL=en_US.UTF-8` there) refuses bytes that are not a valid sequence — `RE error: illegal byte sequence` — which is exactly what 3.2's `%q` makes of the em dash every document in this estate is written with. `quoted` is a BARE command in the `--no-launch` branch, so `set -e` ended `lane-start` there: exit 1, empty stdout, three assertions red and no other platform able to see it. The one caller that passes a multi-line argument is this amendment's own — the `--no-launch` print of a launch carrying the handoff's top block as its first prompt — which is why it went red here and nowhere before. It is now POSIX quoting of the file's own, in `lane-start` and `lane-handoff`: safe words bare, anything else in single quotes with `'\''` for its own. `restart` carries the same line and is untouched — #43 deletes that file in flight and a conflict there costs it a round. COPILOT ROUND 1 (`db206db`), the four inline findings: * `lane-handoff:842` — the `--restart`/`--exit` gate tested only the object-log write. The record is THREE writes: the ROW is what every other lane reads this lane's state from, and the HANDOFF's top block is literally the respawn's first prompt. It now gates on all three and each refusal names the act that clears it. * `lane-start:1692` — `readlink -f` is not stock macOS userland, so `real_of` fell back to the UNRESOLVED path, two spellings of one directory compared as two directories, and the shared-`projects/` case — every case on a launcher-configured workstation — would have moved a transcript that never needed moving. Now `( CDPATH=''; cd -P -- "$1" && pwd -P )`. * `lane-start:1781` and `:1788` — the sibling `<uuid>/` move's status was discarded and the pointer's write was suppressed. The `.jsonl`, its sibling and the pointer are ONE TRANSACTION now: each step is checked, a step that cannot complete puts back what the steps before it moved (`ft_rollback`) and refuses, and the refusal names anything the rollback itself could not undo. * DECLINED, both mode findings (`lane-handoff:1`, `tests/test_repo_hygiene.py:198`): `git ls-tree db206db lane-handoff` → `100755`, and `git ls-files -s` says the same today. What they read is that test's docstring describing the FIRST Amendment 17(a) commit; it now names `e25b54c` as the commit that fixed the mode and points at `git ls-files -s`. The same stale rationale in the A17 fixture is corrected. From round 1's SUPPRESSED list: `lane-start:1776` (`--dry-run` moved the transcript before reaching the exit that says it moved nothing), `lane-handoff:612` (`handoff_written=1` set whether or not the write succeeded), `lane-handoff:494` (a failed `mktemp` gave a WRITERS section with a count and no entries), `lane-handoff:395` (the record's `transcript` came from `$sess_uuid`, not the resolved `$uuid`, so a handoff from a bare shell wrote `transcript none` about a conversation whose id the same line carries), `lane-start:1687` and `:1719` (`$CLAUDE_PROFILES_HOME` ignored by both profile walks, though this repository's own README documents it), `lane-start:1881` (a failed `lane-agent` read launched the default agent, which is the one thing that read's own refusal forbids — it now refuses and names `--agent`), and `lane-start:1997` (a lane with NO ROW wrote `RESUMED` as its object log's first line). COPILOT ROUND 2 (`ac0c697`): * `lane-handoff:303` — the read fence treated exit 2 as "no answer", but `canon_lane` spends 2 on a register holding two rows that differ only by case. `lane-handoff` fell through to the next rung and would have renamed a window, written a record and respawned a pane for whichever lane it answered with. The refusal is now asked for by its own words, as `lane-start:755-767`, `lane-end` and `restart` ask for it, and relayed. * `lane-handoff:360` and `:403` — the lane is canonicalised through `canon-lane` BEFORE the window rename, so the row's spelling is what the rename, the top block, the payload, the log's lane field and the restart line all carry; and a `--lane` that is not a lane name is refused there rather than after the window has been renamed. * `lanes-edit.sh:3946`/`:3963` — `pause_subfields_check` accepted a payload carrying exactly one of `agent`/`transcript`, and an empty value parsed like an absent one. Both are refused now, with the value judged before the pair so a malformed one is still refused for the malformation. * `lanes-edit.sh:5723` — `--utc` was taken for every verb and only its shape was checked; it is the late `PAUSED`'s seam and is refused for everything else, because file order is what every state read means by "last". * `lane-start:1899` — `lane-transcript` answers for the LANE, so `--agent codex` over a record that says `agent claude` would have appended `Codex <claude uuid>` to the row's cell. The id is carried only where the recorded agent IS the agent being launched. * `lane-start:1982` — the launched agent's name is exported, so a `codex` session's own handoff does not record `agent claude`. FILED, NOT FOLDED IN: #55 (`swapped`'s first field is the LOG's spelling and not the register row's — Amendment 15's claim, landed on `main` with #41, so it predates this diff) and #56 (the cross-profile transcript-holder scan tests only `kill -0`, where `lanes-edit.sh`'s one liveness contract tests three things). Both claimed by this lane. AMENDMENT 17 ADDENDUM 1, in force 2026-09-14T20:59:31Z (brettheap/new-workstation#40, `26a0d5b`), whose adoption line names this issue: * (h) the record names the KIND, and there are THREE: `--in-process` writes `in-process`, `--restart`/`--exit`/`--late` write `respawn`, and a PLAIN handoff writes `unknown` — the act that follows it is not this command's to know. The word is in the payload (`; kind <k>`) and in the line's FREE TEXT after the why (`clear in-process`, `clear respawn`, `kind unknown`), which is the addendum's own spelling. * (i) the WRITERS section is a list to COUNT, not a list to relaunch, and its first line is the clause's own words under EVERY kind. * (j) the kind says what to EXPECT and never what to do, so `relaunch every writer below` and `relaunch NONE of them` are both gone from the template. * (k) one worktree, one writer, in the first acts, with the retire act for a second one found. AND THE SUITE'S OWN LOCK (#51). Four `python3 -m pytest tests -q` runs were live at once on this workstation on 2026-09-14, every one past a guard copied into four briefs: `pgrep -af '…' | grep -v pgrep >/dev/null` never waits, because `grep` under the harness is a shell FUNCTION whose status is 1 when its stdout is `/dev/null`, and its pattern is unanchored besides. `tests/run.sh` is that guard written ONCE — wait, take `${TMPDIR:-/tmp}/openrepotools-pytest.lock` (`flock`, or a `mkdir` lock on macOS, which has none), wait again inside it, then run the suite — named in `AGENTS.md` and `docs/README-lanes.md` as the way to run it, parsed by the macOS job with every other bash file here, and pinned by a hygiene test that holds the lock path in both places. Closes #51 (with #36). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019UFwD7bCS73jaUMJ2vuo5m * A lock nothing can validate is stale and not eternal, a transcript never moves onto an occupied name, and the two acts that reach a handoff through a symlink resolve it the way macOS can — Copilot round 3 The round before this one went green on all four CI jobs, macOS included, which is what made these findings readable rather than hidden behind three red cases. `tests/run.sh` — THE LOCK THIS PULL REQUEST SHIPS AS THE WAY TO RUN THE SUITE, and three things a `mkdir` lock has to get right that the first shape of it got wrong (`tests/run.sh:109`, `:113`, `:120`): * A LOCK WITH NO PID IN IT IS STALE, NOT ETERNAL. The pid is written the instant after `mkdir` returns, and a run killed in that instant left a directory nothing could validate — which the loop waited on for ever, blocking the estate's one test entry point for everybody. * A TAKEOVER IS A CLAIM, NOT A DELETE. Two waiters that both saw a dead holder both `rm -rf`'d the name, and if one had already re-made it the other deleted the NEW holder's lock and both suites ran. It is a `mv` now — one rename, one winner, the loser loops — with the claimed directory RE-READ after the rename, because the only way a live holder can be behind that name is if it appeared between the read and the rename, and then it is put straight back. A stale state must also hold for three polls before it is claimed at all. * THE SIGNAL HANDLERS EXIT. `trap 'rm -rf …' EXIT INT TERM` released the lock on a Ctrl-C and then carried on running the suite, which is the collision the lock exists for. `lane-start:1878` — AN OCCUPIED DESTINATION IS REFUSED BEFORE ANYTHING MOVES. `mv <dir> <existing dir>` does not fail: it moves the source INSIDE it. A `<uuid>/` already in this profile would therefore have taken the other profile's sidecar as `<uuid>/<uuid>/`, been marked moved, and left the lane resuming with the transcript's state split from the transcript. Which of two `<uuid>` directories is this lane's is not a thing to guess at, so the read names what is there and stops — and a name that is NOT a directory still falls to the transaction below, where `mv` really does fail and the rollback puts the transcript back. `lane-handoff:812` and its twin in `lane-start` — `readlink -f` IS NOT IN THE STOCK macOS USERLAND, which is the same rule `real_of` took last round. Where it is absent the fallback hands the path back UNRESOLVED, so `hs_repo` — which git answers with a PHYSICAL path — and `hs_rel`, derived from the symlinked spelling, disagree; `git add` then refuses the pathspec and the handoff this act has just written, or the Rule 3 stamp it has just spliced, is left uncommitted. A handoff is reached through the estate's `handoffs` symlink on every workstation that has one. Both now resolve the PARENT with `cd -P`/`pwd -P`. `lane-handoff:1052` — `head -c 8192 … | grep -q` TAKES SIGPIPE UNDER `pipefail`. `grep -q` exits the instant it matches, `head` writing the rest of a word larger than 8192 bytes dies with 141, and the pipeline's status is that — so the estate's OWN `lane` was classified as somebody else's and `/ctx` respawned through the launcher instead of the word. `grep` reads all of the bounded input now, and the suite's fake `lane` is padded past 8192 bytes so the three PATH cases prove it. `lane-start:2132` — A LAUNCHER THIS WORKSTATION DOES NOT HAVE IS REFUSED BEFORE ANY WRITE. The row, the object log and the Rule 3 stamp are all written before the `exec`, so a `codex` that is not installed recorded the lane as RESUMED and then exited 127: a false transition in two append-only files that a person has to repair by hand. `lane-handoff:860` — the `window` sub-field's fence gains `; ` and `"`, the two its own comment already claimed it dropped. `window` is two space-separated refs in ONE sub-field, so a `; ` inside it is read back as the end of the sub-field and every reader recovers a window ref that is not the lane's. FILED, NOT FOLDED IN: #65 — the `/ctx` respawn recognises this estate's `lane` by a string in the word's own head, which is a heuristic and not provenance: any executable can carry it. Tightening that to the directory `--install` places these commands in is a change to the behaviour Amendment 18 Addendum 2 (i-8) adopted, and to three of this suite's PATH fixtures with it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019UFwD7bCS73jaUMJ2vuo5m * The codex-absent case asks its question on a PATH this file built, because the workstation it was written on HAS codex installed Four assertions of the round-3 case `--agent codex on a workstation with no codex is refused` went red on Eagle and green on every CI runner, which is the shape of a fixture asking a different question rather than of a defect: the workstation carries `~/.npm-global/bin/codex`, so the refusal correctly did not fire and the launch went ahead. `a17_path_without <word>` is the generalisation of the `a17_path_without_lane` the three `lane` cases already use, and for the reason that helper's own comment gives — *a case that asked "what happens where there is no `lane`" against a workstation that has one would go green on the answer to a different question*. The codex case now builds its PATH the same way. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019UFwD7bCS73jaUMJ2vuo5m * The codex-absent case is not asked, and the test file says why: this estate installs that launcher in /usr/bin, so "a PATH without codex" is a PATH without bash The round-3 fix at `lane-start:2132` stands — a launcher the table knows and this workstation does not have is refused in 5a, before the row, the object log and the Rule 3 stamp are written, rather than after `exec` exits 127 and leaves a false PAUSED→RESUMED transition in two append-only files. Its case cannot be asked here. `a17_path_without codex` is how the three `lane` cases build their PATHs, and on this workstation `codex` is `/usr/bin/codex`, `/bin/codex` AND `~/.npm-global/bin/codex` — the launcher is installed globally on every lane workstation — so subtracting every directory that holds it returns the EMPTY string and takes `bash`, `git`, `awk` and `sed` with it: the run then dies at its own shebang with `/usr/bin/env: 'bash': No such file or directory`. That is why the four assertions were green on every CI runner (which has no codex) and red at the desk, which is the exact failure mode the `a17_path_without_lane` comment exists to prevent. So the reason is written where the case would have been, with what a fixture would have to express to ask it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019UFwD7bCS73jaUMJ2vuo5m * The merge takes main's openRepoShape pin, which `git add -A` had put back `git add -A` while resolving the merge staged the submodule at the commit this worktree happened to have checked out (`ba14e1d`, this branch's base), which reverted `main`'s own pin bump to `39d5c98` (#46) in the gitlink while `contracts/openreposhape-pin.yaml` carried main's. The pin file and the gitlink move in ONE commit and never apart — AGENTS.md rule 3 of the pinned standard — so the gitlink is put back where main has it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019UFwD7bCS73jaUMJ2vuo5m * The re-mode case names the skill it actually chmods, because Amendment 17(a) renamed that act and the case came from a branch written before the rename Both Linux CI jobs went red at `5c162df` — the merge of `main` at `b5244e2` — on one assertion of `test_a_skill_whose_bytes_are_right_and_whose_mode_is_not_is_re_moded`, and the defect is a name spelled twice in one file. `skill_paths()` DERIVES its two paths from `SKILL_NAMES`, so on this branch it hands back `handoff`'s — Amendment 17(a) renamed the act from `lane-swap` to `handoff` and kept `lane-swap` as an alias file — while the case that #40 and #44 added on `main` asserts the printed line with the literal `lane-swap:`. The installer was right: it chmod'ed the path it was given and named the skill that owns it (`handoff: … (mode restored to 644)`). The merge that brought a case written before a rename on to the branch that made it is exactly where a spelled name goes stale, and the file's own header says so five lines above the constant it should have used. Both assertions take `{SKILL_DIR_NAME}` now, which is the same derivation the paths take. Merges `origin/main` at `a954435` (#50, `commit_push`'s conflict die and its `tests/test_lane_helpers.sh` § #32) on top of `b5244e2` (#44, the installer's mode stamping and unwritable-target refusal; #53's `skills/restart/SKILL.md`). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019UFwD7bCS73jaUMJ2vuo5m * The `--in-process` help says what to EXPECT, `--late --in-process` is refused as the contradiction it is, and a comment stops claiming a refusal `canon_lane` does not make — Copilot rounds 4 to 6 Three findings taken; the other ten are #72, filed with what each would cost, because every one of them hardens an act that already refuses rather than fixing something that writes the wrong thing. * `lane-handoff:65` and its `--in-process` usage line still told the reader the top block would say *relaunch NONE of them* — the instruction Amendment 17 Addendum 1 (j) removed from the template two commits ago. `usage()` PRINTS that comment block, so the command was handing a person the opposite of the adopted rule while generating the right block. Both now say the block tells the next session what to EXPECT, and that what to DO is clause (i)'s count. * `--late --in-process` was not refused, and the kind block takes the `in-process` arm first — so a late record could have said `kind in-process` and told the next session to expect writers live that died with the process the record is about. A late record is written for a session that has ALREADY ENDED; that is what makes it late. * And the comment over the `canon-lane` read claimed it refuses "a `--lane` this estate has no name for". It does not: `canon_lane` answers with the TYPED spelling where no row matches, deliberately, because `lane-start` uses the same resolver for a lane it is about to create. What that read refuses is an AMBIGUOUS register (15(d)) and a value that is not a lane name at all; a well-formed lane with no row is named by the writes below, and the comment says so now rather than promising a check that is not there. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019UFwD7bCS73jaUMJ2vuo5m * The documented guard counts the way the wrapper counts, and `pytest_live` stops reporting a failure in the same breath as a zero — Copilot rounds 7 and 8 Three threads on one inconsistency and one on its neighbour, all of them this branch's own: * `AGENTS.md` and `docs/README-lanes.md` showed the guard with `pgrep -fc`, which `tests/run.sh` deliberately does NOT use — `-c` is not in every `pgrep` this repository runs under, and it is the COUNT and never `pgrep`'s exit status that decides. A document that shows a person a non-portable form of the very guard the wrapper exists to make portable is worse than one that shows none. Both snippets count with `awk` now, as the wrapper does, and both say the wrapper is the canonical implementation and why the lines are repeated at all. * `tests/run.sh:66` — `pgrep` exits 1 when it matches nothing and `set -o pipefail` makes that the pipeline's, so `pytest_live` printed `0` and returned a FAILURE together. Every caller today reads the printed count, which is what its own comment says; the explicit `return 0` is what keeps that true for the first caller that uses it in a condition. The two remaining findings of those rounds — parametrising the skill-placement assertions over `SKILL_NAMES`, and an `INSTALLABLES=( … )` regex that tolerates a wrapped array — are #72's kind and are noted there. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019UFwD7bCS73jaUMJ2vuo5m * The skill records the KIND its command records, and asks `window-session` the question that read answers — Copilot round 9 Two conformance gaps between the two halves of ONE act, which is the thing Amendment 17(a) exists to prevent: `skills/handoff/SKILL.md` is `/handoff` and `/ctx` for a session with no `lane-handoff` on `PATH`, so a fact the command writes and the skill does not is a record whose shape depends on which door the person came through. * `skills/handoff/SKILL.md:476` — the skill's `PAUSED` payload carried Amendment 17(b)'s two sub-fields and not Addendum 1 (h)'s `kind`. A record from the skill was therefore one no reader could tell a surviving writer from a dead one by, while the top block it writes in the same act states the kind. The payload gains `; kind <k>` and the line's free text gains the same word after the why — `clear in-process`, `clear respawn`, `kind unknown`. * `skills/handoff/SKILL.md:612` — the `/ctx` respawn asked `window-session` with `#{window_id}` alone (`@21`). That read matches a live record on the HARNESS's own `tmux` field, `<session>:<@id>`, and the three spellings of one window are never derived from each other — `lane-start:975-984` says so and `lane-handoff` reads it that way. The skill's `/ctx` therefore found no record, left `$pane` empty, and respawned something that was not the lane's pane. It asks with `#{session_name}:#{window_id}` now. Three cases in `tests/test_lane_helpers.sh` § "Amendment 17", beside the ones that already hold the skill to the command's words. DECLINED, from the same round: `lane-start:2177`, that `--agent claude` should skip the recorded transcript. Amendment 17(c) is explicit the other way — *"`claude` with its transcript here resumes 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"* — and the suite's `--agent claude with no transcript here` case is the branch that takes a new session. `LANE_START_FRESH=1` is the seam for *a new session even though the transcript is here*, and it is what `/ctx` sets. FILED: `lane-handoff:924`'s late-record race is #72's kind and is noted there — the preflight reads the lane's last line before the poll and the refresh, and a `RESUMED` appended in that window would be overtaken by the `PAUSED` this writes. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019UFwD7bCS73jaUMJ2vuo5m * The skill's row flip reads BOTH state-cell shapes, because an ordinary fresh row is the one it did not know — Copilot round 10 `| WORD ·` is a state cell with history after it and `| WORD |` is one with none, and a fresh row from `add-row` is the second. The skill's parser knew only the first, so for those rows `$state` was empty, `replace-in-row` had no anchor, and `/handoff` through the skill left the lane RUNNING in the register with its handoff already refreshed and its PAUSED line already written — the one state this act exists to make impossible. `lane-handoff` has read both shapes all along and keeps whichever punctuation the row carries; the skill does the same now, including in the replacement it hands the writer. Two cases in `tests/test_lane_helpers.sh` § "Amendment 17", beside this round's other two. The round's other finding — a multi-line `why` reaching `append-line` and the top block before the event writer validates it — is #72's finding 6, filed in round 4 and noted again there with what `append-line` adds to it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019UFwD7bCS73jaUMJ2vuo5m --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Lane: openRepoTools-3
Pins
upstream/openRepoShapeto opensoft/openRepoShape's newmaintip,39d5c98, landed as PR opensoft/openRepoShape#161 (squashed): docs and
templates now name
$AGENT_PROTOCOL_ROOTinstead of hard-coding~/.agents/workspace.yaml.Compare check (rule 2 of AGENTS.md's "The pinned standard at
upstream/openRepoShape"):
Independently cross-checked: opensoft/openRepoShape PR #161's merge commit
is this same sha, confirming it is the tip of main and not an orphaned
branch commit.
Bump command run exactly as contracts/openreposhape-pin.yaml states:
ba14e1d9308cb912e32f5d20e097bec89d9455a726a314f34239dd314c0cb7eab2da2915fc2d4bd27ae9c81349052fc4e6b4355e39d5c986fcfac1a160474bfe91c5f1c37fccc72ca44c0165beb9d3b6ddfce46925bf04b8d19934d5327b5a304b5f3f11af699b02The digest was recomputed by the bump command above against the pinned
checkout's own
scripts/repo_shape.py, never hand-edited, and the pin fileand the gitlink move together.
git statusafter staging showed onlycontracts/openreposhape-pin.yamland the
upstream/openRepoShapegitlink changed.Suite:
python3 -m pytest tests -q→ 571 passed in 1080.08s (0:18:00),run serialized behind the shared pytest lock (sibling worktrees were
building concurrently).
tests/test_upstream_pin.pyand the estate teststhat read the eight files out of the submodule are included and pass.
Lane: openrepotools-3 (openRepoTools-3)
🤖 Generated with Claude Code
Summary by Sourcery
Pin upstream/openRepoShape to the latest verified standard revision and update its integrity metadata.
Enhancements:
Tests: