Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 59 additions & 4 deletions docs/release-notes/v1.1.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,66 @@ v1.0.0 is not on PyPI, and 1.1.0 is the first version there. This release is pub
- `release.yml` is run by hand, on an annotated tag, with the version. It is adapted from openRepoShape v1.1.0's. Its build refuses unless the ref is the version's annotated tag and the tag names the run's commit; that commit is on `main` or on `release/vX.Y`; the `testpypi` and `pypi` environments each name a required reviewer and limit deployments to `v*` tags; the commit's four CI jobs ran in a push or dispatch run of `tests.yml` and the newest succeeded; and the tree digest computed here equals the one computed from GitHub's tree listing. It then builds twice from `git archive`, stamps the build, and requires one file.
- It uploads by trusted publishing, with no token: to TestPyPI, then an install check on Ubuntu, on macOS (run again under macOS's own bash 3.2) and on Ubuntu with Python 3.9, then to PyPI. Each upload waits for Brett Heap's approval in its environment. A pre-release `X.Y.ZrcN` reaches TestPyPI only. Only `opensoft/openRepoTools-code` may publish a final version, and nothing uploads to PyPI from `opensoft/openRepoTools`.
- **Releases are annotated tags** (opensoft/openRepoTools#228). A release is an annotated tag `vX.Y.Z` on a commit on `main` or on `release/vX.Y`, never a branch and never a version number committed to a file, and a tag is never moved or reused. `release/vX.Y` is cut at `vX.Y.0` and carries the patch tags. A fix lands on `main` first, then reaches the release branch by a fast-forward, a merge, or a pull request of `git cherry-pick -x`. A version is uploaded once, and a bad upload is fixed by the next patch.
- **The lane tools name what they could not read in a triad's legs** (opensoft/openRepoTools#255, opensoft/openRepoTools#271). It closes two gaps in opensoft/openRepoTools#246, which taught the lane tools to look inside a triad's legs; each broke that change's rule that a read that failed is never an empty one. `lane-handoff` names every tree-inventory record that is not a whole schema-1 one in its NOT POLLED note, and the lane stays SWAPPING. A leg directory this account cannot search is unreadable and never `absent`: `lane-worktrees sweep` exits 3, `lane-end` refuses over it, `lane-reconcile` gives it an `unreadable` row, and `lane-handoff` withholds its tree. A dependency nested in a leg whose directory, or one above it, this account cannot search is unreadable to the sweep too: it exits 3, and `lane-end` refuses over it. A leg directory that is not there at all is still `absent`. One known gap remains (opensoft/openRepoTools#272): the sweep also reads a declared leg beneath a directory this account cannot search as `absent`, so `lane-end` does not hold on it. These readers run only in an assembly, a checkout whose `project.yaml` declares a leg, so a checkout with no `project.yaml` sees no change.
- **`lane-handoff` reads the lane's lifecycle whole** (opensoft/openRepoTools#280, opensoft/openRepoTools#283). It used to pipe `lanes-edit.sh lane-state` into an `awk` that exits as soon as it has printed the one field it wants. Under `pipefail`, a `lane-state` that wrote again after that died of SIGPIPE, so now and then the read exited 141, the handoff said the lifecycle could not be read, and it recorded no RUNNING to SWAPPING to SWAPPED transition. That failed safe, but whether it happened depended on timing alone, and it could turn a pull request's `tests` job red at random. The handoff now takes `lane-state`'s whole output first and parses it afterwards, so its status is `lane-state`'s own. The read of the operation of a lane that is still SWAPPING, which only names that operation in a note, is made the same way.

## What else changed since v1.0.0

- **The openRepoShape pin moved.** This release pins openRepoShape at v1.1.0, `190133d` on its `main`, the commit its tests were verified against (opensoft/openRepoTools#233). v1.0.0 pinned `7f84ca4`.
- **`<other-changes>`**: the other changes that landed on `main` after `aaa7bc8` and before the release commit, by area, one line each with its pull request.
- **The estate commands** (`park`, `resume` and `status`):
- `resume` and `status` hold each leg to the branch bootstrap puts it on: the leg row's own `branch:`, else the root's `tracking_branch` (opensoft/openRepoTools#238).
- `park`, `resume` and `status` find a family folder named for its repository or for its display name, and `resume` names the holder's repository from `family.yaml` where it is on disk (opensoft/openRepoTools#240).
- `park`'s not-carried report counts a leg's unpushed commits on the branch its own row declares, else the root's `tracking_branch` (opensoft/openRepoTools#249).
- `family.yaml` values are read the way openRepoShape v1.1.0 reads them, `status` names one family laid out twice, and `resume` finds a holder by its id when its record names another folder (opensoft/openRepoTools#251).
- **The register and `lanes-edit.sh`:**
- `swapped` names a lane by the register row's spelling, not the log file's (opensoft/openRepoTools#201).
- `superseded_by` follows a chain of TAKEOVERs to its last link, so one lane holds the object (opensoft/openRepoTools#204).
- The lane listing reads a row's state phrase when its log is missing, so a migrated PAUSED row stops showing NO LOG (opensoft/openRepoTools#206).
- `managed-projection` reads this checkout's row as the writers do, `lane-trees` tells an unlistable trees directory from no inventory, and the manual's seven-column row is qualified (opensoft/openRepoTools#213).
- `lanes-edit.sh commit` with nothing staged still publishes the local commits that origin lacks, when each of them only adds or changes a register or handoff file, so the recovery's re-run of `commit` pushes the edit it stranded, and the conflict recovery warns that `reset --hard` drops a peer's commits (opensoft/openRepoTools#214).
- A one-line record cannot take a newline: `append-line` and `lane-handoff`'s why refuse it before writing, and the deferred `lane-start` command keeps `--agent` (opensoft/openRepoTools#218).
- `lanes-index` follow-ups: `export` reads one snapshot, `history --index` says its closing stderr count, a foreign source is refused before the lock, a damaged table reads as unusable, an unread lane stays NOT READ in the index, and the worktrees footer names the workstation (opensoft/openRepoTools#219).
- A register that could not be read no longer reads as a lane with no session ids, so the dead-lane `--force` check and `duplicate-holder` fail closed (opensoft/openRepoTools#221).
- Register sweeps and reads refuse what they could not read: `retire-rows`, `archive-rows`, `migrate-state-cells`, the DORMANT class, `next-free` and `add-row` (opensoft/openRepoTools#230).
- Lifecycle reads that failed are no longer answers, `set-lane-tree`'s fence closes with its operation, and a lane sidecar is valid only when whole (opensoft/openRepoTools#252).
- The register's rewrites refuse a copy or write they cannot prove and put a cut-short register back, `retire-rows` refuses an unpushed log rename before it writes and calls a lane closed only from its published log, and `add-row` refuses an archive row it cannot read and takes back a row refused after its rebase (opensoft/openRepoTools#263).
- A lane listing that is not whole no longer removes indexed worktree rows: the inventory read says PARTIAL, `lanes --worktrees` prints it NOT WHOLE, and `lanes-index` writes nothing over it; an older helper's tree with no path stays a tree (opensoft/openRepoTools#289).
- **`lane`, `lane-start`, `lane-end`, the name guard and their helpers:**
- `lane-end`'s synopsis says what a DUPLICATE retire does, a state cell that breaks the phrase's grammar is read whole instead of narrowed, and the TAKEOVER grammar table and two `tests.yml` header comments are corrected (opensoft/openRepoTools#202).
- `lane-start`'s transcript follow counts a holder only when `transcript-holders` verifies it, not on `kill -0` (opensoft/openRepoTools#203).
- `duplicate-holder` and `lane-end --retire` read a `--resume` path whole and act on every verified child, not the first (opensoft/openRepoTools#205).
- The name guard and the SessionStart hook name an unreadable register or binding log instead of guessing a branch (opensoft/openRepoTools#208).
- `lanes` filters `lanes-edit.sh`'s no-fetch notice out of its stderr with a `grep` that now takes its pattern as `-e`'s argument, so under macOS's BSD `grep` the `--` after the pattern ends the options and is no longer read as a file name, and every other line is printed as `lanes-edit.sh` wrote it, with no `grep: --: No such file or directory` error and no temporary file's name in front; the suite's `repoG#8` assertion can now fail, and it stops counting the bash files in prose (opensoft/openRepoTools#209).
- Three wrapper reads that failed no longer read as no answer: `lane`'s window-name check asks the unpushed local row too, `lanes`' hidden-row probe reads its whole stream, and `lane-end --retire-dormant` refuses without its stderr capture (opensoft/openRepoTools#210).
- `claude-current` falls back from a native Claude Code that does not run to the next one that does, and `claude-restart-check` recognises a running native in a custom `CLAUDE_CURRENT_NATIVE_DIR`, symlinked included (opensoft/openRepoTools#211).
- `lane-start` fails closed on three fences: a new lane's rename is read back and undone when another window took the name, a row or log that says RETIRED is not started again, and a new lane never takes a window named for another registered lane (opensoft/openRepoTools#216).
- `lane` and `lane-handoff` refuse empty and flag-shaped flag values, and `lane-handoff` renames the window only once the handoff can no longer be refused (opensoft/openRepoTools#220).
- A silent tmux is no longer read as a dead window, the companion verdict is read off the lane's live window from any window, and the guard's cure for a lane named before Rule 4 says what it cannot fill in (opensoft/openRepoTools#222).
- `lane-start` gains a guard-only binding mode that stamps the transcript being bound, so the offer's yes no longer records a RESUMED nobody is in (opensoft/openRepoTools#223).
- Under `set -e`, `lanes --worktrees`, `openRepoTools wip init` and `lane-end` no longer end on macOS's bash 3.2 where a utility run through `command` fails, and a scan of the shipped scripts keeps that shape out (opensoft/openRepoTools#294).
- **The handoff and its skill:**
- The handoff skill commits the handoff in the checkout it was published in, by its own path, and refuses foreign staged entries and in-progress operations (opensoft/openRepoTools#199).
- Every shell block in the handoff skill parses, and the skill stops calling `/rename` the only act there is (opensoft/openRepoTools#200).
- The handoff skill resolves `lanes-edit.sh` on `PATH` first, its comments no longer promise write (c) without a workstation, and it refuses the object-log and register-line writes for a lane that has never had a session recorded (opensoft/openRepoTools#207).
- `rename-lane`'s Rule 3 handoff stamp is published through a same-directory temporary file and one atomic rename, so a writer killed mid-stamp leaves the handoff whole (opensoft/openRepoTools#212).
- The handoff skill's step-1 fence refuses Amendment 15(d)'s exit 2 instead of reading it as no answer, and its window ref is checked as a whole string (opensoft/openRepoTools#260).
- The handoff skill's two PAUSED writes carry the why it computed, sanitized as `lane-handoff` sanitizes it, and a why carrying a line break is refused before step 1 (opensoft/openRepoTools#264).
- **The lane tools look inside a triad's legs and paired feature trees**, so the sweep, `lane-end`'s gate, `lane-handoff`, `lane-reconcile` and the daily report can see a lane's work there, and a checkout with no `project.yaml` is treated as before (opensoft/openRepoTools#246).
- **The test suite and its checks:**
- Follow-ups to the test roots of opensoft/openRepoTools#190: a refused root's value is named, the pin's commit is checked, paired feature worktrees are found, redirected roots show under `-q`, the lane manual's sections run, and the installer-source test is restated (opensoft/openRepoTools#195).
- Clause (c)'s TAIL case is read on a checkout at a short fixed path, and `lane-start`'s row stamp is driven at three checkout lengths, so the case no longer answers by the length of the run root (opensoft/openRepoTools#215).
- The shell suite's wrapper stops the suite's process group on a timeout, an interrupt, TERM or hangup, the launcher precedence of `lane <name>` is pinned with launchers the suite names, and the pty driver's comment says what it counts (opensoft/openRepoTools#217).
- The hygiene check refuses host paths under the bench root, with an allowance for quoted `grep` patterns, and the consumer reads and the durable-intent sample no longer carry them (opensoft/openRepoTools#229).
- `tests/run.sh` refuses to start when it cannot record its lock's owner, and its cleanup removes only a lock that is still its own (opensoft/openRepoTools#232).
- The hygiene check's end-of-options rule splits a line only outside quotes, and the suite stops counting its bash files (opensoft/openRepoTools#239).
- The hygiene check reads every exit-3 die of `lanes-edit.sh` against its cause and both documented rows, so a die that claims nothing was pushed, or a fourth die no row documents, fails it (opensoft/openRepoTools#259).
- The shell suite times each of its sections and its exit-trap teardown, and prints both in its transcript and in CI's step summary (opensoft/openRepoTools#261).
- The shell suite's wrapper prints the suite's timing table and teardown line on a pass, where CI's log can read them (opensoft/openRepoTools#265).
- CI and the release workflow run on `ubuntu-24.04`, because `ubuntu-latest` is now Ubuntu 26.04, where setup-python has no Python 3.9 and the TERM-ignoring kill test fails: every Ubuntu runner in `tests.yml` and `release.yml` is pinned to it, the tests and the 006 contract lines that name the label follow, and `macos-latest` is unchanged (opensoft/openRepoTools#296).
- **The triad migration's records:**
- The migration's evidence of 2026-10-08 and 2026-10-09 is recorded: test roots and CI patches, the installer entry point, restore and rollback, opensoft/openRepoTools#192's corrections, T018 and the Gate B status (opensoft/openRepoTools#196).
- T006's `assembly-0001` and T010's code-leg `tests.yml` patch are re-cut against the files that opensoft/openRepoTools#228's series leaves, T009's assembly-root length-caps patch is added, and lines 17 and 33 of the Gate B walk are marked PARTLY until they are reviewed, as part of opensoft/openRepoTools#186 (opensoft/openRepoTools#266).
- **`<other-changes>`**: the changes that landed on `main` after `a42946e` and before the release commit and have no line above, by area, one line each with its pull request.

## Install and upgrade

Expand Down Expand Up @@ -81,10 +136,10 @@ Before the tag, fill in every placeholder below or cut its paragraph, then cut t
- [ ] **`<tag-time>` and `<tag-words>`**: the exact UTC second and Brett Heap's own words, as the tag message gives them.
- [ ] **`<pypi-url>`**: PyPI's page for `openrepotools` 1.1.0, filled in once PyPI serves it. Neither pypi.org nor test.pypi.org held the project when this was read on 2026-10-18 (both answered 404), and the page is expected at `https://pypi.org/project/openrepotools/1.1.0/`.
- [ ] **The hook pair, with no placeholder**: #237 landed as opensoft/openRepoTools#247 (`586dea2`, merged 2026-10-18T14:29:20Z), and #237 is in the `v1.1.0` milestone on Brett Heap's word. Re-read the hook-pair paragraph against `main` at the release commit: which entries wait, what the message says, and that our exact guard entry is taken back out of a file that carries it while the pair is deferred (at drafting, `openRepoTools:187` and `:3377-3392`; README says it too).
- [ ] **`<pr-count>`**: the number of pull requests that landed on `main` in `opensoft/openRepoTools` between v1.0.0's commit, `aaa7bc8`, and the release commit, counted at the tag.
- [ ] **`<other-changes>`**: the list under "What else changed since v1.0.0", written from the history from `aaa7bc8` to the release commit. The pin line above it is already written.
- [ ] **`<pr-count>`**: the number of pull requests that landed on `main` in `opensoft/openRepoTools` between v1.0.0's commit, `aaa7bc8`, and the release commit, counted at the tag. At drafting it was 53, counted at `a42946e`: each of the 53 commits of `aaa7bc8..a42946e` is the squash of one pull request, and none is a merge.
- [ ] **`<other-changes>`**: the closing line of the list under "What else changed since v1.0.0", for the changes that land after `a42946e`. The list above it was drafted on 2026-10-20 from the squash titles of `aaa7bc8..a42946e`, by area, one line each with its pull request. It carries 44 of the 53 pull requests in that range, the openRepoShape pin's (#233) at its head and 43 by area; the other 9 have their lines under "What 1.1.0 adds": the package series of #228 (#262, #267, #268, #269, #270 and #284), #237's hook pair (#247), #255's fix (#271) and #280's fix (#283). Lines for the changes after `a42946e` were added to it on 2026-10-21, each in its area: #263, #289, #294 and #296. They are not in those counts. At the tag, redo the list from `aaa7bc8` to the release commit, add a line for each pull request after `a42946e` that has none, check that every pull request in that range has a line in these notes, and cut this placeholder's line. The openRepoShape pin's line is already written.
- [ ] **`<workBenches#165 state>`**: whether opensoft/workBenches#165 has landed, and whether workBenches has taken a version that accepts pipx's link. If it has, rewrite the "One install route or the other" paragraph to say so; if not, keep it as it stands.
- [ ] **The pin, with no placeholder**: `contracts/openreposhape-pin.yaml` at the release commit still names `190133d`. If the pin moved, correct the pin line, and the commit it names must be on openRepoShape's `main`.
- [ ] **The milestone**: re-read the `v1.1.0` milestone. It held two issues at drafting time, #228 and #237. Each that lands before the tag gets its line above, and each that does not is moved out by Brett Heap.
- [ ] **The milestone**: re-read the `v1.1.0` milestone. It held two issues at drafting time, #228 and #237. By 2026-10-20 it held six entries: #228, still open; #237, closed by its merged pull request #247; #255, closed; and #280, closed by its merged pull request #283. Each closed entry has its line above under "What 1.1.0 adds" (#255's pull request is #271, which is not in the milestone). Each that lands before the tag gets its line above, and each that does not is moved out by Brett Heap.

This draft is `opensoft/openRepoTools-spec`'s `docs/release-notes/v1.1.0.md`.
Loading