Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions .agents/docs/2026-07-08-index-side-adoption-plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Index-side adoption plan — mcpp 0.0.85 train (floor, strict lint, scan_overrides, long brackets)

Companion to mcpp repo
`.agents/docs/2026-07-08-descriptor-index-evolution-roadmap.md` (master) and
its two design docs (same date). This doc is the mcpp-index execution detail.

Rule of the whole rollout: **floor first, new grammar/keys after** — enforced
mechanically by lint once P1 lands (lint parses with the pinned mcpp; before
the pin reaches 0.0.85, new-grammar descriptors cannot merge).

---

## P0 — merge PR #63 as-is (pre-train)

fmt 12.2.0 via `generated_files` works on today's 0.0.81 (verified locally
2026-07-08: lint pass, sha256 match, member test green, generated file =
upstream `src/fmt.cc` minus exactly the `import std;` guard). Don't couple it
to the train; migrate it in P2.

## P1 — floor PR (single atomic PR)

1. `index.toml` at repo root:

```toml
[index]
spec = "1"
min_mcpp = "0.0.85"
latest_mcpp = "0.0.85"
```

2. `.github/workflows/validate.yml`: `MCPP_VERSION` 0.0.81 → 0.0.85.
3. lint job: add the pinned-mcpp download step (same snippet as the workspace
job) and run `mcpp xpkg parse --strict` over changed (PR) / all (push,
nightly) descriptors — **in addition to** the existing `lua5.4 loadfile`
check (the xim side executes real Lua; both grammars stay guarded).
4. `tools/publish_mcpp_index.sh`: pack `index.toml` into the artifact tree
(one `cp` next to the existing `pkgs/` copy). Pointer untouched.
5. `docs/repository-and-schema.md`: floor paragraph (what breaks for
pre-0.0.85 clients, why now).

## P2 — fmt: generated_files → scan_overrides

`pkgs/f/fmtlib.fmt.lua` descriptor `mcpp` segment becomes:

```lua
mcpp = {
schema = "0.1",
language = "c++23",
import_std = true,
modules = { "fmt" },
include_dirs = { "*/include", "*/src" },
sources = { "*/src/fmt.cc" }, -- upstream file, verbatim
cxxflags = { "-DFMT_IMPORT_STD" },
scan_overrides = {
["*/src/fmt.cc"] = { provides = { "fmt" }, imports = { "std" } },
},
targets = { ["fmt"] = { kind = "lib" } },
}
```

- Deletes the 3.4 KB escaped `generated_files` copy entirely.
- `tests/examples/fmtlib.fmt/` member unchanged — it is the live CI proof
(also the matrix's first `import_std = true` package build on mac/win).
- mcpp-side reconciliation (mandatory for override files) audits the declared
`(provides, imports)` against the compiler's `.ddi` every build.

## P3 — long-bracket migrations (one PR per package)

`pkgs/n/nlohmann.json.lua`, `pkgs/c/compat.eigen.lua`: `generated_files`
escaped strings → `[==[ … ]==]`. Mechanical; reviewer checks the parity
oracle output (content via lua5.4 == content via `mcpp xpkg parse --json`),
which the lint step re-verifies anyway.

## P4 — docs refresh

`docs/repository-and-schema.md`:
- replace "`generated_files` … 不支持 `[[…]]`" with: long brackets require
mcpp ≥ 0.0.85 (index floor guarantees this; lint enforces).
- new row in the case-index table: "guarded-import module unit →
`scan_overrides`" pointing at `pkgs/f/fmtlib.fmt.lua` post-P2.
- mention `mcpp xpkg parse --strict` as the local reproduction of lint.

## Verification / rollback

- Every PR rides the existing `mcpp test --workspace` 3-OS matrix.
- P1 is the only PR with blast radius (floor + version bump together): if
0.0.85 misbehaves in CI, revert P1 alone restores the 0.0.81 world; P2/P3
cannot have merged yet (lint gate).
- CN mirror for fmt (from PR #63 review) remains a separate follow-up via
gtc/mcpp-res — unrelated to this train.
38 changes: 31 additions & 7 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ on:
env:
# Bumped to 0.0.78: carries L3 build.mcpp native build program (build-mcpp member),
# compat.openblas Windows recipe (bin/libopenblas.dll staged beside the .exe).
MCPP_VERSION: "0.0.81"
MCPP_VERSION: "0.0.85"

jobs:
lint:
Expand Down Expand Up @@ -59,6 +59,30 @@ jobs:
done
[ $fail -eq 0 ] && echo "All package files valid."
exit $fail
# ── Single-source-of-truth grammar check ─────────────────────────
# `mcpp xpkg parse` uses EXACTLY the resolver's parser, so what
# passes here is what builds for users of the pinned MCPP_VERSION.
# Strict by default: unknown mcpp-segment keys fail (they would be
# silently ignored at build time). This also mechanically enforces
# the rollout rule "floor first, new grammar after": descriptors
# needing a newer grammar cannot pass a lint pinned to an older mcpp.
- name: Download pinned mcpp
run: |
curl -L -fsS -o mcpp.tar.gz \
"https://github.com/mcpp-community/mcpp/releases/download/v${MCPP_VERSION}/mcpp-${MCPP_VERSION}-linux-x86_64.tar.gz"
tar -xzf mcpp.tar.gz
echo "MCPP=$PWD/mcpp-${MCPP_VERSION}-linux-x86_64/bin/mcpp" >> "$GITHUB_ENV"
- name: Parse descriptors with the resolver grammar (mcpp xpkg parse)
run: |
fail=0
for f in pkgs/*/*.lua; do
if ! "$MCPP" xpkg parse "$f" > /dev/null; then
echo "::error file=$f::mcpp xpkg parse failed (resolver grammar)"
fail=1
fi
done
[ $fail -eq 0 ] && echo "All descriptors parse with mcpp ${MCPP_VERSION}."
exit $fail

mirror-cn-reachable:
# Closed-loop guard for the CN mirror: every CN url referenced by a
Expand Down Expand Up @@ -111,20 +135,20 @@ jobs:
include:
- platform: linux
os: ubuntu-latest
archive: mcpp-0.0.81-linux-x86_64.tar.gz
root: mcpp-0.0.81-linux-x86_64
archive: mcpp-0.0.85-linux-x86_64.tar.gz
root: mcpp-0.0.85-linux-x86_64
mcpp: bin/mcpp
xlings: registry/bin/xlings
- platform: macos
os: macos-15
archive: mcpp-0.0.81-macosx-arm64.tar.gz
root: mcpp-0.0.81-macosx-arm64
archive: mcpp-0.0.85-macosx-arm64.tar.gz
root: mcpp-0.0.85-macosx-arm64
mcpp: bin/mcpp
xlings: registry/bin/xlings
- platform: windows
os: windows-latest
archive: mcpp-0.0.81-windows-x86_64.zip
root: mcpp-0.0.81-windows-x86_64
archive: mcpp-0.0.85-windows-x86_64.zip
root: mcpp-0.0.85-windows-x86_64
mcpp: bin/mcpp.exe
xlings: registry/bin/xlings.exe
steps:
Expand Down
15 changes: 14 additions & 1 deletion docs/repository-and-schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,26 @@ tools/gtc gitcode CLI,见 cn-mirror.md
| `c_standard` | C 源码:`"c99"` 或 `"c11"` |
| `modules` | module 库:`{ "x.y" }` |
| `include_dirs` | glob 列表,暴露给消费者的头目录 |
| `generated_files` | `{ ["相对路径"]="内容字符串" }`;不支持 `[[…]]`,须以 `\n`、`\"` 转义 |
| `generated_files` | `{ ["相对路径"]="内容字符串" }`;mcpp ≥ 0.0.85 支持 Lua 长括号 `[==[…]==]` 多行字符串(推荐,可读可 review);转义单行串仍兼容 |
| `scan_overrides` | `{ ["glob"]={ provides={…}, imports={…} } }`;声明式扫描结果,命中文件跳过 M1 文本扫描(适用于带条件 import 守卫的上游模块单元,如 fmt 的 src/fmt.cc);构建期由编译器 P1689 输出自动对账,声明错误响亮失败(mcpp ≥ 0.0.85)|
| `sources` | glob 列表,编入 lib 的源码 |
| `cflags` / `cxxflags` / `ldflags` | 追加至对应规则 |
| `targets` | `{ ["name"]={ kind="lib"/"bin", main=…, soname=… } }` |
| `features` | `{ ["f"]={ sources={…} } }`,仅识别 sources |
| `deps` | `{ ["ns.name"]="ver" }`,扁平或点号式 |

## index 版本契约(index.toml)

仓库根的 `index.toml` 声明 `[index] min_mcpp` —— 能解析本索引全部描述符的最老
mcpp 版本。契约随树旅行:`publish_mcpp_index.sh` 把它打进 artifact,git clone 与
`[indices] path =` 本地索引天然携带。mcpp ≥ 0.0.85 在打开索引树时检查,违反时报
`E0006` + 升级指引(调试逃生口 `MCPP_INDEX_FLOOR=ignore`)。

规则(由 lint 机械强制,非纪律):**floor 先行、新文法在后**——lint 用 CI pin 的
mcpp 跑 `xpkg parse`(strict:未知键即失败),所以需要更新文法/键的描述符在
`MCPP_VERSION` 与 `min_mcpp` 同步提升之前物理上合不进 main。本地复现:
`mcpp xpkg parse pkgs/<x>/<name>.lua`。

## CI 行为(validate.yml)

- 触发条件:PR(改动 `pkgs/**/*.lua`、`tests/**`、`README.md` 或本 workflow)、push 至 main、nightly cron、手动触发。
Expand Down
11 changes: 11 additions & 0 deletions index.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Index→client version contract (design: mcpp .agents/docs/2026-07-08-index-
# version-semantics-and-descriptor-grammar-design.md D3). The contract travels
# WITH the index tree: packed into the artifact, present in git checkouts and
# path-indices alike. mcpp >= 0.0.85 checks it at the index-open choke point
# (E0006 on violation). Bump min_mcpp ONLY together with the CI MCPP_VERSION
# pin — lint parses descriptors with the pinned mcpp, which enforces the
# "floor first, new grammar after" rollout rule mechanically.
[index]
spec = "1"
min_mcpp = "0.0.85"
latest_mcpp = "0.0.85"
3 changes: 3 additions & 0 deletions tools/publish_mcpp_index.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ info() { echo "[mcpp-index] $*"; }
TREE="$OUT/tree"; mkdir -p "$TREE"
cp -a "$SRC/pkgs" "$TREE/"
[ -f "$SRC/README.md" ] && cp "$SRC/README.md" "$TREE/" || true
# index.toml carries the index→client version contract (min_mcpp floor);
# it must travel with the tree so unpacked snapshots enforce it offline.
[ -f "$SRC/index.toml" ] && cp "$SRC/index.toml" "$TREE/" || true
tar --sort=name --owner=0 --group=0 --numeric-owner -czf "$OUT/$BASE.tar.gz" -C "$TREE" . 2>/dev/null \
|| tar -czf "$OUT/$BASE.tar.gz" -C "$TREE" .
SHA="$(sha256sum "$OUT/$BASE.tar.gz" | awk '{print $1}')"
Expand Down
Loading