From 0a8ad432ee4a8d4d0d18d2b2e87b57b0156d643e Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Thu, 6 Aug 2026 08:53:27 +0800 Subject: [PATCH 1/3] =?UTF-8?q?chore:=20=E8=BA=AB=E4=BB=BD=E5=AF=B9?= =?UTF-8?q?=E9=BD=90=E4=B8=8A=E6=B8=B8=20=E2=80=94=E2=80=94=20ggml-org:lla?= =?UTF-8?q?macpp@b10069,=E7=89=88=E6=9C=AC=E5=8D=B3=20checkpoint?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit README 里那句话就是这次改动的理由: Version `0.1.0` maps to llama.cpp `b10069`. 一个需要对照表才能读懂的版本号,没有在告诉消费者他拿到的是哪一版库 —— 而这正是版本 号唯一的用途。同一条修正在整个生态展开(mcpp-index#163):imgui@0.0.6 其实是 ImGui 1.92.8,ffmpeg@0.0.3 是 FFmpeg 8.1.2,opencv@0.0.10 是 OpenCV 5.0.0。 命名空间同理。`mcpplibs` 是 mcpp 的默认命名空间(`kDefaultNamespace`),不是"上游是 谁"的答案;llama.cpp 是 ggml-org 的。 **b10069 不是 semver,mcpp 能处理 —— 已实测。** 造本地索引写入该版本键,解析、版本 键匹配、wire 寻址(`probe:tinyver@b10069`)全部正常。不成立的只有范围(`^b10069` 解 析不了),所以消费者精确 pin。范围支持见 mcpp#363。 版本方案是被写进代码和测试的,所以一起改而不是只改 manifest: * `tools/check_release.py` 的 `Version` 由 major/minor/patch 换成 (build, revision):`b10069`,同 checkpoint 的 wrapper 修复为 `b10069.1`。排序仍 然成立(build 是整数),"不得发布更旧版本"的检查原样保留。 * **新增一条更强的不变量**:`_identity_from_text` 现在校验版本命名的 checkpoint 与 lock 里 vendored 的 checkpoint 一致。以前这靠 major/minor/patch 的转换规则事后监 管,现在版本与 checkpoint 是同一个字符串,漂移在结构上不可能发生。 * release tag 即版本本身(`b10069`),也就是上游自己的 tag 形态,不再是 `v` 前缀。 * `docs/upstream-update-policy.md` 的 Version Model 整节重写,并诚实记下代价:排序 不再可比,原先由版本分量承载的 major/minor/patch 契约转由 API 快照闸门与发布说明 承担。 * 单测相应改写;`test_build_contract` 另加一条断言,把 package.version 与 manifest 生成的 `#define GGML_VERSION` 绑在一起。 9 个测试模块全过。 --- README.md | 22 +++---- docs/upstream-update-policy.md | 41 +++++++++---- docs/validation/{0.1.0.md => b10069.md} | 12 ++-- mcpp.toml | 16 ++++- tests/unit/test_build_contract.py | 10 ++- tests/unit/test_check_release.py | 67 ++++++++++---------- tests/unit/test_repository_contract.py | 3 +- tools/audit_snapshot.py | 2 +- tools/check_release.py | 82 ++++++++++++++++++------- tools/gen_exports.py | 2 +- 10 files changed, 169 insertions(+), 88 deletions(-) rename docs/validation/{0.1.0.md => b10069.md} (94%) diff --git a/README.md b/README.md index 24f695e..a86295b 100644 --- a/README.md +++ b/README.md @@ -7,29 +7,29 @@ module for mcpp. The public module is: import llamacpp; ``` -Version `0.1.0` maps to llama.cpp `b10069`. CPU is the default backend. Metal -is an additive feature for macOS ARM64. +The package version IS llama.cpp's build number: `b10069`. CPU is the default +backend. Metal is an additive feature for macOS ARM64. ## Add The Package -After `0.1.0` is published in mcpp-index: +After `b10069` is published in mcpp-index: ```bash -mcpp add mcpplibs:llamacpp@0.1.0 +mcpp add ggml-org:llamacpp@b10069 ``` The equivalent manifest entry is: ```toml -[dependencies.mcpplibs] -llamacpp = "0.1.0" +[dependencies.ggml-org] +llamacpp = "b10069" ``` For Metal on macOS ARM64: ```toml -[dependencies.mcpplibs] -llamacpp = { version = "0.1.0", features = ["backend-metal"] } +[dependencies.ggml-org] +llamacpp = { version = "b10069", features = ["backend-metal"] } ``` ## Minimal CPU Program @@ -106,18 +106,18 @@ nonzero before reporting success if either Metal buffer is absent. ## Supported Boundary -`0.1.0` includes: +`b10069` includes: - the public llama.cpp C API exposed through `import llamacpp;`; - the CPU backend on Linux x86_64, Linux ARM64, Windows x86_64, and macOS ARM64; - the Metal backend on macOS ARM64; - architecture-specific x86_64 and ARM64 CPU source selection. -`0.1.0` does not include `mtmd`, CUDA, Vulkan, RPC, or other upstream backends. +`b10069` does not include `mtmd`, CUDA, Vulkan, RPC, or other upstream backends. It also does not claim that every upstream model architecture has been tested. Deprecated upstream C APIs remain exported for API completeness; code that calls them may receive the deprecation warnings defined by upstream. See [the update policy](docs/upstream-update-policy.md) for versioning and -checkpoint selection, and [the 0.1.0 validation record](docs/validation/0.1.0.md) +checkpoint selection, and [the b10069 validation record](docs/validation/b10069.md) for exact evidence and remaining release gates. diff --git a/docs/upstream-update-policy.md b/docs/upstream-update-policy.md index 236547c..8b526fa 100644 --- a/docs/upstream-update-policy.md +++ b/docs/upstream-update-policy.md @@ -8,10 +8,13 @@ checkpoints proven by the complete platform and API gate. The wrapper and upstream project have separate identities: -- `llama.cpp-m` has its own semantic version. +- `llama.cpp-m` carries **upstream's version verbatim**, not a version of its + own. See "Version Model" below for why that replaced a separate semantic + version. - Every wrapper release maps to exactly one upstream tag and commit. -- The package coordinate is `mcpplibs:llamacpp`; consumers use - `import llamacpp;`. +- The package coordinate is `ggml-org:llamacpp`; consumers use + `import llamacpp;`. The namespace names whose library this is — llama.cpp is + ggml-org's — rather than who packaged it (see mcpp-index#163). - mcpp-index points only to immutable `llama.cpp-m` releases, never a moving upstream branch. @@ -25,16 +28,32 @@ verified source under `third_party/llama.cpp/` and does not use a Git submodule. ## Version Model -The initial wrapper release is `0.1.0`, based on upstream `b10069`. +**The wrapper version IS the upstream build number.** The first release is +`b10069`, because that is the llama.cpp it contains. -| Change | Required wrapper version change | -|---|---| -| Wrapper fix on the same upstream checkpoint | Patch | -| New upstream checkpoint or additive API/model/backend support | Minor | -| Module/feature rename or intentional public API removal | Major | +This replaced a separate semantic version (`0.1.0`). The reason is visible in +what the old README had to say next to it: *"Version `0.1.0` maps to llama.cpp +`b10069`."* A version that needs a lookup table to read is not telling the +consumer which library they are getting — which is the one thing a version is +for. The same correction is being applied across the ecosystem +(mcpp-index#163): `imgui@0.0.6` was ImGui 1.92.8, `ffmpeg@0.0.3` was FFmpeg +8.1.2, `opencv@0.0.10` was OpenCV 5.0.0. -This policy applies before `1.0.0`: an upstream update cannot silently break a -published module contract. +| Change | Wrapper version | +|---|---| +| New upstream checkpoint | that checkpoint's build number (`b10420`) | +| Wrapper fix on the same upstream checkpoint | a dotted revision (`b10069.1`) | +| Module/feature rename or intentional public API removal | a new checkpoint release, called out in the release notes | + +**What this costs.** `bNNNNN` is not semver, so mcpp cannot express a RANGE over +it — `^b10069` does not parse, and consumers pin exactly. Verified that exact +pinning does work end to end: resolution, version-key matching and wire +addressing all handle a literal non-semver key (mcpp#363 tracks range support). + +Since ordering is no longer comparable, the "major/minor/patch" contract above +cannot be carried by the version string. An upstream update still may not +silently break a published module contract — that guarantee now rests on the +API snapshot gate and the release notes rather than on a version component. Every release records: diff --git a/docs/validation/0.1.0.md b/docs/validation/b10069.md similarity index 94% rename from docs/validation/0.1.0.md rename to docs/validation/b10069.md index dcb9b10..8a25845 100644 --- a/docs/validation/0.1.0.md +++ b/docs/validation/b10069.md @@ -1,15 +1,15 @@ -# llama.cpp-m 0.1.0 Validation +# llama.cpp-m b10069 Validation This record separates completed local evidence from GitHub Actions evidence -that requires an authorized push. Version `0.1.0` is not published by this +that requires an authorized push. Version `b10069` is not published by this branch. ## Release Identity | Field | Value | |---|---| -| Wrapper | `llama.cpp-m 0.1.0` | -| Package | `mcpplibs:llamacpp@0.1.0` | +| Wrapper | `llama.cpp-m b10069` | +| Package | `ggml-org:llamacpp@b10069` | | Module | `import llamacpp;` | | Upstream tag | `b10069` | | Upstream commit | `178a6c44937154dc4c4eff0d166f4a044c4fceba` | @@ -22,7 +22,7 @@ The final local release contract printed: Snapshot matches. All exports match. Snapshot matches. -llama.cpp-m 0.1.0 -> llama.cpp b10069 (178a6c44937154dc4c4eff0d166f4a044c4fceba) +llama.cpp-m b10069 -> llama.cpp b10069 (178a6c44937154dc4c4eff0d166f4a044c4fceba) ``` ## GitHub Actions Status @@ -143,7 +143,7 @@ The `actionlint` image was pulled as GitHub Actions remains authoritative for actual workflow execution and the required platform matrix. -## Unsupported In 0.1.0 +## Unsupported In b10069 - `mtmd` multimodal API; - CUDA, Vulkan, RPC, and other upstream backends; diff --git a/mcpp.toml b/mcpp.toml index 0e72fa5..14079b2 100644 --- a/mcpp.toml +++ b/mcpp.toml @@ -1,6 +1,20 @@ +# The namespace names whose library this is, not who packaged it; the version +# says which upstream you are getting. `mcpplibs` is mcpp's DEFAULT namespace +# (kDefaultNamespace), not an answer to "whose library" — llama.cpp is +# ggml-org's, and this repository only adds the C++23 module layer. +# +# The version is upstream's build number VERBATIM. `0.1.0` needed a lookup +# table to read, and the README carried it: "Version 0.1.0 maps to llama.cpp +# b10069". A version that needs a decoder ring is not a version. +# +# `b10069` is not semver, and mcpp handles it — verified: resolution, version-key +# matching and wire addressing all work on a literal non-semver key. What it +# cannot do is RANGES over it (`^b10069` is not expressible), so consumers pin +# exactly. See mcpp#363; rule and migration table in mcpp-index#163. [package] +namespace = "ggml-org" name = "llamacpp" -version = "0.1.0" +version = "b10069" description = "C++23 module package for llama.cpp b10069" license = "MIT" standard = "c++23" diff --git a/tests/unit/test_build_contract.py b/tests/unit/test_build_contract.py index 23e97a8..6fc61d0 100644 --- a/tests/unit/test_build_contract.py +++ b/tests/unit/test_build_contract.py @@ -74,7 +74,15 @@ def target_sources(self, predicate: str) -> list[str]: def test_identity_and_public_module_are_cxx23(self): package = self.manifest["package"] self.assertEqual(package["name"], "llamacpp") - self.assertEqual(package["version"], "0.1.0") + # The namespace names whose library this is (mcpp-index#163); the version + # IS the upstream checkpoint, so it must agree with the build info the + # manifest generates for ggml. + self.assertEqual(package["namespace"], "ggml-org") + self.assertEqual(package["version"], "b10069") + self.assertIn( + f'#define GGML_VERSION "{package["version"]}"', + self.manifest["generated_files"]["generated/ggml_build_info.h"], + ) self.assertEqual(package["standard"], "c++23") self.assertIn("src/llamacpp.cppm", self.base_sources()) self.assertEqual(self.manifest["targets"], {"llama": {"kind": "lib"}}) diff --git a/tests/unit/test_check_release.py b/tests/unit/test_check_release.py index 191ea6e..66e6d27 100644 --- a/tests/unit/test_check_release.py +++ b/tests/unit/test_check_release.py @@ -10,7 +10,7 @@ def write_release_tree(root: Path) -> None: (root / "mcpp.toml").write_text( - '[package]\nname = "llamacpp"\nversion = "0.1.0"\n', + '[package]\nname = "llamacpp"\nversion = "b10069"\n', encoding="utf-8", ) (root / "upstream.lock").write_text( @@ -39,9 +39,9 @@ def tearDown(self): self.tempdir.cleanup() def test_tag_matches_package_version_and_lock_mapping(self): - identity = check_release.load_identity(self.root, "v0.1.0") + identity = check_release.load_identity(self.root, "b10069") - self.assertEqual(str(identity.version), "0.1.0") + self.assertEqual(str(identity.version), "b10069") self.assertEqual(identity.upstream_tag, "b10069") self.assertEqual( identity.upstream_commit, @@ -50,7 +50,7 @@ def test_tag_matches_package_version_and_lock_mapping(self): def test_rejects_tag_version_mismatch(self): with self.assertRaisesRegex(ValueError, "tag.*version"): - check_release.load_identity(self.root, "v0.1.1") + check_release.load_identity(self.root, "b10069.1") def test_rejects_noncanonical_archive_mapping(self): lock = self.root / "upstream.lock" @@ -62,7 +62,7 @@ def test_rejects_noncanonical_archive_mapping(self): ) with self.assertRaisesRegex(ValueError, "archive URL"): - check_release.load_identity(self.root, "v0.1.0") + check_release.load_identity(self.root, "b10069") def test_rejects_consistent_mapping_to_upstream_fork(self): lock = self.root / "upstream.lock" @@ -75,10 +75,10 @@ def test_rejects_consistent_mapping_to_upstream_fork(self): ) with self.assertRaisesRegex(ValueError, "official upstream repository"): - check_release.load_identity(self.root, "v0.1.0") + check_release.load_identity(self.root, "b10069") def test_changed_existing_tag_mapping_fails(self): - current = check_release.load_identity(self.root, "v0.1.0") + current = check_release.load_identity(self.root, "b10069") existing = current._replace(upstream_commit="f" * 40) with self.assertRaisesRegex(ValueError, "immutable"): @@ -93,37 +93,40 @@ def git(_root, *arguments): if arguments[0] == "rev-parse": return completed(arguments, 0, "d" * 40) if arguments[-1].endswith(":mcpp.toml"): - return completed(arguments, 0, '[package]\nversion = "0.1.0"\n') + return completed(arguments, 0, '[package]\nversion = "b10069"\n') return completed(arguments, 1) with mock.patch.object(check_release, "_git", side_effect=git): with self.assertRaisesRegex(ValueError, "existing release tag"): - check_release._tag_identity(self.root, "v0.1.0") + check_release._tag_identity(self.root, "b10069") - def test_same_checkpoint_wrapper_fix_requires_patch_bump(self): - previous = check_release.ReleaseIdentity.for_test("0.1.0", "b10069") - patch = check_release.ReleaseIdentity.for_test("0.1.1", "b10069") - minor = check_release.ReleaseIdentity.for_test("0.2.0", "b10069") + def test_same_checkpoint_wrapper_fix_requires_a_revision_bump(self): + # The build number names the checkpoint, so a same-checkpoint release can + # only move the revision. Moving the build number instead would claim a + # checkpoint that is not the one vendored. + previous = check_release.ReleaseIdentity.for_test("b10069", "b10069") + revision = check_release.ReleaseIdentity.for_test("b10069.1", "b10069") + wrong_build = check_release.ReleaseIdentity.for_test("b10123", "b10069") - check_release.validate_version_transition(previous, patch) - with self.assertRaisesRegex(ValueError, "patch"): - check_release.validate_version_transition(previous, minor) + check_release.validate_version_transition(previous, revision) + with self.assertRaisesRegex(ValueError, "build number"): + check_release.validate_version_transition(previous, wrong_build) - def test_changed_checkpoint_requires_at_least_minor_bump(self): - previous = check_release.ReleaseIdentity.for_test("0.1.0", "b10069") - patch = check_release.ReleaseIdentity.for_test("0.1.1", "b10123") - minor = check_release.ReleaseIdentity.for_test("0.2.0", "b10123") + def test_changed_checkpoint_takes_that_checkpoints_build_number(self): + previous = check_release.ReleaseIdentity.for_test("b10069", "b10069") + forward = check_release.ReleaseIdentity.for_test("b10123", "b10123") + backward = check_release.ReleaseIdentity.for_test("b10069.1", "b10123") - with self.assertRaisesRegex(ValueError, "minor"): - check_release.validate_version_transition(previous, patch) - check_release.validate_version_transition(previous, minor) + check_release.validate_version_transition(previous, forward) + with self.assertRaisesRegex(ValueError, "higher build number"): + check_release.validate_version_transition(previous, backward) def test_rejects_candidate_older_than_an_existing_release(self): - current = check_release.ReleaseIdentity.for_test("0.1.1", "b10069") - higher = check_release.ReleaseIdentity.for_test("0.2.0", "b10123") - lower = check_release.ReleaseIdentity.for_test("0.1.0", "b10069") + current = check_release.ReleaseIdentity.for_test("b10069.1", "b10069") + higher = check_release.ReleaseIdentity.for_test("b10123", "b10123") + lower = check_release.ReleaseIdentity.for_test("b10069", "b10069") tags = subprocess.CompletedProcess( - [], 0, stdout="v0.2.0\nv0.1.0\n", stderr="" + [], 0, stdout="b10123\nb10069\n", stderr="" ) with mock.patch.object(check_release, "_git", return_value=tags): @@ -131,12 +134,12 @@ def test_rejects_candidate_older_than_an_existing_release(self): check_release, "_tag_identity", side_effect=lambda _root, tag: { - "v0.2.0": higher, - "v0.1.0": lower, + "b10123": higher, + "b10069": lower, }[tag], ): with self.assertRaisesRegex(ValueError, "newer release already exists"): - check_release._previous_identity(self.root, current, "v0.1.1") + check_release._previous_identity(self.root, current, "b10069.1") def test_vendored_source_rejects_git_metadata_and_submodules(self): check_release.validate_vendor_boundary(self.root) @@ -167,10 +170,10 @@ def test_repository_checks_invoke_import_export_and_snapshot_check_modes(self): self.assertEqual(call.kwargs["cwd"], self.root) def test_mapping_line_is_stable(self): - identity = check_release.load_identity(self.root, "v0.1.0") + identity = check_release.load_identity(self.root, "b10069") self.assertEqual( check_release.format_mapping(identity), - "llama.cpp-m 0.1.0 -> llama.cpp b10069 " + "llama.cpp-m b10069 -> llama.cpp b10069 " "(178a6c44937154dc4c4eff0d166f4a044c4fceba)", ) diff --git a/tests/unit/test_repository_contract.py b/tests/unit/test_repository_contract.py index 990b095..6e921b8 100644 --- a/tests/unit/test_repository_contract.py +++ b/tests/unit/test_repository_contract.py @@ -26,8 +26,9 @@ def test_no_submodule_or_consumer_time_upstream_fetch(self): def test_package_and_module_identity(self): manifest = (ROOT / "mcpp.toml").read_text(encoding="utf-8") module = (ROOT / "src/llamacpp.cppm").read_text(encoding="utf-8") + self.assertRegex(manifest, r'(?m)^namespace\s*=\s*"ggml-org"$') self.assertRegex(manifest, r'(?m)^name\s*=\s*"llamacpp"$') - self.assertRegex(manifest, r'(?m)^version\s*=\s*"0\.1\.0"$') + self.assertRegex(manifest, r'(?m)^version\s*=\s*"b10069"$') self.assertIn("export module llamacpp;", module) def test_vendored_tree_is_not_locally_patched(self): diff --git a/tools/audit_snapshot.py b/tools/audit_snapshot.py index 71d4493..aa40978 100644 --- a/tools/audit_snapshot.py +++ b/tools/audit_snapshot.py @@ -502,7 +502,7 @@ def main() -> int: root = args.source.resolve() if not (root / 'include/llama.h').is_file(): - ap.error(f'mcpplibs:llamacpp source tree not found: {root}') + ap.error(f'ggml-org:llamacpp source tree not found: {root}') expected = None if args.check: diff --git a/tools/check_release.py b/tools/check_release.py index 1b7819b..83dd99c 100644 --- a/tools/check_release.py +++ b/tools/check_release.py @@ -2,6 +2,7 @@ import argparse from pathlib import Path +import re import subprocess import sys import tomllib @@ -15,19 +16,39 @@ class Version(NamedTuple): - major: int - minor: int - patch: int + """The wrapper version IS upstream's build number. + + `b10069` is llama.cpp b10069, and a wrapper-only fix on the same checkpoint + adds a revision: `b10069.1`. This replaced a separate semantic version whose + README had to carry a decoder ring next to it ("Version 0.1.0 maps to + llama.cpp b10069"); see docs/upstream-update-policy.md and mcpp-index#163. + + Ordering still works — the build number is an integer — so the "must not + release something older" checks below are unchanged. What is gone is the + major/minor/patch contract; the drift it used to police is now impossible by + construction, because the version and the checkpoint are the same string. + """ + + build: int # upstream llama.cpp build number + revision: int # wrapper revision on that checkpoint; 0 when absent @classmethod def parse(cls, value: str) -> "Version": - parts = value.split(".") - if len(parts) != 3 or any(not part.isdigit() for part in parts): - raise ValueError(f"invalid semantic version: {value}") - return cls(*(int(part) for part in parts)) + match = re.fullmatch(r"b(\d+)(?:\.([1-9]\d*))?", value) + if not match: + raise ValueError( + f"invalid wrapper version: {value!r} — expected upstream's build " + f"number (b10069), optionally with a wrapper revision (b10069.1)" + ) + return cls(int(match.group(1)), int(match.group(2) or 0)) def __str__(self) -> str: - return f"{self.major}.{self.minor}.{self.patch}" + return f"b{self.build}" + (f".{self.revision}" if self.revision else "") + + @property + def upstream_tag(self) -> str: + """The checkpoint this version names.""" + return f"b{self.build}" class ReleaseIdentity(NamedTuple): @@ -69,10 +90,21 @@ def _identity_from_text(manifest_text: str, lock_text: str, tag: str) -> Release except (KeyError, TypeError) as error: raise ValueError(f"invalid release identity: missing {error}") from error - if tag != f"v{identity.version}": + # The tag is the version verbatim, which is also upstream's own tag form + # (ggml-org/llama.cpp tags releases `b10069`, not `vb10069`). + if tag != str(identity.version): raise ValueError( f"release tag {tag} does not match package version {identity.version}" ) + # The version NAMES the vendored checkpoint. Before, this was a convention + # the transition rules policed after the fact; now a mismatch is simply not + # a valid identity. + if identity.version.upstream_tag != identity.upstream_tag: + raise ValueError( + f"package version {identity.version} names checkpoint " + f"{identity.version.upstream_tag}, but the lock vendors " + f"{identity.upstream_tag}" + ) if identity.upstream_repository != OFFICIAL_UPSTREAM_REPOSITORY: raise ValueError( f"official upstream repository must be {OFFICIAL_UPSTREAM_REPOSITORY}" @@ -133,21 +165,25 @@ def validate_version_transition( and current.upstream_commit == previous.upstream_commit ) if same_checkpoint: - if not ( - current.version.major == previous.version.major - and current.version.minor == previous.version.minor - and current.version.patch > previous.version.patch - ): - raise ValueError("a same-checkpoint wrapper fix requires a patch bump") + # Same checkpoint means the same build number, so the only thing left to + # move is the wrapper revision. + if current.version.build != previous.version.build: + raise ValueError( + "a same-checkpoint release must keep the checkpoint's build number" + ) + if current.version.revision <= previous.version.revision: + raise ValueError( + "a same-checkpoint wrapper fix requires a revision bump " + "(b10069 -> b10069.1)" + ) return - if not ( - current.version.major > previous.version.major - or ( - current.version.major == previous.version.major - and current.version.minor > previous.version.minor + # A new checkpoint IS a new build number; `_identity_from_text` has already + # checked that the version names the checkpoint actually vendored, so the + # only thing left is that releases move forward. + if current.version.build <= previous.version.build: + raise ValueError( + "a changed upstream checkpoint requires its own, higher build number" ) - ): - raise ValueError("a changed upstream checkpoint requires at least a minor bump") def validate_vendor_boundary(root: Path) -> None: @@ -218,7 +254,7 @@ def _previous_identity( if tag == current_tag: continue try: - version = Version.parse(tag.removeprefix("v")) + version = Version.parse(tag) except ValueError: continue if version > current.version: diff --git a/tools/gen_exports.py b/tools/gen_exports.py index ba6a610..c23c433 100644 --- a/tools/gen_exports.py +++ b/tools/gen_exports.py @@ -538,7 +538,7 @@ def main(argv=None): upstream = Path(args.upstream) if args.upstream else DEFAULT_UPSTREAM_DIR if not args.upstream and not (upstream / "include/llama.h").is_file(): print( - f"mcpplibs:llamacpp upstream tree not found: {upstream}", + f"ggml-org:llamacpp upstream tree not found: {upstream}", file=sys.stderr, ) return 1 From d839daffd9d8e8dd0a6cc25f3937c2d12cbae153 Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Thu, 6 Aug 2026 08:55:20 +0800 Subject: [PATCH 2/3] =?UTF-8?q?ci:=20mcpp=20pin=20=E6=8A=AC=E5=88=B0=20202?= =?UTF-8?q?6.8.5.4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI 此前就已经红,与本次身份迁移无关:pin 的 mcpp 低于索引声明的 min_mcpp, 每次都停在同一个地方 —— error: index requires mcpp >= 2026.8.3.3 but this is mcpp [E0006] 索引下限是一道机器闸门(mcpp#349):索引是数据、mcpp 是程序,发布数据不得让程序 失效,所以下限只在描述符真的读不动时才抬。这里要动的是客户端这一侧。 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9ab6926..5539d1c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ permissions: contents: read env: - MCPP_VERSION: "2026.7.28.2" + MCPP_VERSION: "2026.8.5.4" MCPP_RELEASE_BASE: https://github.com/mcpp-community/mcpp/releases/download jobs: From 18cb39183312c6ec6afff8cfff93593da67cf12e Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Thu, 6 Aug 2026 09:45:20 +0800 Subject: [PATCH 3/3] =?UTF-8?q?fix(ci):=20release-contract=20=E4=BB=8E=20m?= =?UTF-8?q?anifest=20=E8=AF=BB=20tag,=E8=80=8C=E4=B8=8D=E6=98=AF=E7=A1=AC?= =?UTF-8?q?=E7=BC=96=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `--tag v0.1.0` 是版本号的第二份拷贝,版本方案一改它就落后 —— ValueError: release tag v0.1.0 does not match package version b10069 check_release.py 已经强制 tag 等于版本,那就从 manifest 读,不再留第二处要记得改 的地方。 --- .github/workflows/ci.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5539d1c..baa0eb6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -251,4 +251,11 @@ jobs: - name: Verify release mapping and reproducibility env: GITHUB_TOKEN: ${{ github.token }} - run: python3 tools/check_release.py --tag v0.1.0 + run: | + # The tag IS the package version — check_release.py enforces it — so + # read it from the manifest rather than hardcoding a second copy here. + # The hardcoded `v0.1.0` is exactly what broke when the version scheme + # moved to upstream's checkpoint (mcpp-index#163). + tag=$(sed -n 's/^version *= *"\(.*\)"/\1/p' mcpp.toml | head -1) + echo "release contract for tag: $tag" + python3 tools/check_release.py --tag "$tag"