docs(landing): correct the runbook against what the real run proved - #500
Merged
Conversation
…skip-ci] The landing executed on 2026-08-01 as #497, #498 and #499 — all three slices merged with zero conflicts, and the final tree comparison came back with nine differing files, every one EXPECTED. This records that outcome and fixes the three claims the run disproved. Guard B's enumeration must not be narrowed to `$FORK..origin/main`. Seven of the eight hand-listed commits are ancestors of the fork, so that range yields 8 files where the curated list yields 21, dropping `package.json`, both workflow files and `KICKOFF-landing-runbook.md` — precisely the regressions `fee27061` exists to undo and that slice A excludes by hand. The reason is structural: prep's history is older than the fork, so a slice can revert `main` work that landed before the divergence point, and any enumeration bounded below by the fork is blind to that class. Nothing slipped through on the run, and it was checked rather than assumed — the wider 21-file guard was re-run retroactively across the whole landing and every removed line is a genuine supersession. PR #457 does not close itself. A PR's diff is computed against the merge-base, and landing content by replay never moves it, so #457 sat open reporting 73 changed files after its content had fully landed. It has to be closed by hand once the tip-to-tip diff is clean. Adds a rule that any `--delete-branch` needs its dependents enumerated first, open PRs that declare the branch as their base included, not only things downstream of it in ancestry. This run hit the harmless ancestry case when `land/slice-a` was deleted before slice B needed it as a rebase base. The streamer landing hit the base-ref case an hour earlier: GitHub closed the dependent PR silently, its content dropped out of that landing, and the automation reported success. Also records that the version-conflict path is still unexercised — `main` was ahead at 188/40 but no slice touched either version file — and clears the `RNSentry` note that #495 resolved. [skip-ci]
…it [skip-ci] The end-to-end check passed from `main` on a physical iPhone 17 Pro, but only after three false starts the Verification section did not warn about. A bare `npx expo run:ios --device` cannot sign this app on a physical device. Xcode's automatic signing regenerates its own Team Provisioning Profile every build and ignores hand-made ones, so the profile never carries App Groups and the build dies during "Planning build" with six errors and xcodebuild exit 65. That is exactly the failure #480 exists to solve, and it ships `scripts/dev-device.sh` for it — the six errors mean the wrong command was used, not that signing regressed. The existing block is right for a simulator, and only its `<simulator-udid>` placeholder said so. The other two faults arrived together and are independent, which matters because either can occur alone. The first is that a Metro already listening on 8081 captures the device. `expo run:ios` is non-interactive here, so it answers its own port-conflict prompt with `Skipping dev server`, and the device attaches to whatever already owns the port — on this run a server rooted at the repo root on `land/integration-prep` rather than the worktree under test. This is the dangerous one precisely because it is silent: with a healthy bundler it produces a working app showing another branch's code, and the log reports success. The remedy is to check the port owner before trusting the result and to confirm the bundle root in the Metro log. The second is that a long-lived Metro's resolver cache goes stale when its tree is rewritten underneath it. That server had been running for eight hours across the whole landing and could no longer resolve `react/jsx-runtime`, which was present on disk in both trees the entire time. This has nothing to do with which branch is served — it reproduces on the correct branch, with no mismatch to point at — so it is documented as its own failure with `--clear` as the fix. Both were visible in one red screen, and only the module path in the error revealed that the tree was also wrong. Recording them as one story would send the next reader hunting a branch-contamination bug that does not exist. [skip-ci]
RonenMars
force-pushed
the
docs/landing-runbook-post-run-corrections
branch
from
August 1, 2026 22:10
acdd00c to
78b7be5
Compare
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.
The landing executed on 2026-08-01 as #497, #498 and #499.
All three slices merged with zero conflicts; the final tree comparison against the frozen prep snapshot came back with nine differing files, every one classified EXPECTED — no drift, nothing unexplained.
#457is closed.This turns the runbook from a plan into a record, and fixes the three claims the run disproved.
It targets
land/integration-preprather thanmainbecause that is where the live copy of the document is.1. Guard B's enumeration must not be narrowed to
$FORK..origin/mainThis is the substantive one, and it is a latent safety defect rather than a stale number.
A companion document rewrote the guard's file enumeration as
log --name-only $FORK..origin/mainand expected it to reproduce the curated 21-file list.It yields 8.
Seven of the eight hand-listed commits are ancestors of
$FORK, so that range excludes them by construction.The 15 files it drops include
package.json,.github/workflows/test.yml,.github/workflows/deploy.ymlandKICKOFF-landing-runbook.md— precisely the regressionsfee27061exists to undo and that slice A excludes by hand.The guard meant to catch that class of mistake would have been blind to all of it.
The reason is structural and now stated in the document: prep's history is older than the fork, so a slice can revert
mainwork that landed before the divergence point, not only after it.Any enumeration bounded below by
$FORKcannot see that class.The curated list stays; the recipe is corrected.
Nothing slipped through on the real run, and that was checked rather than asserted: the wider 21-file guard was re-run retroactively across the whole landing, and every removed line is a genuine supersession (
expo-mcpdropped by #489,test:e2e:mockrewritten by #470, the ship scripts moving theirSENTRY_RELEASEexports, the Sentry investigation losing real org names by design, this document superseding its own text)..github/workflows/deploy.yml,CLAUDE.mdanddocs/troubleshooting.mdare additions only.The
CLAUDE.mdcase is written up with its mechanism: both slice B and slice C carried a copy predating #495, Guard B returned additions only on both (+16/−0 and +10/−0), and the reason is thatgit rebaseapplies patches rather than whole files, so non-overlapping hunks compose.That was likely but never guaranteed — the guard is what turned it from an assumption into a fact.
2.
#457does not close itselfThe old text said its diff shrinks as slices merge until it is empty and closes itself.
After all three slices merged it was still open, still reporting 73 changed files and +3446/−1126, while the tip-to-tip tree diff had drained to the nine EXPECTED files.
A PR's diff is computed against the merge-base, and every prep commit landed under a new SHA — slice A as a fresh cherry-pick, B and C as rebased replays — so nothing prep points at became reachable from
mainand the merge-base never moved.Any PR whose content lands by replay rather than by merge must be closed by hand.
3. A
--delete-branchneeds its dependents enumerated firstNew rule, stated generally: before deleting any branch on
origin, list everything that depends on that ref — open PRs declaring it as their base branch included, not only things downstream of it in ancestry.Ancestry-stacked is harmless; this run hit that case when
land/slice-awas deleted before slice B needed it as a rebase base, and--onto origin/main $A_ENDis the same operation.Base-ref-stacked is not.
GitHub closes such a PR automatically and the closure reads like ordinary cleanup.
The equivalent landing on the streamer repo hit this an hour earlier: the dependent PR was closed silently, its content dropped out of that landing, and the automation reported success.
The check is one
gh pr list --json baseRefNamecommand.Also
mainwas ahead at 188/40 during the real run, but no slice touchesapp.jsonorandroid/app/build.gradle, so no conflict arose. It was not exercised by the rehearsal either and must not be read as proven.RNSentrynote in the risks table is cleared — fix(ios): add RNSentry to the path-dependent Podfile.lock checksum list #495 closed that gap.docs/landing/rather than a path outside the repo.Deliberately not included
sessionNames.test.tsstill needs adding to the load-sensitive suite list indocs/troubleshooting.md.That file lives on
main, so it wants its own one-line PR there rather than being bundled into a prep-targeted change.It is recorded as outstanding in the document.