|
| 1 | +# 260712 — PR batch landing (#96–#103) with review fixes |
| 2 | + |
| 3 | +## Objective |
| 4 | + |
| 5 | +Land all 8 open PRs from Wibias on lidge-jun/opencodex, honoring the parallel sol-reviewer |
| 6 | +verdicts (2026-07-12 session 019f54d8): merge approved content, fix the named blockers on the |
| 7 | +PR branches, merge in stack order, and leave main green with zero open PRs from the batch. |
| 8 | + |
| 9 | +## Ground truth (explored) |
| 10 | + |
| 11 | +- Stack: `cde614a1`(#96) → `c6af7f90`(#97) → `6bb3aecf`(#98) → `e8794d22`(#99) → |
| 12 | + `84d601f9`(#100) → `37b4b2d6`(#101) → `21e58b09`(#102), all on fork `Wibias/opencodex`, |
| 13 | + all base=main. #103 = `aa888074` (independent; overlaps only `src/server/management-api.ts`, |
| 14 | + `gui/src/pages/Debug.tsx`). |
| 15 | +- Permissions: admin on repo; `maintainerCanModify: true` on PRs → can push fix commits to fork |
| 16 | + branches. main unprotected; merge-commit method is repo precedent (PR #87). |
| 17 | +- `origin/dev` == `origin/main` == `182ddae9` (v2.7.8). Land to main; fast-forward dev in WP7. |
| 18 | +- Bun 1.3.14 `node:zlib` enforces `maxOutputLength` for gzip AND zstd (verified: |
| 19 | + ERR_BUFFER_TOO_LARGE) → bomb fix is straightforward. |
| 20 | +- Worktree HEAD has an unrelated unpushed commit `953fb5b9` (another task's work) — do not |
| 21 | + touch it; all landing work happens on branches cut from `origin/main` / fork branches. |
| 22 | + |
| 23 | +## Landing mechanics (decision) |
| 24 | + |
| 25 | +Fix-on-fork-branch + `gh pr merge N --merge` in stack order. Identical SHAs reach main, so each |
| 26 | +successor PR's ORIGINAL stack prefix disappears from its diff; GitHub marks each PR merged |
| 27 | +(attribution preserved). Drafts get `gh pr ready N` first. `--merge` is REQUIRED throughout — |
| 28 | +squash/rebase would break the ancestry assumption (audit blocker 3). Fix commits pushed to a |
| 29 | +predecessor branch land on main via that predecessor's merge; successor branches never contain |
| 30 | +them, but 3-way merges cannot revert them (successor side unchanged since base). After EVERY |
| 31 | +merge, verify the next PR's `mergeStateStatus` and effective diff before merging it. |
| 32 | + |
| 33 | +Merge order: #103 → #96 → #97 → #98 → #99 → #100 → #101 → #102. |
| 34 | + |
| 35 | +Known conflict point (audit blocker 2, verified via merge-tree): after #103 lands, |
| 36 | +`gui/src/pages/Debug.tsx` CONFLICTS for #99..#102 tips. Resolution: WP5 merges origin/main into |
| 37 | +the #99 branch and resolves Debug.tsx ONCE (combine #99 lint refactor + #103 injection wiring). |
| 38 | +After #99 lands, #100–#102 merge cleanly (their own commits don't touch Debug.tsx, so 3-way has |
| 39 | +only one changed side). #96–#98 are unaffected (verified: no conflict vs aa888074). |
| 40 | + |
| 41 | +## Work-phase map (dependency-ordered, one PABCD cycle each) |
| 42 | + |
| 43 | +| WP | Doc | Content | |
| 44 | +|----|-----|---------| |
| 45 | +| 1 | 010 | Plan (this doc set) + merge #103 | |
| 46 | +| 2 | 020 | #96 + bounded decompression + SSRF resolution/reserved-ranges + activation tests → merge | |
| 47 | +| 3 | 030 | #97 + restore GUI build gate in ci.yml → merge | |
| 48 | +| 4 | 040 | #98 as-is → merge | |
| 49 | +| 5 | 050 | #99 + Usage.tsx cancellation guard → merge | |
| 50 | +| 6 | 060 | #100/#101/#102 as-is → merge | |
| 51 | +| 7 | 070 | Closeout: verify zero open batch PRs, main CI green, dev fast-forward, comments | |
| 52 | + |
| 53 | +## Reviewer verdicts folded in |
| 54 | + |
| 55 | +- #96 BLOCK: bomb cap post-allocation (`src/server/request-decompress.ts:43-48`); SSRF passes |
| 56 | + non-literal hostnames unresolved (`src/lib/destination-policy.ts:82-110`); reserved IPv4 |
| 57 | + ranges incomplete. → WP2 fixes. |
| 58 | +- #97 BLOCK: deletes GUI build gate (`.github/workflows/ci.yml:73-76`). → WP3 restores. |
| 59 | +- #99 BLOCK: `gui/src/pages/Usage.tsx` fetch has no cancellation → stale overwrite. → WP5 fixes. |
| 60 | +- #98/#101/#102/#103 approved (nits recorded, non-blocking). #100 fixture commit legitimate. |
| 61 | + |
| 62 | +## Rebutted residuals (recorded, not implemented) |
| 63 | + |
| 64 | +- DNS rebinding pinning + redirect-hop validation (reviewer #96): the proxy is a loopback |
| 65 | + service whose providers are configured by the machine owner; validation-time resolution + |
| 66 | + reserved-range default-deny is proportionate. Full dial-time pinning needs a custom dialer |
| 67 | + Bun fetch does not expose. Recorded here + in WP2 commit message. |
| 68 | +- #103 locale-time nit, #102 exhaustion-test nit, #98 adapter-level regression tests: cosmetic / |
| 69 | + non-blocking; noted for future work, not this batch. |
| 70 | + |
| 71 | +## Rollback / partial-landing policy (audit blocker 5) |
| 72 | + |
| 73 | +- Capture each merge-commit SHA in the goalplan ledger as it lands. |
| 74 | +- If main CI fails after merge N: STOP merging successors; prefer fix-forward on main; if |
| 75 | + infeasible, `git revert -m 1 <merge-sha>` in reverse landing order back to the last green SHA. |
| 76 | +- If a pushed fork fix must be withdrawn pre-merge: push a revert commit to the fork branch |
| 77 | + (never force-push another author's branch). |
| 78 | + |
| 79 | +## Verification contract |
| 80 | + |
| 81 | +Each WP: targeted `bun test` locally on the fix branch before push; PR checks green before |
| 82 | +merge; WP6/WP7 run the full suite. Security fixes carry activation tests |
| 83 | +(C-ACTIVATION-GROUNDING-01). Final: `gh pr list` empty for batch, `gh run list --branch main` |
| 84 | +green. |
| 85 | + |
| 86 | +## DONE — 2026-07-12 landing record |
| 87 | + |
| 88 | +All 8 PRs merged in planned order; every merge gated on the predecessor's main CI green. |
| 89 | + |
| 90 | +| PR | Merge SHA | Fix commits added on branch | |
| 91 | +|----|-----------|------------------------------| |
| 92 | +| #103 | d7b0a3fb | — | |
| 93 | +| #96 | 93fd0897 | 94a1ce72 (inflation-time cap), 74202966 (SSRF DNS + reserved ranges) | |
| 94 | +| #97 | d55a1e3a | — (amended: gate returns enhanced in #99; see 030) | |
| 95 | +| #98 | 576d8c45 | — | |
| 96 | +| #99 | 44db2ec1 | a0257db2 (Debug.tsx resolution), 77efcaf7 (Usage.tsx abort guard) | |
| 97 | +| #100 | 464fd7d4 | — | |
| 98 | +| #101 | 5dadf6d8 | 910fcaca (GUI-gate contract test) | |
| 99 | +| #102 | 47072be3 | — | |
| 100 | + |
| 101 | +Evidence: full suite 2145 pass / 0 fail at WP5 tip; gui lint+build clean; typecheck exit 0; |
| 102 | +per-PR CI green at each tip; `dev` fast-forwarded to main (47072be3). Out-of-scope: dependabot |
| 103 | +PRs #105+ opened by #97's new dependabot.yml — left for the owner. Deferred nits: #102 |
| 104 | +retry-exhaustion test, #98 adapter-level regression tests, #103 locale-time format. |
| 105 | +What did NOT happen (LOOP-PESSIMIST-01): dial-time DNS pinning/redirect validation |
| 106 | +(rebutted residual, loopback threat model); a #97 gate-restore commit (superseded by |
| 107 | +stack-internal #99 re-introduction — first plan draft had it wrong). |
0 commit comments