From d98a850a9a4abdd27a1d52118fd6459adc97e0fd Mon Sep 17 00:00:00 2001 From: nichinichisou Date: Mon, 5 Oct 2026 00:18:44 +0800 Subject: [PATCH] fix(music-data): name the mismatch when an engine package is rejected A replay or recommendation engine package whose build.json has another format now says so, with the format it has and the one expected, instead of reporting a commit difference. A commit difference names both commits. A missing deck model identity is reported before the package files are read. Co-Authored-By: Claude Opus 5.5 --- src/nnnotes/replaydata.py | 11 +++++++---- tests/test_replaydata.py | 7 ++++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/nnnotes/replaydata.py b/src/nnnotes/replaydata.py index 9615d1d..1f9d864 100644 --- a/src/nnnotes/replaydata.py +++ b/src/nnnotes/replaydata.py @@ -29,8 +29,13 @@ def _package(files: dict[str, bytes], source: Path, model: dict | None, name: st built = json.loads((source / "build.json").read_text(encoding="utf8")) except (OSError, ValueError): raise deckdata.DeckDataError(f"{name}: missing or malformed build.json") from None - if built.get("format") != build_format or not model or built.get("commit") != model.get("commit"): - raise deckdata.DeckDataError(f"{name}: build.json commit differs from the pinned deck model") + if not model or not model.get("commit"): + raise deckdata.DeckDataError(f"{name}: the pinned deck model identity is required") + if built.get("format") != build_format: + raise deckdata.DeckDataError(f"{name}: build.json format is {built.get('format')!r}, not {build_format}") + if built.get("commit") != model["commit"]: + raise deckdata.DeckDataError(f"{name}: build.json commit {built.get('commit')!r} differs from the pinned " + f"deck model {model['commit']}") js_path, wasm_path, build_path = f"{prefix}/{js}", f"{prefix}/{wasm}", f"{prefix}/build.json" for file, path in ((js, js_path), (wasm, wasm_path)): if not (source / file).is_file(): @@ -38,8 +43,6 @@ def _package(files: dict[str, bytes], source: Path, model: dict | None, name: st files[path] = (source / file).read_bytes() if not files[wasm_path].startswith(b"\x00asm\x01\x00\x00\x00"): raise deckdata.DeckDataError(f"{name}: not a WASM v1 module") - if not model.get("commit"): - raise deckdata.DeckDataError(f"{name}: the pinned deck model identity is required") if built.get("jsSha256") != hashlib.sha256(files[js_path]).hexdigest() or \ built.get("wasmSha256") != hashlib.sha256(files[wasm_path]).hexdigest(): raise deckdata.DeckDataError(f"{name}: JS/WASM SHA differs from build.json") diff --git a/tests/test_replaydata.py b/tests/test_replaydata.py index f1f2276..b80b4ac 100644 --- a/tests/test_replaydata.py +++ b/tests/test_replaydata.py @@ -47,7 +47,8 @@ def test_engine_manifest_rejects_stale_pin_and_changed_wasm(tmp_path): (engine / "build.json").write_text(json.dumps(built)) stale = tmp_path / "stale" stale.mkdir() - with pytest.raises(musicdata.MusicDataError, match="commit differs"): + stale_pin = f"build.json commit '0{{40}}' differs from the pinned deck model {FakeDeck.COMMIT}" + with pytest.raises(musicdata.MusicDataError, match=stale_pin): export(stale, deck=FakeDeck(), replay_dir=stale / "replay", replay_engine=engine) assert not (stale / "music.json").exists() built["commit"] = FakeDeck.COMMIT @@ -128,8 +129,8 @@ def test_recommend_engine_shares_the_model_of_the_deck_data(tmp_path): @pytest.mark.parametrize("change,message", [ - ("commit", "recommend engine: build.json commit differs"), - ("format", "recommend engine: build.json commit differs"), + ("commit", "recommend engine: build.json commit '0{40}' differs from the pinned deck model"), + ("format", "recommend engine: build.json format is 'ournotes.replay-engine/1', not ournotes.recommend-engine/1"), ("wasm", "recommend engine: JS/WASM SHA differs"), ("missing", "recommend engine: missing ournotes_recommend.js"), ("no-replay-dir", "--recommend-engine needs --replay-dir"),