# Session Log -- 2026-09-04 ## Summary Picked up from yesterday's first real Streams-native release rehearsal. Found and fixed several real bugs while exercising the process further: a README.md link-rendering regression (root-caused to a missed Copy Up), a stale/wrong "Directory Structure Changes" section in `sdp_upgrade.sh`'s embedded docs, and -- the big one -- an unescaped quote that had been silently truncating `upgrade.sh -man`'s entire ~580 lines of documentation down to an 8-line stub for as long as the SBD feature text existed. Wrote up the "Merge Down, Copy Up" mantra as an explicit process rule after the second regression traced to the same root cause. Ran the full SDP+P4D upgrade exercise for real on a BSW Gen6 lab, found and fixed a real, long-standing naive-lexicographic-version-comparison bug in both `upgrade.sh` and `sdp_upgrade.sh` (confirmed it also explains a known, years-old internal-P4D-build pain point the user described). Filled in the HMS URL. Adopted a new SDP Version-file format (`YYYY.N.P[.SUFFIX]`) on the `r26.1.0.BETA` rehearsal stream. Set up a new Jenkins job and a new standing Gen7 QA lab for `//p4-sdp/main` (in progress/partially blocked, see below). ## README.md link regression, root cause, and the "Merge Down, Copy Up" mantra User reported the Swarm rendering fix from 2026-09-03 (site-relative `/view/` links) had "come back" broken on both `r26.1.0.BETA` and `main`. Root cause: `main` never actually received that fix -- it was made in `dev` (and manually patched into `r26.1.0.BETA`) but never Copied Up into `main`; the only `main`-side README.md edit since then (change 33463) was an unrelated platform-support text fix. When `r26.1.0.BETA` was later refreshed *from* `main` (to catch it up on unrelated changes, change 33471), that Copy-Up-from-main step faithfully propagated `main`'s stale, never-fixed content right over BETA's previously-good copy -- a real regression caught by the user re-testing a link they'd already confirmed fixed. Fixed via Copy Up from `dev` into `main` (33478) and re-synced into BETA (33480). This is the second time this exact class of bug has bitten this cycle (the first was `doc/ReleaseNotes.adoc`'s Jobs-Fixed list, found and fixed 2026-09-03/04 morning). Wrote up an explicit "Merge Down, Copy Up" mantra -- always Merge Down before a Copy Up, in either direction, with rare exceptions for deliberate cherry-picking -- as a new callout in `doc/ReleaseProcessOverview.md` (change 33482/33483) and as a feedback memory (`feedback_merge_down_before_copy_up.md`). ## `sdp_upgrade.sh` EDITME fix (change 33485/33487) The "Directory Structure Changes" section described a not-yet-implemented `/opt/perforce/ p4-sdp` OS-package migration (SDP-1158, deferred to 2026.2, 0% implemented) as if it were current 2026.1 behavior. Replaced with an accurate description of the two structures that actually exist today (legacy/depot-mount, and the `install_sdp.sh`-created `/opt/perforce/helix-sdp` structure since 2024.2). Also removed an orphaned `EDITME - END` marker and filled in a blank FILES AND DIRECTORIES table entry. ## The `upgrade.sh -man` truncation bug (change 33492/33493/33494-33496) While fixing an unrelated wording nit (user asked to drop "at least" from "unconditionally raises 'security' to at least 4" -> "to 4", to avoid drawing attention to security levels above 4 which SDP doesn't support), regenerating `doc/gen/upgrade.sh.man.txt` turned up something serious: the file was suspiciously short (8 lines vs. 34-676 for every other script). Root cause: an unescaped double-quote inside the `-opt-out-of-security-update` help text (`'p4d -r "-cset security="'`) broke bash's parsing of the *entire* multi-hundred-line DESCRIPTION+OPTIONS `msg()` call in the `-man` handler -- confirmed via `bash -x` showing the parser choking right at the broken quote, producing a bash runtime error that `gen_script_man_pages.sh` silently swallows (`2>/dev/null`, only checks the output file is non-empty). Net effect: **`upgrade.sh -man` had been producing almost no real content since the SBD text was added**, and since `SDP_Guide.Unix.html` includes that generated man page via `include::`, the customer-facing Developer/SDP Guide was silently missing nearly all of `upgrade.sh`'s documented content, including the `-Os`/ `-opt-out-of-security-update` section itself. Fixed the quote escaping; verified `upgrade.sh -man` now produces its full ~580 lines. Systematically checked all 15 other scripts in `gen_script_man_pages.sh`'s list (both by actually running each with the same minimal environment the generator uses, capturing stderr instead of discarding it, and via a textual pattern search) -- confirmed this was an isolated incident, nothing else affected. Also found and deleted an orphaned `doc/gen/get_helix_binaries.sh.man.txt` (leftover from before the `get_p4_binaries.sh` rename; `dev` only, `main` never had it). Filed **SDP-1387** (deferred, not urgent, per the user): make `gen_script_man_pages.sh` flag non-empty stderr from a script's `-man`/`-h` invocation as an error, instead of silently discarding it -- this exact check would have caught the bug immediately, since the bash runtime error was going to stderr the whole time. ## Real Gen6 upgrade exercise, twice, and the version-comparison bug (change 33502/33503) Wrote a new skill, `bsw-gen6-lab-create` (`//BattleSchool/main/ai/skills/`), documenting how to spin up a BSW Gen6 lab via `genlab.sh`, including a first-run `lab 0` idiosyncrasy (run it twice; a topology-role misconfiguration self-corrected on a third attempt on the second lab, cause not fully understood, not pursued further tonight) and a real `-u` Usage-tag bug in `genlab.sh` itself (`UserDefinedResourceUsageTag` vs. `UserDefinedResourceTag` mismatch -- fixed in `//BattleSchool/main`, change 2764053, merged down cleanly into `//BattleSchool/ Gen7`, change 2764055). Ran the full outer-to-inner SDP-then-P4D upgrade exercise for real on lab `bsw-sdp-upgrade-test` (SDP 2023.2->2026.1, P4D 2023.1->2026.1). Hit the new SDP-1350 Secure By Default guard for real (every host at `security=0`, the lab's intentional low-friction config) -- used `-Os` on non-master hosts and `-Os -opt-out-of-security-update` together on the commit server (found that `-opt-out-of-security-update` is commit-server-only *and* doesn't bypass the abort by itself, needing `-Os` alongside it). All verification passed: `p4 upgrades` (60/60 steps completed after allowing ~1 minute settling time), `p4 pull -ljv` before/after, `p4 servers -J` full-topology checks, `security` configurable correctly restored to 0. User then asked to make the SDP Version-file format decision real (`2026.1.0.BETA` instead of `2026.1`) and asked what else besides Release Notes/generating tools might depend on the exact format. Investigation found a real, confirmed break: `sdp_upgrade.sh`'s downgrade- detection logic does a naive lexicographic string comparison, and a longer/differently- shaped version string (more dot-components) sorts as *less than* a shorter one sharing the same prefix -- would misclassify the exact `2026.1` -> `2026.1.0.BETA` transition as a downgrade. Real customers are safe (the actual prior release, 2025.2, differs in the year digit early enough to save the old comparison by luck), but our own rehearsal/testing environments already stamped `2026.1` are not. The user then revealed this is the *same* long-standing bug class behind a real, years-old pain point: Perforce's internal-only P4D builds use a deliberately different version scheme (e.g. `2025.1.PREP-TEST_ONLY`) to make it obvious you're not on an official release, and `upgrade.sh`'s own downgrade check has the identical naive-comparison problem with those strings. Fixed both scripts with a new, numeric-aware `compare_versions()` / `_leading_numeric_ version_core()` function pair (duplicated identically in each file -- they don't share a library) that separates a trailing numeric changelist/build number from the "core" release number, takes only the leading numeric run of the core (silently ignoring any non-numeric internal/pre-release suffix), zero-pads to a fixed width, and compares numerically rather than lexicographically -- fixing both the suffix-insertion bug and a related digit-width bug (`9` vs `10`-style misordering) in one pass. Verified against 12 hand-built scenarios (including the real 2025.2->2026.1.0 GA transition, same-version equality despite differing suffix/CL-embedding shape, and internal-build-vs-internal-build ordering both directions) before touching the real scripts. Propagated dev->main->r26.1.0.BETA, repackaged and republished `main`'s live tarball, and re-verified the entire upgrade exercise end-to-end a *second* time on a brand-new lab (`bsw-sdp-upgrade-test2`) with all fixes in place -- clean pass, identical to the first run. Then made the Version-format change for real on `r26.1.0.BETA` (change 33519): `Rev. SDP/ MultiArch/2026.1/33441 (...)` -> `Rev. SDP/MultiArch/2026.1.0.BETA/33441 (...)`. Real GA on 2026-09-08 will naturally get `2026.1.0` (no suffix) from the normal Step 15 tooling; no code changes needed for that, this was purely a data/rehearsal decision. Did not touch `main`'s or `dev`'s current Version file. ## HMS URL filled in (change 33507/33508) User supplied the one URL needed for both `README.md` and `doc/SDP_Legacy_Upgrades.Unix.adoc`'s `EDITME-UpdateThisURL` placeholders: `https://swarm.workshop.perforce.com/projects/ perforce_software-hms` (the P4 Code Review project home page for HMS -- still pointing at HMS's own Classic depot home today, but will be silently retargeted, no SDP-side update needed, whenever HMS moves its own "main branch" to a `//p4-hms/main` stream). ## Release Notes: called out the new `-Os`/`-opt-out-of-security-update` options (33489-33491) Expanded the SBD "What's New" bullet to explicitly describe `-Os` and `-opt-out-of-security- update`, when each is needed, and the commit-server-only restriction -- prompted directly by hitting this for real during the Gen6 upgrade exercise above. ## Two disposable EC2 test VMs from 2026-09-02 terminated `i-0dac4107629a1c421` (disposable-test-u24-1) and `i-0160e0ab72d868a67` (disposable-test-r9-1), both in us-east-2, terminated per the user's request. ## New Jenkins job for `//p4-sdp/main`, blocked by a pre-existing host issue Created `p4-sdp-build_main` (cloned virtual stream `//p4-sdp/build_main` off `//p4-sdp/main`, cloned job config from `p4-sdp-build_dev`, reloaded Jenkins) per the `sdp-jenkins-build-check` skill's documented procedure. Every trigger attempt (4 total, including one after a full host reboot at the user's request) hit a rootless-podman/systemd container crash -- three different failure signatures across attempts (`container state improper`, `OCI runtime error: crun: read pipe failed`), with `Failed to set RLIMIT_CORE: Operation not permitted` and `failed to write to /proc/self/oom_score_adj: Permission denied` present in every crash log. The existing `p4-sdp-build_dev` job's container also crashed once (exit 137) during this, real evidence the RAM-contention risk flagged before creating the job was legitimate. The skill's documented "remove bad images, let them rebuild" fix did not reliably resolve it (matching the skill's own caveat that this fix is provisional). User manually retriggered (build #4, no changes) -- failed again, same signature, ruling out simple flakiness/timing. A fork then researched this further: found the *exact same crash class* already happened 2026-08-24/25 (a multi-day investigation at the time, exhaustively eliminated parallel-sync settings, stream-mode vs view-mode, virtual-stream remapping, checkout size, and a host package regression -- never cleanly attributed to one cause, eventually resolved via a Dockerfile fix plus Robert's own podman updates and a full container-store wipe). Confirmed no package drift since then, cgroup delegation (`Delegate=`) and `loginctl` linger for `jenkins` both still correctly in place, disk/inodes fine, `podman info` clean, and `main`'s image genuinely builds successfully (ruling out the historical "silently falls through to a stale cached image" bug). Per instruction, did a full container/image wipe (all containers and images, including the base image) -- got past the previous crash signature entirely on the rebuild, but the container now dies within ~2 seconds of `podman run --detach` (confirmed via a manual retry-loop, not just Jenkins) with no kernel OOM-killer event logged, so `exit 137` here isn't real memory pressure either. Also found (untouched) a real, unrelated gap: `test/run_docker_tests.sh` does `podman exec` immediately after `podman run --detach` with no readiness check at all -- worth fixing regardless, but wouldn't explain this near-instant crash. Not resolved tonight; see "Open / carried forward" for the Robert-handoff writeup. ## New standing Gen7 QA lab for `//p4-sdp/main` Per the user's guidance (separate `//BattleSchool/Gen7`-stream workspace, still `aws/vpc` relative to root, no license-fix or double-`lab 0` needed for Gen7, `-r us-east-1` only), stood up a second Gen7 lab (`bsw-SDP-QA-main`) alongside the existing standing dev-targeted one, without touching the latter. Created `//p4-sdp/main_insitu` (cloned from the `dev_insitu` template) and a new locked client `bot_SDP_QA.p4c-bos-01.SDP_QA_main`, following the naming convention the team designed specifically for this parallel-stream scenario (see `docs/SDP-QA-LabEnvironment.adoc`'s "Insitu Workspace Naming Convention" section). Copied credentials from the existing lab; verified a real, correct sync of `//p4-sdp/main` content. New SSH wrapper scripts at `~/ppn/7c_main/sdp_qa/` (separate directory, existing dev lab's wrappers untouched). Running `lab qa_build` surfaced that the actual CLI test suite installs from a *different* piece of infrastructure than the insitu client: a DVCS clone at `/opt/perforce/.dev/sdp`, baked into the AMI and (on this fresh lab) still bound to a stale, pre-rebrand snapshot (`Version` file said `2025.1/dev_rebrand`) under the user's personal P4 identity, which I don't have credentials for. Per the user ("just blast and re-clone"), wiped it and did a fresh `p4 clone -f //p4-sdp/main/...` as `bot_Claude_Anthropic` -- confirmed correct content (`2026.1/33441`) afterward. Re-ran `lab qa_build`: the stale-content symptoms (a `helix-sdp`- named backup path, a stale `r25.1` doc URL -- both false alarms from testing old content, not real bugs in current `main`, a correction made to the user after initially flagging them) were gone, but a *new* failure appeared (`Root directory ... invalid: chdir: /opt/perforce/ p4-sdp/p4/sdp/.p4root: No such file or directory`) -- looks like leftover partial `/opt/perforce/p4-sdp` structure from the *first* (stale-content) failed install attempt that wasn't fully cleaned before the second attempt. Not chased further tonight given the hour; see "Open / carried forward." ## Open / carried forward - **Jenkins podman crash**: still unresolved. User manually kicked off a 4th build attempt ("try try again," no changes made) -- crashed again with the familiar `container state improper` signature. Same failure class as 2026-08-24/25, recurring with no config/package drift since the last confirmed-working state. After a full container/image wipe, the container now dies within ~1-2 seconds of `podman run --detach` (not a stale-image or slow-startup issue), no kernel OOM event logged. Two consistent clues in every crash: `Failed to set RLIMIT_CORE: Operation not permitted` and `conmon: failed to write to /proc/self/oom_score_adj: Permission denied`. A research fork raised an untracked SELinux/systemd-policy change as one possible explanation for the capability/policy-denial flavor of these clues, but the user is skeptical ("Nothing would have changed with SELinux since our last attempts, so I think we can rule that out???") -- flagged to Robert as a tentative idea, not a confirmed cause. Sent Robert a Slack message (2026-09-04 evening, DM channel) asking him to look at the newly-configured `//p4-sdp/main` job (`p4-sdp-build_main`) when he gets a chance -- US is off Monday 2026-09-07 (Labor Day) but it's not a UK holiday, so there's a reasonable chance he gets to it before Tuesday. Jenkins-on-`main` is generally considered critical path to shipping 2026.1 on Tuesday 2026-09-08, **but** the user explicitly floated an override: if we're confident nothing Jenkins would have caught has actually regressed since it last worked on `//p4-sdp/dev` (i.e., if every failure here is purely "that Jenkins box is flaky"), the user may decide to ship Tuesday without a green Jenkins run on `main`. Longer-term, the user hopes to retire this whole test suite once its unique coverage is ported to the other SDP test suites, so this box's flakiness is a shrinking concern, not a growing one. - **Gen7 `main` QA lab**: `lab qa_build` still fails, now on what looks like leftover `/opt/perforce/p4-sdp` structure from the first (stale-DVCS-clone) attempt. Try a full `DANGER_CLEAN.sh` (or equivalent) pass, or just re-run `lab qa_build` once more now that the DVCS clone is correct, before assuming this needs deeper investigation. **User has now explicitly put a clean Gen7 test run on `main` on the critical path to shipping Tuesday 2026-09-08** -- unlike the Jenkins item above, no stated override/flexibility on this one. - **Gen6 lab-reset (`lab 0`) retest, post-upgrade**: after the first SDP+P4D upgrade exercise on `bsw-sdp-upgrade-test`, `lab 0` started failing quickly and repeatedly on that same lab; not yet known whether the upgrade itself broke the lab-reset mechanism or whether that was a fluke isolated to the first environment (the second exercise, on a fresh lab `bsw-sdp-upgrade-test2`, was not itself re-tested with a post-upgrade `lab 0`). User wants to run `lab 0` again in a lab, after a successful upgrade, specifically to answer this question before Tuesday. - **`doc/gen/get_helix_binaries.sh.man.txt`**: confirmed orphaned and deleted from `dev`; `main` never had it, nothing further needed. - **HMS URL**: done, both placeholders filled in dev->main. - **Version-format change**: done on `r26.1.0.BETA` only, as decided. Real GA on 2026-09-08 will get `2026.1.0` naturally from the normal release tooling -- no further action needed unless the user wants `main`/`dev`'s *current* Version file updated preemptively too (explicitly not done this session, per the user's framing that this was specifically about "the new environment"/BETA). - **SDP-1387** (gen_script_man_pages.sh stderr check): filed, deferred, no code changes made. - **"We've Moved" Classic SDP changes**: still staged from 2026-09-04 morning, reviewed and approved by the user, gated on the real GA shipping 2026-09-08 (see `project_sdp1170_stale_url_safety` memory). Not touched further tonight. - **The "Hot Fix" glossary entry / 2026.2 Release Notes content / disposable EC2s**: no change from earlier status (see 2026-09-04 morning's summary in this same log, or memory). - User is wrapping up for the night; plans to pick back up Tuesday morning (2026-09-08, release day) unless time opens up over the weekend. Three items above (Jenkins-on-`main`, Gen7 `main` QA lab clean run, Gen6 post-upgrade `lab 0` retest) are the specific carry- forwards called out for Tuesday; the Gen7 and `lab 0` items are release-blocking, Jenkins is critical-path-with-a-possible-override (see bullet above).