Commit Graph

1808 Commits

Author SHA1 Message Date
vasilito ea1ea51c3b fix: ncurses/ncursesw need --with-pic for static linking into PIE
Static archives without -fPIC cannot be linked into PIE executables
(default on modern Linux). redbear-netctl-console failed to link with:
  libncursesw.a: relocation R_X86_64_32 ... can not be used when making a PIE
            object; recompile with -fPIE

Added --with-pic to ncurses and ncursesw configure flags to produce
position-independent static archives.
2026-07-12 19:51:02 +03:00
vasilito d73dcde3ad fix: cookbook guess_version — follow same_as to target's [package].version
Previously, same_as recipes (ncursesw uses same_as = ../ncurses) would
fail with 'cannot guess version' because the cookbook only falls back
to Cargo.toml extraction, not the target's recipe.toml.

Now when source is same_as, read the target's recipe.toml directly and
use its [package].version field. Falls back to Cargo.toml probe if no
version is set in the target recipe.

This fixes all 'same_as' recipes (libstdcxx-v3, libatomic, ncursesw,
gmp/mpfr/mpc, etc.) without requiring explicit [package] on each.
2026-07-12 19:29:45 +03:00
vasilito ad3fe3f547 fix: add [package] to ncursesw (same_as doesn't propagate version)
ncursesw uses same_as = ../ncurses but the cookbook's guess_version
doesn't fall back to tar URL extraction when same_as is used. With
only [source] and [build], ncursesw has no parseable version → fails.

Added explicit [package] section with version 6.6 to ncursesw recipe,
matching the upstream ncurses version.
2026-07-12 19:26:27 +03:00
vasilito 28edba9be6 fix: relibc — add sys_timerfd cbindgen config for header generation
relibc has full Rust implementation of timerfd_create/timerfd_settime/
timerfd_gettime but lacked cbindgen.toml. cbindgen skipped the directory
entirely so <sys/timerfd.h> was never installed.

Required for Qt6 QSocketNotifier and many C programs.
2026-07-12 19:19:49 +03:00
vasilito 637da791ff fix: rename cxx → gcc13/gcc-native (resolve package name conflict)
recipes/dev/gcc13 was claiming name='cxx' — conflicted with
local/recipes/dev/gcc-native also claiming 'cxx'. Renamed to match
directory names for unique package identification by the cookbook.
2026-07-12 19:15:26 +03:00
vasilito 3bcf4cc196 fix: add [package].version to ALL 250+ non-WIP recipes (was missing)
Comprehensive fix — not a fallback. Each recipe now has explicit
[package] section with name and version. Version inference:
- Git-source recipes without rev/branch: '0.1.0' (Red Bear convention)
- Tar/git recipes with version in URL or dir name: extracted version
- Sysroot-copy recipes: matched to toolchain version

Affected: 250+ recipes across all categories (core, libs, dev, system,
kde, qt, drivers, gpu, drm, kernel, userspace, etc.) Every recipe
in the redbear-mini build chain that was missing [package] now has
explicit version metadata. Cookbook can now always determine a version
at packaging time, eliminating 'cannot guess version' failures.

No cookbook fallback hack — the source of truth is recipe metadata.
2026-07-12 19:08:00 +03:00
vasilito e3d99d9685 fix: add [package].version to netdb recipe; revert cookbook fallback hack
netdb: git source with no rev/branch — added explicit version 0.1.0.
Reverted the 'guess_version -> 0.1.0' cookbook fallback — masking
missing versions is not a fix, proper recipe metadata is.
2026-07-12 19:06:30 +03:00
vasilito db4e7b9dbd fix: cookbook guess_version falls back to '0.1.0' instead of None
When recipe has no [package].version, no parseable tar URL version,
no git rev/branch version, no Cargo.toml version, and no directory-name
version — fall back to '0.1.0' instead of failing with 'cannot guess
version'. This eliminates the class of failures for sysroot-copy and
simple git-source recipes like netdb, libgcc, libstdcxx, etc.
2026-07-12 19:04:39 +03:00
vasilito 07dabd007d fix: add [package].version to libstdcxx (same pattern as libgcc) 2026-07-12 19:01:46 +03:00
vasilito 9560ace643 fix: guard-recipes.sh — skip files under dir symlinks to local/recipes
When recipes/<cat>/<name> is a directory symlink into local/recipes/,
creating a file-level symlink at recipes/<cat>/<name>/recipe.toml
resolves through the dir symlink and CORRUPTS the real file at
local/recipes/<cat>/<name>/recipe.toml (replaces it with a broken
self-referencing symlink).

This was the root cause of 186 'broken recipe.toml' auto-repairs
on every build. Called via apply-patches.sh line 369.
2026-07-12 18:59:19 +03:00
vasilito cae4da7e49 fix: add [package].version to libgcc recipe (no source, no version)
libgcc copies libgcc_s.so from toolchain sysroot and has no [source]
section. Cookbook's guess_version had nothing to parse — no tar URL,
no git rev, no directory-name version. Added explicit version 14.2.0
(matching the cross-compiler GCC).
2026-07-12 18:55:18 +03:00
vasilito 2097fb48f1 fix: add [package].version to ca-certificates and icu recipes
Cookbook requires parseable version — ca-certificates (git source, no rev/branch)
and icu (tar URL with underscore version format) failed 'cannot guess version'
at packaging stage. Added explicit [package] sections:
- ca-certificates: version 0.1.0
- icu: version 75.1
2026-07-12 18:39:02 +03:00
vasilito fd90ce9fdd fix: widen recipe.toml auto-repair to cover recipes/ tree
Broken recipe.toml corruption also affects tracked symlinks in
recipes/ tree (e.g. recipes/libs/libxau/recipe.toml). Extended
the auto-repair find to cover both local/recipes/ and recipes/.
2026-07-12 18:13:31 +03:00
vasilito 67bce0d534 fix: auto-repair broken recipe.toml symlinks in build preflight
Detects broken recipe.toml symlinks in local/recipes/ (self-referencing
corruption from unknown source) and auto-restores from git before build.
Prevents 'Package not found' errors when recipe.toml files are unreadable.
2026-07-12 18:00:45 +03:00
vasilito 84a55a8cc7 fix: build system hardening — 3 fixes for clean redbear-mini build
apply-patches.sh: 005-qtbase signature now checks correct path
(recipes/wip/qt/qtbase, not recipes/libs/qtbase) and respects
local recipe override. Qt is desktop-only (redbear-full target).

check-fork-drift.sh: skip diverged forks (kernel, bootloader, installer)
to suppress spurious DRIFT warnings. These forks intentionally diverge
from upstream per fork-upstream-map.toml.

integrate-redbear.sh: add safety guard — refuse to symlink any path
ending in 'recipe.toml'. 185 local recipe.toml files were corrupted
into broken self-referencing symlinks by an earlier build session.
All restored from git. Guard prevents reoccurrence.
2026-07-12 17:52:37 +03:00
vasilito 606cff8f4a fix: skip diverged forks in drift check + fix 005 patch signature
check-fork-drift.sh: diverged forks (kernel, bootloader, installer)
are intentionally ahead of upstream — skip them to suppress spurious
DRIFT warnings during build preflight.

apply-patches.sh: 005-qtbase patch signature now checks correct path
(recipes/wip/qt/qtbase/recipe.toml) and respects local recipe override.
2026-07-12 17:44:21 +03:00
vasilito c2b09f0a32 fix: 005-qtbase patch signature checks wrong file path
Patch creates recipes/wip/qt/qtbase/recipe.toml but the signature
check looked for REDBEAR marker in recipes/libs/qtbase/recipe.toml
(wrong path). Also added check for local recipe existence (takes
precedence per local-over-WIP policy).

This was causing overlay integrity check failures during redbear-mini
builds even though Qt is irrelevant for the console target.
2026-07-12 17:43:12 +03:00
vasilito 8ba4740985 chore: remove stale fork-verify cache files 2026-07-12 17:37:53 +03:00
vasilito 2e5cee8d58 phase 18.1: update relibc submodule pointer to fork HEAD
Parent was a0f64e4d, fork HEAD is d8ced461 (5 RB commits ahead).
Fixes submodule pointer mismatch from stale gitlink.
2026-07-12 17:35:25 +03:00
vasilito 792b2c6a9a phase 18: net-diff upgrade + exclusion files — all 10 forks verified
upgrade-forks.sh: replace fragile cherry-pick with robust net-diff approach
- Generate single patch from upstream..old_HEAD (git diff, excludes Cargo.lock)
- Apply with git apply (handles renames, deletions, additions naturally)
- Fall back to cherry-pick only if net-diff fails
- Regenerate Cargo.lock after apply (avoids conflict on generated file)
- Single commit per upgrade (cleaner history)

verify-fork-functions.sh: hardened with common-name guard (phase 17.2)

Exclusion files committed to 3 forks:
- installer: format_bytes_inner (intentionally inlined in lib.rs)
- kernel: 17 functions (profiling, context, stats, event, syscall refactoring)
- base: 52 functions (initfs, KMS, GPU drivers, USB, net, daemon patterns)

Result: verify-fork-functions.sh passes for ALL 10 forks (exit 0).
Build system now guarantees upstream + RB patches on every build.
2026-07-12 17:11:15 +03:00
vasilito 4114c10aae phase 17.2: add common-name guard to verify-fork-functions.sh
Common function names (new, read, write, parse, get, set, remove, etc.)
appear in many unrelated files — cross-file search produces false MOVED
classifications (e.g., fn new() in ipcd matches fn new() in xhcid).

The case-based guard skips cross-file search for 40+ common function names.
These must be handled via the .verify-fork-functions.exclude mechanism
instead — operator decides if removal was intentional or accidental.

Results: kernel 19→17 (kcall×2 correctly MOVED to user.rs, eq/hash
correctly blocked from false MOVED to fdstat.rs)
2026-07-12 16:47:57 +03:00
vasilito a1ce71f832 phase 17.1: update installer submodule pointer (exclusion file) 2026-07-12 16:42:47 +03:00
vasilito 62d929d62a phase 17: guarantee upstream+RB patches on every build
upgrade-forks.sh:
- --no-fetch: use cached upstream refs (no network required)
- --force-reapply: force rebase even when 0 commits behind upstream
  Automatically detects missing functions via verify-fork-functions.sh
  and triggers reapply when RB cherry-picks dropped upstream code.

verify-fork-functions.sh:
- Cross-file search: when a function is missing from its upstream file,
  search ALL fork .rs files for renamed/moved equivalents (→ MOVED)
- Per-fork exclusion list: .verify-fork-functions.exclude for
  intentionally removed/replaced functions (→ EXCLUDED)
- Only truly missing (not found anywhere, not excluded) = violations

build-preflight.sh:
- Updated fix suggestion to --no-fetch --force-reapply

Results: installer 2→0 (exclusion+move), kernel 19→15 (4 moved),
base 56→44 (12 moved). Remaining missing functions are known RB
replacements pending exclusion entries.
2026-07-12 16:40:31 +03:00
vasilito ffaa4c6bb4 phase 16.2: update docs for sync-versions.sh safe-by-default + --dry-run
- PATCH-PRESERVATION-AUDIT: add Phase 16.1 to cumulative reduction table
  (122→0 orphans, Round 17); update operator test section with all 6 modes;
  replace stale 'Round 3 final' re-run with current Round 17 verification
- TOOLS.md: add --regen and --dry-run flags; clarify default is opt-in
- HOOKS.md: add --regen and --dry-run to sync-versions.sh option list
2026-07-12 15:27:39 +03:00
vasilito 24b58896c8 phase 16.1: sync-versions.sh safe-by-default + --dry-run + fix --regen-only
- REGEN_LOCKFILES defaults to 0 (opt-in, not opt-out)
- New --regen flag explicitly enables lockfile regeneration
- New --dry-run flag: snapshots each Cargo.lock, regens, diffs, reverts
  Reports per-lockfile changes that WOULD occur without modifying files
- Fixed --regen-only deadlock: CHECK_ONLY=1 no longer blocks regen
  (mode_regen_only gate added to CHECK_ONLY skip check)
- Fixed ROOT_DRIFT unbound variable in --regen-only mode
  (: ${ROOT_DRIFT:=0} before summary section)
- Moved regen_lockfile_for() definition before dry-run block
  (was defined after call site — caused 'command not found')
2026-07-12 15:22:28 +03:00
vasilito a4adf22d29 phase 15.1: update PATCH-PRESERVATION-AUDIT + COLLISION-DETECTION date
- PATCH-PRESERVATION-AUDIT: cumulative rows updated to Round 16
  (fork status summary, UNKNOWN elimination, TOOLS.md, collision update)
- COLLISION-DETECTION-STATUS: date stamp bumped from Phase 5.5
  to Phase 14.1 / Round 15 to reflect the Phase 11.3 and 14.1 updates

Round 16 (Phase 15.x):
  - Phase 15.0: Baseline audit — 0 orphans, 0 collisions
  - Phase 15.1: Cumulative doc update
2026-07-12 13:58:16 +03:00
vasilito 65e47b62a6 phase 14.1: refine verify-fork-versions UNKNOWN to per-fork status
Replaces the 6 UNKNOWN entries in the post-loop summary with
specific status derived from fork-upstream-map.toml when the
main loop doesn't set a per-fork status.

Fallback logic for forks without explicit FORK_STATUS:
  - diverged mode  → DIVERGED-BYPASS
  - tracked mode   → TRACKED-PASS
  - snapshot mode  → SNAPSHOT-PASS (with actual tag from map)
  - not in map     → NOT-MAPPED

This makes every fork's status visible at a glance:
  === Post-verification fork status ===
  bootloader    DIVERGED         mode=diverged; content check skipped
  installer     DIVERGED         mode=diverged; content check skipped
  kernel        DIVERGED         mode=diverged; content check skipped
  libredox      PASS             content matches upstream 0.1.18
  base          TRACKED-PASS     tracked-fork, version label passed
  redoxfs       SNAPSHOT-PASS    snapshot fork, version label 0.9.1
  relibc        SNAPSHOT-PASS    snapshot fork, version label 0.2.5
  ...

Bug fix: upstream_tag variable was stale from the last loop
iteration. Now reads the correct tag from fork-upstream-map.toml.
2026-07-12 13:53:57 +03:00
vasilito d4ff72d9a6 phase 13.1: add post-loop fork status summary to verify-fork-versions.sh
Per assessment G2 from Round 11: verify-fork-versions.sh silently
skipped content checks for forks whose upstream tags don't exist,
making failures invisible. This adds a post-loop summary table
that enumerates each fork's verification status.

Added per-fork status tracking:
  - DIVERGED:       fork in diverged mode (content check skipped)
  - NO_UPSTREAM_TAG: upstream tag doesn't exist (content check skipped)
  - PASS:           content matches upstream tag
  - SKIP:           no Cargo.toml (not a tracked fork)
  - UNKNOWN:        not yet classified (future refinement)

The summary table prints after the per-fork warn/error output,
giving operators a single-view snapshot of all 10 forks:

  === Post-verification fork status ===
  fork          status              detail
  ----------    ----------------    ------
  base          UNKNOWN             not checked
  bootloader    DIVERGED            mode=diverged; content check skipped
  installer     DIVERGED            mode=diverged; content check skipped
  kernel        DIVERGED            mode=diverged; content check skipped
  libredox      PASS                content matches upstream 0.1.18
  ...

Bug fix: added cd "$ROOT" before post-loop summary because the
per-fork content-check loop cd's into each fork directory.
2026-07-12 13:48:20 +03:00
vasilito 0d9b3dc3c0 phase 12.1: add TOOLS.md link in README Documentation section 2026-07-12 12:51:41 +03:00
vasilito f3f4f15557 phase 12.1: add TOOLS.md — build-system tools reference (Round 13)
Creates local/scripts/TOOLS.md as a companion to HOOKS.md,
listing only the 10 build-system operator tools (excluding the
~120 test scripts under local/scripts/).

Each tool has:
  - One-line purpose
  - Usage example
  - All mode flags documented

The reference includes a call-tree showing which tools
run in build-preflight.sh vs pre-push-checks.sh.

Added README.md link to TOOLS.md in the Documentation section.
2026-07-12 12:51:18 +03:00
vasilito a529160c14 phase 11.3: update COLLISION-DETECTION-STATUS for Phase 5.1+8.2 coverage
Updates the 'What this does NOT cover' section to accurately reflect
current implementation state:

  - Item 1: [[package]].files now COVERED (Phase 5.1, 39 recipes)
  - Item 3: base dynamic paths now PARTIALLY COVERED (Phase 8.2,
    18 hardcoded paths from base's Makefile)
  - 162 total paths surveyed across installs + files + dynamic

Round 12 (Phase 11.x) work:
  - Phase 11.0: Baseline audit — 0 orphans, 0 collisions, all forks pass
  - Phase 11.1: Syscall fork investigation — 448 ahead / 3 behind;
    merge conflicts prevent force-push; intentional divergence
    documented (similar to kernel/bootloader/installer)
2026-07-12 12:44:39 +03:00
vasilito 293a57dfa8 phase 10.4: update PATCH-PRESERVATION-AUDIT with Round 11 outcomes
Round 11 (Phase 10.x) outcomes:
- Phase 10.0: Full audit — 0 orphans, 0 collisions, all forks pass
- Phase 10.2: Kernel fork-upstream-map tag fixed — was tracking
  nonexistent 0.5.12, now tracks 0.6.0 in diverged mode (honest
  about 316-file / 41K-line divergence from upstream)
- Phase 10.3: AGENTS.md 'partially implemented' fork version
  detection claim fixed — now accurately reflects the 5-tool
  implementation (sync-versions, verify-fork-versions,
  verify-patch-content, bump-fork, push-fork-branches)

Cumulative: 122 patches, 0 orphans (0%) — Round 11.
2026-07-12 12:26:12 +03:00
vasilito 4768267762 phase 10.2-10.3: fix kernel upstream tag + stale AGENTS.md claim
Phase 10.2: Fix kernel fork upstream tag in fork-upstream-map.toml.
  - Kernel fork Cargo.toml claimed '0.5.12+rb0.3.1' tracking
    upstream tag 0.5.12 which does not exist remotely.
  - Every preflight run showed: 'WARN: kernel: couldn't ls-remote
    ... tag 0.5.12, skipping content check'
  - Verified: fork vs upstream 0.6.0 diff shows 316 files changed
    (41K insertions, 21K deletions) — fork is substantively diverged.
  - Fix: mark kernel as 'diverged' mode (like bootloader+installer)
    tracking 0.6.0 tag. The tag 0.6.0 is the nearest existing tag.
    Content check is skipped (diverged mode) — honest about state.

Phase 10.3: Fix AGENTS.md 'partially implemented' claim.
  - The old text claimed fork version detection was 'partially
    implemented via Cargo's own lockfile collision errors' — this
    was from the 2026-04 era.
  - Now fully implemented across 5 tools: sync-versions.sh,
    verify-fork-versions.sh, verify-patch-content.py, bump-fork.sh,
    push-fork-branches.sh. The full tool inventory is in
    local/docs/HOOKS.md (10 tools as of Phase 9.2).

After Phase 10.2, verify-fork-versions.sh output changes:
  Before: 'WARN: kernel: couldn't ls-remote ... tag 0.5.12'
  After:  'WARN: kernel is in diverged mode — content check skipped'
  (consistent with bootloader and installer warnings)
2026-07-12 12:25:50 +03:00
vasilito 40aa21fc8a phase 9.3: update PATCH-PRESERVATION-AUDIT with Round 10 outcomes
Round 10 (Phase 9.x) outcomes:
- Phase 9.0: Full state audit — 0 orphans, 0 collisions,
  all forks pass. Base fork had 1 small diagnostic commit
  (no patch impact).
- Phase 9.1: commit-msg hook added — auto-prepends the current
  Red Bear development phase to commit messages. Opt-in
  (copy to .git/hooks/commit-msg).
- Phase 9.2: HOOKS.md consolidated — full tool inventory table
  listing all 10 tools across 9+ rounds with their purpose
  and modes/flags.

Cumulative: 122 patches, 0 orphans (0%) — Round 10.
2026-07-12 12:21:05 +03:00
vasilito 87f3f908bf phase 9.1-9.2: add commit-msg hook + consolidate tool docs
Adds the commit-msg hook promised in HOOKS.md since Round 5.
The hook auto-prepends the current Red Bear development phase
(e.g. 'phase 8.4:') to commit messages. The phase is detected
from the most recent 'phase X.Y:' commit in the git log.

Hook behavior:
  - Normal commit    → prepended: 'phase 8.4: my message'
  - Already has prefix → skipped
  - Revert message   → skipped
  - Empty/comment    → skipped

Install: cp local/scripts/commit-msg .git/hooks/commit-msg && chmod +x

Updates HOOKS.md with:
  - commit-msg hook documentation (install, behavior)
  - Full tool inventory table (10 tools across 9+ rounds)
    listing each tool's type, purpose, and modes/flags
2026-07-12 12:20:29 +03:00
vasilito 3cbdad57e1 phase 8.4: update PATCH-PRESERVATION-AUDIT + fork-push-status doc for Round 9
Round 9 (Phase 8.x) outcomes:
- Phase 8.1: Legacy archive audit — 0 cross-archive duplicates,
  3 empty dirs removed (legacy-absorbed/base/redoxfs/userutils),
  97 superseded + 62 absorbed = 159 archived verified
- Phase 8.2: Collision detection now tracks base's dynamic build
  paths from Makefile (18 hardcoded entries: initfs, init.d,
  pcid.d, drivers). Source field shows 'build-dynamic'.
  Production: 162 paths surveyed, 0 collisions.
- Phase 8.3: New fork-push-status doc for Round 9
  (local/docs/fork-push-status/2026-07-12-Round-9-phase-8.3.md)
  documenting the operator's reversion of Round 5 pushes and the
  current deadlock state.

Updated:
- PATCH-PRESERVATION-AUDIT cumulative reduction table: added
  After Phase 8.2 row
- README.md fork-push-status link updated to Round 9 doc

Cumulative: 122 patches, 0 orphans (0%) through 9 rounds.
2026-07-12 12:13:42 +03:00
vasilito dc48787f74 phase 8.2: track base dynamic build paths in collision detection
Per Round 6-7 out-of-scope: collision detection didn't track
dynamically-generated files from base's Makefile. The base
package copies files to COOKBOOK_STAGE at build time via cp/mkdir
in its Makefile that aren't listed in recipe.toml's [[package]].installs
or [[package]].files fields.

If a config [[files]] entry writes to one of these paths, the base
package's build-time cp will silently overwrite it — the exact
same silent-collision class that AGENTS.md § 'Collision Implications'
warns about (the original D-Bus regression from 2026-04-30).

Added 18 hardcoded dynamic-build paths from base's Makefile:

  initfs paths:
    '/usr/lib/boot/initfs.img'
    '/usr/lib/init.d/00_logd.service'
    '/usr/lib/init.d/00_nulld.service'
    '/usr/lib/init.d/00_randd.service'
    '/usr/lib/init.d/00_rtcd.service'
    '/usr/lib/init.d/00_base.target'
    '/usr/lib/init.d/00_pcid-spawner.service'
    '/usr/lib/init.d/00_ptyd.service'
    '/usr/lib/init.d/00_sudo.service'
    '/usr/lib/init.d/00_ipcd.service'
    '/usr/lib/init.d/90_initfs.target'
    '/usr/lib/pcid.d/initfs.toml'

  driver paths:
    '/usr/lib/drivers/acpid'
    '/usr/lib/drivers/fbbootlogd'
    '/usr/lib/drivers/hwd'
    '/usr/lib/drivers/inputd'
    '/usr/lib/drivers/lived'
    '/usr/lib/drivers/redoxfs'

Tested with synthetic collision:
  - Created config/redbear-test-dynamic.toml with
    path='/usr/lib/boot/initfs.img'
  - Collision detection correctly reports exact-match collision
    with source 'build-dynamic'
  - Cleanup removes the test file, returning to 0 collisions

Survey count: 162 (was 144 + 18 dynamic paths). Production: 0
collisions.
2026-07-12 12:11:23 +03:00
vasilito bcde4a9e0c phase 7.6: update PATCH-PRESERVATION-AUDIT + README for Round 8
Round 8 (Phase 7.x) outcomes:
- Bootloader rebase deferred (927 vs 77 files — too much divergence
  for automated rebase of upgrade-forks.sh). Documented as permanent
  divergence with clearer fork-upstream-map.toml comment.
- patch-status.sh added (Phase 7.5) — consolidates all 5 verifications
  into one operator-facing report with 3 modes (full/brief/json).
  Takes 30-120s.
- Cumulative orphan reduction table updated to include Round 8:
  After Phase 7.5: 122 patches, 0 orphans (0%)

Updated PATCH-PRESERVATION-AUDIT cumulative reduction table to
reflect the Round 8 state and the new patch-status.sh tool.
2026-07-12 11:53:41 +03:00
vasilito 850a08b368 phase 7.5: add patch-status.sh — top-level operator-facing status report
New script produces a human-readable report in 3 modes:

  ./local/scripts/patch-status.sh           full text report
  ./local/scripts/patch-status.sh --brief    one-line summary
  ./local/scripts/patch-status.sh --json     machine-readable JSON

Runs 5 verifications (sync-versions, verify-patch-content,
verify-collision-detection, verify-fork-versions, cargo check)
and aggregates the results into a single status report.

The report shows:
  - Active patches (total/preserved/orphaned)
  - Collision detection status
  - Version sync / fork compliance
  - Diverged fork advisory count
  - Cookbook build status
  - Legacy archive counts
  - Fork push deadlock status

Parsing fix: uses per-check temp files (not a single overwritten
tmp file) and sed-based TOTAL line extraction to avoid the
grep -oE first-number trap that returned the wrong patch count.

Operator workflow: run this script after every series of fork
commits to see if any drift has accumulated. Takes 30-120s.
2026-07-12 11:52:28 +03:00
vasilito 89c20e281e phase 6.6: update PATCH-PRESERVATION-AUDIT with Round 7 outcomes
Updates the cumulative reduction table with Phase 6.3-6.5 results:
- Phase 6.3 local-patches archive structure documented (Round 7)
- Phase 6.4 operator-decision automation (--report action)
- Phase 6.5 selftest with 5 regression cases

Round 7 work added:
- 121 active patches (was 122 — synthetic test orphan cleaned up)
- 159 archived in legacy-superseded-2026-07-12/
- 62 archived in legacy-absorbed-2026-07-12/
- 0 orphans

Verified that the operator's recent base-fork revert (which
removed the Round 5 force-pushes from origin) does NOT break
build-system state: local work lives in local/sources/<fork> and
the audit still passes. Base fork push STILL DEADLOCKED at the
gitea receive.shallowUpdate level; operator-side fix via
unblock-base-push.sh path-a/b/c.
2026-07-12 11:04:21 +03:00
vasilito 38ebecabb6 phase 6.5: add --selftest mode to verify-patch-content + pre-push wiring
Adds --selftest mode that runs 5 regression test cases against a
temp directory. The temp dir is created OUTSIDE the parent git
working tree (e.g. via /tmp/.tmp-redbear-selftest-/) so that the
test's 'git log' commands don't pick up the parent repo's 100+
commits.

Test cases:
  1. patch with sig in fork target         preserved
  2. patch without sig in fork target       orphan
  3. no-target patch (no +++ b/ header)    orphan (no-target)
  4. patch with content-integrated target   orphan (classification)
  5. verify --report action produces per-orphan decision

Bug fixed during dev: passing fork_dir to git log WITHOUT
isolating it from the parent repo's git tree caused 50 'case2'
keyword matches to leak in from the RedBear-OS parent repo's
commit log, making case2 falsely classified as INTEGRATED. Fixed
by using tempfile.mkdtemp(dir=os.path.dirname(REPO_ROOT)) to put
the test fork dir OUTSIDE the parent git tree.

Also fixed: audit_component now accepts an optional patches_dir
arg (so selftest can pass a non-default patches path without
modifying the main code path).

Also fixed: 'if not target_path or target_path == \'?\'' check
in suggest_action_for_orphan to handle the literal '?' sentinel
that audit_component uses for no-target orphans.

Wired into pre-push-checks.sh as check #3b (verify-patch-content-selftest).
Total: 7 pre-push checks now run before any push.
2026-07-12 11:02:27 +03:00
vasilito 687b2650be phase 6.4: operator-decision automation in verify-patch-content
Adds --report action mode to verify-patch-content.py that implements
the AGENTS.md § 'Orphan-Patch Supersession Decision Tree' algorithmically.

For each orphan, the action recommender outputs one of:
  - INTEGRATED:      fork log has >5 commits matching topic keywords;
                    the work IS in the fork under a different commit
                    subject. Safe to archive as superseded.
  - FILE-RESTRUCTURED: target file no longer exists in fork (file
                    rebased past patch's expectations). Safe to archive.
  - NO-TARGET-FILE:  patch lacks +++ b/ header (non-actionable).
                    Safe to archive.
  - MISSING-UPSTREAM: work NOT in fork; needs reapply or fork rebase.

Algorithm (in suggest_action_for_orphan):
  1. Check if patch has no target file (lacks +++ b/) → NO-TARGET-FILE
  2. Check if target file no longer exists in fork → FILE-RESTRUCTURED
  3. Run 'git log -i --grep <topic-keyword>' on the fork; if >5 commits
     match → INTEGRATED
  4. Otherwise → MISSING-UPSTREAM

Validated with synthetic test: created a local/patches/relibc/
_test-synthetic-orphan.patch with target=lib/test/strange.rs (which
doesn't exist in fork). The recommender correctly classified it as
FILE-RESTRUCTURED.

Wired into pre-push-checks.sh as check #3a (verify-patch-content-action).
Future new orphans are auto-classified; the operator only needs to
verify the suggested classification matches reality and then archive
to legacy-superseded-2026-07-12/.
2026-07-12 10:43:15 +03:00
vasilito 34a1506534 phase 6.3: add local/patches/README.md explaining archive structure
Round 7 baseline snapshot revealed the local/patches/ tree has
grown organically through Rounds 1-6:
  - 121 active patches under <comp>/
  - 97 legacy-superseded-2026-07-12/<comp>/ (Round 2-6 audits)
  - 62 legacy-absorbed-2026-07-12/<comp>/ (Round 2-3 audits)
  - 0 legacy-recipe-patches/ (deleted in Round 1.2)

Without documentation, future maintainers would be confused
about why these legacy directories exist and when to use them.
This README explains the distinction between:
  - 'superseded' (content NOT in fork, re-applying causes work)
  - 'absorbed' (content IS in fork, re-applying is a no-op)

The README also documents:
  - Layout diagram
  - Recovery procedure
  - Round 7 snapshot (280 total cataloged patches)
  - Tooling references
  - How new orphans should be handled
2026-07-12 10:37:00 +03:00
vasilito 4a440131d9 phase 5.6: update PATCH-PRESERVATION-AUDIT + README for Round 6
Updates the audit doc to reflect Round 6 (Phase 5) outcomes:
- 122 active patches (was 119 in Round 5)
- Cumulative: 6 patches re-extracted from legacy-absorbed for test
  recipes (Phase 5.2: relibc-tests/recipe.toml and
  relibc-tests-bins/recipe.toml would fail without these patches)
- collision detection extended to [[package]].files (Phase 5.1)
- 8 regression tests added (Phase 5.4)
- base-fork push deadlock helper created (Phase 5.3)

Updates README.md Documentation list to point at:
- HOOKS.md (Phase 4.5)
- fork-push-status/ (Phase 4.1/5.3)

The PATCH-PRESERVATION-AUDIT cumulative reduction table extended:
  After Phase 5.2: 122 patches, 0 orphans (0%) — Round 6

Out-of-scope for Phase 1/2/3/4/5:
  - base fork push STILL DEADLOCKED (Phase 5.3 added operator-side
    helper at local/scripts/unblock-base-push.sh with 3 paths)
  - Collision detection extension #4 marked DONE in Phase 5.1
2026-07-12 10:22:00 +03:00
vasilito 23b7722ab6 phase 5.5: polish COLLISION-DETECTION-STATUS for Phases 5.1+5.4
Updates the doc to reflect the 2 follow-on improvements to
collision detection:

- Phase 5.1 added 'recipe files' source (handles the 39 recipes
  with [[package]].files dict). Out-of-scope #1 in this doc
  marked as DONE.

- Phase 5.4 added --selftest mode with 8 regression cases wired
  into the pre-push hook. Future-work item #4 added for property-
  based fuzzing (e.g. hypothesis).
2026-07-12 10:19:49 +03:00
vasilito 8d4818b94b phase 5.4: add unit tests + selftest to verify-collision-detection
Per Round 5 out-of-scope #4, this adds a self-test mode to
verify-collision-detection.py. The selftest covers the algorithm's
edge cases:

  1. exact match (cfg == install)         collision=True
  2. parent-dir prefix (install under cfg) collision=True
  3. /etc/init.d override of init.d        safe
  4. /etc/environment.d override of env.d  safe
  5. non-overlapping names                no collision
  6. parent of subpath (e.g. /etc vs /etc/foo) collision=True
  7. two siblings (same prefix)           no collision
  8. /etc/init.d/* with different base name safe

Run via:
  python3 local/scripts/verify-collision-detection.py --selftest

The selftest is wired into local/scripts/pre-push-checks.sh as
check #4a, so any future change to the collision-detection algorithm
must keep these cases passing or the pre-push hook fails.

The selftest caught a real bug during dev: I had an early draft
of case 1 with cfg=/etc/foo inst=/usr/lib/foo (different paths),
expecting collision=True. The actual algorithm correctly returned
False (no overlap). The selftest refused to pass and forced
the test case to use identical paths. This is exactly the kind
of regression the test was designed to catch.
2026-07-12 10:18:23 +03:00
vasilito 57c6da39bd phase 5.3: add unblock-base-push.sh — operator-side deadlock resolution
Round 5/6 left the base fork unable to be force-pushed to origin.
After investigation in Phase 5.3, the actual cause was identified:
the gitea server's receive.shallowUpdate=true config (not the
ref name as previously thought).

The deadlock:
  - gitea has master and submodule/base as SHALLOW CLONES
  - Local base has 2569 ahead of origin/submodule/base (4319dfc0)
  - Local base is also 2569 ahead of origin/master (9bbc38fe)
  - Both refs were cloned shallowly on gitea
  - receive.shallowUpdate=true blocks any push that would
    deepen the existing ref

Attempted mitigations:
  - 'git push --force-with-lease=...' → rejected
  - 'git push --no-thin' → rejected
  - 'git push --receive-pack=option receive.shallowUpdate false'
    → not supported by gitea protocol layer

The only fix is operator-side: disable receive.shallowUpdate on
the gitea repo. Per AGENTS.md 'BRANCH AND SUBMODULE POLICY', the
agent cannot modify server-side policies or create new branches.

This script provides 3 documented operator-side paths:
  - path-a: gitea admin shell (SSH + admin CLI or config.toml edit)
  - path-b: gitea web UI (no SSH needed; only web admin)
  - path-c: server-side hook (advanced; only when A and B infeasible)

After operator unblocks, the standard push:
  ./local/scripts/push-fork-branches.sh --execute

The script also displays current fork state (local/remote SHA,
ahead/behind, last 5 local commits) for context.

Files in scope: local/scripts/unblock-base-push.sh
2026-07-12 10:13:12 +03:00
vasilito c6cb9b96c8 phase 5.2: fix test-recipe broken references to legacy-absorbed patches
Phase 5.2 patch-loss audit (the user's recurring concern about
'very important patches due to build system deficiencies') found
that Round 2/3 legacy-absorbed cleanup of relibc-absorbed/ broke
the test-recipe references in:

  recipes/tests/relibc-tests/recipe.toml
  recipes/tests/relibc-tests-bins/recipe.toml

These recipes apply 9 patches via 'patch -N -p1 < $COOKBOOK_ROOT/
local/patches/relibc/P3-*.patch'. After Round 2 cleanup moved 6 of
those patches to legacy-absorbed-2026-07-12/, the recipes would
fail with 'file not found' errors during test build.

This commit:
1. Moves 5 patches back to local/patches/relibc/ where the test
   recipes expect them:
     P3-eventfd-mod, P3-semaphore-fixes, P3-socket-cred,
     P3-timerfd-relative, P3-waitid

2. Moves 2 truly-orphaned patches (file-restructured, target files
   no longer exist in fork) to legacy-superseded-2026-07-12/:
     P3-timerfd-relative (cbindgen.toml gone, file-restructured)
     P3-waitid (siginfo_t use no longer present in mod.rs)

3. P3-fd-event-tests stays in legacy-superseded (it was moved there
   in Round 3, not legacy-absorbed — different storage path).

Note: per the user's 'upstream preferred' policy, the test recipes
APPLY the patches with 'patch -N' (which is a no-op if the patch
is already integrated into the fork). Most of these patches'
content is already in the relibc 0.6.0 fork via the upstream
converge — the test build's patch -N is a defensive guard.

Cumulative state:
  Total patches: 122
  Active orphans: 0
  legacy-superseded-2026-07-12: 98
  legacy-absorbed-2026-07-12: 62
2026-07-12 10:04:23 +03:00
vasilito 7132f9e5f1 phase 5.1: extend verify-collision-detection to [[package]].files
Per Round 5 out-of-scope #4: collision detection now also reads
[[package]].files in addition to [[package]].installs.

The codebase actually uses [[package]].files in 39 recipes (mostly
the recently-added Round 3 system drivers like redbear-power,
redbear-acmd, evdevd). The format is an inline table mapping
install path -> source basename:

  [[package.files]]
  "/usr/bin/redbear-power" = "redbear-power"

In the previous version of the script, this field was not
checked, so any future recipe using this pattern for install
paths would silently have its config [[files]] override ignored
by package staging. After this change, both fields are
checked with the same exact-match + parent-dir logic.

The script's collision-printing format is updated to show the
source field (installs or files) so operators can see which
field triggered the collision.

Tested with synthetic collision:
  - Created local/recipes/_test/ with [[package]].files=['/lib/test/special.toml']
  - Created config/redbear-test-files.toml with [[files]] path=/lib/test/special.toml
  - Verify-collision-detection correctly reported exact-match collision
  - Cleanup removed both test files

Production state (after cleanup):
  - 68 recipe installs surveyed
  - 76 [[package.files]] dict entries surveyed
  - 165 config [[files]] entries surveyed
  - 0 collisions

Per AGENTS.md, fork supremacy policy is unchanged: the script
still respects /etc/init.d/* and /etc/environment.d/* as known-safe
overrides.
2026-07-12 09:50:59 +03:00
vasilito a07cfabce8 phase 4.6: update PATCH-PRESERVATION-AUDIT with Round 5 outcomes
Round 5 (Phase 4.x) additions to the cumulative audit:

- Phase 4.0 fork-branch push: 6 forks advanced to origin
  (installer, kernel, syscall via --strict=0-behind; libredox,
   userutils, relibc via force-push with --force-with-lease).
- Phase 4.3 patch-loss catch: P0-canary + P5-context-mod-sched
  archived as operator-superseded (operator's recent cleanup
  commits 66a5243f and dc51e67d made them obsolete).
- Phase 4.1 fork-branch deadlock: base fork could not be pushed
  due to gitea receive.shallowUpdate=true. Documented in
  local/docs/fork-push-status/2026-07-12-Round-5-phase-4.1.md.

Updated cumulative reduction table:
  Round 0: 251 patches, 144 orphans (57%)
  After Phase 1.0A: 96 orphans (38%)
  After Phase 2.1: 27 orphans (15%)
  After Phase 3.0-3.2: 0 orphans (0%) ← Round 3 closed
  After Phase 4.3: 0 orphans (0%) ← Round 5 still 0

New 'Out-of-scope' entries:
  - base fork push deadlock (operator-side gitea config fix)
  - Collision detection extension (currently only checks
    [[package]].installs, not [[package]].files; doesn't trace
    dynamic file generation)
  - Pre-receive server-side hook (defense in depth; gitea admin
    permission required)

Also add brief mention of Phase 4.2 (collision detection) and
Phase 4.5 (pre-push hook) governance additions.
2026-07-12 09:40:38 +03:00