Files
RedBear-OS/local/docs/RELEASE-BUMP-WORKFLOW.md
T
vasilito 6d8ef13dc1 LG Gram Round 1: redox-driver-sys stub replacements + doc reference fixes
Round 1 of the LG Gram 16Z90TP compatibility work. Two parallel
workstreams in one commit:

1. Stub replacements in redox-driver-sys (per project zero-tolerance
   policy):

   - load_dmi_acpi_quirks() (was hardcoded AcpiQuirkFlags::empty()):
     real loader walking a new compiled-in DMI_ACPI_QUIRK_RULES table
     (currently empty — documented why) plus a new [[dmi_acpi_quirk]]
     TOML section parser in toml_loader.rs. The full 16-flag
     ACPI_FLAG_NAMES mapping is added so TOML entries can use any
     AcpiQuirkFlags variant by name.

   - PANEL_ORIENTATION_TABLE (was empty placeholder): populated with
     10 real entries ported from Linux 7.x
     drivers/gpu/drm/drm_panel_orientation.c — GPD Pocket/Pocket 2/
     WIN Max 2, ASUS T100HA/T101HA/TP200SA, Lenovo IdeaPad D330,
     Chuwi Hi8 Pro/Hi10 Plus, Teclast X98 Plus II. Each entry cites
     its Linux source commit.

   - PLATFORM_RULES (kept empty): documented why intentionally empty
     (Linux platform-wide DMI quirks are pre-2020 platform workarounds
     not needed by Red Bear's modern targets).

2. Broken reference fixes after the 2026-07-25 archive
   (commit 589a1044e6 moved 9 docs to legacy-obsolete-2026-07-25/
   but didn't update references). 30+ files referenced the moved
   docs by their old local/docs/<name>.md path. This commit updates
   every reference to point at local/docs/legacy-obsolete-2026-07-25/
   <name>.md so links work again. Files touched: AGENTS.md,
   README.md, docs/{AGENTS,README,07-RED-BEAR-OS-IMPLEMENTATION-PLAN}.md,
   local/AGENTS.md, 14 docs under local/docs/, local/patches/README.md,
   5 scripts under local/scripts/.

The matching acpid+ps2d consumer wiring landed earlier today in
submodule/base commit 45452c5a (force_s2idle, no_legacy_pm1b,
kbd_deactivate_fixup). The bootstrap reference fix is submodule/base
commit 263a41a9. Both are tracked by the updated submodule pointer
in this commit.

Build verification: redox-driver-sys 80 cargo tests pass. acpid/ps2d
host tests not runnable (require cross-compile). Canonical build
attempts uncovered two pre-existing failures unrelated to Round 1:
relibc edition-2024 unsafe-block issue in crtn, and the base fork's
'common' path resolution relies on the build script's overlay
integrity auto-repair which is currently failing. Neither is in code
touched by Round 1.

See local/docs/evidence/lg-gram/ASSESSMENT-2026-07-26.md for the full
round-by-round assessment and next-round plan.
2026-07-26 16:59:32 +09:00

15 KiB
Raw Blame History

Red Bear OS — Release-Bump Workflow

Status: canonical operator runbook (2026-07-18) Audience: operators performing a Red Bear OS release bump Scope: moving version labels, fork sources, and the external desktop stack forward across a release-branch switch.

This document is the runbook for the release-bump pipeline. It is the companion to two contracts:

  • local/AGENTS.md § "Version conventions — two categories" and § "No-fake-version-label rule" — the policies this pipeline enforces.
  • local/scripts/TOOLS.md — the tool inventory (modes, flags, where each tool runs).

If the docs disagree, AGENTS.md is the policy authority and TOOLS.md is the behavioural contract of each script. This document is the workflow that sits on top of both.


TL;DR — the 30-second version

A Red Bear OS release bump is four steps. The first is human; the rest are mechanical or operator-judgement.

Step What Who/What Touches source?
1. Cut the branch Create the release branch on gitea (0.3.2) Operator only No
2. Switch + label-sync git checkout 0.3.2 → hook rewrites all version labels to match the branch (or run ./local/scripts/bump-release.sh by hand) post-checkout hook (opt-in) or operator No — labels only
3. Source upgrades ./local/scripts/bump-release.sh --with-sources --with-external rebases eligible forks to newer upstream tags and bumps the Qt6/KF6/Plasma recipes Operator Yes — real rebases + recipe bumps
4. Rebuild + stabilize Rebuild, fix patch fallout, regenerate lockfiles Operator Yes

Nothing in steps 24 ever auto-commits. Every step that changes the tree prints the exact git add / git commit sequence the operator should run.


The four-step release model in detail

Step 1 — Cut the release branch (operator only)

Per local/AGENTS.md § "BRANCH AND SUBMODULE POLICY", release branches are created by the operator only — one per Red Bear OS release cycle. Agents must never create branches. The branch name MUST be an anchored semver: 0.3.1, 0.3.2, 0.4.0. Non-semver names (master, submodule/*, recovered/*) are never release branches and are ignored by every tool in this pipeline.

The branch is created on the canonical gitea repo (https://gitea.redbearos.org/vasilito/RedBear-OS.git) from the prior release tip, then fetched locally:

git fetch origin
git checkout 0.3.2          # tracks origin/0.3.2

Nothing else happens at branch creation time. The bump machinery fires on the checkout, not on the branch creation.

Step 2 — Switch and label-sync

When the operator checks out the new release branch, two things can happen:

A. If the post-checkout hook is installed (opt-in; see local/docs/legacy-obsolete-2026-07-25/HOOKS.md):

git checkout 0.3.2
# post-checkout-version-sync.sh fires automatically:
#   - guards pass (semver branch, clean tree, no rebase in progress, …)
#   - detects root Cargo.toml is at 0.3.1, not 0.3.2
#   - runs: sync-versions.sh --no-regen   (labels only)
#   - prints the follow-up hint pointing at step 3

The hook does the label-only half of the bump:

  • Cat 0 (cookbook root Cargo.toml): version = "0.3.1""0.3.2".
  • Cat 1 (in-house crates under local/recipes/*/source/): same.
  • Cat 2 (upstream forks under local/sources/*/): the suffix moves — 0.9.0+rb0.3.10.9.0+rb0.3.2. The upstream base (0.9.0) is preserved because no source rebase has happened yet.

The hook explicitly does NOT:

  • regenerate lockfiles (--regen is never passed — it is a separate explicit step in step 4),
  • touch fork source content,
  • commit anything,
  • run on non-semver branches or dirty trees,
  • block the checkout under any circumstance (always exits 0).

B. If the hook is not installed, run the orchestrator by hand:

./local/scripts/bump-release.sh           # label sync + reports, no mutations beyond labels
# or equivalently for labels only:
./local/scripts/sync-versions.sh --no-regen

bump-release.sh (no args) delegates the label rewrite to sync-versions.sh --no-regen and additionally prints a fork-upstream report and an external-version report so the operator can see what step 3 will need to touch.

After step 2 the tree has correct labels but possibly stale sources and lockfiles. The operator should commit the label bump:

git add -A
git commit -m "release: sync version labels to 0.3.2"

Step 3 — Source upgrades

This is the expensive half. It is always operator-initiated via explicit flags and never triggered by the hook.

3a. Cat 2 fork source bumps — --with-sources

./local/scripts/bump-release.sh --with-sources

For each fork in local/fork-upstream-map.toml, bump-release.sh:

  1. Classifies the fork by its map mode column (decision tree below).
  2. For eligible forks (mode snapshot or tracked), git ls-remote --tags the upstream URL, find the latest anchored-semver tag, and compare to the fork's current base (the <X.Y.Z> before +rb).
  3. If upstream moved: invoke upgrade-forks.sh --to=<tag> <fork>, which fetches + pins upstream_ref to refs/tags/<tag>, creates a backup branch (rb-backup/<fork>), resets, re-applies the Red Bear net-diff, falls back to cherry-pick if needed, regenerates the fork lockfile, and runs verify-fork-functions.sh.
  4. On success: set the fork Cargo.toml version = "<tag>+rb<branch>", update map column 3 in place, and print the exact commit commands for the parent repo and the submodule/<fork> branch.
  5. On failure: report, leave map/label untouched. No partial state.

Per the no-fake-label rule (local/AGENTS.md § "No-fake-version-label rule (STRICT)"), labels never move without matching source content. When upstream is unchanged, only the +rb<branch> suffix moves (already done in step 2). When upstream moved, the fork is really rebased first, then the label moves to match.

3b. External desktop stack — --with-external

./local/scripts/bump-release.sh --with-external
# or just the version report first:
./local/scripts/check-external-versions.sh

This drives the rewritten, map-driven bump-graphics-recipes.sh over the Qt6/KF6/Plasma desktop stack and singletons (mesa, libdrm, libwayland, sddm, …) declared in local/external-upstream-map.toml. Groups resolve their version once (e.g. all KF6 frameworks move to the same frameworks/X.Y/), symlinked recipes are deduped by realpath so qtbase is bumped exactly once, and each recipe is validated with repo validate-patches <recipe> after the bump. Results land in .redbear-recipe-bump/last-report.txt with the line format:

recipe= old= new= patches_total= patches_pass= patches_fail= fail_details=

Failing patch validation is reported, not auto-fixed and never causes a recipe to be removed (per the AGENTS.md ABSOLUTE RULE). Failures become work items for step 4 (stabilization).

The two flags compose:

./local/scripts/bump-release.sh --with-sources --with-external

Step 4 — Rebuild and stabilize

After sources move, the build invalidation machinery fires automatically:

  • Source fingerprints — each recipe's content-hash cache (BLAKE3 of build deps) detects that the fork tarball changed and forces a rebuild.
  • relibc ABI wipe — when relibc itself moved, every downstream recipe is rebuilt against the new libc.a.
  • Prefix auto-rebuildbuild-redbear.sh detects that relibc/kernel/ base have commits newer than prefix/.../libc.a and rebuilds the prefix before any recipe build begins.
  • Preflight gatesbuild-preflight.sh re-runs sync-versions.sh --check, verify-fork-versions.sh, verify-patch-content.py, and verify-collision-detection.py before the build proceeds.

Stabilization work then proceeds in the normal build-fix loop: patch failures surfaced by step 3's report are fixed at the root cause (real implementation, no stubs — see local/AGENTS.md § "STUB AND WORKAROUND POLICY"). Lockfile regeneration is a separate explicit operator step:

./local/scripts/sync-versions.sh --regen      # after labels + sources settle

Fork decision tree (for --with-sources)

The fork's mode column in local/fork-upstream-map.toml decides what bump-release.sh --with-sources is allowed to do. Modes currently in use:

Mode Meaning Source-bump eligible?
snapshot Imported from an archived upstream snapshot; git history tracks a single upstream tag. (syscall, libredox, redoxfs, redox-scheme, relibc, userutils) Yes — auto source-bump when upstream semver moves.
tracked Fork follows an upstream ref (e.g. main); content checked but not byte-pinned. (base) Yes — but base's map tag is main, so it always resolves to suffix-only (see below).
diverged Fork has diverged materially from upstream; no clean rebase path without operator work. (kernel, bootloader, installer) No — report-only. Escape hatch: --force-diverged.

Decision logic, per fork:

mode == snapshot or tracked:
    latest_upstream = git ls-remote --tags <url> | latest anchored semver
    if latest_upstream > current_base:
        action = source-bump   (upgrade-forks.sh --to=<latest_upstream>)
    else:
        action = suffix-only   (already done in step 2)

mode == diverged:
    action = report-only
    # operator may pass --force-diverged to attempt a rebase anyway

tag == main  (base special case):
    action = suffix-only, always
    # base member crates carry no +rb suffix and the verifier accepts that
    # (see AGENTS.md § "Version conventions — two categories")

Bootloader note (special case)

bootloader is diverged and additionally has genuinely unrelated git history — there is no merge-base between the fork HEAD and upstream master. git merge-base HEAD upstream/master fails. This means upgrade-forks.sh cannot compute a net-diff to reapply and any attempt to source-bump it would destroy committed work.

bump-release.sh NEVER attempts a bootloader source bump, even with --force-diverged. It reports bootloader as action=report-only with the guidance:

Bootloader fork has no merge-base with upstream. A one-time git replace --graft <fork-head> <upstream-tag> intervention is required to synthesize a common ancestor before any rebase can be attempted. This is future work; the orchestrator never performs it.

The graft path (documented for the future, not run by any script today):

cd local/sources/bootloader
git replace --graft $(git rev-parse HEAD) <upstream-tag-sha>
# now upgrade-forks.sh can compute a merge-base and reapply the Red Bear delta

Until that graft lands, bootloader stays at its current upstream base and only its +rb<branch> suffix moves with each release bump.


Notes and invariants

Cargo.toml.orig files are never touched

Every Cat 2 fork may carry a Cargo.toml.orig that mirrors the upstream Cargo.toml byte-for-byte (Cargo leaves it behind when the fork edits the real Cargo.toml). sync-versions.sh, bump-release.sh, and the post-checkout hook all edit ONLY the live Cargo.toml. Cargo.toml.orig is a read-only witness of upstream state and MUST stay byte-identical to upstream so that verify-fork-versions.sh can compute the Red Bear delta.

Lockfile regeneration is a separate explicit step

sync-versions.sh --no-regen (the default, and what the hook calls) rewrites version labels but does not regenerate Cargo.lock. Lockfile regen is opt-in via sync-versions.sh --regen and should be run after both labels and sources have settled, because a source rebase can pull new transitive deps that an earlier label-only regen would miss.

Nothing auto-commits

Every step that changes the tree prints the exact commit sequence:

  • Parent repo (RedBear-OS on the release branch): label bumps, map column-3 updates, recipe tarball/blake3/rev updates.
  • submodule/<fork> branches: fork source rebases.

The operator runs git add / git commit / git push themselves. This is non-negotiable per local/AGENTS.md § "BRANCH AND SUBMODULE POLICY" and the project's general "agents never commit unless asked" rule.

Role of provision-release.sh and REDBEAR_RELEASE

provision-release.sh is the freeze-time tool: it provisions a new immutable release archive from a Redox ref into sources/redbear-<release>/. It is invoked explicitly and human-initiated, never by the bump pipeline.

REDBEAR_RELEASE=<x.y.z> is the env var that switches the build into sealed/release mode: sources are extracted from the immutable archive, online fetching is completely disabled, and local forks are ignored. In development mode REDBEAR_RELEASE MUST be unset (see .config rules in AGENTS.md § "BUILD COMMANDS"). The bump pipeline runs in development mode; it has no behaviour in sealed mode.


Cross-references

Topic Where
Version categories (Cat 1 / Cat 2), +rb suffix rules local/AGENTS.md § "Version conventions — two categories"
No-fake-version-label rule (labels match source content) local/AGENTS.md § "No-fake-version-label rule"
Latest-upstream-before-freeze rule local/AGENTS.md § "Local fork dependency rule"
Local fork dependency rule (path deps, no version strings) local/AGENTS.md § "Local fork dependency rule"
Branch and submodule policy (operator-only branches) local/AGENTS.md § "BRANCH AND SUBMODULE POLICY"
Tool inventory + modes local/scripts/TOOLS.md
Hook install / bypass / inventory local/docs/legacy-obsolete-2026-07-25/HOOKS.md
Fork → upstream tag/mode map local/fork-upstream-map.toml
External desktop-stack version map local/external-upstream-map.toml
Post-checkout hook source local/scripts/post-checkout-version-sync.sh
Installer source local/scripts/install-git-hooks.sh
Orchestrator source local/scripts/bump-release.sh

Appendix — full worked example

Bumping from 0.3.1 to 0.3.2 with the hook installed:

# Step 1 — operator creates 0.3.2 on gitea (out of band), then:
git fetch origin
git checkout 0.3.2
# ⟶ post-checkout hook fires:
#    post-checkout-version-sync: branch '0.3.2' root Cargo.toml at '0.3.1' -> '0.3.2'
#    post-checkout-version-sync: running sync-versions.sh --no-regen (labels only, no lockfile regen)
#    ... sync output ...
#    post-checkout-version-sync: label sync complete for branch '0.3.2'.
#    follow-up steps (NOT run automatically): ...

git add -A && git commit -m "release: sync version labels to 0.3.2"

# Step 3 — source upgrades (operator decides)
./local/scripts/bump-release.sh --with-sources --with-external
# ⟶ per-fork decision lines, per-recipe validation report at
#    .redbear-recipe-bump/last-report.txt. Prints commit commands.

# Step 4 — rebuild + stabilize
./local/scripts/sync-versions.sh --regen        # lockfiles
./local/scripts/build-redbear.sh redbear-mini   # build + preflight gates
# fix any patch fallout at the root cause; commit on 0.3.2 / submodule/<fork>

Without the hook, step 2 becomes:

git checkout 0.3.2
./local/scripts/bump-release.sh                 # labels + reports
git add -A && git commit -m "release: sync version labels to 0.3.2"

The rest is identical.