Skip to content

Commit 834b027

Browse files
committed
feat: add reproducible env state engine, lock sync, and self-healing rebuilds
This commit introduces Omnipkg’s first full reproducibility and environment recovery layer. Design note: The canonical lock state is the true environment identity. The local `.omnipkg/omnipkg.lock` is only a local attachment / envelope. This commit establishes the first working implementation of that model. Core additions: - Added `8pkg export` to snapshot a full multi-interpreter environment into a canonical TOML lock state. - Added `8pkg sync` to restore, rebuild, and reconcile environments from those lock states. - Added machine-global canonical lock registry under `~/.config/omnipkg/locks/states` for deduplicated known-good env identities. - Added privacy-scrubbed / path-agnostic lock metadata so exported states can be reused across machines without leaking local filesystem details. Healing / recovery: - Added rebuild-oriented sync flow for recovering from broken or nuked envs. - Added metadata repair / “Phase 0 Heal” behavior to recover missing or corrupt package metadata before hard failure. - Added stronger snapshot + last-known-good behavior around package operations. - Improved interpreter adoption / recovery flow, including managed Python bootstrap repair paths. Execution / runtime hardening: - Replaced fragile mtime dispatcher invalidation with content hashing. - Improved executable / dispatcher propagation across adopted interpreters. - Hardened re-exec flow to use `-m omnipkg.cli` and avoid broken editable shim edge cases. - Improved binary-only package handling for validation / verification logic. Daemon / worker stability: - Hardened daemon shutdown and orphan cleanup behavior. - Improved worker IPC reliability by bypassing redirected stdout boundaries. - Reduced failure modes around long-running background worker management. Python 3.7 / legacy editable install fixes: - Fixed sync false-positive behavior caused by legacy egg-link installs from older pip bootstrap flows. - Detects legacy `omnipkg.egg-link` installs as requiring sync. - Cleans stale egg-link / easy-install.pth artifacts after successful sync so Python 3.7 contexts do not resync forever. This is the foundational commit for: - reproducible rebuilds - lock-driven recovery - canonical env identity - future orphan-state recovery / tombstoning - future compatibility scoring / proven-build telemetry - future container / template generation from known-good states New files: • src/omnipkg/integration/reproducible.py (2385 lines) Modified: • src/omnipkg/cli.py (+113/-13 lines) • src/omnipkg/common_utils.py (+33/-8 lines) • src/omnipkg/core.py (+504/-196 lines) • src/omnipkg/dispatcher.c (+220/-4 lines) • src/omnipkg/dispatcher.py (+255/-89 lines) • src/omnipkg/installation/verification_strategy.py (+40/-23 lines) • src/omnipkg/integration/reproducible.py (+2385/-0 lines) • src/omnipkg/isolation/worker_daemon.py (+189/-37 lines) • src/omnipkg/package_meta_builder.py (+22/-9 lines) • pyproject.toml (+1/-1 lines) • setup.py (+12/-3 lines) [gitship-generated]
1 parent 7c3de5e commit 834b027

11 files changed

Lines changed: 3748 additions & 357 deletions

File tree

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ backend-path = ["."]
66

77
[project]
88
name = "omnipkg"
9-
version = "2.5.0"
9+
version = "2.5.1"
1010
authors = [
1111
{ name = "1minds3t", email = "1minds3t@proton.me" },
1212
]

setup.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,12 @@ def _install_dispatcher_binary(install_dir=None):
4646
)
4747
if result.returncode != 0:
4848
print(f" [dispatcher] Compilation failed, using Python dispatcher:")
49-
print(f" {result.stderr.strip()}")
49+
# Pass -v to gcc to see the full linker invocation
50+
result = subprocess.run(
51+
["gcc", "-v", "-O2", "-o", str(binary_out), str(c_source)],
52+
capture_output=False, # This will stream the output directly to the GHA console
53+
text=True
54+
)
5055
return
5156

5257
# Overwrite the pip-generated wrapper scripts
@@ -106,16 +111,20 @@ def run(self):
106111
# macOS: -march=native fails on Universal (dual-arch) builds
107112
# Windows: Uses MSVC flags (handled separately)
108113

114+
import platform
115+
109116
_c_args = ["-O3"]
110117

111-
# Only enable native optimization on Linux
118+
# ⬇️ THIS IS THE FIX ⬇️
119+
# Only enable native optimization on Linux.
120+
# macOS universal builds will fail with -march=native.
112121
if platform.system() == "Linux":
113122
_c_args.append("-march=native")
114123

115124
atomic_extension = Extension(
116125
name="omnipkg.isolation.omnipkg_atomic",
117126
sources=["src/omnipkg/isolation/atomic_ops.c"],
118-
extra_compile_args=_c_args,
127+
extra_compile_args=_c_args, # <--- Use our new conditional args
119128
optional=True,
120129
)
121130

src/omnipkg/cli.py

Lines changed: 113 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -580,19 +580,20 @@ def run_config_wizard(cm: ConfigManager, parser_prog: str) -> int:
580580
# ─────────────────────────────────────────────────────────────────────────────
581581

582582
def create_8pkg_parser():
583-
"""Creates parser for the 8pkg alias — cached after first build."""
584583
import omnipkg.cli as _cli_mod
585-
if _cli_mod._CACHED_8PKG_PARSER is not None:
586-
return _cli_mod._CACHED_8PKG_PARSER
584+
_lang_key = _.current_lang
585+
if _lang_key in (_cli_mod._CACHED_8PKG_PARSER or {}):
586+
return _cli_mod._CACHED_8PKG_PARSER[_lang_key]
587+
if _cli_mod._CACHED_8PKG_PARSER is None:
588+
_cli_mod._CACHED_8PKG_PARSER = {}
587589
parser = create_parser()
588590
parser.prog = "8pkg"
589591
parser.description = _(
590592
"🚀 The intelligent Python package manager that eliminates dependency hell (8pkg = ∞pkg)"
591593
)
592594
epilog_parts = parser.epilog.split("\n")
593-
updated_epilog = "\n".join([line.replace("omnipkg", "8pkg") for line in epilog_parts])
594-
parser.epilog = updated_epilog
595-
_cli_mod._CACHED_8PKG_PARSER = parser
595+
parser.epilog = "\n".join(line.replace("omnipkg", "8pkg") for line in epilog_parts)
596+
_cli_mod._CACHED_8PKG_PARSER[_lang_key] = parser
596597
return parser
597598

598599

@@ -1018,6 +1019,11 @@ def create_parser():
10181019
action="store_true",
10191020
help=_("Diagnose only — show the healing plan without making any changes"),
10201021
)
1022+
doctor_parser.add_argument(
1023+
"--rebuild",
1024+
action="store_true",
1025+
help=_("Nuclear option: dump active packages to requirements, wipe broken bubbles, reinstall everything clean"),
1026+
)
10211027
doctor_parser.add_argument(
10221028
"--yes", "-y",
10231029
dest="force",
@@ -1203,6 +1209,83 @@ def create_parser():
12031209
"--yes", "-y", dest="force", action="store_true", help=_("Skip confirmation")
12041210
)
12051211

1212+
# --- export ---
1213+
export_parser = subparsers.add_parser(
1214+
"export",
1215+
help=_("Snapshot current environment to a reproducible lock file"),
1216+
formatter_class=argparse.RawTextHelpFormatter,
1217+
epilog=_(
1218+
"Writes to <venv_root>/.omnipkg/omnipkg.lock by default.\n"
1219+
"Use --output to override, e.g. for sharing or CI artifacts.\n\n"
1220+
"Examples:\n"
1221+
" 8pkg export # write to default location\n"
1222+
" 8pkg export -o /tmp/my.lock # explicit path\n"
1223+
" 8pkg export --python 3.11 # only capture python 3.11\n"
1224+
),
1225+
)
1226+
export_parser.add_argument(
1227+
"--output", "-o",
1228+
metavar="FILE",
1229+
help=_("Override default lock file location"),
1230+
)
1231+
export_parser.add_argument(
1232+
"--python", "-p",
1233+
metavar="VER",
1234+
action="append",
1235+
dest="pythons",
1236+
help=_("Only export this python version (repeatable: -p 3.11 -p 3.10)"),
1237+
)
1238+
export_parser.add_argument(
1239+
"--venv-root",
1240+
metavar="PATH",
1241+
help=_("Override venv root detection"),
1242+
)
1243+
1244+
# --- sync ---
1245+
sync_parser = subparsers.add_parser(
1246+
"sync",
1247+
help=_("Rebuild environment from lock file (DESTRUCTIVE)"),
1248+
formatter_class=argparse.RawTextHelpFormatter,
1249+
epilog=_(
1250+
"Reads from <venv_root>/.omnipkg/omnipkg.lock by default.\n"
1251+
"Clears and reinstalls all packages for each python in the lock file.\n\n"
1252+
"Examples:\n"
1253+
" 8pkg sync # sync from default lock file\n"
1254+
" 8pkg sync /path/to/other.lock # explicit lock file\n"
1255+
" 8pkg sync --python 3.11 # only sync python 3.11\n"
1256+
" 8pkg sync --yes # skip confirmation (CI/Docker)\n"
1257+
),
1258+
)
1259+
sync_parser.add_argument(
1260+
"lock_file",
1261+
metavar="LOCK_FILE",
1262+
nargs="?", # optional — defaults to canonical path
1263+
default=None,
1264+
help=_("Lock file to sync from (default: <venv_root>/.omnipkg/omnipkg.lock)"),
1265+
)
1266+
sync_parser.add_argument(
1267+
"--yes", "-y",
1268+
action="store_true",
1269+
help=_("Skip confirmation prompt (for CI / Docker)"),
1270+
)
1271+
sync_parser.add_argument(
1272+
"--python", "-p",
1273+
metavar="VER",
1274+
action="append",
1275+
dest="pythons",
1276+
help=_("Only sync this python version (repeatable)"),
1277+
)
1278+
sync_parser.add_argument(
1279+
"--dry-run", "-n",
1280+
action="store_true",
1281+
help=_("Print what would happen without making changes"),
1282+
)
1283+
sync_parser.add_argument(
1284+
"--venv-root",
1285+
metavar="PATH",
1286+
help=_("Override venv root detection"),
1287+
)
1288+
12061289
# ── upgrade ───────────────────────────────────────────────────────────────
12071290
upgrade_parser = subparsers.add_parser(
12081291
"upgrade",
@@ -1234,7 +1317,6 @@ def create_parser():
12341317
_cli_mod._CACHED_PARSER[_.current_lang] = parser
12351318
return parser
12361319

1237-
12381320
# ─────────────────────────────────────────────────────────────────────────────
12391321
# MAIN
12401322
# ─────────────────────────────────────────────────────────────────────────────
@@ -1319,21 +1401,22 @@ def main():
13191401
os.environ["OMNIPKG_LANG"] = user_lang
13201402

13211403
if command is None or "-h" in remaining_args or "--help" in remaining_args:
1322-
# Invalidate cached parser so it rebuilds with the correct language
1323-
_cli_mod._CACHED_PARSER = {}
1324-
_cli_mod._CACHED_8PKG_PARSER = None
13251404
prog_name_lower = Path(sys.argv[0]).name.lower()
13261405
parser = create_8pkg_parser() if "8pkg" in prog_name_lower else create_parser()
13271406
parser.print_help()
13281407
return 0
13291408

13301409
# ── Choose minimal vs full init ────────────────────────────────────────────
13311410
use_minimal = False
1332-
if command in {"config", "python"}:
1411+
if command in {"config", "python", "doctor"}:
13331412
use_minimal = True
13341413
elif command == "swap":
13351414
if len(remaining_args) > 1 and remaining_args[1].lower() == "python":
13361415
use_minimal = True
1416+
elif command == "daemon":
1417+
# daemon restart/stop must NEVER go through the daemon — always execv direct
1418+
if len(remaining_args) > 1 and remaining_args[1].lower() in ("restart", "stop", "kill"):
1419+
use_minimal = True
13371420

13381421
# Use pre-built OmnipkgCore from daemon preload if available (full mode only)
13391422
import omnipkg.cli as _cli_mod
@@ -1477,8 +1560,25 @@ def main():
14771560
return 1
14781561

14791562
elif args.command == "doctor":
1480-
return pkg_instance.doctor(dry_run=args.dry_run, force=args.force)
1481-
1563+
return pkg_instance.doctor(dry_run=args.dry_run, force=args.force, rebuild=args.rebuild)
1564+
elif args.command == "export":
1565+
from omnipkg.integration.reproducible import export_lock
1566+
written_path = export_lock(
1567+
output_path=Path(args.output) if args.output else None,
1568+
pythons=args.pythons,
1569+
venv_root=Path(args.venv_root) if args.venv_root else None,
1570+
)
1571+
safe_print(_("📦 Lock file: {}").format(written_path))
1572+
1573+
elif args.command == "sync":
1574+
from omnipkg.integration.reproducible import sync_lock
1575+
sync_lock(
1576+
lock_path=Path(args.lock_file) if args.lock_file else None,
1577+
yes=args.yes,
1578+
pythons=args.pythons,
1579+
dry_run=args.dry_run,
1580+
venv_root=Path(args.venv_root) if args.venv_root else None,
1581+
)
14821582
elif args.command == "heal":
14831583
with temporary_install_strategy(pkg_instance, "latest-active"):
14841584
return pkg_instance.heal(dry_run=args.dry_run, force=args.force)

src/omnipkg/common_utils.py

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -736,14 +736,9 @@ def is_interactive_session():
736736

737737

738738
def _worker_emit(obj: dict) -> None:
739-
"""Write one JSON line to worker stdout (the daemon channel).
740-
741-
Uses sys.stdout directly — the worker is spawned with text=True so this
742-
is the correct transport. The trailing newline is what _reader_thread
743-
uses as a message boundary on the daemon side.
744-
"""
745-
sys.stdout.write(json.dumps(obj, ensure_ascii=True) + "\n")
746-
sys.stdout.flush()
739+
"""Write one JSON line to the real stdout pipe, bypassing StreamRedirector."""
740+
msg = json.dumps(obj, ensure_ascii=True) + "\n"
741+
os.write(1, msg.encode("utf-8"))
747742

748743

749744
def _worker_read_reply() -> dict:
@@ -854,6 +849,36 @@ def simulate_user_choice(choice, message):
854849
safe_print(_("💭 {}").format(message))
855850
return choice.lower()
856851

852+
def _safe_resolve(path: Path) -> Path:
853+
"""
854+
Resolve a path safely for omnipkg identity and path comparisons.
855+
856+
Uses resolve() when possible, falls back to absolute() if resolution fails.
857+
Avoids inconsistent crashes on broken links / partial envs.
858+
"""
859+
try:
860+
return path.resolve()
861+
except Exception:
862+
return path.absolute()
863+
864+
def _canonical_path_str(path: Path) -> str:
865+
"""
866+
Produce a stable canonical string for identity-sensitive path hashing
867+
and comparisons across platforms.
868+
869+
- resolves when possible
870+
- normalizes separators
871+
- lowercases on Windows for drive-letter / casing stability
872+
- strips trailing slash
873+
"""
874+
p = _safe_resolve(path)
875+
s = str(p).replace("\\", "/").rstrip("/")
876+
877+
if os.name == "nt":
878+
s = s.lower()
879+
880+
return s
881+
857882
def _is_relative_to_win(path: Path, base: Path) -> bool:
858883
"""Case-insensitive relative_to for Windows path safety."""
859884
try:

0 commit comments

Comments
 (0)