Repository navigation
Description
Local release trains combine several branches into one PR, one CI run and one release. Today the steps around a train are manual and get forgotten. On 2026-10-23, six Chronicle PRs (#5319, #5316, #5315, #5314, #5312, #5303) stayed open for hours after their branches were already merged into the local train for #5296. They would have rerun CI on every update. Folding is also not connected to local cross-repository verification (the cratis-engineering-local-cross-repo-verification skill in Cratis/AI), so downstream repositories verify against per-PR packages instead of the train's code state.
woksin (2026-10-23): "when this is decided and we know which already existing Prs that will be superseeded that we close these PRs and stop the running workflows associated with them as soon as possible" and "The clossing of PRs and stopping of workflows associated should be a rule / system in the local PI systems we have when we are merging and "release traninging" locally ... this also in someway needs to play nicely together with the "local packaging" system that we have for downstream and upstream package dependency local testing".
Rule (AGENTS.md, "Shipping finished work")
- Bundle branches locally before any PR exists. A PR is opened only for a train, never for a single delivery that will be folded.
- As soon as an existing PR's branch is merged into a local train branch, or it is decided that it will be, close that PR with "Folded into ". Cancel its queued and in-progress runs and move its release-note bullet into the train's note. Do this immediately, not at train push.
- Never push to a branch whose PR is folded or is going to be folded.
System (tooling)
A small pi-train tool, or lane subcommands, backed by a per-repository train manifest (for example .ai-work/trains/<repo>/<train>.json, holding the train branch, base SHA, folded branches with their SHAs and PRs, release bullets, the local package version, and upstream and downstream links):
init <repo> <train-branch>: cut the train from current origin/main and create the manifest.fold <PR|branch>:- Merge the branch into the train locally.
- Record it in the manifest.
- If a PR exists: close it with the standard comment, cancel every non-completed run for its head branch, and copy its release-note bullets into the train note draft.
- Refuse a PR that has unresolved review requests from people other than the author.
planned <PR> <train>: for a fold decided for a later train. Close the PR now with "Will be folded into " and cancel its runs.status: folded, planned and pending items, open PRs whose branch is an ancestor of a train without being closed (anomalies), and runs still active on folded branches.ship: push the train once, open or update the train PR with the aggregated note, and run the repo's PR-body check.- A guard (pre-push hook or pi extension) that refuses a push to a folded branch.
Local packages (works with cross-repo verification)
- Each train code state builds its local packages once, with a train-unique prerelease version such as
<next>-train.<short-sha>. This uses the pi-phase ledger, so an unchanged train state is never rebuilt. - Downstream repositories verify against the train's packages, not per-PR packages. The manifest records which downstream trains or lanes consume which upstream train version.
- Upstream-first ordering: when a downstream train depends on an upstream train,
statusshows the order. The downstream ships only after the upstream releases and the pin is bumped to the released version. Local versions never reach a commit or PR, and the existing guard is reused. - A fold into an upstream train marks the downstream verification stale, and the downstream owner re-verifies against the new train packages.
Done when
- The rule is in
~/.pi/agent/AGENTS.mdand matches the L0 rules file (rule 10). pi-train(init, fold, planned, status, ship, guard) works and has tests, including cancel and close on a sandbox repository or with a mocked gh.lanes statusand the repo-orchestrator brief (Repo orchestrator: one coordinating session per repository when several lanes work in it #20) use the manifest. Thecratis-engineering-local-cross-repo-verificationskill in Cratis/AI references train packages; that part is a separate Cratis/AI issue.- It is released in pi-setup.
Status
State: Paused — Not being worked now. Remaining: slice (c) train packages (waits for Cratis/AI#881, now in AI candidate 8) and lanes status reading the train manifest.
Branch: -
Scope: Rule in AGENTS.md first; pi-train tool in slices (a) fold/planned/status, (b) ship + push guard, (c) train packages and ordering.
Delivered: Nothing yet.
Remaining: To be confirmed.
Follow-ups: None.
Activity
AGENTS.md: fold superseded PRs into release trains immediately (part of
Add local release train init, fold, planned and status (part of #25)
fix(pi-train): review hardening (part of #25)
Merge train-fold: pi-train init/fold/planned/status (part of #25)
woksin commentedon Oct 23, 2026
Slice (a) is released in v2026.10.23.23 and installed live:
pi-traininit, fold, planned and status. The AGENTS.md rule shipped in v2026.10.23.22. Next is slice (b):ship, the push guard, andinit --adoptfor train branches that were assembled by hand. Slice (c) after that covers train packages; the Cratis/AI side is Cratis/AI#881.Add train shipping, adoption and push protections (part of #25)
Fix train push guard failures and review nits (part of #25)
Merge train-fold: pi-train ship, push guard, init --adopt (part of #25)
woksin commentedon Oct 23, 2026
Slice (b) is released in v2026.10.23.25 and installed live. It adds
pi-train ship,init --adopt, thetrainspush guard extension, and an opt-in pre-push hook that lets the push through when the guard itself fails. Remaining: slice (c), train packages and upstream/downstream ordering, together with Cratis/AI#881, andlanes statusplus the repo-orchestrator brief reading the manifest.woksin commentedon Oct 23, 2026
Added to scope (L0, ALL-RULES rule 11, woksin: "prefer as big chunks as makes sense to do in terms of completed time / when they are ready to merge, but it is at least good for the CI pipeline to reduce stress on it"):
pi-train foldandplannedtake a per-delivery--etathat is stored in the manifest.pi-train statusshows a cut recommendation: hold when a pending delivery is due within one gate duration, where the gate duration comes from the pi-phase ledger. The AGENTS.md rule ("Size trains by readiness") is committed and ships with the next release.AGENTS.md: size release trains by delivery readiness (part of #25)
pi-train: cleanup steps never hold a train; one windowed ledger read …
pi-train: snapshot the gate window once per invocation (#25)
pi-train status: report a train whose worktree is gone instead of abo…
pi-train close: mark a train released or abandoned, also when its wor…
pi-train close --shipped/--head and positional train; status flags on…
woksin commentedon Oct 23, 2026
Released in v2026.10.23.30 and .31, and installed live:
foldandplannedtake--eta;pi-train etaupdates or clears an ETA.statusgives a hold or cut recommendation, using a gate duration taken from the pi-phase ledger.pi-train close [--shipped PR#] [--head sha] | [--abandoned]marks a train finished.status --allkeeps going when a train's worktree is missing.Remaining:
lanes statusand the repo-orchestrator brief reading the manifest.