Skip to content

Commit 18ded18

Browse files
2026.10.16.1: the provider port, indices in mcpp's home, upstreams, the system home, filesystems and long paths (#811)
mcpp 2026.10.16.1. Implements `.agents/docs/2026-10-16-xlings-provider-port-and-shared-store-design.md` (the mcpp side; the xlings side is openxlings/xlings#676, released as 2026.10.16.1 and bundled here). Fixes #809. ## The provider port - Every use of xlings goes through one port, `mcpp.provider`. Only the adapter under `src/provider/xlings/` names xlings' commands, protocol and store layout; the composition root `mcpp.provider.select` chooses it. `.github/tools/check_provider_boundary.py` checks the boundary in CI. - Payloads are written by the provider alone. mcpp no longer patches a toolchain's ELF headers, rewrites `specs` or clang `.cfg`, writes `.mcpp_ok` / `.mcpp-fixup.json`, or copies payloads from `~/.xlings`; a build states what a payload lacks on its own command lines. - The handshake: every xlings source is asked what it is (`xlings interface --version`); one that cannot serve this mcpp gives way to the bundled xlings, with a note. ## Ownership, place and refresh - The data and payloads of each index mcpp serves live in mcpp's home: `<MCPP_HOME>/indices/<name>`, `<MCPP_HOME>/xpkgs` (a project's under `<project>/.mcpp`). The provider's own indexes stay under `registry/`. - An owned index is refreshed into a staging directory, judged against its `min_mcpp` there, and exchanged with the copy in use only when this mcpp can read it. - A home from an earlier mcpp keeps working: its index data moves once; payloads under `registry/data/xpkgs` stay and are still found. ## Reuse and the system home - `[xlings] upstream = [...]` (user configuration, else the system configuration `/etc/mcpp/config.toml` / `%ProgramData%\mcpp\config.toml`): a payload of the same identity is linked from an upstream, never copied or written. An upstream must belong to the user or to the system; another user's home is refused. - `mcpp self store dedupe [--apply]` replaces the home's own copies with links. - `mcpp --system` maintains the machine's system home (`self init|doctor|store`, `toolchain install|remove|default`, `index update`); every other command, and a caller without write access, is refused. - `[xlings] home` names a home mcpp made; a home it did not make is refused with a pointer to `upstream`. ## Filesystems and Windows long paths - Scaffold publication and index swaps use what the filesystem holding them measures (atomic no-replace rename, exchange, hard and symbolic links), so NFSv3, SMB, FAT and FUSE homes work (#809). A CI job builds and runs a project on an NFSv3 export. - `windows_long_paths` (target and `[test]` keys) writes `longPathAware` into a PE application manifest; `mcpp.exe` declares it. With long paths off and a long `MCPP_HOME`, the path budget is reported as a degradation. `mcpp self doctor` states the home, its upstreams, its filesystem and the long-path setting. ## Documentation New docs/25 (en/zh) on the home, its indices and its store; docs/91 §4, docs/11, docs/09, docs/04, SPEC-001 1.6, SPEC-004, SPEC-006 v0.8 updated; CHANGELOG 2026.10.16.1. ## Verification All 65 CI checks pass on the final head (Linux, aarch64, macOS, Windows, e2e shards, openkal, target matrix, fresh installs, NFSv3). mcpp-plugins CI built and ran against this branch ([38895101589](https://github.com/mcpp-community/mcpp-plugins/actions/runs/38895101589)). Found and fixed on the way: a package of mcpp's indices is looked for in every store of the home; the runtime is pinned after its payload is installed, so the provider's loader links exist; a toolchain whose runtime cannot be installed is refused naming `xim:glibc@<v>`; `fs_caps`' alias of `std::filesystem` no longer shadows the `mcpp::platform::fs` namespace (GCC 16 crashed reading both). Unit tests for the port, the owned index, the trust check, the manifest key and the resources; e2e 914 (upstream linked, never written; trust; doctor; dedupe; a home mcpp did not make), 915 (system home), 916 (a home from before), 917 (a long home on Windows), plus the existing suites with stub xlings answering the handshake. Locally against xlings 2026.10.16.1: upstream reuse, dedupe, `--system`, and the e2e suites listed pass. Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com>
1 parent 3435540 commit 18ded18

146 files changed

Lines changed: 5017 additions & 3545 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.agents/docs/2026-10-16-xlings-provider-port-and-shared-store-design.md‎

Lines changed: 607 additions & 0 deletions
Large diffs are not rendered by default.

‎.agents/docs/README.md‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ superseded_by: 2026-09-07-....md # when status is superseded
1818
---
1919
```
2020

21-
331 records.
21+
332 records.
2222

2323
## By subject
2424

@@ -121,10 +121,15 @@ Records that declare one. Everything else is listed by date below.
121121
- [The engine gaps left open after the SDK batch](2026-09-12-engine-gaps-after-the-sdk-batch.md) — landed
122122
- [Six open issues: what each one actually is, and what would answer it](2026-09-11-six-open-issues-analysis.md) — active
123123

124+
### xlings
125+
126+
- [mcpp 对 xlings 的依赖:Provider 端口、归属与位置、上游复用、系统级安装、payload 不可变、文件系统能力与长路径(#809)](2026-10-16-xlings-provider-port-and-shared-store-design.md) — active
127+
124128
## By date
125129

126130
### 2026-10
127131

132+
- [mcpp 对 xlings 的依赖:Provider 端口、归属与位置、上游复用、系统级安装、payload 不可变、文件系统能力与长路径(#809)](2026-10-16-xlings-provider-port-and-shared-store-design.md) — active
128133
- [构建依赖的一条管线:配置与产物两轴、包的实例、库接口、兼容系统与工作空间收尾(#797)](2026-10-11-build-dependencies-one-pipeline-design.md) — active
129134
- [一处来源,一种含义:工作空间的传递语义、生成输出、模块角色与首次运行(#786、#785、#778、#790)](2026-10-10-one-source-one-meaning-design.md) — landed
130135
- [LLVM 23.1.3 Part 2:Linux aarch64 默认工具链与 glibc 生态闭环](2026-10-08-llvm-2313-linux-aarch64-ecosystem-part2-design.md) — active

‎.github/actions/bootstrap-mcpp/action.yml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ inputs:
2121
xlings-version:
2222
description: xlings release to bootstrap from
2323
required: false
24-
# Must equal `pinned::kXlingsVersion` in src/xlings/xlings.cppm — enforced by
24+
# Must equal `pinned::kXlingsVersion` in src/provider/xlings/xlings.cppm — enforced by
2525
# .github/tools/check_version_pins.sh, not by this comment. (The previous
2626
# comment here listed the files to keep in lock-step, and that list was
2727
# already incomplete; that is why the check exists.)
@@ -33,7 +33,7 @@ inputs:
3333
# `package.name`, so one of the two was simply unreachable — and which one
3434
# depended on the machine, which is why CI failed on `compat:lua` on
3535
# Windows and `mcpplibs.capi:lua` on Linux. Never pin below that.
36-
default: '2026.10.10.2'
36+
default: '2026.10.16.1'
3737

3838
outputs:
3939
sandbox-key:

‎.github/actions/setup-macos-llvm/action.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ inputs:
1515
# Floor imposed by the index, not a routine bump — see
1616
# .github/actions/bootstrap-mcpp/action.yml for why 0.4.69 is required
1717
# (two packages named `lua` in one repo need openxlings/xlings#381).
18-
default: '2026.10.10.2'
18+
default: '2026.10.16.1'
1919
image:
2020
description: >
2121
The runner label the job runs on (macos-15, xcode-27). It is part of the
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
#!/usr/bin/env python3
2+
"""The provider boundary (.agents/docs/2026-10-16-xlings-provider-port-and-shared-store-design.md §4.3).
3+
4+
mcpp speaks the port's words (mcpp.provider): what xlings' commands, its
5+
protocol, its home layout and its store naming are is the adapter's
6+
(src/provider/xlings/), and only the composition root (src/provider/select.cppm)
7+
names the adapter. Outside them, in src/:
8+
9+
- no `import mcpp.provider.xlings*`;
10+
- none of the layout's spellings in code: "xpkgs", "-x-", "xim-x-",
11+
".xlings.json", "subos", "xim-index-repos", ".mcpp_ok";
12+
- a payload path is used as the provider answered it: no canonical /
13+
weakly_canonical / remove_all applied to one.
14+
15+
Comments are prose and may name anything; string literals and identifiers
16+
in code may not. An exception names its reason on the line:
17+
`// provider-boundary-ok: <why>`.
18+
19+
Exit 0 clean, 1 with the findings listed.
20+
"""
21+
from __future__ import annotations
22+
23+
import argparse
24+
import pathlib
25+
import re
26+
import sys
27+
28+
LITERALS = ['"xpkgs"', '/xpkgs', 'xpkgs/', '-x-', 'xim-x-', '.xlings.json', '"subos"', '/subos', 'subos/',
29+
'xim-index-repos', '.mcpp_ok', '.mcpp-fixup.json']
30+
IMPORT = re.compile(r'^\s*(export\s+)?import\s+mcpp\.provider\.xlings\b')
31+
PAYLOAD_FS = re.compile(r'\b(canonical|weakly_canonical|remove_all)\s*\([^)]*[pP]ayload')
32+
33+
34+
def strip_comments(text: str) -> list[str]:
35+
"""Each line with // and /* */ comments blanked, string literals kept."""
36+
out, in_block = [], False
37+
for line in text.split("\n"):
38+
res, i, in_str = [], 0, None
39+
while i < len(line):
40+
c = line[i]
41+
if in_block:
42+
if line.startswith("*/", i):
43+
in_block = False
44+
i += 2
45+
continue
46+
i += 1
47+
continue
48+
if in_str:
49+
res.append(c)
50+
if c == "\\" and i + 1 < len(line):
51+
res.append(line[i + 1])
52+
i += 2
53+
continue
54+
if c == in_str:
55+
in_str = None
56+
i += 1
57+
continue
58+
if line.startswith("//", i):
59+
break
60+
if line.startswith("/*", i):
61+
in_block = True
62+
i += 2
63+
continue
64+
if c in "\"'":
65+
in_str = c
66+
res.append(c)
67+
i += 1
68+
out.append("".join(res))
69+
return out
70+
71+
72+
def main() -> int:
73+
ap = argparse.ArgumentParser(description=__doc__.split("\n")[0])
74+
ap.add_argument("--root", type=pathlib.Path, default=pathlib.Path(__file__).resolve().parents[2])
75+
ROOT = ap.parse_args().root.resolve()
76+
SRC = ROOT / "src"
77+
ADAPTER = SRC / "provider" / "xlings"
78+
ROOT_MODULE = SRC / "provider" / "select.cppm"
79+
findings = []
80+
for path in sorted(SRC.rglob("*")):
81+
if path.suffix not in (".cppm", ".cpp", ".hpp", ".h") or not path.is_file():
82+
continue
83+
if ADAPTER in path.parents:
84+
continue
85+
raw = path.read_text(encoding="utf-8", errors="replace").split("\n")
86+
code = strip_comments("\n".join(raw))
87+
for n, (line, original) in enumerate(zip(code, raw), 1):
88+
if "provider-boundary-ok:" in original:
89+
continue
90+
rel = path.relative_to(ROOT)
91+
if IMPORT.match(line) and path != ROOT_MODULE:
92+
findings.append(f"{rel}:{n}: imports the adapter; import mcpp.provider.select")
93+
for lit in LITERALS:
94+
if lit in line:
95+
findings.append(f"{rel}:{n}: names the provider's layout ({lit}): {original.strip()}")
96+
break
97+
if PAYLOAD_FS.search(line):
98+
findings.append(f"{rel}:{n}: canonicalises or removes a payload: {original.strip()}")
99+
if findings:
100+
print("provider boundary: " + str(len(findings)) + " finding(s)")
101+
for f in findings:
102+
print(" " + f)
103+
return 1
104+
print("provider boundary: clean")
105+
return 0
106+
107+
108+
if __name__ == "__main__":
109+
sys.exit(main())

‎.github/tools/check_version_pins.sh‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
# Two invariants that used to live only in a comment:
66
#
77
# 1. Every xlings version pinned anywhere in .github/ equals
8-
# `pinned::kXlingsVersion` in src/xlings/xlings.cppm — which is the version
8+
# `pinned::kXlingsVersion` in src/provider/xlings/xlings.cppm — which is the version
99
# `mcpp self env` reports and the one release.yml bundles into the
1010
# tarball as <install>/registry/bin/xlings.
1111
#
1212
# 2. mcpp's own version is identical in all four places that carry it.
1313
#
14-
# Why this exists: src/xlings/xlings.cppm used to say "keep in lock-step with the
14+
# Why this exists: src/provider/xlings/xlings.cppm used to say "keep in lock-step with the
1515
# XLINGS_VERSION pins in release.yml / cross-build-test.yml / ci-linux-e2e.yml"
1616
# and that list was ALREADY incomplete — it omitted both composite actions,
1717
# which sat on 0.4.30 while everything else moved to 0.4.69. CI's sandbox
@@ -38,12 +38,12 @@ strip_comments() { sed 's/#.*//'; }
3838

3939
# ── 1. xlings pins ────────────────────────────────────────────────────────
4040

41-
XLINGS_EXPECTED=$(grep -oE 'kXlingsVersion[[:space:]]*=[[:space:]]*"[^"]+"' src/xlings/xlings.cppm \
41+
XLINGS_EXPECTED=$(grep -oE 'kXlingsVersion[[:space:]]*=[[:space:]]*"[^"]+"' src/provider/xlings/xlings.cppm \
4242
| grep -oE '"[^"]+"' | tr -d '"' | head -1)
4343
[ -n "$XLINGS_EXPECTED" ] || {
44-
echo "FAIL: could not read kXlingsVersion from src/xlings/xlings.cppm" >&2; exit 1; }
44+
echo "FAIL: could not read kXlingsVersion from src/provider/xlings/xlings.cppm" >&2; exit 1; }
4545

46-
note "expected xlings pin: $XLINGS_EXPECTED (src/xlings/xlings.cppm)"
46+
note "expected xlings pin: $XLINGS_EXPECTED (src/provider/xlings/xlings.cppm)"
4747

4848
# Anchored patterns only — a bare "version-looking number on a line mentioning
4949
# xlings" would also match `xlings install llvm@20.1.7`, which pins LLVM, not

‎.github/tools/run_published_arm64_cn.sh‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ base=${XLINGS_HOME:?cold isolated home required}
1212
mkdir -p "$base/bootstrap" "$base/probes" "$base/reports"
1313
cd "$base"
1414
# Derive the client version from the repository's existing single pin.
15-
xl_version=$(python3 - "$repo/src/xlings/xlings.cppm" <<'PY'
15+
xl_version=$(python3 - "$repo/src/provider/xlings/xlings.cppm" <<'PY'
1616
import pathlib,re,sys
1717
s=pathlib.Path(sys.argv[1]).read_text()
1818
m=re.search(r'kXlingsVersion\s*=\s*"([0-9.]+)"',s)

‎.github/workflows/bootstrap-macos.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
# Dormant (workflow_dispatch only), but kept in step with the rest —
1818
# check_version_pins.sh holds it there. Floor: 0.4.69, below which the
1919
# index cannot resolve two packages that share a short name.
20-
XLINGS_VERSION: '2026.10.10.2'
20+
XLINGS_VERSION: '2026.10.16.1'
2121
steps:
2222
- uses: actions/checkout@v4
2323

‎.github/workflows/ci-bootstrap.yml‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ jobs:
4141
os: [ubuntu-24.04, macos-15, windows-2025]
4242
env:
4343
XLINGS_NON_INTERACTIVE: '1'
44-
XLINGS_VERSION: '2026.10.10.2'
44+
XLINGS_VERSION: '2026.10.16.1'
4545
steps:
4646
- uses: actions/checkout@v4
4747

@@ -50,7 +50,7 @@ jobs:
5050
shell: bash
5151
run: |
5252
set -euo pipefail
53-
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.10.10.2
53+
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.10.16.1
5454
echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH"
5555
echo "$HOME/.xlings/bin" >> "$GITHUB_PATH"
5656
@@ -124,7 +124,7 @@ jobs:
124124
shell: bash
125125
run: |
126126
set -euo pipefail
127-
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.10.10.2
127+
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.10.16.1
128128
echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH"
129129
130130
- name: Install the newest release and build the tree with it (mcpp build --strict)

‎.github/workflows/ci-fresh-install.yml‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ jobs:
152152
env:
153153
XLINGS_NON_INTERACTIVE: '1'
154154
run: |
155-
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.10.10.2
155+
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.10.16.1
156156
echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH"
157157
158158
- name: Install mcpp and config mirror
@@ -315,7 +315,7 @@ jobs:
315315

316316
- name: Install xlings + mcpp
317317
run: |
318-
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.10.10.2
318+
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.10.16.1
319319
# Deliberately NOT writing to $GITHUB_PATH here. On container
320320
# images that declare no PATH in their config (opensuse/
321321
# tumbleweed), appending a single dir to GITHUB_PATH makes the
@@ -464,7 +464,7 @@ jobs:
464464
# (older ones carry minos=15 and refuse to start).
465465
# v0.4.51+: in-process sha256 — this image has no sha256sum
466466
# binary, so pinned fetches failed before it.
467-
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.10.10.2
467+
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.10.16.1
468468
echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH"
469469
470470
- name: Install mcpp and config mirror

0 commit comments

Comments
 (0)