Repository navigation
fix: a partial caret or tilde requirement treats unwritten segments as wildcards - #866
Merged
Sunrisepeak merged 1 commit intoOct 30, 2026
Conversation
…s wildcards `^0` and `^0.0` bounded their range at 0.0.1, and `~1` and `~0` at 1.1 and 0.1. The caret branch chose the segment to bump through major(), minor() and patch(), which read a segment that was never written as 0, so `^0` fell through to bumping the patch; the tilde branch always bumped the minor. A dependency written `"^0"` against an index with 0.3.0 and 0.4.0 failed with "matches none of", and `"~1"` never selected 1.1.0 or later. The grammar is Cargo's, and Cargo reads an unwritten segment as a wildcard: `^0` is >=0.0.0, <1.0.0; `^0.0` is >=0.0.0, <0.1.0; `~1` is >=1.0.0, <2.0.0. mcpp.xpkg_version already bounds a partial caret this way. The caret bound now bumps the leftmost non-zero segment, looking no further than the patch and stopping at the last segment written; the tilde bound holds the major alone when no minor is written. Every fully written requirement (`^0.0.0`, `^0.0.3`, `^1.2.3`, `~1.2`, the four-segment date versions) keeps its bound. Unit tests cover the partial caret and tilde forms next to the existing caret and tilde cases, and docs/05-dependencies.md (both languages) lists the two forms. Closes mcpp-community#864
Sunrisepeak
added a commit
that referenced
this pull request
Oct 30, 2026
…t; the TOML writer escapes every control character #866: a bare requirement is a caret, so "0" and "0.0" take the wildcard bounds as well (<1.0.0, <0.1.0); a unit test pins bare against caret, docs/05 states it in both languages. #867: with \b, \f and \uXXXX read, a value may hold any control character; escape_string escapes U+0000-U+001F and U+007F (short forms where TOML has one, \uXXXX elsewhere, never the reader's \0), so serialize writes TOML. A round trip test covers every control character. Design 2026-10-30 part 2 §17. Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com>
Sunrisepeak
added a commit
that referenced
this pull request
Oct 30, 2026
…866/#867 follow-ups; canary build steps; --pkg-format polyglot; ldflags files as link inputs (#869) * design 2026-10-30 part 2: mcpp plugins and mcppls -- layers, the project's mcpp, mcppls's contract, entries, test cases, the manifest's rules as LSP, CLion native, distribution; one file for every system (#849): the APE and polyglot probes, the polyglot carrier model Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com> * 2026.10.31.1: `features` in --protocol-version and every envelope, `program` in self env, and how a tool runs mcpp for a project (docs/50) A client gates on a feature (`target-sets`, `pkg-format-list`) rather than a version number; every envelope's `mcpp` field carries the list beside the version, so one `self env` gives both and a job's envelope says when either changed. `self env` names the file that is running, so a tool that ran `mcpp` through a shim in a project's directory reads which mcpp the project uses. Design 2026-10-30 part 2 §4.0, §4.3. Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com> * a workspace's lock entry is keyed the same way whatever members a command plans (#868) Two members spelling one dependency two ways (`tinyhttps.workspace = true` and `[dependencies.mcpplibs] tinyhttps.workspace = true`) made `-p` of each write its own key and hash. The key is now the workspace's spelling: its `[dependencies]`, `[workspace.dependencies]`, then every member in the order `members` lists them, selected or not (docs/07, e2e 990). Closes #868 Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com> * the follow-ups of #866 and #867: a bare partial requirement is a caret; the TOML writer escapes every control character #866: a bare requirement is a caret, so "0" and "0.0" take the wildcard bounds as well (<1.0.0, <0.1.0); a unit test pins bare against caret, docs/05 states it in both languages. #867: with \b, \f and \uXXXX read, a value may hold any control character; escape_string escapes U+0000-U+001F and U+007F (short forms where TOML has one, \uXXXX elsewhere, never the reader's \0), so serialize writes TOML. A round trip test covers every control character. Design 2026-10-30 part 2 §17. Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com> * release canaries print the longest build steps of every build they made A canary's time is mostly its project's build (xlings: 1750 s of 47 min); each canary now ends with the 20 longest steps read from every .ninja_log beneath it, and `release_canaries.py steps <dir>` prints them for any tree. Design 2026-10-30 part 2 §11. Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com> * a file [build] ldflags names by absolute path is a link input A replaced prebuilt archive named in [build] ldflags did not relink the program: the word reached the linker but no link edge depended on it, and the clangd ok-image probe deleted its image to take a new library. A word that names an existing file by absolute path is now an implicit input of every non-archive link that carries it (docs/04, e2e 991). Design 2026-10-30 part 2 §25.3 C1. Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com> * one file for several systems: --pkg-format polyglot (SPEC-014 2.1 §5.3, #849) An ok image's single files of every leg and system (--systems all unless stated) are assembled into one <name>-<version>.exe. The Windows program leads: its DOS header is a shell assignment (MZqFpD='...') followed by a two-line script, the PE header moves down by a multiple of the file alignment and the offsets it holds move with it; the other systems' programs follow unchanged, and the POSIX script last. Windows starts the file as the PE it is (Authenticode signs it); Linux and macOS start it through sh, which copies the system's program to the single-file cache by SPEC-014 §5.2's rules, checks its sha256 and executes it. Without Windows the file is a #!/bin/sh script. The carriers are signed before assembly (the Windows one excepted) and the file after. polyglot is not in a --pkg-format list, a native target is refused, and mcpp emit xpkg names the file it refuses. mcpp run --pkg-format single-file and polyglot run the file directly (polyglot through sh on POSIX); they were refused as unknown formats; tar, zip and dir are refused as containers. Design 2026-10-30 part 2 §19.6; e2e 992, unit test_pack_polyglot. Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com> * CI: the new e2e tests' durations in the Linux shards; e2e 992 also in the wine job, where its file runs as a Windows program Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com> * the binary states 2026.10.31.1; #868 reads each member's manifest as written The version module still named 2026.10.30.1 (help, version and the subsystem contract test compare it with mcpp.toml). Loading every member through load_member_manifest for its spelling of a dependency also ran the inheritance a planned member receives, whose position-reading notes then reached the root's own build (e2e 911 R5); the manifests are now read as written, the way workspace_members reads them. Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com> * a tree's POSIX launcher names macOS's quarantine mark on its runner, with the command that removes it A package a browser downloaded carries com.apple.quarantine on every file, and macOS refuses to start an unsigned runner so marked; the launcher says so before it starts the runner (SPEC-014 §4.3; mcpp design 2026-10-30 part 2 §10 D6). Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com> * docs: the part 2 design is active and indexed; docs/50's heading for how a tool runs mcpp is a noun phrase Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com> --------- Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A caret or tilde requirement whose version leaves segments unwritten read them as zeros:
^0and^0.0were bounded at<0.0.1,~1at<1.1and~0at<0.1. A dependency"^0"against an index with 0.3.0 and 0.4.0 failed withconstraint '^0' matches none of: [0.3.0, 0.4.0], and"~1"never reached 1.1.0.matchesnow follows Cargo's partial requirements, whichmcpp.xpkg_versionalready follows for the caret. A segment that is not written is a wildcard:^0→<1.0.0,^0.0→<0.1.0;^0.0.0stays<0.0.1.~1→<2.0.0;~1.2and~1.2.3stay<1.3.0.The grammar notes at the top of
version_req.cppmand the constraint list indocs/05-dependencies.md(both languages) name the two forms.Closes #864.
Criteria
VersionReq.PartialCaretBoundsFollowTheWrittenSegmentsandVersionReq.PartialTildeWithOnlyAMajorHoldsTheMajor(tests/unit/test_version_req.cpp). On aarch64 Linux with the bootstrap 2026.10.29.1 binary,mcpp test test_version_reqfails both before the change (matches("^0.0", 0.0.7),matches("~1", 1.1.0),matches("~0", 0.4.0)are false) and passes all 31 after it.mcpp test, 156 passed, 0 failed) andmcpp test -p versioningpass on aarch64 Linux. Other hosts are left to CI.[indices]path index publishingacme.gadget0.3.0 and 0.4.0): the released binary refusesgadget = "^0"and"~0"with "matches none of". The binary built from this branch resolves both to 0.4.0, builds, runs the program and writesversion = "0.4.0"tomcpp.lock.Intersections
^2026.7.27.3→<2027)MatchCaretBare,MatchCaretZeroMajor,CaretUpperBoundZeroesTheFourthSegment, and the^0.0.0/^0.0.3/^0.5cases in the new test~X.Y[.Z]holds the minor; date versions zero the tailMatchTilde,TildeUpperBoundZeroesTheFourthSegment, the~1.2case in the new testRangesDoNotSeePrereleasesUnlessAskedFor,CaretUpperBoundDoesNotLeakIntoTheNextMajorsPrereleaseCompatibility
Only requirements spelled
^0,^0.0,~N(one segment) change. Each now admits the versions Cargo admits, a superset of what it admitted before. A manifest that failed to resolve with one of them now resolves. One that resolved now selects the highest match in the wider range, and the lock records it. All other requirement spellings, and bare versions (exact addresses), are unchanged.Checks before merging
bash .github/tools/check_docs_style.sh,check_docs_structure.shandcheck_version_pins.shpass.python3 .github/tools/check_workflow_assertions.pypasses (a step asserts what its name says).git log origin/main..HEAD -i --grep='Co-Authored-By'prints nothing.compose one from the branch's commits. Suggested subject:
fix: a partial caret or tilde requirement treats unwritten segments as wildcards.