feat: settle contested slots in the pack and the report

This commit is contained in:
Abdessamad Derraz committed 2026-09-05 09:08:43 +02:00
1 parent 0a5c287325
commit adcd177e12
5 files changed
+94 -5

No files matched your search

+22 -3
View File
@@ -60,6 +60,7 @@ from common import (
import packresolve
import region as region_mod
import slot as slot_mod
import slots
from deterministic_zip import _FIXED_DATE_TIME, rebuild_zip_deterministic
from nativemode import (
digest_algorithm,
@@ -602,10 +603,24 @@ def generate_pack(
from common import resolve_platform_cores
validation_index = {}
slot_overrides: dict[str, str] = {}
if emu_profiles:
validation_index = _build_validation_index(
{name: emu_profiles[name] for name in resolve_platform_cores(config, emu_profiles)}
)
platform_profiles = {
name: emu_profiles[name]
for name in resolve_platform_cores(config, emu_profiles)
}
validation_index = _build_validation_index(platform_profiles)
# Where a source-verified profile contradicts the scraped baseline on
# one destination, the pack answers to the platform it is built for.
# In existence mode the frontend never reads the bytes, so serving the
# emulator's file satisfies both sides and nothing is traded away.
mode = config.get("verification_mode", "existence")
for conflict in slots.find_conflicts(
config, platform_profiles, db, base_dest
):
decision = slots.arbitrate(conflict, mode)
if decision.serves_both and decision.winner.local_path:
slot_overrides[conflict.destination] = decision.winner.local_path
# Filter systems by target if specified
plat_cores = (
@@ -729,6 +744,10 @@ def generate_pack(
offline=offline,
)
override = slot_overrides.get(full_dest)
if override and status not in ("external", "release_asset"):
local_path, status = override, "slot_arbitrated"
if status == "external":
file_ext = os.path.splitext(file_entry["name"])[1] or ""
with tempfile.NamedTemporaryFile(
+8
View File
@@ -392,6 +392,14 @@ def main():
results["verify"] = ok
all_ok = all_ok and ok
# Step 3b: Destinations both layers claim, and how each was settled. The
# ones the pack settles by itself must stay at zero cost; the rest name an
# upstream declaration no build can repair, so this reports and never gates.
run(
[sys.executable, "scripts/slots.py"],
"3b/8 slot arbitration",
)
# Step 4: Generate packs
pack_output = ""
if not args.skip_packs:
+13 -2
View File
@@ -283,6 +283,12 @@ def main() -> int:
parser.add_argument("--platforms-dir", default="platforms")
parser.add_argument("--emulators-dir", default="emulators")
parser.add_argument("--json", action="store_true", help="JSON output")
parser.add_argument(
"--strict",
action="store_true",
help="exit non-zero on any contested destination, not only on one the "
"pack should have settled by itself",
)
args = parser.parse_args()
with open(args.db, encoding="utf-8") as handle:
@@ -332,11 +338,16 @@ def main() -> int:
print(f" {format_decision(decision)}")
total = sum(len(c) for c in found.values())
print(
f"\n{total} contested destinations. {fixable} the pack can settle on "
f"\n{total} contested destinations. {fixable} the pack settles on "
f"its own, {total - fixable} rest on an upstream declaration."
)
if not args.strict and total:
print(
"Reported, not failed: the remainder needs the upstream list "
"corrected, which no build can do. Use --strict to gate on them."
)
return 1 if found else 0
return 1 if (found and args.strict) else 0
if __name__ == "__main__":
+26
View File
@@ -30,6 +30,8 @@ import os
import sys
import zipfile
import slots
sys.path.insert(0, os.path.dirname(__file__))
from common import (
build_target_cores_cache,
@@ -793,6 +795,23 @@ def verify_platform(
mode = normalize_mode(config.get("verification_mode"))
platform = config.get("platform", "unknown")
# The builder settles a destination claimed by both layers; this must read
# the same decision, or the two tools describe different packs.
slot_overrides: dict[str, str] = {}
if emu_profiles:
base_dest = config.get("base_destination", "")
arbitrated = {
name: emu_profiles[name]
for name in resolve_platform_cores(config, emu_profiles)
}
for conflict in slots.find_conflicts(config, arbitrated, db, base_dest):
decision = slots.arbitrate(conflict, mode)
if decision.serves_both and decision.winner.local_path:
key = conflict.destination
if base_dest and key.startswith(f"{base_dest}/"):
key = key[len(base_dest) + 1:]
slot_overrides[key] = decision.winner.local_path
has_zipped = any(
fe.get("zipped_file")
for sys in config.get("systems", {}).values()
@@ -876,6 +895,13 @@ def verify_platform(
zip_contents,
data_dir_registry=data_dir_registry,
)
override = slot_overrides.get(
sanitize_pack_path(
file_entry.get("destination", file_entry.get("name", ""))
)
)
if override:
local_path, resolve_status = override, "slot_arbitrated"
if not reads_file_contents(mode):
result = verify_entry_existence(
file_entry,